diff --git a/hb_server/apps/pm/migrations/0003_auto_20211014_1503.py b/hb_server/apps/pm/migrations/0003_auto_20211014_1503.py new file mode 100644 index 0000000..c4b3798 --- /dev/null +++ b/hb_server/apps/pm/migrations/0003_auto_20211014_1503.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.6 on 2021-10-14 07:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0003_auto_20210812_0909'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('mtm', '0022_auto_20211014_0944'), + ('pm', '0002_alter_productionplan_count'), + ] + + operations = [ + migrations.AddField( + model_name='productionplan', + name='is_planed', + field=models.BooleanField(default=False, verbose_name='是否已排产'), + ), + migrations.CreateModel( + name='SubProductionPlan', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('start_date', models.DateField(verbose_name='计划开工日期')), + ('end_date', models.DateField(verbose_name='计划完工日期')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subproductionplan_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('process', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.process', verbose_name='关联大工序')), + ('production_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.productionplan', verbose_name='关联主生产计划')), + ('subproduction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.subproduction', verbose_name='关联生产分解')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subproductionplan_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ('workshop', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.organization', verbose_name='生产车间')), + ], + options={ + 'verbose_name': '子生产计划', + 'verbose_name_plural': '子生产计划', + }, + ), + ] diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index 062e0f1..0693ed8 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -1,4 +1,4 @@ -from apps.system.models import CommonAModel +from apps.system.models import CommonAModel, Organization from django.db import models from django.contrib.auth.models import AbstractUser from django.db.models.base import Model @@ -6,10 +6,9 @@ import django.utils.timezone as timezone from django.db.models.query import QuerySet from utils.model import SoftModel, BaseModel -from apps.mtm.models import Material +from apps.mtm.models import Material, Process, SubProduction from apps.sam.models import Order - class ProductionPlan(CommonAModel): """ 生产计划 @@ -20,7 +19,7 @@ class ProductionPlan(CommonAModel): count = models.IntegerField('生产数量', default=1) start_date = models.DateField('计划开工日期') end_date = models.DateField('计划完工日期') - + is_planed = models.BooleanField('是否已排产', default=False) class Meta: verbose_name = '生产计划' verbose_name_plural = verbose_name @@ -28,3 +27,24 @@ class ProductionPlan(CommonAModel): def __str__(self): return self.number +class SubProductionPlan(CommonAModel): + """ + 子生产计划 + """ + production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE) + subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE) + start_date = models.DateField('计划开工日期') + end_date = models.DateField('计划完工日期') + workshop = models.ForeignKey(Organization, verbose_name='生产车间', on_delete=models.CASCADE) + process = models.ForeignKey(Process, verbose_name='关联大工序', on_delete=models.CASCADE) + + class Meta: + verbose_name = '子生产计划' + verbose_name_plural = verbose_name + +# class ProductionProgress(BaseModel): +# """ +# 子计划生产进度 +# """ +# subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE) +# material = models. \ No newline at end of file diff --git a/hb_server/apps/pm/serializers.py b/hb_server/apps/pm/serializers.py index 7542527..3606838 100644 --- a/hb_server/apps/pm/serializers.py +++ b/hb_server/apps/pm/serializers.py @@ -1,7 +1,8 @@ -from apps.pm.models import ProductionPlan +from apps.pm.models import ProductionPlan, SubProductionPlan from rest_framework import serializers from apps.sam.serializers import OrderSerializer -from apps.mtm.serializers import MaterialSimpleSerializer +from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer +from apps.system.serializers import OrganizationSimpleSerializer class ProductionPlanCreateFromOrderSerializer(serializers.ModelSerializer): @@ -22,3 +23,15 @@ class ResourceCalSerializer(serializers.Serializer): class ResourceCalListSerializer(serializers.ListSerializer): child = ResourceCalSerializer() + +class SubProductionPlanListSerializer(serializers.ModelSerializer): + workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True) + process_ = ProcessSimpleSerializer(source='process_', read_only=True) + class Meta: + model=SubProductionPlan + fields = '__all__' + +class SubProductionPlanUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = SubProductionPlan + fields = ['start_date', 'end_date'] diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index aa06248..2d5b0d2 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -3,9 +3,9 @@ from apps.em.models import Equipment from apps.em.serializers import EquipmentSerializer from apps.mtm.models import InputMaterial, Step, SubProduction, UsedStep from apps.system.mixins import CreateUpdateModelAMixin -from apps.pm.serializers import ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer -from rest_framework.mixins import CreateModelMixin, ListModelMixin -from apps.pm.models import ProductionPlan +from apps.pm.serializers import ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer +from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin +from apps.pm.models import ProductionPlan, SubProductionPlan from rest_framework.viewsets import GenericViewSet, ModelViewSet from django.shortcuts import render from apps.sam.models import Order @@ -55,11 +55,46 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel instance = serializer.save(create_by=request.user, product=order.product) updateOrderPlanedCount(instance.order) return Response() + + @action(methods=['post'], detail=True, perms_map={'post':'*'}) + def gen_subplan(self, request, pk=None): + """ + 生成子计划 + """ + production_plan=self.get_object() + if production_plan.is_planed: + raise APIException('已生成子计划') + subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number') + for i in subps: + SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i, + start_date=production_plan.start_date, end_date=production_plan.end_date, + workshop=i.process.workshop, process=i.process, create_by=request.user) + production_plan.is_planed=True + production_plan.save() + return Response() + +class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateModelMixin, GenericViewSet): + """ + 子生产计划-列表/修改 + """ + perms_map = {'*': '*'} + queryset = SubProductionPlan.objects.select_related('process', 'workshop') + search_fields = [] + filterset_fields = ['production_plan'] + ordering_fields = ['id'] + ordering = ['-id'] + + def get_serializer_class(self): + if self.action == 'list': + return SubProductionPlanListSerializer + elif self.action == 'update': + return SubProductionPlanUpdateSerializer + class ResourceViewSet(GenericViewSet): perms_map = {'*': '*'} - @action(methods=['post'], detail=False, perms_map={'get':'*'}, serializer_class=ResourceCalListSerializer) + @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=ResourceCalListSerializer) def cal(self, request, pk=None): """ 物料消耗计算 @@ -85,7 +120,7 @@ class ResourceViewSet(GenericViewSet): 'count':m['count']*i['count'], 'inv_count':m['material__count']}) return Response(res) - @action(methods=['post'], detail=False, perms_map={'get':'*'}, serializer_class=ResourceCalListSerializer) + @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=ResourceCalListSerializer) def cal_equip(self, request, pk=None): """ 设备状态查看