Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shijing 2021-11-23 10:01:16 +08:00
commit 8e37c13f06
12 changed files with 215 additions and 22 deletions

View File

@ -0,0 +1,27 @@
from django_filters import rest_framework as filters
from apps.mtm.models import Material, Step
from apps.pm.models import SubProductionProgress
from apps.wpm.models import Operation, WProduct
from apps.wpm.services import WpmServies
class SubproductionProgressFilterSet(filters.FilterSet):
operation = filters.NumberFilter(method='filter_operation')
class Meta:
model = SubProductionProgress
fields = ['material', 'subproduction_plan', 'operation', 'type']
def filter_operation(self, queryset, name, value):
operation = Operation.objects.get(pk=value)
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
step = operation.step
if wproducts.exists():
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
else:
subplans = WpmServies.get_subplans_queyset_from_step(step)
queryset = queryset.filter(subproduction_plan__in=subplans)
if step.type == Step.STEP_TYPE_NOM:
queryset = queryset.exclude(material__type=Material.MA_TYPE_HALFGOOD)
return queryset

View File

@ -0,0 +1,23 @@
# Generated by Django 3.2.9 on 2021-11-22 07:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pm', '0014_subproductionplan_number'),
]
operations = [
migrations.AddField(
model_name='subproductionplan',
name='main_count_ok',
field=models.IntegerField(default=0, verbose_name='合格数'),
),
migrations.AddField(
model_name='subproductionprogress',
name='count_ok',
field=models.IntegerField(default=0, verbose_name='合格数量'),
),
]

View File

@ -56,6 +56,7 @@ class SubProductionPlan(CommonAModel):
main_product = models.ForeignKey(Material, verbose_name='主要产品', on_delete=models.CASCADE, null=True, blank=True)
main_count = models.IntegerField('应产出数', default=0)
main_count_real = models.IntegerField('实际产出数', default=0)
main_count_ok = models.IntegerField('合格数', default=0)
steps = models.JSONField('工艺步骤', default=list)
@ -80,3 +81,4 @@ class SubProductionProgress(BaseModel):
count = models.IntegerField('应出入数')
count_pick = models.IntegerField('实际领用数', default=0)
count_real = models.IntegerField('实际消耗/产出数', default=0)
count_ok = models.IntegerField('合格数量', default=0)

View File

@ -1,4 +1,4 @@
from apps.pm.views import ProductionPlanViewSet, ResourceViewSet, SubProductionPlanViewSet
from apps.pm.views import ProductionPlanViewSet, ResourceViewSet, SubProductionPlanViewSet, SubProductionProgressViewSet
from django.db.models import base
from rest_framework import urlpatterns
from django.urls import path, include
@ -7,6 +7,7 @@ from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('production_plan', ProductionPlanViewSet, basename='production_plan')
router.register('subproduction_plan', SubProductionPlanViewSet, basename='subproduction_plan')
router.register('subproduction_progress', SubProductionProgressViewSet, basename='subproduction_progress')
router.register('resource', ResourceViewSet, basename='resource')
urlpatterns = [
path('', include(router.urls)),

View File

@ -1,4 +1,5 @@
from datetime import timezone
from typing import List
from django.db import transaction
from rest_framework import serializers
from rest_framework.views import APIView
@ -7,6 +8,7 @@ from apps.em.serializers import EquipmentSerializer
from apps.inm.models import MaterialBatch
from apps.inm.serializers import MaterialBatchSerializer
from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep
from apps.pm.filters import SubproductionProgressFilterSet
from apps.system.mixins import CreateUpdateModelAMixin
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
@ -67,7 +69,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
return Response()
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PlanDestorySerializer)
def destory(self, request, pk=None):
def deletes(self, request, pk=None):
"""
批量物理删除
"""
@ -178,6 +180,17 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
have = MaterialBatchSerializer(instance=objs, many=True).data
return Response({'need':need, 'have':have})
class SubProductionProgressViewSet(ListModelMixin, GenericViewSet):
"""
生产进度
"""
perms_map = {'*': '*'}
queryset = SubProductionProgress.objects.select_related('material', 'subproduction_plan')
search_fields = []
serializer_class = SubProductionProgressSerializer
filterset_class = SubproductionProgressFilterSet
ordering_fields = ['id']
ordering = ['id']
class ResourceViewSet(GenericViewSet):

View File

