Merge branch 'master' of https://e.coding.net/ctcdevteam/ehs/ehs_server
This commit is contained in:
commit
d1bd74fd5d
|
@ -0,0 +1,24 @@
|
||||||
|
# Generated by Django 3.2.12 on 2025-01-09 07:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0034_auto_20250108_1016'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ftestdefect',
|
||||||
|
name='is_main',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否主要缺陷'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ftestdefect',
|
||||||
|
name='ftest',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='defects_ftest', to='qm.ftest', verbose_name='关联检验'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -307,10 +307,11 @@ class FtestDefect(BaseModel):
|
||||||
缺陷明细
|
缺陷明细
|
||||||
"""
|
"""
|
||||||
ftest = models.ForeignKey(
|
ftest = models.ForeignKey(
|
||||||
Ftest, verbose_name='关联检验', on_delete=models.CASCADE)
|
Ftest, verbose_name='关联检验', on_delete=models.CASCADE, related_name="defects_ftest")
|
||||||
test_user = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE, null=True, blank=True)
|
test_user = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE)
|
defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE)
|
||||||
has = models.BooleanField('是否发现', default=False)
|
has = models.BooleanField('是否发现', default=False)
|
||||||
|
is_main = models.BooleanField('是否主要缺陷', default=False)
|
||||||
|
|
||||||
|
|
||||||
class Ptest(CommonAModel):
|
class Ptest(CommonAModel):
|
||||||
|
|
|
@ -249,7 +249,7 @@ class FtestDefectSerializer(CustomModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FtestDefect
|
model = FtestDefect
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = EXCLUDE_FIELDS_BASE + ['ftest']
|
read_only_fields = EXCLUDE_FIELDS_BASE + ['ftest', 'is_main']
|
||||||
|
|
||||||
|
|
||||||
class FtestItemProcessSerializer(CustomModelSerializer):
|
class FtestItemProcessSerializer(CustomModelSerializer):
|
||||||
|
@ -285,10 +285,13 @@ class FtestProcessSerializer(CustomModelSerializer):
|
||||||
for item in ftestitems:
|
for item in ftestitems:
|
||||||
FtestItem.objects.create(ftest=instance, **item)
|
FtestItem.objects.create(ftest=instance, **item)
|
||||||
is_ok = True
|
is_ok = True
|
||||||
|
has_is_main = False
|
||||||
for item2 in ftestdefects:
|
for item2 in ftestdefects:
|
||||||
defect:Defect = item2["defect"]
|
defect:Defect = item2["defect"]
|
||||||
if defect.okcate in [Defect.DEFECT_NOTOK] and item2["has"]:
|
if defect.okcate in [Defect.DEFECT_NOTOK] and item2["has"]:
|
||||||
is_ok = False
|
is_ok = False
|
||||||
|
if not has_is_main:
|
||||||
|
item2["is_main"] = True
|
||||||
FtestDefect.objects.create(ftest=instance, **item2)
|
FtestDefect.objects.create(ftest=instance, **item2)
|
||||||
instance.is_ok = is_ok
|
instance.is_ok = is_ok
|
||||||
instance.save()
|
instance.save()
|
||||||
|
@ -308,16 +311,22 @@ class FtestProcessSerializer(CustomModelSerializer):
|
||||||
setattr(ins, k, v)
|
setattr(ins, k, v)
|
||||||
ins.save()
|
ins.save()
|
||||||
is_ok = True
|
is_ok = True
|
||||||
|
has_is_main = False
|
||||||
for item2 in ftestdefects:
|
for item2 in ftestdefects:
|
||||||
try:
|
try:
|
||||||
ins = FtestDefect.objects.get(ftest=instance, defect=item2["defect"])
|
ins:FtestDefect = FtestDefect.objects.get(ftest=instance, defect=item2["defect"])
|
||||||
except FtestDefect.DoesNotExist:
|
except FtestDefect.DoesNotExist:
|
||||||
raise ParseError("新的缺陷项!")
|
raise ParseError("新的缺陷项!")
|
||||||
for k, v in item2.items():
|
for k, v in item2.items():
|
||||||
setattr(ins, k, v)
|
setattr(ins, k, v)
|
||||||
ins.save()
|
ins.save()
|
||||||
|
if ins.is_main:
|
||||||
|
has_is_main = True
|
||||||
if ins.has and ins.defect.okcate in [Defect.DEFECT_NOTOK]:
|
if ins.has and ins.defect.okcate in [Defect.DEFECT_NOTOK]:
|
||||||
is_ok = False
|
is_ok = False
|
||||||
|
if not has_is_main:
|
||||||
|
ins.is_main = True
|
||||||
|
ins.save()
|
||||||
instance.is_ok = is_ok
|
instance.is_ok = is_ok
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.12 on 2025-01-09 07:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0035_auto_20250109_1526'),
|
||||||
|
('wpm', '0083_mlogbw_ftest'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mlogbw',
|
||||||
|
name='ftest',
|
||||||
|
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='mlogbw_ftest', to='qm.ftest', verbose_name='关联检验'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -19,6 +19,7 @@ import logging
|
||||||
from apps.wpm.services_2 import get_alldata_with_batch_and_store
|
from apps.wpm.services_2 import get_alldata_with_batch_and_store
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from apps.wpmw.models import Wpr, WprDefect
|
from apps.wpmw.models import Wpr, WprDefect
|
||||||
|
from ..qm.models import Defect, FtestDefect
|
||||||
|
|
||||||
myLogger = logging.getLogger('log')
|
myLogger = logging.getLogger('log')
|
||||||
|
|
||||||
|
@ -177,7 +178,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
else:
|
else:
|
||||||
wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup, state=WMaterial.WM_OK)
|
wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup, state=WMaterial.WM_OK)
|
||||||
if not wm_qs.exists():
|
if not wm_qs.exists():
|
||||||
wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, belong_dept=belong_dept, mgroup=None, state=WMaterial.WM_OK)
|
wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma,
|
||||||
|
belong_dept=belong_dept, mgroup=None, state=WMaterial.WM_OK)
|
||||||
|
|
||||||
count_x = wm_qs.count()
|
count_x = wm_qs.count()
|
||||||
if count_x == 1:
|
if count_x == 1:
|
||||||
|
@ -219,7 +221,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
wm.update_by = user
|
wm.update_by = user
|
||||||
wm.save()
|
wm.save()
|
||||||
if material_in.tracking == Material.MA_TRACKING_SINGLE:
|
if material_in.tracking == Material.MA_TRACKING_SINGLE:
|
||||||
raise ParseError("加工前不良的物料暂不支持单件")
|
raise ParseError("加工前不良的物料暂不支持单件追踪")
|
||||||
|
|
||||||
|
|
||||||
if material_out: # 需要入车间库存
|
if material_out: # 需要入车间库存
|
||||||
|
@ -232,11 +234,23 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) for mo in m_outs.all()]
|
m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) for mo in m_outs.all()]
|
||||||
if need_store_notok:
|
if need_store_notok:
|
||||||
for item in m_outs:
|
for item in m_outs:
|
||||||
for f in Mlogb._meta.fields:
|
if Mlogbw.objects.filter(mlogb=item).exists():
|
||||||
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
# 获取所有主要的不合格项
|
||||||
notok_sign = f.name.replace('count_n_', '')
|
bw_qs = Mlogbw.objects.filter(mlogb=item)
|
||||||
m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign, item))
|
defect_qs = FtestDefect.objects.filter(ftest__is_ok=False,
|
||||||
stored_notok = True
|
ftest__mlogbw_ftest__mlogb=item, is_main=True).values_list(
|
||||||
|
"defect", flat=True).distinct()
|
||||||
|
for defect in defect_qs:
|
||||||
|
xcount = bw_qs.filter(ftest__defects_ftest__defect=defect).count()
|
||||||
|
if xcount > 0:
|
||||||
|
m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item))
|
||||||
|
|
||||||
|
else:
|
||||||
|
for f in Mlogb._meta.fields:
|
||||||
|
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
||||||
|
notok_sign = f.name.replace('count_n_', '')
|
||||||
|
m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign, item))
|
||||||
|
stored_notok = True
|
||||||
# 这里有一个漏洞,在产出物为兄弟件的情况下,不合格品的数量是记录在mlog上的,
|
# 这里有一个漏洞,在产出物为兄弟件的情况下,不合格品的数量是记录在mlog上的,
|
||||||
# 而不是mlogb上,以上的额外处理就没有效果了, 不过光子不记录不合格品
|
# 而不是mlogb上,以上的额外处理就没有效果了, 不过光子不记录不合格品
|
||||||
else:
|
else:
|
||||||
|
@ -244,9 +258,14 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
# 一次填写的暂时不处理不合格品
|
# 一次填写的暂时不处理不合格品
|
||||||
|
|
||||||
for mo in m_outs_list:
|
for mo in m_outs_list:
|
||||||
mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign, mlog_or_b = mo
|
mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign_or_defect, mlog_or_b = mo
|
||||||
wm_state = WMaterial.WM_OK if notok_sign is None else WMaterial.WM_NOTOK
|
wm_state = WMaterial.WM_OK if notok_sign_or_defect is None else WMaterial.WM_NOTOK
|
||||||
lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': notok_sign, 'state': wm_state}
|
lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None,
|
||||||
|
'notok_sign': None, 'defect': None, 'state': wm_state}
|
||||||
|
if isinstance(notok_sign_or_defect, Defect):
|
||||||
|
lookup['defect'] = notok_sign_or_defect
|
||||||
|
elif notok_sign_or_defect is not None:
|
||||||
|
lookup['notok_sign'] = notok_sign_or_defect
|
||||||
if into_wm_mgroup:
|
if into_wm_mgroup:
|
||||||
lookup['mgroup'] = mgroup
|
lookup['mgroup'] = mgroup
|
||||||
stored_mgroup = True
|
stored_mgroup = True
|
||||||
|
@ -274,9 +293,9 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
raise ParseError("日志与明细数量不一致,操作失败")
|
raise ParseError("日志与明细数量不一致,操作失败")
|
||||||
for item in mlogbws:
|
for item in mlogbws:
|
||||||
if item.wpr:
|
if item.wpr:
|
||||||
Wpr.change_or_new(wpr=item.wpr, wm=wm)
|
Wpr.change_or_new(wpr=item.wpr, wm=wm, ftest=item.ftest)
|
||||||
else:
|
else:
|
||||||
wpr = Wpr.change_or_new(number=item.number, wm=wm)
|
wpr = Wpr.change_or_new(number=item.number, wm=wm, ftest=item.ftest)
|
||||||
item.wpr = wpr
|
item.wpr = wpr
|
||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,9 @@ class MlogViewSet(CustomModelViewSet):
|
||||||
# delete_auditlog(instance, instance.id)
|
# delete_auditlog(instance, instance.id)
|
||||||
if instance.ticket:
|
if instance.ticket:
|
||||||
instance.ticket.delete()
|
instance.ticket.delete()
|
||||||
|
ftestIds = list(Ftest.objects.filter(mlogbw_ftest__mlogb__mlog=instance).values_list('id', flat=True))
|
||||||
instance.delete()
|
instance.delete()
|
||||||
|
Ftest.objects.filter(id__in=ftestIds).delete()
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
|
@ -489,15 +491,18 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
||||||
ins: Mlogb = instance
|
ins: Mlogb = instance
|
||||||
if ins.mlog.submit_time is not None:
|
if ins.mlog.submit_time is not None:
|
||||||
raise ParseError('生产日志已提交不可编辑')
|
raise ParseError('生产日志已提交不可编辑')
|
||||||
|
qs = Mlogb.objects.none()
|
||||||
|
if ins.mlogb_to:
|
||||||
|
qs = qs|Mlogb.objects.filter(id=ins.mlogb_to.id)
|
||||||
if ins.mtask:
|
if ins.mtask:
|
||||||
query_dict = {"material_out__isnull": False, "mlog": ins.mlog, "mtask": ins.mtask}
|
query_dict = {"material_out__isnull": False, "mlog": ins.mlog, "mtask": ins.mtask}
|
||||||
route = ins.mtask.route
|
route = ins.mtask.route
|
||||||
if route.batch_bind:
|
if route.batch_bind:
|
||||||
query_dict["batch__contains"] = ins.batch
|
query_dict["batch__contains"] = ins.batch
|
||||||
qs = Mlogb.objects.filter(**query_dict)
|
qs = Mlogb.objects.filter(**query_dict) | qs
|
||||||
# 需要删除子集ftest记录
|
# 需要删除子集ftest记录
|
||||||
ftestIds = Mlogbw.objects.filter(mlogb__in=qs).values_list("ftest__id", flat=True)
|
ftestIds = list(Ftest.objects.filter(mlogbw_ftest__mlogb__in=qs).values_list('id', flat=True))
|
||||||
Mlogb.objects.filter(**query_dict).delete()
|
qs.delete()
|
||||||
Ftest.objects.filter(id__in=ftestIds).delete()
|
Ftest.objects.filter(id__in=ftestIds).delete()
|
||||||
instance.delete()
|
instance.delete()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from apps.qm.models import FtestDefect
|
||||||
from apps.utils.models import BaseModel
|
from apps.utils.models import BaseModel
|
||||||
from apps.mtm.models import Material
|
from apps.mtm.models import Material
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
|
@ -19,7 +21,7 @@ class Wpr(BaseModel):
|
||||||
wm = models.ForeignKey("wpm.wmaterial", verbose_name="车间物料", on_delete=models.CASCADE, null=True, blank=True)
|
wm = models.ForeignKey("wpm.wmaterial", verbose_name="车间物料", on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def change_or_new(cls, wpr=None, number=None, mb=None, wm=None, old_mb=None, old_wm=None):
|
def change_or_new(cls, wpr=None, number=None, mb=None, wm=None, old_mb=None, old_wm=None, ftest=None):
|
||||||
if wpr is None and number is None:
|
if wpr is None and number is None:
|
||||||
raise ParseError("id和number不能同时为空")
|
raise ParseError("id和number不能同时为空")
|
||||||
if mb and wm:
|
if mb and wm:
|
||||||
|
@ -51,6 +53,10 @@ class Wpr(BaseModel):
|
||||||
if wm:
|
if wm:
|
||||||
ins.material = wm.material
|
ins.material = wm.material
|
||||||
ins.save()
|
ins.save()
|
||||||
|
if ftest: # 通过检验变更其缺陷项
|
||||||
|
WprDefect.objects.filter(wpr=ins).delete()
|
||||||
|
for ftestdefect in FtestDefect.objects.filter(ftest=ftest):
|
||||||
|
WprDefect.objects.create(wpr=ins, defect=ftestdefect.defect, is_main=ftestdefect.is_main)
|
||||||
return ins
|
return ins
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
Loading…
Reference in New Issue