Merge branch 'master' of https://e.coding.net/ctcdevteam/ehs/ehs_server
This commit is contained in:
commit
7664dfefa4
|
@ -0,0 +1,42 @@
|
||||||
|
# Generated by Django 3.2.12 on 2024-08-12 02:48
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0050_auto_20240701_0936'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('qm', '0017_alter_testitem_field_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ftestwork',
|
||||||
|
name='count_notok_json',
|
||||||
|
field=models.JSONField(blank=True, default=dict, verbose_name='不合格项数量统计'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ftestwork',
|
||||||
|
name='submit_time',
|
||||||
|
field=models.DateTimeField(blank=True, null=True, verbose_name='提交时间'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ftestwork',
|
||||||
|
name='submit_user',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='提交人'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='ftestwork',
|
||||||
|
name='wm',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wpm.wmaterial', verbose_name='关联车间库存'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ftestwork',
|
||||||
|
name='count',
|
||||||
|
field=models.IntegerField(verbose_name='检验数量'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -2,7 +2,7 @@ from django.db import models
|
||||||
from apps.system.models import CommonAModel, CommonADModel, User
|
from apps.system.models import CommonAModel, CommonADModel, User
|
||||||
from apps.utils.models import CommonBDModel, BaseModel
|
from apps.utils.models import CommonBDModel, BaseModel
|
||||||
from apps.mtm.models import Material, Mgroup, Team
|
from apps.mtm.models import Material, Mgroup, Team
|
||||||
from apps.wpm.models import SfLog
|
from apps.wpm.models import SfLog, WMaterial
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
class NotOkOption(models.TextChoices):
|
class NotOkOption(models.TextChoices):
|
||||||
|
@ -38,6 +38,19 @@ class NotOkOption(models.TextChoices):
|
||||||
md = "md", _("麻点")
|
md = "md", _("麻点")
|
||||||
xh = "xh", _("线痕")
|
xh = "xh", _("线痕")
|
||||||
b = "b", _("扁")
|
b = "b", _("扁")
|
||||||
|
zb = "zb", _("棕边")
|
||||||
|
hqbx = "hqbx", _("黑圈变形")
|
||||||
|
dj = "dj", _("倒角")
|
||||||
|
ps = "ps", _("破损")
|
||||||
|
lq = "lq", _("蓝圈")
|
||||||
|
hqnj = "hqnj", _("黑圈内径")
|
||||||
|
hqnjyd = "hqnjyd", _("黑圈内径圆度")
|
||||||
|
hqwj = "hqwj", _("黑圈外径")
|
||||||
|
hqwjyd = "hqwjyd", _("黑圈外径圆度")
|
||||||
|
wj = "cpwj", _("外径")
|
||||||
|
yd = "cpyd", _("圆度")
|
||||||
|
txd = "cptxd", _("同心度")
|
||||||
|
hd = "hq", _("厚度")
|
||||||
|
|
||||||
wz = "wz", _("未知")
|
wz = "wz", _("未知")
|
||||||
|
|
||||||
|
@ -90,14 +103,18 @@ class FtestWork(CommonBDModel):
|
||||||
"""
|
"""
|
||||||
type = models.CharField('检验类型', max_length=20, choices=FTEST_TYPE_CHOICES, default='prod')
|
type = models.CharField('检验类型', max_length=20, choices=FTEST_TYPE_CHOICES, default='prod')
|
||||||
type2 = models.PositiveSmallIntegerField('检验类型2', choices=((10, '抽检'), (20, '全检')), default=10)
|
type2 = models.PositiveSmallIntegerField('检验类型2', choices=((10, '抽检'), (20, '全检')), default=10)
|
||||||
|
wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
test_date = models.DateField('检验日期')
|
test_date = models.DateField('检验日期')
|
||||||
material = models.ForeignKey(
|
material = models.ForeignKey(
|
||||||
Material, verbose_name='产品', on_delete=models.CASCADE)
|
Material, verbose_name='产品', on_delete=models.CASCADE)
|
||||||
batch = models.CharField('生产批次', max_length=20)
|
batch = models.CharField('生产批次', max_length=20)
|
||||||
count = models.IntegerField('总数量')
|
count = models.IntegerField('检验数量')
|
||||||
count_sampling = models.IntegerField('抽检数量', default=0)
|
count_sampling = models.IntegerField('抽检数量', default=0)
|
||||||
count_ok = models.IntegerField('合格数量', default=0)
|
count_ok = models.IntegerField('合格数量', default=0)
|
||||||
count_notok = models.IntegerField('不合格数量', default=0)
|
count_notok = models.IntegerField('不合格数量', default=0)
|
||||||
|
count_notok_json = models.JSONField('不合格项数量统计', default=dict, null=False, blank=True)
|
||||||
|
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
|
||||||
|
submit_user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='提交人', null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
class Ftest(CommonBDModel):
|
class Ftest(CommonBDModel):
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from apps.qm.models import QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptest
|
from apps.qm.models import QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptest, NotOkOption
|
||||||
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
|
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
|
||||||
from apps.utils.serializers import CustomModelSerializer
|
from apps.utils.serializers import CustomModelSerializer
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.exceptions import ValidationError
|
||||||
from apps.system.models import Dept, Dictionary
|
from apps.system.models import Dept, Dictionary
|
||||||
from apps.wpm.models import SfLog
|
from apps.wpm.models import SfLog, WMaterial
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +62,29 @@ class QuaStatUpdateSerializer(CustomModelSerializer):
|
||||||
class FtestWorkCreateUpdateSerializer(CustomModelSerializer):
|
class FtestWorkCreateUpdateSerializer(CustomModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FtestWork
|
model = FtestWork
|
||||||
fields = ['id', 'test_date', 'material', 'batch', 'count', 'count_sampling', 'count_ok', 'count_notok']
|
fields = ['id', 'wm', 'test_date', 'count', 'count_sampling', 'count_ok', 'count_notok', 'count_notok_json']
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
if 'wm' not in attrs:
|
||||||
|
raise ValidationError('请选择车间库存')
|
||||||
|
wm:WMaterial = attrs['wm']
|
||||||
|
attrs['material'] = wm.material
|
||||||
|
attrs['batch'] = wm.batch
|
||||||
|
count_notok_json = attrs.get('count_notok_json', None)
|
||||||
|
if count_notok_json is None:
|
||||||
|
raise ValidationError('不合格项不能为Null')
|
||||||
|
count_notok = 0
|
||||||
|
for k, v in count_notok_json.items():
|
||||||
|
k_2 = k.replace('count_n_', '')
|
||||||
|
if k not in NotOkOption.values():
|
||||||
|
raise ValidationError(f'不支持的不合格项{k_2}')
|
||||||
|
if isinstance(v, int) and v >= 0:
|
||||||
|
count_notok = count_notok + v
|
||||||
|
else:
|
||||||
|
raise ValidationError(f'不合格项{k_2}必须为非负整数')
|
||||||
|
attrs['count_notok'] = count_notok
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class FtestWorkSerializer(CustomModelSerializer):
|
class FtestWorkSerializer(CustomModelSerializer):
|
||||||
material_name = serializers.StringRelatedField(
|
material_name = serializers.StringRelatedField(
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
from apps.qm.models import FtestWork
|
||||||
|
from apps.wpm.models import WMaterial
|
||||||
|
from apps.system.models import User
|
||||||
|
from rest_framework.exceptions import ParseError
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
|
def ftestwork_submit(ins:FtestWork, user: User):
|
||||||
|
wm:WMaterial = ins.wm
|
||||||
|
# 更新对应的车间库存
|
||||||
|
wm.count = wm.count - ins.count_notok
|
||||||
|
if wm.count >= 0:
|
||||||
|
# 已检测的数量
|
||||||
|
wm.count_xtest = wm.count_xtest + ins.count
|
||||||
|
wm.save()
|
||||||
|
else:
|
||||||
|
raise ParseError("车间库存不足")
|
||||||
|
# 生成合格的
|
||||||
|
count_ok = ins.count_ok
|
||||||
|
if count_ok > 0:
|
||||||
|
wm_ok = WMaterial()
|
||||||
|
wm_ok.material = wm.material
|
||||||
|
wm_ok.count = count_ok
|
||||||
|
wm_ok.batch = wm.batch
|
||||||
|
wm_ok.mgroup = wm.mgroup
|
||||||
|
wm_ok.belong_dept = wm.belong_dept
|
||||||
|
wm_ok.save()
|
||||||
|
# 生成不合格的
|
||||||
|
count_notok_json = ins.count_notok_json
|
||||||
|
for k, v in count_notok_json.items():
|
||||||
|
if v > 0:
|
||||||
|
wm_n = WMaterial()
|
||||||
|
wm_n.material = wm.material
|
||||||
|
wm_n.count = v
|
||||||
|
wm_n.batch = wm.batch
|
||||||
|
wm_n.mgroup = wm.mgroup
|
||||||
|
wm_n.belong_dept = wm.belong_dept
|
||||||
|
wm_n.notok_sign = k.replace('count_n_', '')
|
||||||
|
wm_n.save()
|
||||||
|
ins.submit_user = user
|
||||||
|
ins.submit_time = timezone.now()
|
||||||
|
ins.save()
|
|
@ -1,7 +1,9 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin
|
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.exceptions import ParseError
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.serializers import Serializer
|
||||||
from apps.qm.models import QuaStat, TestItem, Ftest, Ptest, FtestWork
|
from apps.qm.models import QuaStat, TestItem, Ftest, Ptest, FtestWork
|
||||||
from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer, FtestSerializer, PtestSerializer, \
|
from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer, FtestSerializer, PtestSerializer, \
|
||||||
FtestWorkCreateUpdateSerializer, FtestWorkSerializer
|
FtestWorkCreateUpdateSerializer, FtestWorkSerializer
|
||||||
|
@ -15,6 +17,7 @@ from apps.wpm.models import SfLog
|
||||||
from apps.qm.filters import QuaStatFilter, TestItemFilter
|
from apps.qm.filters import QuaStatFilter, TestItemFilter
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from apps.qm.models import NotOkOption
|
from apps.qm.models import NotOkOption
|
||||||
|
from apps.qm.services import ftestwork_submit
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
class NotOkOptionView(APIView):
|
class NotOkOptionView(APIView):
|
||||||
|
@ -124,3 +127,27 @@ class FtestWorkViewSet(CustomModelViewSet):
|
||||||
update_serializer_class = FtestWorkCreateUpdateSerializer
|
update_serializer_class = FtestWorkCreateUpdateSerializer
|
||||||
select_related_fields = ['material']
|
select_related_fields = ['material']
|
||||||
filterset_fields = ['material', 'batch']
|
filterset_fields = ['material', 'batch']
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
ins:FtestWork = self.get_object()
|
||||||
|
if ins.submit_time is not None:
|
||||||
|
raise ParseError('已提交无法修改')
|
||||||
|
return super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
ins:FtestWork = self.get_object()
|
||||||
|
if ins.submit_time is not None:
|
||||||
|
raise ParseError('已提交无法删除')
|
||||||
|
return super().destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@action(methods=['post'], detail=True, perms_map={'post': 'ftestwork.submit'}, serializer_class=Serializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def submit(self, request, *args, **kwargs):
|
||||||
|
"""提交检验工作
|
||||||
|
|
||||||
|
提交检验工作
|
||||||
|
"""
|
||||||
|
ins:FtestWork = self.get_object()
|
||||||
|
if ins.submit_time is not None:
|
||||||
|
ftestwork_submit(ins, request.user)
|
||||||
|
return Response()
|
|
@ -48,7 +48,8 @@ class WMaterialFilter(filters.FilterSet):
|
||||||
"mgroup": ["exact", "in", "isnull"],
|
"mgroup": ["exact", "in", "isnull"],
|
||||||
"mgroup__name": ["exact", "in"],
|
"mgroup__name": ["exact", "in"],
|
||||||
"count": ["gte", "lte", "exact"],
|
"count": ["gte", "lte", "exact"],
|
||||||
"notok_sign": ["exact", "in", "isnull"]
|
"notok_sign": ["exact", "in", "isnull"],
|
||||||
|
"count_xtest": ["gte", "isnull"]
|
||||||
}
|
}
|
||||||
|
|
||||||
class MlogFilter(filters.FilterSet):
|
class MlogFilter(filters.FilterSet):
|
||||||
|
@ -86,12 +87,15 @@ class HandoverFilter(filters.FilterSet):
|
||||||
"recive_dept__name": ["exact"],
|
"recive_dept__name": ["exact"],
|
||||||
"send_date": ["exact"],
|
"send_date": ["exact"],
|
||||||
"material__type": ["exact", "in"],
|
"material__type": ["exact", "in"],
|
||||||
|
"material__process": ["exact", "in"],
|
||||||
|
"material__process__name": ["exact", "contains", "in"],
|
||||||
"submit_time": ["isnull"],
|
"submit_time": ["isnull"],
|
||||||
"mlog": ["isnull"],
|
"mlog": ["isnull"],
|
||||||
"send_mgroup": ["exact"],
|
"send_mgroup": ["exact"],
|
||||||
"send_mgroup__name": ["exact"],
|
"send_mgroup__name": ["exact"],
|
||||||
"recive_mgroup": ["exact"],
|
"recive_mgroup": ["exact"],
|
||||||
"recive_mgroup__name": ["exact"],
|
"recive_mgroup__name": ["exact"],
|
||||||
|
"type": ["exact", "in"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Generated by Django 3.2.12 on 2024-08-12 02:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0059_auto_20240809_1508'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlog',
|
||||||
|
name='count_n_hd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='厚度'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlog',
|
||||||
|
name='count_n_ps',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='破损'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlog',
|
||||||
|
name='count_n_txd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='同心度'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlog',
|
||||||
|
name='count_n_wj',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='外经'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlog',
|
||||||
|
name='count_n_yd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='圆度'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlogb',
|
||||||
|
name='count_n_hd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='厚度'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlogb',
|
||||||
|
name='count_n_ps',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='破损'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlogb',
|
||||||
|
name='count_n_txd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='同心度'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlogb',
|
||||||
|
name='count_n_wj',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='外经'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlogb',
|
||||||
|
name='count_n_yd',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='圆度'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -179,7 +179,13 @@ class Mlog(CommonADModel):
|
||||||
count_n_wm = models.PositiveIntegerField('雾面', default=0)
|
count_n_wm = models.PositiveIntegerField('雾面', default=0)
|
||||||
count_n_md = models.PositiveIntegerField('麻点', default=0)
|
count_n_md = models.PositiveIntegerField('麻点', default=0)
|
||||||
count_n_xh = models.PositiveIntegerField('线痕', default=0)
|
count_n_xh = models.PositiveIntegerField('线痕', default=0)
|
||||||
|
count_n_ps = models.PositiveIntegerField('破损', default=0)
|
||||||
|
count_n_wj = models.PositiveIntegerField('外经', default=0)
|
||||||
|
count_n_yd = models.PositiveIntegerField('圆度', default=0)
|
||||||
|
count_n_txd = models.PositiveIntegerField('同心度', default=0)
|
||||||
|
count_n_hd = models.PositiveIntegerField('厚度', default=0)
|
||||||
|
|
||||||
|
|
||||||
count_n_qt = models.PositiveIntegerField('其他', default=0)
|
count_n_qt = models.PositiveIntegerField('其他', default=0)
|
||||||
|
|
||||||
handle_date = models.DateField('操作日期', null=True, blank=True)
|
handle_date = models.DateField('操作日期', null=True, blank=True)
|
||||||
|
@ -240,6 +246,11 @@ class Mlogb(BaseModel):
|
||||||
count_n_wm = models.PositiveIntegerField('雾面', default=0)
|
count_n_wm = models.PositiveIntegerField('雾面', default=0)
|
||||||
count_n_md = models.PositiveIntegerField('麻点', default=0)
|
count_n_md = models.PositiveIntegerField('麻点', default=0)
|
||||||
count_n_xh = models.PositiveIntegerField('线痕', default=0)
|
count_n_xh = models.PositiveIntegerField('线痕', default=0)
|
||||||
|
count_n_ps = models.PositiveIntegerField('破损', default=0)
|
||||||
|
count_n_wj = models.PositiveIntegerField('外经', default=0)
|
||||||
|
count_n_yd = models.PositiveIntegerField('圆度', default=0)
|
||||||
|
count_n_txd = models.PositiveIntegerField('同心度', default=0)
|
||||||
|
count_n_hd = models.PositiveIntegerField('厚度', default=0)
|
||||||
|
|
||||||
class Handover(CommonADModel):
|
class Handover(CommonADModel):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -472,6 +472,8 @@ class HandoverSerializer(CustomModelSerializer):
|
||||||
raise ValidationError('送料车间和送料工段必须有一个')
|
raise ValidationError('送料车间和送料工段必须有一个')
|
||||||
if wm.notok_sign is not None and attrs['type'] in [Handover.H_NORMAL, Handover.H_TEST]:
|
if wm.notok_sign is not None and attrs['type'] in [Handover.H_NORMAL, Handover.H_TEST]:
|
||||||
raise ValidationError('物料不合格,不能进行正常/检验交接')
|
raise ValidationError('物料不合格,不能进行正常/检验交接')
|
||||||
|
if wm.count_xtest is not None:
|
||||||
|
raise ValidationError('物料检验中,不能进行交接')
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
Loading…
Reference in New Issue