@ -1,4 +1,7 @@
from django_filters import rest_framework as filters
from apps.mtm.models import Material, Step
from apps.wpm.services import WpmServies
from .models import Operation, WMaterial, WProduct
class WMaterialFilterSet(filters.FilterSet):
@ -6,12 +9,15 @@ class WMaterialFilterSet(filters.FilterSet):
operation = filters.NumberFilter(method='filter_operation')
class Meta:
model = WMaterial
fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop']
fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop', 'operation']
def filter_operation(self, queryset, name, value):
operation = Operation.objects.get(pk=value)
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
step = operation.step
if wproducts.exists():
pass
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
else:
pass
subplans = WpmServies.get_subplans_queyset_from_step(step)
queryset = queryset.filter(subproduction_plan__in=subplans).exclude(material__type=Material.MA_TYPE_HALFGOOD)
return queryset

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.9 on 2021-11-22 07:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wpm', '0019_auto_20211122_1110'),
]
operations = [
migrations.AlterField(
model_name='operationwproduct',
name='wproduct',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ow_wproduct', to='wpm.wproduct', verbose_name='关联半成品'),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 3.2.9 on 2021-11-23 01:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('wpm', '0020_alter_operationwproduct_wproduct'),
]
operations = [
migrations.RemoveField(
model_name='operationwproduct',
name='production_plan',
),
migrations.RemoveField(
model_name='wproduct',
name='production_plan',
),
]

View File

@ -43,7 +43,6 @@ class WProduct(CommonAModel):
parent = models.JSONField('', default=list, blank=True)
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='wproduct_subplan')
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
operation = models.ForeignKey('wpm.operation', verbose_name='关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation')
@ -66,7 +65,6 @@ class OperationWproduct(BaseModel):
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
production_plan = models.ForeignKey(ProductionPlan, verbose_name='当前主生产计划', on_delete=models.CASCADE)
class OperationMaterial(BaseModel):

View File

@ -326,12 +326,13 @@ class OperationMaterialCreate1Serailizer(serializers.ModelSerializer):
class Meta:
model = OperationMaterial
fields = ['operation', 'wmaterial', 'count']
def create(self, validated_data):
wmaterial = validated_data['wmaterial']
validated_data['material'] = wmaterial.material
validated_data['subproduction_plan'] = wmaterial.subproduction_plan
validated_data['batch'] = wmaterial.batch
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_IN
return super().create(validated_data)
class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
@ -344,6 +345,7 @@ class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
subproduction_progress = validated_data['subproduction_progress']
validated_data['material'] = subproduction_progress.material
validated_data['subproduction_plan'] = subproduction_progress.subproduction_plan
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_OUT
return super().create(validated_data)
class OperationMaterialCreate3Serializer(serializers.ModelSerializer):
@ -351,5 +353,9 @@ class OperationMaterialCreate3Serializer(serializers.ModelSerializer):
class Meta:
model = OperationMaterial
fields = ['operation', 'material']
def create(self, validated_data):
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_TOOL
return super().create(validated_data)

View File

