-
+
{{productionplan.number}}
- {{productionplan.product_.name}}
- {{productionplan.product_.specification}}
- 生产状态没有
+ {{productionplan.product_.name}}
+ {{productionplan.product_.specification}}
+ {{state_[productionplan.state]}}
不合格数没有
@@ -17,7 +17,7 @@
fit
stripe
style="width: 100%"
- height="300"
+ height="500"
>
@@ -58,6 +58,52 @@
+
+
+
+
+
+
+ {{ scope.row.process_name }}
+
+
+ {{ scope.row.count_real }}
+
+
+
+ {{ scope.row.count_ok }}
+
+
+
+ {{ scope.row.count_notok }}
+
+
+
+
+
+
+ 查看
+
+
+
+
+
@@ -69,7 +115,7 @@
diff --git a/hb_client/src/views/qm/wproduct.vue b/hb_client/src/views/qm/wproduct.vue
new file mode 100644
index 0000000..2bca265
--- /dev/null
+++ b/hb_client/src/views/qm/wproduct.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+ {{productionplans.number}}
+ {{productionplans.product_.name}}
+ {{productionplans.product_.specification}}
+ {{state_[productionplans.state]}}
+ 不合格数没有
+
+
+
+
+
+
+
+ {{ scope.row.number }}
+
+
+
+ {{
+ scope.row.step_.name
+ }}
+
+
+ {{
+ actstate_[scope.row.act_state]
+ }}
+
+
+
+
+ 查看
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hb_client/src/views/wpm/need.vue b/hb_client/src/views/wpm/need.vue
index 885df54..4f1a021 100644
--- a/hb_client/src/views/wpm/need.vue
+++ b/hb_client/src/views/wpm/need.vue
@@ -26,7 +26,8 @@
{{ actstate_[scope.row.act_state] }}
-
+
+
{{ scope.row.step_.name }}
@@ -237,15 +238,19 @@
{{ scope.row.step_.name }}
-
+
+
+ {{ ng_sign_[scope.row.ng_sign] }}
+
+
-
+
-
+
+
+ {{ ng_sign_[scope.row.ng_sign] }}
+
+
{{
scope.row.update_time
@@ -455,7 +459,7 @@
{{ scope.row.material_.name }}
-
+
{{
scope.row.warehouse_.name
@@ -765,6 +769,17 @@ export default {
26: "待夹层检验",
70: "报废",
},
+ ng_sign_: {
+ 10: "返工",
+ 20: "返修",
+ 30: "报废",
+ 40: "让步接受",
+ 50: "偏离许可",
+ 60: "降级使用",
+ 70: "退回供方",
+ 80: "召回",
+
+ },
state_: {
0: "制定中",
1: "已下达",
diff --git a/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py b/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py
new file mode 100644
index 0000000..268568c
--- /dev/null
+++ b/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py
@@ -0,0 +1,57 @@
+# Generated by Django 3.2.9 on 2021-12-31 03:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('mtm', '0042_alter_recordformfield_field_type'),
+ ('wpm', '0042_wprouctticket_resp_process'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_cut',
+ field=models.PositiveIntegerField(default=0, verbose_name='切裁片数'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_hua',
+ field=models.PositiveIntegerField(default=0, verbose_name='划伤甩片'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_ok',
+ field=models.PositiveIntegerField(default=0, verbose_name='成品数量'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_other',
+ field=models.PositiveIntegerField(default=0, verbose_name='其他甩片'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_podian',
+ field=models.PositiveIntegerField(default=0, verbose_name='破点甩片'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_qipao',
+ field=models.PositiveIntegerField(default=0, verbose_name='气泡甩片'),
+ ),
+ migrations.AddField(
+ model_name='operationmaterial',
+ name='count_real',
+ field=models.PositiveIntegerField(default=0, verbose_name='生产片数'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='operationmaterial',
+ unique_together={('operation', 'material', 'batch')},
+ ),
+ migrations.AlterUniqueTogether(
+ name='operationwproduct',
+ unique_together={('operation', 'wproduct')},
+ ),
+ ]
diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py
index dd55ceb..1bac267 100644
--- a/hb_server/apps/wpm/models.py
+++ b/hb_server/apps/wpm/models.py
@@ -197,6 +197,10 @@ class OperationWproduct(BaseModel):
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='ow_subplan')
+ class Meta:
+ unique_together = (
+ ('operation','wproduct')
+ )
class OperationMaterial(BaseModel):
"""
@@ -214,6 +218,19 @@ class OperationMaterial(BaseModel):
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True)
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
+ #以下为冷加工下料清单所用字段
+ count_cut = models.PositiveIntegerField('切裁片数', default=0)
+ count_real = models.PositiveIntegerField('生产片数', default=0)
+ count_ok = models.PositiveIntegerField('成品数量', default=0)
+ count_qipao = models.PositiveIntegerField('气泡甩片', default=0)
+ count_podian = models.PositiveIntegerField('破点甩片', default=0)
+ count_hua = models.PositiveIntegerField('划伤甩片', default=0)
+ count_other = models.PositiveIntegerField('其他甩片', default=0)
+ class Meta:
+ unique_together = (
+ ('operation','material', 'batch')
+ )
+
class OperationRecord(BaseModel):
"""
记录表格
diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py
index 18503a4..dcef7f8 100644
--- a/hb_server/apps/wpm/serializers.py
+++ b/hb_server/apps/wpm/serializers.py
@@ -12,6 +12,8 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from apps.pm.serializers import SubproductionPlanSimpleSerializer
from apps.qm.models import TestRecord, TestRecordItem
+from apps.sam.serializers import OrderSimpleSerializer
+from apps.system.models import User
from apps.system.serializers import UserSimpleSerializer
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
from django.db import transaction
@@ -437,7 +439,17 @@ class WproductTicketListSerializer(serializers.ModelSerializer):
step_ = StepSimpleSerializer(source='step', read_only=True)
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
resp_process_ = ProcessSimpleSerializer(source='resp_process', read_only=True)
+ order_ = OrderSimpleSerializer(source='subproduction_plan.production_plan.order', read_only=True)
+ product_ = MaterialSimpleSerializer(source='subproduction_plan.production_plan.product', read_only=True)
class Meta:
model = WprouctTicket
fields = '__all__'
+
+class CuttingListSerializer(serializers.ModelSerializer):
+ subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
+ material_ = MaterialSimpleSerializer(source='material', read_only=True)
+ create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
+ class Meta:
+ model = OperationMaterial
+ fields = '__all__'
\ No newline at end of file
diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py
index bd68bb7..d565482 100644
--- a/hb_server/apps/wpm/services.py
+++ b/hb_server/apps/wpm/services.py
@@ -7,7 +7,7 @@ from apps.mtm.models import Material, Step, SubprodctionMaterial
from apps.qm.models import TestRecord
from apps.system.models import User
from apps.wf.models import State, TicketFlow, Transition
-from apps.wpm.models import WProduct, WproductFlow, WprouctTicket
+from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow, WprouctTicket
from utils.tools import ranstr
class WpmServies(object):
@@ -146,3 +146,38 @@ class WpmServies(object):
setattr(ins, f.name, getattr(instance, f.name, None))
ins.change_str = change_str
ins.save()
+
+ @classmethod
+ def update_cutting_list_with_operation(cls, op:Operation):
+ """
+ 根据车间操作更新下料清单
+ """
+ inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN)
+ outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
+ for i in inputs:
+ sp = i.subproduction_plan
+ i.count_cut = outputs.filter(subproduction_plan=sp).first().count
+ i.count_real = sp.count_real
+ i.count_ok = sp.count_ok
+ wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
+ i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
+ i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
+ i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
+ i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count()
+ i.is_cutting = True
+ i.save()
+
+ @classmethod
+ def update_cutting_list_with_sp(cls, sp:SubProductionPlan):
+ """
+ 根据子计划更新下料清单
+ """
+ wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
+ for i in OperationMaterial.objects.filter(subproduction_plan=sp, is_cutting=True):
+ i.count_real = sp.count_real
+ i.count_ok = sp.count_ok
+ i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
+ i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
+ i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
+ i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count()
+ i.save()
\ No newline at end of file
diff --git a/hb_server/apps/wpm/urls.py b/hb_server/apps/wpm/urls.py
index 77d91f7..b617c02 100644
--- a/hb_server/apps/wpm/urls.py
+++ b/hb_server/apps/wpm/urls.py
@@ -3,7 +3,7 @@ from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
-from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
+from apps.wpm.views import CuttingListViewSet, DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
router = DefaultRouter()
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
@@ -17,6 +17,7 @@ router.register('operation_input', OperationMaterialInputViewSet, basename='oper
router.register('operation_output', OperationMaterialOutputViewSet, basename='operation_output')
router.register('operation_tool', OperationMaterialToolViewSet, basename='operation_tool')
router.register('subplan', WPlanViewSet, basename='wplan')
+router.register('cutting_list', CuttingListViewSet, basename='cutting_list')
urlpatterns = [
path('do/init/', DoFormInit.as_view()),
path('do/submit/', DoFormSubmit.as_view()),
diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py
index c446a47..2a47bca 100644
--- a/hb_server/apps/wpm/views.py
+++ b/hb_server/apps/wpm/views.py
@@ -22,7 +22,7 @@ from apps.wf.serializers import WorkflowSimpleSerializer
from apps.wpm.filters import WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket
-from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
+from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
@@ -385,6 +385,8 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
obj.update_time = timezone.now()
obj.save()
WpmServies.add_wproduct_flow_log(obj, 'scrap')
+ if obj.step.process.id == 1: #如果是冷加工
+ WpmServies.update_cutting_list_with_sp(obj.subproduction_plan)
return Response()
# @action(methods=['get'], detail=False, perms_map={'get':'*'})
@@ -429,7 +431,8 @@ class WproductTicketViewSet(ListModelMixin, GenericViewSet):
玻璃审批工单
"""
perms_map={'*':'*'}
- queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', 'resp_process')
+ queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan',
+ 'resp_process', 'subproduction_plan__production_plan__order', 'subproduction_plan__production_plan')
serializer_class = WproductTicketListSerializer
filterset_fields = ['step', 'material', 'subproduction_plan', 'resp_process']
ordering_fields = ['id']
@@ -579,9 +582,11 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
spp.save()
# 更新动态产品表
if step.type == Step.STEP_TYPE_NOM:
- for i in OperationWproduct.objects.filter(operation=op):
+ ows = OperationWproduct.objects.filter(operation=op)
+ for i in ows:
wp = i.wproduct
wsp = i.subproduction_plan
+
# 获取下一步子工序
newstep, hasNext = WpmServies.get_next_step(wsp, step)
wp.step = newstep
@@ -591,17 +596,21 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
else:
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
wp.material = wsp.product
- # 更新子计划生产进度
- # 如果产品有返工标记不做计算
- if wp.ng_sign not in [WProduct.NG_BACK_FIX, WProduct.NG_BACK_WORK]:
- WpmServies.update_subproduction_progress_main(sp=wsp)
wp.operation = None
wp.update_by = request.user
wp.save()
WpmServies.add_wproduct_flow_log(wp, 'operation_submit')
+
+ for i in ows.values('subproduction_plan').distinct():
+ # 更新进度
+ WpmServies.update_subproduction_progress_main(sp=wsp)
+
elif step.type == Step.STEP_TYPE_DIV:
# 更新物料产出情况
- for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
+ outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
+ if not outputs.exists():
+ raise exceptions.APIException('请选择物料产出')
+ for i in outputs:
if i.subproduction_progress.is_main:
newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
wpr = dict(material=i.material, step=newstep,
@@ -640,6 +649,10 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
raise exceptions.APIException('产出物料未填写或填写错误')
op.is_submited = True
op.save()
+
+ # 如果是冷加工
+ if step.process.id==1:
+ WpmServies.update_cutting_list_with_operation(op=op)
return Response()
@@ -774,6 +787,19 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod
instance.delete()
return Response()
+class CuttingListViewSet(ListModelMixin, GenericViewSet):
+ """
+ 下料清单
+ """
+ perms_map={'*':'*'}
+ queryset = OperationMaterial.objects.select_related('operation',
+ 'subproduction_plan', 'material', 'create_by').filter(operation__step__process__id=1)
+ serializer_class = CuttingListSerializer
+ filterset_fields = ['operation', 'subproduction_plan', 'material']
+ ordering_fields = ['id']
+ ordering = ['-id']
+
+
class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
"""
产出物料