From b4cc887f79ce40d8177808616dcb63c13cc8264c Mon Sep 17 00:00:00 2001 From: caoqianming Date: Sun, 8 Oct 2023 16:38:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20mtask=E5=A2=9E=E5=8A=A0=E5=B7=B2?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E7=8A=B6=E6=80=81=E5=B9=B6=E5=9C=A8=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=90=8E=E4=B8=8D=E5=85=81=E8=AE=B8=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=8F=98=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/pm/migrations/0005_alter_mtask_state.py | 18 ++++++++++ apps/pm/models.py | 2 +- apps/pm/services.py | 15 ++++++++ apps/pm/views.py | 13 +++++++ apps/wpm/serializers.py | 12 +++++++ apps/wpm/services.py | 36 ++++++++++++++++---- apps/wpm/views.py | 12 +++---- 7 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 apps/pm/migrations/0005_alter_mtask_state.py diff --git a/apps/pm/migrations/0005_alter_mtask_state.py b/apps/pm/migrations/0005_alter_mtask_state.py new file mode 100644 index 00000000..d59c1fb9 --- /dev/null +++ b/apps/pm/migrations/0005_alter_mtask_state.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2023-10-08 08:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pm', '0004_auto_20231008_1126'), + ] + + operations = [ + migrations.AlterField( + model_name='mtask', + name='state', + field=models.PositiveIntegerField(choices=[(10, '创建中'), (20, '已下达'), (40, '已提交')], default=10, help_text="((10, '创建中'), (20, '已下达'), (40, '已提交'))", verbose_name='状态'), + ), + ] diff --git a/apps/pm/models.py b/apps/pm/models.py index 8c54667b..df8ea632 100644 --- a/apps/pm/models.py +++ b/apps/pm/models.py @@ -17,7 +17,7 @@ class Mtask(CommonADModel): (MTASK_CREATED, '创建中'), (MTASK_ASSGINED, '已下达'), # (MTASK_WORKING, '生产中'), - # (MTASK_DONE, '已结束') + (MTASK_DONE, '已提交') ) state = models.PositiveIntegerField( '状态', choices=MTASK_STATES, default=MTASK_CREATED, help_text=str(MTASK_STATES)) diff --git a/apps/pm/services.py b/apps/pm/services.py index 4de7fa73..7379a895 100644 --- a/apps/pm/services.py +++ b/apps/pm/services.py @@ -114,3 +114,18 @@ class PmService: from apps.sam.tasks import change_order_state_when_schedue change_order_state_when_schedue.delay(orderitemId_list) + + @classmethod + def mtasks_submit(cls, mtasks: QuerySet[Mtask]): + """ + 锁定生产任务 + """ + from apps.wpm.models import Mlog + from apps.wpm.services import mlog_confirm, update_mtask_count + for mtask in mtasks: + mlogs = Mlog.objects.filter(mtask=mtask) + for mlog in mlogs: + mlog_confirm(mlog) + update_mtask_count(mtask) + mtask.state = Mtask.MTASK_DONE + mtask.save() diff --git a/apps/pm/views.py b/apps/pm/views.py index 73903cf8..913055d1 100644 --- a/apps/pm/views.py +++ b/apps/pm/views.py @@ -59,3 +59,16 @@ class MtaskViewSet(CustomModelViewSet): mtasks = mtasks | Mtask.objects.filter(parent__in=mtasks) mtasks.update(state=Mtask.MTASK_ASSGINED) return Response() + + @action(methods=['post'], detail=False, perms_map={'post': 'mtask.submit'}, serializer_class=PkSerializer) + @transaction.atomic + def submit(self, request): + """提交任务 + + 提交任务后不可更新日志 + """ + ids = request.data.get('ids', []) + mtasks = Mtask.objects.filter( + id__in=ids, parent=None, state=Mtask.MTASK_ASSGINED) + PmService.mtasks_submit(mtasks) + return Response() diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 4230aab7..1b174630 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -1,9 +1,11 @@ from apps.utils.constants import EXCLUDE_FIELDS from apps.utils.serializers import CustomModelSerializer from rest_framework import serializers +from rest_framework.exceptions import ValidationError from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog from apps.system.models import Dictionary +from apps.pm.models import Mtask from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change from apps.mtm.serializers import MaterialSerializer @@ -85,3 +87,13 @@ class MlogSerializer(CustomModelSerializer): model = Mlog fields = '__all__' read_only_fields = EXCLUDE_FIELDS + + def update(self, instance, validated_data): + validated_data.pop('mtask', None) + return super().update(instance, validated_data) + + def validate(self, attrs): + mtask = attrs['mtask'] + if mtask.state != Mtask.MTASK_ASSGINED: + raise ValidationError('该任务状态不可提交日志!') + return attrs diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 1eabbb82..01c925f8 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -8,6 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from rest_framework.exceptions import ParseError from apps.inm.models import MIO, MIOItem +from apps.pm.models import Mtask from apps.mtm.models import Mgroup, Shift, Material from .models import SfLog, SfLogExp, WMaterial, Mlog @@ -103,28 +104,49 @@ def do_in(mio: MIO): raise ParseError('车间物料不足') -def mlog_create(mlog: Mlog): +def mlog_confirm(mlog: Mlog): """ 生产日志创建后需要执行的操作 """ mtask = mlog.mtask + belong_dept = mtask.belong_dept material = mtask.material material_before = mtask.material_before if material_before and material_before.is_hidden is False: # 需要进行车间库存管理 # 需要判断领用数是否合理 material_has_qs = WMaterial.objects.filter( - batch=mlog.batch, material=material_before) + batch=mlog.batch, material=material_before, belong_dept=belong_dept) count_x = material_has_qs.count() if count_x == 1: material_has = material_has_qs.first() elif count_x == 0: - raise ParseError(f'{material_before.name}-批次库存不存在!') + raise ParseError(f'{material_before.name}-{mlog.batch}-批次库存不存在!') else: - raise ParseError(f'{material_before.name}-存在多个相同批次!') + raise ParseError(f'{material_before.name}-{mlog.batch}-存在多个相同批次!') if mlog.count_use > material_has.count: - raise ParseError(f'{material_before.name}-该批次车间库存不足!') + raise ParseError(f'{material_before.name}-{mlog.batch}-该批次车间库存不足!') else: material_has.count = material_has.count - mlog.count_use material_has.save() - # if material.is_hidden is False: # 需要入库 - # wmaterial = WMaterial.objects.get_or_create(batch=mlog.batch, material=material, defaults={}) + if material.is_hidden is False: # 需要入库 + wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material, belong_dept=belong_dept, defaults={ + 'batch': mlog.batch, 'material': material, 'belong_dept': belong_dept + }) + wmaterial.count = wmaterial.count + mlog.count_ok + wmaterial.save() + + +def update_mtask_count(mtask: Mtask): + res = Mlog.objects.filter(mtask=mtask).aaggregate(sum_count_real=Sum( + 'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok')) + mtask.count_real = res['sum_count_real'] if res['sum_count_real'] else 0 + mtask.count_ok = res['sum_count_ok'] if res['sum_count_ok'] else 0 + mtask.count_notok = res['sum_count_notok'] if res['sum_count_notok'] else 0 + mtask.save() + if mtask.parent: + res2 = Mtask.objects.filter(parent=mtask.parent).aaggregate(sum_count_real=Sum( + 'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok')) + mtask.count_real = res2['sum_count_real'] if res2['sum_count_real'] else 0 + mtask.count_ok = res2['sum_count_ok'] if res2['sum_count_ok'] else 0 + mtask.count_notok = res2['sum_count_notok'] if res2['sum_count_notok'] else 0 + mtask.save() diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 68d34279..ca66f173 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -6,13 +6,13 @@ from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModel from rest_framework.response import Response from apps.mtm.models import Material +from apps.pm.models import Mtask from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.mixins import BulkCreateModelMixin from .filters import SfLogExpFilter, SfLogFilter from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog from .serializers import SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogSerializer -from .services import mlog_create # Create your views here. @@ -97,7 +97,7 @@ class WMaterialViewSet(ListModelMixin, CustomGenericViewSet): filterset_fields = ['material', 'belong_dept'] -class MlogViewSet(ListModelMixin, BulkCreateModelMixin, DestroyModelMixin, CustomGenericViewSet): +class MlogViewSet(CustomModelViewSet): """ list: 生产日志 @@ -109,7 +109,7 @@ class MlogViewSet(ListModelMixin, BulkCreateModelMixin, DestroyModelMixin, Custo select_related_fields = ['create_by', 'update_by', 'mtask'] filterset_fields = ['mtask'] - def perform_create(self, serializer): - with transaction.atomic(): - ins = serializer.save() - mlog_create(ins) + def perform_destroy(self, instance): + if instance.mtask.state == Mtask.MTASK_DONE: + raise ParseError('任务已提交日志不可变动') + return super().perform_destroy(instance)