@ -69,7 +69,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
wps.update(step=first_step, is_executed=False,
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
subproduction_plan=sp, production_plan=sp.production_plan, update_by=request.user, update_time=timezone.now())
subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
return Response()
@ -84,7 +84,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
vdata = serializer.data
subplan = self.get_object()
material = subplan.main_product
batch = subplan.production_plan.number
batch = subplan.number
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
wproducts = WProduct.objects.filter(subproduction_plan=subplan,
act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False)
@ -160,7 +160,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
perms_map={'*':'*'}
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False).exclude(operation=None)
serializer_class = WProductListSerializer
filterset_fields = ['step', 'subproduction_plan', 'material', 'production_plan', 'step__process', 'act_state']
filterset_fields = ['step', 'subproduction_plan', 'material', 'step__process', 'act_state']
search_fields = ['number']
ordering_fields = ['id']
ordering = ['id']
@ -207,7 +207,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
# 更新子计划主产品数
instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题
instance.count_ok = instance.count_ok + 1 # 这个地方可能会有问题
instance.save()
else:# 如果不合格
pass
@ -228,7 +228,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
raise exceptions.APIException('半成品不可入库')
material = wproduct.material
batch = wproduct.production_plan.number
batch = wproduct.subproduction_plan.number
# 创建入库记录
remark = vdata.get('remark', '')
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
@ -314,7 +314,6 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
owp['number'] = wpd.number
owp['material'] = wpd.material
owp['subproduction_plan'] = wpd.subproduction_plan
owp['production_plan'] = wpd.production_plan
owps.append(OperationWproduct(**owp))
OperationWproduct.objects.bulk_create(owps)
else:
@ -343,9 +342,90 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
opm.save()
return Response()
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
@transaction.atomic
def submit(self, request, pk=None):
"""
提交车间操作重要
"""
op = self.get_object()
step = op.step
# 检查自定义表单填写
if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
raise exceptions.APIException('存在自定义表单未填写')
# 更新物料消耗进度
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN):
# 更新车间物料
i_wmat = i.wmaterial
i_wmat.count = i_wmat.count- i['count']
i_wmat.save()
# 更新子计划物料消耗情况
sp = i_wmat.subproduction_plan
sp.count_real = sp.count_real + i['count']
sp.save()
# 更新产出
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
if not i.subproduction_progress.is_main:
# 更新车间物料产出情况
ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan,
material=i.material)
ins.count = ins.count + i['count']
ins.save()
# 更新子计划物料产出情况
sp = i.subproduction_progress
sp.count_real = sp.count_real + i['count']
sp.save()
# 更新动态产品表
if step.type == Step.STEP_TYPE_NOM:
for i in OperationWproduct.objects.filter(operation=op):
wp = i.wproduct
wsp = i.subproduction_plan
# 获取下一步子工序
newstep, hasNext = WpmServies.get_next_step(wsp, step)
wp.step = newstep
wp.pre_step = step
if hasNext:
wp.is_executed= False
else:
wp.is_executed = True
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
wp.material = wsp.main_product
# 更新子计划进度
instance = SubProductionProgress.objects.get(subproduction_plan=wsp,
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题,不够严谨
instance.save()
wp.operation = None
wp.save()
elif step.type == Step.STEP_TYPE_DIV:
# 更新物料产出情况
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
if i.subproduction_progress.is_main:
newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
wpr = dict(material=i.material, step=newstep,
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
subproduction_plan=i.subproduction_plan)
for x in range(i.count):
WProduct.objects.create(**wpr)
elif step.type == Step.STEP_TYPE_COMB:
# 隐藏原半成品
ows = OperationWproduct.objects.filter(operation=op)
ows.update(is_hidden=True)
if i.subproduction_progress.is_main:
newstep, hasNext = WpmServies.get_next_step(i.subproduction_plan, step)
wproduct = WProduct()
wproduct.material = i.material
wproduct.step = newstep
wproduct.subproduction_plan = i.subproduction_plan
wproduct.parent = ows.values_list('wproduct', flat=True)
if hasNext:
wproduct.act_state = WProduct.WPR_ACT_STATE_DOING
wproduct.is_executed = False
else:
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
wproduct.is_executed = True
wproduct.save()
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
@ -581,7 +661,6 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
owp['number'] = wp.number
owp['material'] = wp.material
owp['subproduction_plan'] = wp.subproduction_plan
owp['production_plan'] = wp.production_plan
owps.append(OperationWproduct(**owp))
OperationWproduct.objects.bulk_create(owps)
@ -611,8 +690,7 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
wpr = dict(material=ma, step=newstep,
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
subproduction_plan=i['subproduction_plan'],
production_plan=i['subproduction_plan'].production_plan)
subproduction_plan=i['subproduction_plan'])
for x in range(i['count_output']):
WProduct.objects.create(**wpr)
else:
@ -641,7 +719,6 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
wproduct.material = vdata['subproduction_plan'].main_product
wproduct.step = newstep
wproduct.subproduction_plan=vdata['subproduction_plan']
wproduct.production_plan=vdata['subproduction_plan'].production_plan
wproduct.parent = data['wproducts']
if hasNext:
wproduct.act_state=WProduct.WPR_ACT_STATE_DOING

View File

@ -62,7 +62,7 @@ class UpdateDevelop(APIView):
import os
# 更新后端
os.chdir('/home/hberp')
ret = os.popen('git pull https://caoqianming%40ctc.ac.cn:9093qqww@e.coding.net/ctcdevteam/hberp/hberp.git origin develop')
ret = os.popen('git pull https://caoqianming%40ctc.ac.cn:9093qqww@e.coding.net/ctcdevteam/hberp/hberp.git develop')
# 打包前端
# os.chdir('/home/hberp/hb_client')
# os.system('npm run build:prod')