This commit is contained in:
zty 2025-04-27 09:21:23 +08:00
commit 89c8cac7c1
6 changed files with 65 additions and 42 deletions

View File

@ -169,7 +169,7 @@ def do_in(item: MIOItem):
else:
raise ParseError(f'{str(xmaterial)}-{xbatch}车间物料不足')
wm_production_dept = wm.mgroup.belong_dept if wm.mgroup else None
wm_production_dept = wm.mgroup.belong_dept if wm.mgroup else wm.belong_dept
if production_dept is None:
production_dept = wm_production_dept
elif wm_production_dept and production_dept != wm_production_dept:
@ -247,10 +247,8 @@ class InmService:
BatchLog.clear(mio=instance)
else:
for item in MIOItem.objects.filter(mio=instance):
if item.mb: # 说明录入到已有批次
BatchSt.g_create(batch=item.batch)
else:
BatchSt.g_create(batch=item.batch, mio=instance, material_start=item.material)
BatchSt.g_create(
batch=item.batch, mio=instance, material_start=item.material, reuse_node=True)
from apps.pum.services import PumService
if is_reverse:
cls.update_mb(instance, -1)
@ -262,10 +260,8 @@ class InmService:
BatchLog.clear(mio=instance)
else:
for item in MIOItem.objects.filter(mio=instance):
if item.mb:
BatchSt.g_create(batch=item.batch)
else:
BatchSt.g_create(batch=item.batch, mio=instance, material_start=item.material)
BatchSt.g_create(
batch=item.batch, mio=instance, material_start=item.material, reuse_node=True)
if is_reverse:
cls.update_mb(instance, -1)
else:

View File

@ -53,7 +53,7 @@ class WMaterialFilter(filters.FilterSet):
qs = queryset.exclude(material__id__in=matoutIds)|queryset.filter(state=WMaterial.WM_REPAIR)
return qs
elif value == "done":
qs = queryset.filter(material__id__in=matoutIds)|queryset.filter(state=WMaterial.WM_REPAIRED)
qs = queryset.filter(material__id__in=matoutIds).exclude(state=WMaterial.WM_REPAIR)|queryset.filter(state=WMaterial.WM_REPAIRED)
return qs
else:
raise ParseError("请提供工段查询条件")

View File

@ -616,18 +616,32 @@ class BatchSt(BaseModel):
unique_together = [("batch", "version")]
@classmethod
def g_create(cls, batch:str, mio=None, handover=None, mlog=None, material_start=None):
def g_create(cls, batch:str, mio=None, handover=None, mlog=None, material_start=None, reuse_node=False):
"""
创建新的批次
"""
if mio is None and handover is None and mlog is None:
return cls.objects.get_or_create(batch=batch)
try:
node = cls.objects.get(batch=batch)
except cls.DoesNotExist:
return cls.objects.create(batch=batch), True
except cls.MultipleObjectsReturned:
# 兼容性处理
node = cls.objects.filter(batch=batch).order_by('-version').first()
return node, False
else:
version = 1
# 带有来源的批次获取,需检查批次号是否可用
if cls.objects.filter(batch=batch, version=1).exists():
latest_version = BatchSt.objects.filter(batch=batch).aggregate(Max("version"))["version__max"]
version = latest_version + 1
if cls.objects.filter(batch=batch).exists():
if reuse_node:
node = cls.objects.filter(batch=batch).order_by('-version').first()
if node.material_start is not None and node.material_start != material_start:
raise ParseError(f"{batch}-该批次号因物料不同不可引用")
return node, False
else:
raise ParseError(f"{batch}-该批次号不可使用")
# latest_version = BatchSt.objects.filter(batch=batch).aggregate(Max("version"))["version__max"]
# version = latest_version + 1
if mio is None and handover is None and mlog is None:
raise ParseError("mio or handover or mlog must be provided")
ins = cls.objects.create(batch=batch, mio=mio, handover=handover, mlog=mlog, material_start=material_start, version=version)

View File

