下料清单初步完成
This commit is contained in:
parent
8f1746f8a6
commit
4538c32834
|
@ -0,0 +1,59 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-04 08:41
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0042_alter_recordformfield_field_type'),
|
||||
('wpm', '0043_auto_20211231_1130'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='operation',
|
||||
name='use_scrap',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='from_batch',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='源批次'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='from_material',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='om_fmaterial', to='mtm.material', verbose_name='源物料'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='use_scrap',
|
||||
field=models.BooleanField(default=False, verbose_name='是否使用的边角料'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationwproduct',
|
||||
name='ng_sign',
|
||||
field=models.PositiveSmallIntegerField(blank=True, choices=[(10, '返工'), (20, '返修'), (30, '报废'), (40, '让步接收'), (50, '偏离许可'), (60, '降级使用'), (70, '退回供方'), (80, '召回')], null=True, verbose_name='当时的不合格标记'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='coperation',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wp_coperation', to='wpm.operation', verbose_name='创建所关联操作'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproductflow',
|
||||
name='coperation',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wpf_coperation', to='wpm.operation', verbose_name='创建所关联操作'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationmaterial',
|
||||
name='material',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='om_material', to='mtm.material', verbose_name='可能产出的产品'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproductflow',
|
||||
name='operation',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wpf_operation', to='wpm.operation', verbose_name='当前操作'),
|
||||
),
|
||||
]
|
|
@ -96,6 +96,8 @@ class WProduct(CommonAModel):
|
|||
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_operation')
|
||||
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_coperation')
|
||||
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test')
|
||||
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
|
||||
|
@ -144,7 +146,9 @@ class WproductFlow(CommonAModel):
|
|||
|
||||
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
|
||||
on_delete=models.SET_NULL, null=True, blank=True)
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_operation')
|
||||
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_coperation')
|
||||
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
|
||||
on_delete=models.SET_NULL, null=True, blank=True)
|
||||
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
|
||||
|
@ -183,7 +187,6 @@ class Operation(CommonADModel):
|
|||
生产操作
|
||||
"""
|
||||
step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True)
|
||||
use_scrap = models.BooleanField('是否使用的边角料', default=False)
|
||||
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
|
||||
is_submited = models.BooleanField('是否提交', default=False)
|
||||
|
||||
|
@ -196,7 +199,7 @@ class OperationWproduct(BaseModel):
|
|||
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
|
||||
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='ow_subplan')
|
||||
|
||||
ng_sign = models.PositiveSmallIntegerField('当时的不合格标记', choices= WProduct.ng_choices, null=True, blank=True)
|
||||
class Meta:
|
||||
unique_together = (
|
||||
('operation','wproduct')
|
||||
|
@ -209,7 +212,8 @@ class OperationMaterial(BaseModel):
|
|||
type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices)
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
||||
|
||||
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, null=True, blank=True)
|
||||
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE,
|
||||
null=True, blank=True, related_name='om_material')
|
||||
count = models.PositiveSmallIntegerField('消耗或产出数量', null=True, blank=True)
|
||||
|
||||
wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
@ -217,8 +221,12 @@ class OperationMaterial(BaseModel):
|
|||
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
use_scrap = models.BooleanField('是否使用的边角料', default=False)
|
||||
|
||||
#以下为冷加工下料清单所用字段
|
||||
from_material = models.ForeignKey(Material, verbose_name='源物料', on_delete=models.CASCADE,
|
||||
null=True, blank=True, related_name='om_fmaterial')
|
||||
from_batch = models.CharField('源批次', max_length=100, null=True, blank=True)
|
||||
count_cut = models.PositiveIntegerField('切裁片数', default=0)
|
||||
count_real = models.PositiveIntegerField('生产片数', default=0)
|
||||
count_ok = models.PositiveIntegerField('成品数量', default=0)
|
||||
|
@ -226,6 +234,7 @@ class OperationMaterial(BaseModel):
|
|||
count_podian = models.PositiveIntegerField('破点甩片', default=0)
|
||||
count_hua = models.PositiveIntegerField('划伤甩片', default=0)
|
||||
count_other = models.PositiveIntegerField('其他甩片', default=0)
|
||||
|
||||
class Meta:
|
||||
unique_together = (
|
||||
('operation','material', 'batch')
|
||||
|
|
|
@ -350,7 +350,7 @@ class OperationMaterialCreate1Serailizer(serializers.ModelSerializer):
|
|||
wmaterial = serializers.PrimaryKeyRelatedField(required=True, queryset=WMaterial.objects.all())
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = ['operation', 'wmaterial', 'count']
|
||||
fields = ['operation', 'wmaterial', 'count', 'use_scrap']
|
||||
|
||||
def validate(self, attrs):
|
||||
if attrs['count'] <=0:
|
||||
|
@ -376,7 +376,7 @@ class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
|
|||
subproduction_progress = serializers.PrimaryKeyRelatedField(required=True, queryset=SubProductionProgress.objects.all())
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = ['operation', 'subproduction_progress', 'count']
|
||||
fields = ['operation', 'subproduction_progress', 'count', 'use_scrap']
|
||||
|
||||
def create(self, validated_data):
|
||||
subproduction_progress = validated_data['subproduction_progress']
|
||||
|
@ -448,7 +448,7 @@ class WproductTicketListSerializer(serializers.ModelSerializer):
|
|||
|
||||
class CuttingListSerializer(serializers.ModelSerializer):
|
||||
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
from_material_ = MaterialSimpleSerializer(source='from_material', read_only=True)
|
||||
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
|
|
|
@ -154,28 +154,23 @@ class WpmServies(object):
|
|||
"""
|
||||
inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN)
|
||||
outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||
for i in inputs:
|
||||
sp = i.subproduction_plan
|
||||
i.count_cut = outputs.filter(subproduction_plan=sp).first().count
|
||||
i.count_real = sp.count_real
|
||||
i.count_ok = sp.count_ok
|
||||
wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
|
||||
i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
|
||||
i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
|
||||
i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
|
||||
i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count()
|
||||
i.is_cutting = True
|
||||
i.save()
|
||||
|
||||
@classmethod
|
||||
def update_cutting_list_with_sp(cls, sp:SubProductionPlan):
|
||||
"""
|
||||
根据子计划更新下料清单
|
||||
"""
|
||||
wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
|
||||
for i in OperationMaterial.objects.filter(subproduction_plan=sp, is_cutting=True):
|
||||
i.count_real = sp.count_real
|
||||
i.count_ok = sp.count_ok
|
||||
for i in outputs:
|
||||
if i.use_scrap: # 如果使用了边角料
|
||||
i.count_cut = 0
|
||||
i.from_material = SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
|
||||
subproduction__subplan_subprod=i.subproduction_plan).first().material
|
||||
else:
|
||||
input_q = inputs.filter(subproduction_plan=i.subproduction_plan) # 同计划的消耗
|
||||
i.from_material = input_q.first().matrial
|
||||
count_cut = 0
|
||||
from_batch = ''
|
||||
for m in input_q:
|
||||
count_cut = count_cut + m.count
|
||||
from_batch = from_batch + ';' + m.batch if m.batch else from_batch
|
||||
wpfs = WproductFlow.objects.filter(subproduction_plan=i.subproduction_plan,
|
||||
is_lastlog=True, coperation=op)# 筛选本次操作下子计划的产品日志
|
||||
i.count_real = wpfs.count()
|
||||
i.count_ok = wpfs.exclude(scrap_reason=None).count()
|
||||
i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
|
||||
i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
|
||||
i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
|
||||
|
|
|
@ -386,7 +386,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
obj.save()
|
||||
WpmServies.add_wproduct_flow_log(obj, 'scrap')
|
||||
if obj.step.process.id == 1: #如果是冷加工
|
||||
WpmServies.update_cutting_list_with_sp(obj.subproduction_plan)
|
||||
WpmServies.update_cutting_list_with_operation(obj.coperation)
|
||||
return Response()
|
||||
|
||||
# @action(methods=['get'], detail=False, perms_map={'get':'*'})
|
||||
|
@ -510,12 +510,13 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
owp['number'] = wpd.number
|
||||
owp['material'] = wpd.material
|
||||
owp['subproduction_plan'] = wpd.subproduction_plan
|
||||
owp['ng_sign'] = wpd.ng_sign
|
||||
owps.append(OperationWproduct(**owp))
|
||||
OperationWproduct.objects.bulk_create(owps)
|
||||
else:
|
||||
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
||||
# 查询需要填写的自定义表格
|
||||
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO)
|
||||
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO, enabled=True)
|
||||
for i in forms:
|
||||
opr = OperationRecord()
|
||||
opr.operation = op
|
||||
|
@ -555,11 +556,22 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
step = op.step
|
||||
if op.is_submited:
|
||||
raise exceptions.APIException('该操作已提交')
|
||||
# 校验消耗产出是否正确填写
|
||||
omis = OperationMaterial.objects.filter(operation=op,
|
||||
type=SubprodctionMaterial.SUB_MA_TYPE_IN)
|
||||
sps_omi_l = omis.values_list('subproduction_plan', flat=True)
|
||||
omos = OperationMaterial.objects.filter(operation=op,
|
||||
type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||
sps_omo_l = omos.filter(use_scrap=False).values_list('subproduction_plan', flat=True)
|
||||
if set(list(sps_omi_l)) == set(list(sps_omo_l)):
|
||||
pass
|
||||
else:
|
||||
raise exceptions.APIException('消耗与产出不一致')
|
||||
# 检查自定义表单填写
|
||||
if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
|
||||
raise exceptions.APIException('存在自定义表单未填写')
|
||||
# 更新物料消耗进度
|
||||
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN):
|
||||
for i in omis:
|
||||
# 更新车间物料
|
||||
i_wmat = i.wmaterial
|
||||
i_wmat.count = i_wmat.count- i.count
|
||||
|
@ -570,7 +582,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
spp.count_real = spp.count_real + i.count
|
||||
spp.save()
|
||||
# 更新产出
|
||||
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
|
||||
for i in omos:
|
||||
if not i.subproduction_progress.is_main:
|
||||
# 更新车间物料产出情况
|
||||
ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan, material=i.material)
|
||||
|
@ -607,24 +619,23 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
|
||||
elif step.type == Step.STEP_TYPE_DIV:
|
||||
# 更新物料产出情况
|
||||
outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||
if not outputs.exists():
|
||||
if not omos.exists():
|
||||
raise exceptions.APIException('请选择物料产出')
|
||||
for i in outputs:
|
||||
for i in omos:
|
||||
if i.subproduction_progress.is_main:
|
||||
newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
|
||||
wpr = dict(material=i.material, step=newstep,
|
||||
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
|
||||
subproduction_plan=i.subproduction_plan, create_by=request.user)
|
||||
subproduction_plan=i.subproduction_plan,
|
||||
create_by=request.user, coperation=op)
|
||||
for x in range(i.count):
|
||||
ins = WProduct.objects.create(**wpr)
|
||||
# 添加日志
|
||||
WpmServies.add_wproduct_flow_log(ins, 'operation_submit')
|
||||
WpmServies.add_wproduct_flow_log(ins, 'wproduct_create')
|
||||
# 更新进度
|
||||
WpmServies.update_subproduction_progress_main(sp=i.subproduction_plan)
|
||||
elif step.type == Step.STEP_TYPE_COMB:
|
||||
oms_w = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT,
|
||||
subproduction_progress__is_main=True)
|
||||
oms_w = omos.filter(subproduction_progress__is_main=True)
|
||||
if len(oms_w) == 1:
|
||||
oms_w = oms_w[0]
|
||||
# 校验单片数量是否正确, 暂时未写
|
||||
|
@ -640,8 +651,9 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
# 更新子计划进度
|
||||
WpmServies.update_subproduction_progress_main(sp=oms_w.subproduction_plan)
|
||||
wproduct.create_by = request.user
|
||||
wproduct.coperation = op
|
||||
wproduct.save()
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'operation_submit')
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'wproduct_create')
|
||||
# 隐藏原半成品
|
||||
wps = WProduct.objects.filter(ow_wproduct__operation = op)
|
||||
wps.update(is_hidden=True, child=wproduct, update_by=request.user, update_time=timezone.now())
|
||||
|
|
Loading…
Reference in New Issue