@ -359,6 +359,9 @@ class MlogSerializer(CustomModelSerializer):
with transaction.atomic():
mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().create(validated_data)
## 返工没有加工前不良
if instance.is_fix and instance.count_pn_jgqbl >0:
raise ParseError("返工不支持加工前不良")
# 自动生成mlogb
batch_in = instance.batch
wm_in = instance.wm_in
@ -457,6 +460,9 @@ class MlogSerializer(CustomModelSerializer):
with transaction.atomic():
mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().update(instance, validated_data)
## 返工没有加工前不良
if instance.is_fix and instance.count_pn_jgqbl >0:
raise ParseError("返工不支持加工前不良")
wm_in = instance.wm_in
batch_in = instance.batch
if wm_in:
@ -541,33 +547,37 @@ class MlogSerializer(CustomModelSerializer):
attrs['mtype'] = Mlog.MTYPE_SELF # 默认为自生产
fmlog:Fmlog = attrs.get('fmlog', None)
mtaskb = attrs.get('mtaskb', None)
wm_in: WMaterial = attrs.get('wm_in', None)
if fmlog:
attrs['fill_way'] = Mlog.MLOG_12
wm_in: WMaterial = attrs.get('wm_in', None)
if wm_in:
pass
else:
if not wm_in:
raise ParseError('未提供消耗的车间物料')
attrs['mgroup'] = fmlog.mgroup
attrs['is_fix'] = fmlog.is_fix
attrs['mtask'] = fmlog.mtask
attrs['route'] = fmlog.route
attrs['mtype'] = fmlog.mgroup.mtype
if attrs['mtask'] and attrs['mtask'].route:
attrs['route'] = attrs['mtask'].route
# if attrs['mtask'].mtaskb and mtaskb is None:
# raise ParseError('子任务不能为空')
if mtaskb and mtaskb.mtask != fmlog.mtask:
raise ParseError('子任务不一致')
if wm_in.state in [WMaterial.WM_OK]:
pass
else:
if wm_in:
attrs["material_in"] = wm_in.material
attrs["batch"] = wm_in.batch
if attrs["is_fix"]:
attrs["material_out"] = attrs["material_in"]
if wm_in.state in [WMaterial.WM_REPAIR, WMaterial.WM_NOTOK]:
pass
else:
raise ParseError('返修或复检需使用返修品/不合格品')
elif wm_in.state != WMaterial.WM_OK:
raise ParseError('非合格品不可使用')
if wm_in.material != attrs['route'].material_in:
if attrs['route'] and wm_in.material != attrs['route'].material_in:
raise ParseError('消耗物料与工艺步骤不一致')
if attrs['mtype'] == Mlog.MTYPE_OUT:
supplier = attrs.get('supplier', None)
if not supplier:
raise ParseError('外协必须选择外协单位')
if attrs['mtype'] == Mlog.MTYPE_OUT:
supplier = attrs.get('supplier', None)
if not supplier:
raise ParseError('外协必须选择外协单位')
mtask = attrs.get('mtask', None)
count_notok = 0
for i in attrs:
@ -588,8 +598,6 @@ class MlogSerializer(CustomModelSerializer):
else:
if attrs.get('work_end_time', None):
attrs['handle_date'] = localdate(attrs['work_end_time'])
elif attrs.get('work_start_time', None):
attrs['handle_date'] = localdate(attrs['work_start_time'])
mtaskb: Mtaskb = attrs.get('mtaskb', None)
if mtaskb:
mtask = mtaskb.mtask
@ -599,6 +607,8 @@ class MlogSerializer(CustomModelSerializer):
attrs['mgroup'] = mtask.mgroup
attrs['material_in'] = mtask.material_in
material_out = mtask.material_out
if wm_in and wm_in.material != mtask.material_in:
raise ParseError('消耗物料与任务不一致')
attrs['material_out'] = material_out
if mtask.start_date == mtask.end_date:
attrs['handle_date'] = mtask.end_date
@ -628,21 +638,20 @@ class MlogInitSerializer(CustomModelSerializer):
}
def validate(self, attrs):
route: Route = attrs.get('route', None)
mgroup: Mgroup = attrs['mgroup']
is_fix:bool = attrs.get('is_fix', False)
attrs['mtype'] = mgroup.mtype
if is_fix:
attrs["route"] = None
elif route is None:
raise ParseError('缺少工艺路线')
if route and route.process != mgroup.process:
raise ParseError('工序不匹配')
if is_fix:
attrs['hour_work'] = None
attrs['material_in'] = None
attrs['material_out'] = None
if route:
else:
route: Route = attrs.get('route', None)
if not route:
raise ParseError('缺少工艺路线')
if route and route.process != mgroup.process:
raise ParseError('工序不匹配')
attrs['hour_work'] = route.hour_work
attrs['material_in'] = route.material_in
attrs['material_out'] = route.material_out
@ -703,6 +712,8 @@ class MlogbInSerializer(CustomModelSerializer):
raise ParseError("请选择相应车间库存!")
if is_fix: # 返修或复检
if wm_in.state in [WMaterial.WM_REPAIR, WMaterial.WM_NOTOK]:
pass
else:
raise ParseError('返修或复检需使用返修品/不合格品')
elif wm_in.state != WMaterial.WM_OK:
raise ParseError('非合格品不可使用')
@ -1222,6 +1233,7 @@ class FmlogSerializer(CustomModelSerializer):
is_fix = attrs.get("is_fix", False)
if is_fix:
attrs["mtask"] = None
attrs['route'] = None
elif not attrs.get("mtask", None) and not attrs.get("route", None):
raise ParseError("请选择任务或工艺步骤")
mtask: Mtask = attrs['mtask']

View File

@ -961,9 +961,9 @@ def mlog_audit_end(ticket: Ticket):
mlog_submit(ins, ticket.create_by, now)
def get_batch_dag(batch_number: str):
def get_batch_dag(batch_number: str, version=1):
try:
batch_ins = BatchSt.objects.get(batch=batch_number)
batch_ins = BatchSt.objects.get(batch=batch_number, version=version)
except Exception:
raise ParseError("该批次号未构建关系链")
# 收集所有相关批次和边

View File

@ -583,7 +583,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
for wpr in Wpr.objects.filter(wm=wm_in).order_by("number"):
Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbin, defaults={"number": wpr.number})
if qct is None and not (is_fix and mtype == Process.PRO_PROD):
if qct is None:
mlog.qct = Qct.get(material_out, "process")
mlog.save(update_fields = ["qct"])
@ -816,6 +816,7 @@ class BatchLogViewSet(ListModelMixin, CustomGenericViewSet):
获取该批次的DAG图数据
"""
batch = request.data.get("batch", None)
version = request.data.get("version", 1)
if not batch:
raise ParseError("缺少batch参数")
return Response(get_batch_dag(batch))
return Response(get_batch_dag(batch, version))