From ef007e728afcd9468344791eb0c14fc81d0ed7c6 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:12:48 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=89=B9=E9=87=8F=E5=85=A5=E5=BA=93remar?= =?UTF-8?q?k=E9=9D=9E=E5=BF=85=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/.gitignore | 1 + hb_server/apps/inm/models.py | 61 ++-- hb_server/apps/inm/views.py | 49 +-- hb_server/apps/wpm/filters.py | 28 +- hb_server/apps/wpm/models.py | 235 +++++++++----- hb_server/apps/wpm/serializers.py | 4 +- hb_server/apps/wpm/views.py | 520 +++++++++++++++--------------- 7 files changed, 507 insertions(+), 391 deletions(-) diff --git a/hb_server/.gitignore b/hb_server/.gitignore index 55fdc78..5e37fef 100644 --- a/hb_server/.gitignore +++ b/hb_server/.gitignore @@ -1,5 +1,6 @@ .vscode/ .vs/ +.idea/ venv/ __pycache__/ *.pyc diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index 363c0db..0fe74a4 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -17,6 +17,7 @@ class WareHouse(CommonAModel): number = models.CharField('仓库编号', max_length=20, unique=True) name = models.CharField('仓库名称', max_length=20, unique=True) place = models.CharField('具体地点', max_length=50) + class Meta: verbose_name = '仓库信息' verbose_name_plural = verbose_name @@ -24,37 +25,44 @@ class WareHouse(CommonAModel): def __str__(self): return self.name + class Inventory(BaseModel): """ 库存物料 """ - material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息') + material = models.ForeignKey( + Material, on_delete=models.CASCADE, verbose_name='物料信息') count = models.PositiveIntegerField('仓库物料存量', default=0) - warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + warehouse = models.ForeignKey( + WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + class Meta: verbose_name = '库存表' verbose_name_plural = verbose_name + class MaterialBatch(BaseModel): """ 物料批次 """ - material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息') - warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + material = models.ForeignKey( + Material, on_delete=models.CASCADE, verbose_name='物料信息') + warehouse = models.ForeignKey( + WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') count = models.PositiveIntegerField('存量', default=0) batch = models.CharField('批次号', max_length=100, default='') expiration_date = models.DateField('有效期', null=True, blank=True) + class Meta: verbose_name = '库存表' verbose_name_plural = verbose_name - class FIFO(CommonADModel): """ 出入库记录 """ - FIFO_TYPE_DO_OUT = 1 # 生产领料 + FIFO_TYPE_DO_OUT = 1 # 生产领料 FIFO_TYPE_SALE_OUT = 2 FIFO_TYPE_PUR_IN = 3 FIFO_TYPE_DO_IN = 4 @@ -66,7 +74,8 @@ class FIFO(CommonADModel): ) type = models.IntegerField('出入库类型', default=1) is_audited = models.BooleanField('是否审核', default=False) - auditor = models.ForeignKey(User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True) + auditor = models.ForeignKey( + User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True) inout_date = models.DateField('出入库日期') remark = models.CharField('备注', max_length=1000, default='') @@ -75,38 +84,46 @@ class FIFOItem(BaseModel): """ 出入库详细条目 """ + need_test = models.BooleanField('是否需要检验', default=False) is_tested = models.BooleanField('是否已检验', default=False) is_testok = models.BooleanField('是否检验合格', default=False) - warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库') - material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE) + warehouse = models.ForeignKey( + WareHouse, on_delete=models.CASCADE, verbose_name='仓库') + material = models.ForeignKey( + Material, verbose_name='物料类型', on_delete=models.CASCADE) count = models.PositiveIntegerField('数量', default=0) batch = models.CharField('批次号', max_length=100, default='') - fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True) + fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', + on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True) + class IProduct(BaseModel): """ 具体产品条目 """ number = models.CharField('物品编号', unique=True, max_length=50) - material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE) - warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') + material = models.ForeignKey( + Material, verbose_name='物料类型', on_delete=models.CASCADE) + warehouse = models.ForeignKey( + WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') batch = models.CharField('所属批次号', max_length=100, default='') wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, - null=True, blank=True, related_name='iproduct_wproduct') + null=True, blank=True, related_name='iproduct_wproduct') is_saled = models.BooleanField('是否售出', default=False) + class FIFOItemProduct(BaseModel): """ 出入库产品 """ - fifoitem = models.ForeignKey(FIFOItem, verbose_name='关联出入库具体产品', on_delete=models.CASCADE) + fifoitem = models.ForeignKey( + FIFOItem, verbose_name='关联出入库具体产品', on_delete=models.CASCADE) wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True, - related_name='fifoitem_wproduct') + related_name='fifoitem_wproduct') number = models.CharField('物品编号', max_length=50) - material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE) - iproduct = models.ForeignKey(IProduct, verbose_name='关联库存产品', null=True, blank=True, on_delete=models.SET_NULL) - - - - + material = models.ForeignKey( + Material, verbose_name='物料类型', on_delete=models.CASCADE) + iproduct = models.ForeignKey( + IProduct, verbose_name='关联库存产品', null=True, blank=True, on_delete=models.SET_NULL) diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index e91d156..2b3af52 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -6,8 +6,8 @@ from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveMod from rest_framework.viewsets import GenericViewSet, ModelViewSet from apps.inm.filters import IProductFilterSet, MbFilterSet -from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse,Inventory -from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer +from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse, Inventory +from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer, InventorySerializer from apps.inm.signals import update_inm from apps.mtm.models import Material from apps.pm.services import PmService @@ -16,10 +16,13 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from rest_framework.response import Response from django.db import transaction +from django.utils import timezone from apps.wpm.services import WpmServies # Create your views here. + + class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet): """ 仓库-增删改查 @@ -32,26 +35,30 @@ class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet): ordering_fields = ['create_time'] ordering = ['-create_time'] - def get_serializer_class(self): + def get_serializer_class(self): if self.action in ['create', 'update']: return WareHouseCreateUpdateSerializer return WareHouseSerializer + class InventoryViewSet(ListModelMixin, GenericViewSet): """ 仓库物料表 """ perms_map = {'*': '*'} - queryset = Inventory.objects.select_related('material', 'warehouse').filter(count__gt=0).all() + queryset = Inventory.objects.select_related( + 'material', 'warehouse').filter(count__gt=0).all() serializer_class = InventorySerializer filterset_fields = ['material', 'warehouse'] search_fields = [] ordering_fields = ['create_time'] ordering = ['-create_time'] + class MaterialBatchViewSet(ListModelMixin, GenericViewSet): perms_map = {'*': '*'} - queryset = MaterialBatch.objects.select_related('material', 'warehouse').filter(count__gt=0).all() + queryset = MaterialBatch.objects.select_related( + 'material', 'warehouse').filter(count__gt=0).all() serializer_class = MaterialBatchSerializer # filterset_fields = ['material', 'warehouse'] filterset_class = MbFilterSet @@ -59,7 +66,7 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet): ordering_fields = ['create_time'] ordering = ['-create_time'] - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MaterialBatchQuerySerializer) def query(self, request, pk=None): """ 复杂查询 @@ -67,9 +74,11 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet): data = request.data serializer = MaterialBatchQuerySerializer(data=data) serializer.is_valid(raise_exception=True) - queryset = self.queryset.filter(warehouse__id=data['warehouse'], material__id__in=data['materials']) + queryset = self.queryset.filter( + warehouse__id=data['warehouse'], material__id__in=data['materials']) return Response(MaterialBatchSerializer(instance=queryset, many=True).data) + class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): """ 出入库记录详情表 @@ -77,7 +86,8 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): perms_map = {'*': '*'} queryset = FIFOItem.objects.select_related('material', 'fifo').all() serializer_class = FIFOItemSerializer - filterset_fields = ['material', 'fifo', 'fifo__type', 'is_tested', 'is_testok'] + filterset_fields = ['material', 'fifo', + 'fifo__type', 'is_tested', 'is_testok'] search_fields = [] ordering_fields = ['create_time'] ordering = ['-create_time'] @@ -87,7 +97,7 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): raise APIException('该出入库记录已通过审核, 无法删除') return super().perform_destroy(instance) - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=InmTestRecordCreateSerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=InmTestRecordCreateSerializer) def test(self, request, pk=None): """ 检验 @@ -99,9 +109,9 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): if 'is_testok' not in vdata: raise APIException('未填写检验结论') with transaction.atomic(): - obj = serializer.save(create_by = self.request.user) + obj = serializer.save(create_by=self.request.user) tris = [] - for m in record_data: # 保存记录详情 + for m in record_data: # 保存记录详情 m['field_value'] = m['field_value'] m['is_testok'] = m['is_testok'] if 'is_testok' in m else True m['test_record'] = obj @@ -115,6 +125,7 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): obj.fifo_item.save() return Response() + class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): """ 出入库记录 @@ -131,14 +142,14 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): if self.action == 'list': return FIFOListSerializer return super().get_serializer_class() - + def destroy(self, request, *args, **kwargs): obj = self.get_object() if obj.is_submited: raise exceptions.APIException('该记录已审核,不可删除') return super().destroy(request, *args, **kwargs) - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=FIFOInPurSerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=FIFOInPurSerializer) def in_pur(self, request, pk=None): """ 采购入库 @@ -148,7 +159,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): serializer.save(create_by=request.user) return Response() - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer) + @action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=serializers.Serializer) def audit(self, request, pk=None): """ 审核通过 @@ -162,19 +173,21 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): with transaction.atomic(): obj.is_audited = True obj.auditor = request.user + obj.inout_date = timezone.now() # 也是审核日期 obj.save() - update_inm(obj) # 更新库存 + update_inm(obj) # 更新库存 return Response() - + class IProductViewSet(ListModelMixin, GenericViewSet): """ 半成品库存表 """ perms_map = {'*': '*'} - queryset = IProduct.objects.select_related('material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order') + queryset = IProduct.objects.select_related( + 'material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order') serializer_class = IProductListSerializer filterset_class = IProductFilterSet search_fields = [] ordering_fields = ['create_time'] - ordering = ['-create_time'] \ No newline at end of file + ordering = ['-create_time'] diff --git a/hb_server/apps/wpm/filters.py b/hb_server/apps/wpm/filters.py index e47fec7..c8392d3 100644 --- a/hb_server/apps/wpm/filters.py +++ b/hb_server/apps/wpm/filters.py @@ -4,39 +4,50 @@ from apps.mtm.models import Material, Step from apps.wpm.services import WpmServies from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct + class WMaterialFilterSet(filters.FilterSet): operation = filters.NumberFilter(method='filter_operation') + class Meta: model = WMaterial - fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop', 'operation'] + 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(): - subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts) + subplans = WpmServies.get_subplans_queryset_from_wproducts( + wproducts) else: subplans = WpmServies.get_subplans_queyset_from_step(step) - queryset = queryset.filter(subproduction_plan__in=subplans).exclude(material__type=Material.MA_TYPE_HALFGOOD) + queryset = queryset.filter(subproduction_plan__in=subplans).exclude( + material__type=Material.MA_TYPE_HALFGOOD) return queryset class WProductFilterSet(filters.FilterSet): tag = filters.CharFilter(method='filter_tag') - production_plan = filters.NumberFilter(field_name='subproduction_plan__production_plan') + production_plan = filters.NumberFilter( + field_name='subproduction_plan__production_plan') + class Meta: model = WProduct - fields = ['step', 'subproduction_plan', 'material', 'step__process', 'act_state', 'material__type'] + fields = ['step', 'subproduction_plan', 'material', + 'step__process', 'act_state', 'material__type'] def filter_tag(self, queryset, name, value): if value == 'no_scrap': queryset = queryset.exclude(act_state=WProduct.WPR_ACT_STATE_SCRAP) return queryset + class CuttingFilterSet(filters.FilterSet): - production_plan = filters.NumberFilter(field_name='subproduction_plan__production_plan') + production_plan = filters.NumberFilter( + field_name='subproduction_plan__production_plan') + class Meta: model = OperationMaterial fields = ['operation', 'subproduction_plan', 'material'] @@ -44,10 +55,11 @@ class CuttingFilterSet(filters.FilterSet): class OperationRecordFilterSet(filters.FilterSet): wproduct = filters.NumberFilter(method='filter_wproduct') + class Meta: model = OperationRecord fields = ['operation', 'form'] - + def filter_wproduct(self, queryset, name, value): queryset = queryset.filter(operation__ow_operation__wproduct__id=value) - return queryset \ No newline at end of file + return queryset diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 4ecb946..dd870b4 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -13,15 +13,20 @@ from utils.model import SoftModel, BaseModel from simple_history.models import HistoricalRecords from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm, SubprodctionMaterial from apps.em.models import Equipment + + class WMaterial(BaseModel): """ 车间生产物料 """ - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE) - material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE) + material = models.ForeignKey( + Material, verbose_name='关联物料', on_delete=models.CASCADE) batch = models.CharField('批次号', max_length=100, null=True, blank=True) count = models.PositiveIntegerField('当前数量', default=0) + class WProduct(CommonAModel): """ 动态半成品/成品表 @@ -37,7 +42,7 @@ class WProduct(CommonAModel): WPR_ACT_STATE_TOFINALTEST = 60 WPR_ACT_STATE_SCRAP = 70 WPR_ACT_STATE_SELLED = 80 - act_state_choices=( + act_state_choices = ( (WPR_ACT_STATE_TORETEST, '待复检'), (WPR_ACT_STATE_DOWAIT, '操作准备中'), (WPR_ACT_STATE_DOING, '操作进行中'), @@ -69,7 +74,7 @@ class WProduct(CommonAModel): NG_DOWN = 60 NG_BACK_FROM = 70 NG_RECALL = 80 - + ng_choices = ( (NG_BACK_WORK, '返工'), (NG_BACK_FIX, '返修'), @@ -80,29 +85,39 @@ class WProduct(CommonAModel): (NG_BACK_FROM, '退回供方'), (NG_RECALL, '召回') ) - number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50) - material = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE) - pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, on_delete=models.CASCADE, related_name='w_pre_step') - step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, related_name='w_step') - act_state = models.IntegerField('进行状态', default=0, choices=act_state_choices) + number = models.CharField( + '物品编号', unique=True, null=True, blank=True, max_length=50) + material = models.ForeignKey( + Material, verbose_name='所属物料状态', on_delete=models.CASCADE) + pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, + on_delete=models.CASCADE, related_name='w_pre_step') + step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, + related_name='w_step') + act_state = models.IntegerField( + '进行状态', default=0, choices=act_state_choices) is_hidden = models.BooleanField('是否隐藏', default=False) - child = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE, related_name='wproduct_child') + child = models.ForeignKey('self', blank=True, null=True, + on_delete=models.CASCADE, related_name='wproduct_child') 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') - - scrap_reason = models.IntegerField('报废原因', choices=scrap_reason_choices, null=True, blank=True) - ng_sign = models.PositiveSmallIntegerField('不合格标记', choices=ng_choices, null=True, blank=True) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, + related_name='wproduct_subplan') - warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True) + scrap_reason = models.IntegerField( + '报废原因', choices=scrap_reason_choices, null=True, blank=True) + ng_sign = models.PositiveSmallIntegerField( + '不合格标记', choices=ng_choices, null=True, blank=True) - operation = models.ForeignKey('wpm.operation', verbose_name='当前操作', - on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_operation') - coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作', - on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_coperation') - test = models.ForeignKey('qm.testrecord', verbose_name='当前检验', - on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test') - ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', - on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket') + 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='wp_operation') + coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作', + on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_coperation') + test = models.ForeignKey('qm.testrecord', verbose_name='当前检验', + on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test') + ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', + on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket') is_mtested = models.BooleanField('是否军检', default=False) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) @@ -115,50 +130,68 @@ class WProduct(CommonAModel): 最后提交的工序自检 """ return self.test_wproduct.filter(type=TestRecord.TEST_PROCESS, is_submited=True).order_by('-id').first() - + class WprouctTicket(CommonAModel): """ 玻璃审批工单 """ - + number = models.CharField('物品编号', null=True, blank=True, max_length=50) - wproduct = models.ForeignKey(WProduct, verbose_name='关联产品', on_delete=models.CASCADE) - material = models.ForeignKey(Material, verbose_name='所在物料状态', on_delete=models.CASCADE) - step = models.ForeignKey(Step, verbose_name='所在步骤/发现步骤', on_delete=models.CASCADE) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE) - - resp_process = models.ForeignKey(Process, verbose_name='责任工序', on_delete=models.CASCADE, null=True, blank=True) - ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket') - decision = models.PositiveSmallIntegerField('最终决定', choices=WProduct.ng_choices, null=True, blank=True) + wproduct = models.ForeignKey( + WProduct, verbose_name='关联产品', on_delete=models.CASCADE) + material = models.ForeignKey( + Material, verbose_name='所在物料状态', on_delete=models.CASCADE) + step = models.ForeignKey( + Step, verbose_name='所在步骤/发现步骤', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE) + + resp_process = models.ForeignKey( + Process, verbose_name='责任工序', on_delete=models.CASCADE, null=True, blank=True) + ticket = models.ForeignKey( + 'wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket') + decision = models.PositiveSmallIntegerField( + '最终决定', choices=WProduct.ng_choices, null=True, blank=True) + class WproductFlow(CommonAModel): """ 动态产品表日志 """ - wproduct = models.ForeignKey(WProduct, on_delete=models.CASCADE, verbose_name='关联产品', null=True, blank=True) + wproduct = models.ForeignKey( + WProduct, on_delete=models.CASCADE, verbose_name='关联产品', null=True, blank=True) number = models.CharField('物品编号', null=True, blank=True, max_length=50) - material = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE) - pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, on_delete=models.CASCADE, related_name='wl_pre_step') - step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, related_name='wl_step') - act_state = models.IntegerField('进行状态', default=0, choices=WProduct.act_state_choices) + material = models.ForeignKey( + Material, verbose_name='所属物料状态', on_delete=models.CASCADE) + pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, + on_delete=models.CASCADE, related_name='wl_pre_step') + step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, + related_name='wl_step') + act_state = models.IntegerField( + '进行状态', default=0, choices=WProduct.act_state_choices) is_hidden = models.BooleanField('是否隐藏', default=False) - child = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE, related_name='wproduct_child') + child = models.ForeignKey('self', blank=True, null=True, + on_delete=models.CASCADE, related_name='wproduct_child') remark = models.CharField('备注', max_length=200, null=True, blank=True) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE) - scrap_reason = models.IntegerField('报废原因', choices= WProduct.scrap_reason_choices, null=True, blank=True) - ng_sign = models.PositiveSmallIntegerField('不合格标记', choices= WProduct.ng_choices, null=True, blank=True) + scrap_reason = models.IntegerField( + '报废原因', choices=WProduct.scrap_reason_choices, null=True, blank=True) + ng_sign = models.PositiveSmallIntegerField( + '不合格标记', choices=WProduct.ng_choices, null=True, blank=True) - 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='wpf_operation') - coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作', - on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_coperation') - test = models.ForeignKey('qm.testrecord', verbose_name='当前检验', - on_delete=models.SET_NULL, null=True, blank=True) - ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', - on_delete=models.SET_NULL, null=True, blank=True) + 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='wpf_operation') + coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作', + on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_coperation') + test = models.ForeignKey('qm.testrecord', verbose_name='当前检验', + on_delete=models.SET_NULL, null=True, blank=True) + ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', + on_delete=models.SET_NULL, null=True, blank=True) is_mtested = models.BooleanField('是否军检', default=False) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) @@ -179,65 +212,88 @@ class Pick(CommonADModel): (PICK_FROM_WAREHOUSE, '仓库领取'), (PICK_FROM_WPRODUCT, '半成品领取'), ) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE) - type = models.PositiveSmallIntegerField(choices=type_choice, default=PICK_FROM_WAREHOUSE) - fifo = models.ForeignKey(FIFO, verbose_name='关联的出入库记录', on_delete=models.CASCADE, null=True, blank=True) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE) + type = models.PositiveSmallIntegerField( + choices=type_choice, default=PICK_FROM_WAREHOUSE) + fifo = models.ForeignKey( + FIFO, verbose_name='关联的出入库记录', on_delete=models.CASCADE, null=True, blank=True) + class PickWproduct(BaseModel): """ 领取半成品时详情 """ - pick = models.ForeignKey(Pick, verbose_name='关联领料', on_delete=models.CASCADE) - wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='pw_wproduct') + pick = models.ForeignKey(Pick, verbose_name='关联领料', + on_delete=models.CASCADE) + wproduct = models.ForeignKey( + WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='pw_wproduct') 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) + material = models.ForeignKey( + Material, verbose_name='领取时的物料状态', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey( + SubProductionPlan, verbose_name='领取时所属子生产计划', on_delete=models.CASCADE) + class Operation(CommonADModel): """ 生产操作 """ - step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True) + step = models.ForeignKey(Step, verbose_name='操作步骤', + on_delete=models.CASCADE, null=True, blank=True) remark = models.CharField('操作备注', max_length=200, null=True, blank=True) is_submited = models.BooleanField('是否提交', default=False) + class OperationWproduct(BaseModel): """ 生产操作半成品关联表 """ - operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='ow_operation') - wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='ow_wproduct') + operation = models.ForeignKey( + Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='ow_operation') + wproduct = models.ForeignKey( + WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='ow_wproduct') 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, related_name='ow_subplan') - ng_sign = models.PositiveSmallIntegerField('当时的不合格标记', choices= WProduct.ng_choices, null=True, blank=True) + 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') + ng_sign = models.PositiveSmallIntegerField( + '当时的不合格标记', choices=WProduct.ng_choices, null=True, blank=True) place = models.CharField('摆放位置', null=True, blank=True, max_length=200) + class Meta: unique_together = ( - ('operation','wproduct') + ('operation', 'wproduct') ) + class OperationMaterial(BaseModel): """ 生产操作物料消耗产出表 """ - type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices) - operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, related_name='om_operation') - - material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, - null=True, blank=True, related_name='om_material') + type = models.IntegerField( + '类型', default=0, choices=SubprodctionMaterial.type_choices) + operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, + related_name='om_operation') + + material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, + null=True, blank=True, related_name='om_material') count = models.PositiveSmallIntegerField('消耗或产出数量', null=True, blank=True) - wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True) - subproduction_progress = models.ForeignKey(SubProductionProgress, verbose_name='关联的生产进度', on_delete=models.CASCADE, null=True, blank=True) + wmaterial = models.ForeignKey( + WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True) + subproduction_progress = models.ForeignKey(SubProductionProgress, verbose_name='关联的生产进度', on_delete=models.CASCADE, + null=True, blank=True) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True) + 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) use_scrap = models.BooleanField('是否使用的边角料', default=False) - #以下为冷加工下料清单所用字段 - from_material = models.ForeignKey(Material, verbose_name='源物料', on_delete=models.CASCADE, - null=True, blank=True, related_name='om_fmaterial') + # 以下为冷加工下料清单所用字段 + from_material = models.ForeignKey(Material, verbose_name='源物料', on_delete=models.CASCADE, + null=True, blank=True, related_name='om_fmaterial') from_batch = models.CharField('源批次', max_length=100, null=True, blank=True) count_cut = models.PositiveIntegerField('切裁片数', default=0) count_real = models.PositiveIntegerField('生产片数', default=0) @@ -246,29 +302,38 @@ class OperationMaterial(BaseModel): 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') + ('operation', 'material', 'batch') ) + class OperationRecord(BaseModel): """ 记录表格 """ - form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', on_delete=models.CASCADE, related_name='or_form') - operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, related_name='or_operation') + form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', + on_delete=models.CASCADE, related_name='or_form') + operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, + related_name='or_operation') is_filled = models.BooleanField('是否填写', default=True) + class OperationRecordItem(BaseModel): """ 记录表格字段值 """ - form_field = models.ForeignKey(RecordFormField, verbose_name='关联字段', on_delete=models.CASCADE, related_name='ori_form_field') + form_field = models.ForeignKey(RecordFormField, verbose_name='关联字段', on_delete=models.CASCADE, + related_name='ori_form_field') field_value = models.JSONField('录入值', null=True, blank=True) - operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE, related_name='item_operation_record') + operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE, + related_name='item_operation_record') + class OperationEquip(BaseModel): - operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation') - equip = models.ForeignKey(Equipment, verbose_name='生产设备', on_delete=models.CASCADE, related_name='oe_equip') - remark = models.TextField('备注', null=True, blank=True) \ No newline at end of file + operation = models.ForeignKey( + Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation') + equip = models.ForeignKey(Equipment, verbose_name='生产设备', + on_delete=models.CASCADE, related_name='oe_equip') + remark = models.TextField('备注', null=True, blank=True) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 95a9e2d..d9f09dd 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -418,12 +418,12 @@ class WplanPutInSerializer(serializers.Serializer): class WproductPutInSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") - remark = serializers.CharField(label="入库备注", required =False) + remark = serializers.CharField(label="入库备注", required =False, default="") class WproductPutInsSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID', many=True) - remark = serializers.CharField(label="入库备注", required =False, allow_null=True) + remark = serializers.CharField(label="入库备注", required =False, default="") class OperationEquipListSerializer(serializers.Serializer): diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 8aee33d..0920983 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -1,66 +1,77 @@ -from django.db.models.expressions import F -from django.shortcuts import render from rest_framework.generics import CreateAPIView, GenericAPIView -from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin -from rest_framework.utils import serializer_helpers -from rest_framework.utils.field_mapping import get_relation_kwargs -from rest_framework.views import APIView -from rest_framework.viewsets import GenericViewSet, ModelViewSet -from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse +from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, \ + ListModelMixin, RetrieveModelMixin, UpdateModelMixin +from rest_framework.viewsets import GenericViewSet +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct from apps.inm.signals import update_inm from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer from apps.pm.models import SubProductionPlan, SubProductionProgress -from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer +from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionProgressSerializer from apps.qm.models import TestRecord, TestRecordItem from apps.qm.serializers import TestRecordDetailSerializer -from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin +from apps.system.mixins import CreateUpdateModelAMixin from rest_framework.decorators import action from apps.wf.models import Workflow -from apps.wf.serializers import WorkflowSimpleSerializer from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet -from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket +from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, \ + OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket + +from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, \ + OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, \ + OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, \ + OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, \ + OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, \ + OperationListSerializer, OperationWproductUpdateSerializer, PickHalfsSerializer, \ + PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \ + WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \ + WpmTestFormInitSerializer, WproductMtestSerializer, 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, OperationWproductUpdateSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductMtestSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions, serializers - from apps.wpm.services import WpmServies from django.utils import timezone -from utils.tools import ranstr from rest_framework import status from django.db.models import Count + + # Create your views here. + + class WPlanViewSet(ListModelMixin, GenericViewSet): """ 车间生产计划 """ perms_map = {'*': '*'} - queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'product').exclude(state=0) + queryset = SubProductionPlan.objects.select_related( + 'process', 'workshop', 'subproduction', 'product').exclude(state=0) search_fields = [] serializer_class = SubProductionPlanListSerializer - filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop'] + filterset_fields = ['production_plan', + 'process', 'state', 'product', 'workshop'] ordering_fields = [] ordering = ['-update_time'] - @action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfsSerializer) + @action(methods=['post', 'get'], detail=True, perms_map={'post': '*', 'get': '*'}, serializer_class=PickHalfsSerializer) @transaction.atomic def pick_half(self, request, pk=None): """ 领半成品 """ sp = self.get_object() - if request.method=='GET': + if request.method == 'GET': """ 领半成品 """ - spps = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN, - material__type=Material.MA_TYPE_HALFGOOD, subproduction_plan=sp).select_related('material') + spps = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN, + material__type=Material.MA_TYPE_HALFGOOD, + subproduction_plan=sp).select_related('material') return Response(SubProductionProgressSerializer(instance=spps, many=True).data) - elif request.method=='POST': - serializer= PickHalfsSerializer(data=request.data) + elif request.method == 'POST': + serializer = PickHalfsSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.validated_data first_step = Step.objects.get(pk=sp.steps[0]['id']) @@ -71,17 +82,18 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): pick.create_by = request.user pick.save() for i in vdata: - if 'wproducts' in i and len(i['wproducts'])>0: + if 'wproducts' in i and len(i['wproducts']) > 0: spp = i['id'] spp.count_pick = spp.count_pick + len(i['wproducts']) # if spp.count_pick > spp.count: # raise exceptions.APIException('超过计划数') spp.save() - wps = WProduct.objects.filter(pk__in=[x.id for x in i['wproducts']], act_state=WProduct.WPR_ACT_STATE_OK) - wps.update(step=first_step, - act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None, - subproduction_plan=sp, update_by=request.user, update_time=timezone.now()) - + wps = WProduct.objects.filter( + pk__in=[x.id for x in i['wproducts']], act_state=WProduct.WPR_ACT_STATE_OK) + wps.update(step=first_step, + act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None, + subproduction_plan=sp, update_by=request.user, update_time=timezone.now()) + for m in i['wproducts']: m.step = first_step m.act_state = WProduct.WPR_ACT_STATE_TORETEST @@ -91,9 +103,10 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): m.update_by = request.user m.update_time = timezone.now() m.save() - WpmServies.add_wproduct_flow_log(instance=m, change_str='pick_half') + WpmServies.add_wproduct_flow_log( + instance=m, change_str='pick_half') pw = PickWproduct() - pw.pick =pick + pw.pick = pick pw.wproduct = m pw.number = m.number pw.material = m.material @@ -101,103 +114,47 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): pw.save() sp.is_picked = True sp.save() - - return Response() - - # @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer) - # @transaction.atomic - # def putin(self, request, pk=None): - # """ - # 半成品入库 - # """ - # serializer= WplanPutInSerializer(data=request.data) - # serializer.is_valid(raise_exception=True) - # vdata = serializer.validated_data - # subplan = self.get_object() - # material = subplan.product - # batch = subplan.number - # warehouse = vdata['warehouse'] - # wproducts = WProduct.objects.filter(subproduction_plan=subplan, - # act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False) - # if wproducts.exists(): - # # 创建入库记录 - # remark = vdata.get('remark', '') - # fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN, - # is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) - # # 创建入库明细 - # fifoitem = FIFOItem() - # fifoitem.is_tested = True - # fifoitem.is_testok = True - # fifoitem.warehouse = warehouse - # fifoitem.material = material - # fifoitem.count = wproducts.count() - # fifoitem.batch = batch - # fifoitem.fifo = fifo - # fifoitem.subproduction_plan = subplan - # fifoitem.save() - # # 创建入库明细半成品 - # ips = [] - # for i in wproducts: - # ip = {} - # ip['fifoitem'] = fifoitem - # ip['wproduct'] = i - # ip['number'] = i.number - # ip['material'] = material - # ips.append(FIFOItemProduct(**ip)) - # FIFOItemProduct.objects.bulk_create(ips) - # # 创建IProduct - # ips2 = [] - # for i in wproducts: - # ip = {} - # ip['warehouse'] = warehouse - # ip['batch'] = batch - # ip['wproduct'] = i - # ip['number'] = i.number - # ip['material'] = material - # ips2.append(IProduct(**ip)) - # IProduct.objects.bulk_create(ips2) - # # 更新库存并修改半成品进行状态 - # update_inm(fifo) - # wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user, update_time=timezone.now()) - - # return Response() + return Response() class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet): """ 车间物料表 """ - perms_map={'*':'*'} - queryset = WMaterial.objects.select_related('material', 'subproduction_plan').filter(count__gt=0) + perms_map = {'*': '*'} + queryset = WMaterial.objects.select_related( + 'material', 'subproduction_plan').filter(count__gt=0) serializer_class = WMaterialListSerializer filterset_class = WMaterialFilterSet ordering_fields = ['material__number'] ordering = ['material__number'] - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PickSerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=PickSerializer) def pick(self, request, pk=None): """ 领料 """ - serializer= PickSerializer(data=request.data, context={'request': request}) + serializer = PickSerializer( + data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) serializer.save() return Response() + class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): """ 半成品 """ - perms_map={'*':'*'} - queryset = WProduct.objects.select_related('step', 'material', - 'subproduction_plan', 'warehouse').prefetch_related('wproduct_child') + perms_map = {'*': '*'} + queryset = WProduct.objects.select_related('step', 'material', + 'subproduction_plan', 'warehouse').prefetch_related('wproduct_child') serializer_class = WProductListSerializer filterset_class = WProductFilterSet search_fields = ['number'] ordering_fields = ['id'] ordering = ['id'] - + def get_serializer_class(self): if self.action == 'retrieve': return WProductDetailSerializer @@ -209,7 +166,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): queryset = queryset.filter(is_hidden=False) return queryset - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestFormInitSerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WpmTestFormInitSerializer) @transaction.atomic def test_init(self, request, pk=None): """ @@ -224,18 +181,19 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): raise exceptions.APIException('存在进行中检验') # 根据情况创建一条检验记录 - if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, - WProduct.WPR_ACT_STATE_TORETEST, WProduct.WPR_ACT_STATE_TOFINALTEST, WProduct.WPR_ACT_STATE_TOCOMBTEST]: + if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, + WProduct.WPR_ACT_STATE_TORETEST, WProduct.WPR_ACT_STATE_TOFINALTEST, + WProduct.WPR_ACT_STATE_TOCOMBTEST]: raise exceptions.APIException('该产品当前状态不可检验') - + savedict = dict( - create_by = self.request.user, + create_by=self.request.user, wproduct=wproduct, - material=wproduct.material, - number=wproduct.number, - subproduction_plan=wproduct.subproduction_plan, - step=wproduct.step, - form=form) + material=wproduct.material, + number=wproduct.number, + subproduction_plan=wproduct.subproduction_plan, + step=wproduct.step, + form=form) if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 查找最近一条检验记录 trs = wproduct.last_process_test @@ -263,26 +221,29 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): tri.save() return Response(TestRecordDetailSerializer(instance=tr).data) - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WproductPutInsSerializer) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductPutInsSerializer) @transaction.atomic def putins(self, request, pk=None): """ 半成品批量入库 """ - serializer= WproductPutInsSerializer(data=request.data) + serializer = WproductPutInsSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.validated_data - wproducts = WProduct.objects.filter(pk__in=[x.id for x in vdata['wproducts']]) + wproducts = WProduct.objects.filter( + pk__in=[x.id for x in vdata['wproducts']]) warehouse = vdata['warehouse'] for i in wproducts: if i.act_state is not WProduct.WPR_ACT_STATE_OK: raise exceptions.APIException('存在不可入库半成品') # 聚合一下 - wproducts_a = wproducts.values('subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id')) + wproducts_a = wproducts.values( + 'subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id')) # 创建入库记录 remark = vdata.get('remark', '') fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN, - is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) + is_audited=True, auditor=request.user, inout_date=timezone.now(), + create_by=request.user, remark=remark) # 创建入库明细 for i in wproducts_a: spi = SubProductionPlan.objects.get(pk=i['subproduction_plan']) @@ -297,9 +258,10 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): fifoitem.subproduction_plan = spi fifoitem.save() - wproducts_items = wproducts.filter(subproduction_plan=i['subproduction_plan'], material=i['material']) + wproducts_items = wproducts.filter( + subproduction_plan=i['subproduction_plan'], material=i['material']) ips = [] - for i in wproducts_items: + for i in wproducts_items: # 创建入库明细半成品 ip = {} ip['fifoitem'] = fifoitem @@ -318,14 +280,14 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): i.save() WpmServies.add_wproduct_flow_log(i, 'putins') return Response() - - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer) + + @action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=WproductPutInSerializer) @transaction.atomic def putin(self, request, pk=None): """ 半成品入库 """ - serializer= WproductPutInSerializer(data=request.data) + serializer = WproductPutInSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.validated_data wproduct = self.get_object() @@ -337,14 +299,15 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): # 创建入库记录 remark = vdata.get('remark', '') fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN, - is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) + is_audited=True, auditor=request.user, inout_date=timezone.now(), + create_by=request.user, remark=remark) # 创建入库明细 fifoitem = FIFOItem() fifoitem.is_tested = True fifoitem.is_testok = True fifoitem.warehouse = warehouse fifoitem.material = material - fifoitem.count = 1 # 单个半成品入库 + fifoitem.count = 1 # 单个半成品入库 fifoitem.batch = batch fifoitem.fifo = fifo fifoitem.subproduction_plan = wproduct.subproduction_plan @@ -361,13 +324,13 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): FIFOItemProduct.objects.bulk_create(ips) # 更新库存并修改半成品进行状态 update_inm(fifo) - wproduct.act_state=WProduct.WPR_ACT_STATE_INM - wproduct.warehouse=warehouse + wproduct.act_state = WProduct.WPR_ACT_STATE_INM + wproduct.warehouse = warehouse wproduct.save() WpmServies.add_wproduct_flow_log(wproduct, 'putin') return Response() - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=ScrapSerializer) + @action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=ScrapSerializer) def scrap(self, request, pk=None): """ 报废操作 @@ -379,7 +342,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): if obj.act_state == WProduct.WPR_ACT_STATE_NOTOK: pass elif obj.step.process.id == 1 and \ - obj.act_state in [WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_TOTEST]: # 如果是冷加工可直接报废 + obj.act_state in [WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_TOTEST]: # 如果是冷加工可直接报废 if vdata.get('scrap_reason', None): obj.scrap_reason = vdata['scrap_reason'] else: @@ -391,7 +354,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): obj.update_time = timezone.now() obj.save() WpmServies.add_wproduct_flow_log(obj, 'scrap') - if obj.step.process.id == 1: #如果是冷加工 + if obj.step.process.id == 1: # 如果是冷加工 WpmServies.update_cutting_list_with_operation(obj.coperation) return Response() @@ -403,34 +366,36 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): # wfs = Workflow.objects.filter(key__startswith= 'wp_') # return WorkflowSimpleSerializer(instance=wfs, many=True).data - @action(methods=['get'], detail=True, perms_map={'get':'*'}) + @action(methods=['get'], detail=True, perms_map={'get': '*'}) def wf_bhg(self, request, pk=None): """ 发起不合格审理单 """ obj = self.get_object() - if obj.act_state != WProduct.WPR_ACT_STATE_NOTOK or obj.ng_sign is not None\ - or obj.ticket is not None: + if obj.act_state != WProduct.WPR_ACT_STATE_NOTOK or obj.ng_sign is not None \ + or obj.ticket is not None: raise exceptions.APIException('该产品不可发起不合格审理') - workflow = Workflow.objects.filter(name='不合格品审理单', is_deleted=False).first() + workflow = Workflow.objects.filter( + name='不合格品审理单', is_deleted=False).first() if workflow: - test_record = TestRecord.objects.filter(wproduct=obj, is_deleted=False, is_testok=False).order_by('-id').first() + test_record = TestRecord.objects.filter( + wproduct=obj, is_deleted=False, is_testok=False).order_by('-id').first() exist_data = { - 'wproduct':obj.id, - 'wproduct_number':obj.number, - 'wproduct_name':obj.material.name, - 'wproduct_specification':obj.material.specification, - 'finder':request.user.id, - 'find_process':obj.step.process.id, - 'tester':test_record.create_by.id + 'wproduct': obj.id, + 'wproduct_number': obj.number, + 'wproduct_name': obj.material.name, + 'wproduct_specification': obj.material.specification, + 'finder': request.user.id, + 'find_process': obj.step.process.id, + 'tester': test_record.create_by.id } - ret = {'workflow':workflow.id} + ret = {'workflow': workflow.id} ret['exist_data'] = exist_data return Response(ret) else: raise exceptions.APIException('未找到对应审批流程') - - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductMtestSerializer) + + @action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=WproductMtestSerializer) @transaction.atomic def mtest(self, request, pk=None): """ @@ -446,7 +411,8 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): is_mtestok = request.data.get('is_mtestok') obj.is_mtestok = is_mtestok if is_mtestok: - WpmServies.update_plan_state_by_mtestok(obj.subproduction_plan.production_plan) + WpmServies.update_plan_state_by_mtestok( + obj.subproduction_plan.production_plan) obj.save() change_str = 'mtest_notok' if is_mtestok: @@ -454,7 +420,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): WpmServies.add_wproduct_flow_log(instance=obj, change_str=change_str) return Response() - @action(methods=['get'], detail=True, perms_map={'get':'*'}) + @action(methods=['get'], detail=True, perms_map={'get': '*'}) def card(self, request, pk=None): """ 流程卡 @@ -469,35 +435,40 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): ret.append(line1) steps_list_full_1 = card_data['parents'][0]['step_list_full'] for index, item in enumerate(steps_list_full_1): - linex = [str(index+1), item['step_name']] + linex = [str(index + 1), item['step_name']] for i in card_data['parents']: linex.append(i['step_list_full'][index]['actions']) ret.append(linex) ret.append(['序号', '工序', card_data['number']]) step_list_full = card_data['step_list_full'] for index, item in enumerate(step_list_full): - ret.append([str(index+1), item['step_name'], item['actions']]) + ret.append([str(index + 1), item['step_name'], item['actions']]) return Response(ret) + class WproductTicketViewSet(ListModelMixin, GenericViewSet): """ 玻璃审批工单 """ - perms_map={'*':'*'} - queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', - 'resp_process', 'subproduction_plan__production_plan__order', 'subproduction_plan__production_plan') + perms_map = {'*': '*'} + 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'] + filterset_fields = ['step', 'material', + 'subproduction_plan', 'resp_process'] ordering_fields = ['id'] ordering = ['-id'] -class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet): +class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, + GenericViewSet): """ 生产操作记录 """ - perms_map={'*':'*'} - queryset = Operation.objects.select_related('step').prefetch_related('ow_operation', 'oe_operation', 'or_operation').all() + perms_map = {'*': '*'} + queryset = Operation.objects.select_related('step').prefetch_related( + 'ow_operation', 'oe_operation', 'or_operation').all() serializer_class = OperationListSerializer filterset_fields = ['step', 'step__process', 'is_submited'] ordering_fields = ['id'] @@ -537,9 +508,10 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd @transaction.atomic def create(self, request, *args, **kwargs): data = request.data - serializer = OperationCreateSerializer(data=data, context={'request':self.request}) + serializer = OperationCreateSerializer( + data=data, context={'request': self.request}) serializer.is_valid(raise_exception=True) - vdata = serializer.validated_data #校验之后的数据 + vdata = serializer.validated_data # 校验之后的数据 step = vdata['step'] op = Operation() op.step = step @@ -550,9 +522,10 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd # 创建操作所用半成品关联记录 if 'wproducts' in vdata: owps = [] - splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts']) + splans = WpmServies.get_subplans_queryset_from_wproducts( + vdata['wproducts']) for wpd in vdata['wproducts']: - wpd.operation= op + wpd.operation = op wpd.act_state = WProduct.WPR_ACT_STATE_DOING wpd.update_by = request.user wpd.save() @@ -567,9 +540,11 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd owps.append(OperationWproduct(**owp)) OperationWproduct.objects.bulk_create(owps) else: - splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts']) + splans = WpmServies.get_subplans_queryset_from_wproducts( + vdata['wproducts']) # 查询需要填写的自定义表格 - forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO, enabled=True) + forms = RecordForm.objects.filter( + step=step, type=RecordForm.RF_TYPE_DO, enabled=True) for i in forms: opr = OperationRecord() opr.operation = op @@ -591,15 +566,16 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd ope.save() # 查询所需的工具工装 for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, - subproduction__subplan_subprod__in = splans, is_deleted=False).distinct(): + subproduction__subplan_subprod__in=splans, + is_deleted=False).distinct(): opm = OperationMaterial() opm.operation = op opm.material = i.material opm.type = SubprodctionMaterial.SUB_MA_TYPE_TOOL opm.save() return Response() - - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer) + + @action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=serializers.Serializer) @transaction.atomic def submit(self, request, pk=None): """ @@ -609,17 +585,18 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd step = op.step if op.is_submited: raise exceptions.APIException('该操作已提交') - omis = OperationMaterial.objects.filter(operation=op, - type=SubprodctionMaterial.SUB_MA_TYPE_IN) - omos = OperationMaterial.objects.filter(operation=op, - type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + omis = OperationMaterial.objects.filter(operation=op, + type=SubprodctionMaterial.SUB_MA_TYPE_IN) + omos = OperationMaterial.objects.filter(operation=op, + type=SubprodctionMaterial.SUB_MA_TYPE_OUT) # 校验消耗产出是否正确填写 if op.step.type == Step.STEP_TYPE_DIV: sps_omi_l = omis.values_list('subproduction_plan', flat=True) - sps_omo_l = omos.filter(use_scrap=False).values_list('subproduction_plan', flat=True) + sps_omo_l = omos.filter(use_scrap=False).values_list( + 'subproduction_plan', flat=True) if set(list(sps_omi_l)) != set(list(sps_omo_l)): raise exceptions.APIException('消耗与产出不一致') - + # 实际消耗物料校验 # 检查自定义表单填写 @@ -629,18 +606,19 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd for i in omis: # 更新车间物料 i_wmat = i.wmaterial - i_wmat.count = i_wmat.count- i.count + i_wmat.count = i_wmat.count - i.count i_wmat.save() # 更新子计划物料消耗情况 spp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan, - material=i_wmat.material) + material=i_wmat.material) spp.count_real = spp.count_real + i.count spp.save() # 更新产出 for i in omos: if not i.subproduction_progress.is_main: # 更新车间物料产出情况 - ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan, material=i.material) + ins, _ = WMaterial.objects.get_or_create( + subproduction_plan=i.subproduction_plan, material=i.material) ins.count = ins.count + i.count ins.save() # 更新子计划物料产出情况 @@ -659,7 +637,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd wp.step = newstep wp.pre_step = step if hasNext: - wp.act_state= WProduct.WPR_ACT_STATE_DOWAIT + wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT else: wp.act_state = WProduct.WPR_ACT_STATE_TOTEST wp.material = wsp.product @@ -678,23 +656,27 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd raise exceptions.APIException('请选择物料产出') for i in omos: if i.subproduction_progress.is_main: - newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step) + newstep, _ = WpmServies.get_next_step( + i.subproduction_plan, step) wpr = dict(material=i.material, step=newstep, - act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', - subproduction_plan=i.subproduction_plan, - create_by=request.user, coperation=op) + act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', + subproduction_plan=i.subproduction_plan, + create_by=request.user, coperation=op) for x in range(i.count): ins = WProduct.objects.create(**wpr) # 添加日志 - WpmServies.add_wproduct_flow_log(ins, 'wproduct_create') + WpmServies.add_wproduct_flow_log( + ins, 'wproduct_create') # 更新进度 - WpmServies.update_subproduction_progress_main(sp=i.subproduction_plan) + WpmServies.update_subproduction_progress_main( + sp=i.subproduction_plan) elif step.type == Step.STEP_TYPE_COMB: oms_w = omos.filter(subproduction_progress__is_main=True) if len(oms_w) == 1: oms_w = oms_w[0] # 校验单片数量是否正确, 暂时未写 - newstep, hasNext = WpmServies.get_next_step(oms_w.subproduction_plan, step) + newstep, hasNext = WpmServies.get_next_step( + oms_w.subproduction_plan, step) wproduct = WProduct() wproduct.material = oms_w.material wproduct.step = newstep @@ -704,32 +686,34 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd else: wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST # 更新子计划进度 - WpmServies.update_subproduction_progress_main(sp=oms_w.subproduction_plan) + WpmServies.update_subproduction_progress_main( + sp=oms_w.subproduction_plan) wproduct.create_by = request.user wproduct.coperation = op wproduct.save() WpmServies.add_wproduct_flow_log(wproduct, 'wproduct_create') # 隐藏原半成品 - wps = WProduct.objects.filter(ow_wproduct__operation = op) - wps.update(is_hidden=True, child=wproduct, update_by=request.user, update_time=timezone.now()) + wps = WProduct.objects.filter(ow_wproduct__operation=op) + wps.update(is_hidden=True, child=wproduct, + update_by=request.user, update_time=timezone.now()) else: raise exceptions.APIException('产出物料未填写或填写错误') op.is_submited = True op.save() # 如果是冷加工 - if step.process.id==1: + if step.process.id == 1: WpmServies.update_cutting_list_with_operation(op=op) return Response() - class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet): """ 操作使用的半成品 """ - perms_map={'*':'*'} - queryset = OperationWproduct.objects.select_related('subproduction_plan', 'material').all() + perms_map = {'*': '*'} + queryset = OperationWproduct.objects.select_related( + 'subproduction_plan', 'material').all() serializer_class = OperationWproductListSerializer filterset_fields = ['material', 'subproduction_plan', 'operation'] ordering_fields = ['id'] @@ -751,12 +735,14 @@ class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMix wp.save() return Response() + class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet): """ 操作使用的设备 """ - perms_map={'*':'*'} - queryset = OperationEquip.objects.select_related('operation', 'equip').all() + perms_map = {'*': '*'} + queryset = OperationEquip.objects.select_related( + 'operation', 'equip').all() serializer_class = OperationEquipListSerializer filterset_fields = ['operation', 'equip'] ordering_fields = ['id'] @@ -766,7 +752,7 @@ class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, if self.action == 'update': return OperationEquipUpdateSerializer return super().get_serializer_class() - + def update(self, request, *args, **kwargs): instance = self.get_object() if instance.operation.is_submited: @@ -781,12 +767,14 @@ class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, instance.delete() return Response() + class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin, GenericViewSet): """ 操作使用的自定义表格 """ - perms_map={'*':'*'} - queryset = OperationRecord.objects.select_related('operation', 'form').all() + perms_map = {'*': '*'} + queryset = OperationRecord.objects.select_related( + 'operation', 'form').all() serializer_class = OperationRecordListSerializer filterset_class = OperationRecordFilterSet ordering_fields = ['id'] @@ -798,6 +786,7 @@ class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin elif self.action == 'retrieve': return OperationRecordDetailSerializer return super().get_serializer_class() + @transaction.atomic() def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -806,7 +795,6 @@ class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin instance.delete() return Response() - def update(self, request, *args, **kwargs): serializer = OperationRecordSubmitSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -828,8 +816,9 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod """ 消耗物料 """ - perms_map={'*':'*'} - queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN) + perms_map = {'*': '*'} + queryset = OperationMaterial.objects.select_related( + 'operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN) serializer_class = OperationMaterialListSerializer filterset_fields = ['operation', 'subproduction_plan'] ordering_fields = ['id'] @@ -839,8 +828,9 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod if self.action == 'create': return OperationMaterialCreate1Serailizer return super().get_serializer_class() - - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=OperationMaterialCreate1ListSerailizer) + + @action(methods=['post'], detail=False, perms_map={'post': '*'}, + serializer_class=OperationMaterialCreate1ListSerailizer) def creates(self, request, pk=None): """ 批量创建消耗物料 @@ -850,7 +840,6 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod serializer.save() return Response() - @transaction.atomic() def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -859,13 +848,16 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod instance.delete() return Response() + class CuttingListViewSet(ListModelMixin, GenericViewSet): """ 下料清单 """ - perms_map={'*':'*'} - queryset = OperationMaterial.objects.select_related('operation', - 'subproduction_plan', 'material', 'operation__create_by').filter(operation__step__id=1, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + perms_map = {'*': '*'} + queryset = OperationMaterial.objects.select_related('operation', + 'subproduction_plan', 'material', + 'operation__create_by').filter(operation__step__id=1, + type=SubprodctionMaterial.SUB_MA_TYPE_OUT) serializer_class = CuttingListSerializer filterset_class = CuttingFilterSet ordering_fields = ['id'] @@ -876,8 +868,9 @@ class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyMo """ 产出物料 """ - perms_map={'*':'*'} - queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + perms_map = {'*': '*'} + queryset = OperationMaterial.objects.select_related( + 'operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT) serializer_class = OperationMaterialListSerializer filterset_fields = ['operation', 'subproduction_plan'] ordering_fields = ['id'] @@ -887,8 +880,9 @@ class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyMo if self.action == 'create': return OperationMaterialCreate2Serailizer return super().get_serializer_class() - - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=OperationMaterialCreate2ListSerailizer) + + @action(methods=['post'], detail=False, perms_map={'post': '*'}, + serializer_class=OperationMaterialCreate2ListSerailizer) def creates(self, request, pk=None): """ 批量创建产出物料 @@ -906,12 +900,14 @@ class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyMo instance.delete() return Response() + class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): """ 工具工装 """ - perms_map={'*':'*'} - queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL) + perms_map = {'*': '*'} + queryset = OperationMaterial.objects.select_related( + 'operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL) serializer_class = OperationMaterialListSerializer filterset_fields = ['operation', 'subproduction_plan'] ordering_fields = ['id'] @@ -921,7 +917,7 @@ class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyMode if self.action == 'create': return OperationMaterialCreate3Serializer return super().get_serializer_class() - + @transaction.atomic() def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -930,9 +926,11 @@ class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyMode instance.delete() return Response() + class DoFormInit(CreateAPIView, GenericAPIView): - perms_map={'*':'*'} - serializer_class=OperationInitSerializer + perms_map = {'*': '*'} + serializer_class = OperationInitSerializer + def post(self, request, format=None): """ 调用操作表单 @@ -944,24 +942,28 @@ class DoFormInit(CreateAPIView, GenericAPIView): ret = {} ret_0 = {} ret_0['step'] = data['step'] - splans =[] + splans = [] ret_0['input'] = [] # ret_0['subproduction_plan'] = data['subproduction_plan'] if 'wproducts' in data and data['wproducts']: ret_0['wproducts'] = data['wproducts'] - splans = WProduct.objects.filter(id__in=data['wproducts']).values_list('subproduction_plan', flat=True) + splans = WProduct.objects.filter(id__in=data['wproducts']).values_list( + 'subproduction_plan', flat=True) # 调出所属子计划现有物料 - ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data + ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter( + subproduction_plan__in=splans), many=True).data else: if 'subproduction_plan' in vdata: splans = [vdata['subproduction_plan']] else: - splans = SubProductionPlan.objects.filter(is_deleted=False, - subproduction__usedstep_subproduction__step=vdata['step'], state=3) + splans = SubProductionPlan.objects.filter(is_deleted=False, + subproduction__usedstep_subproduction__step=vdata[ + 'step'], + state=3) ret_0['wproducts'] = [] - ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data + ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter( + subproduction_plan__in=splans), many=True).data - for i in ret_0['input']: i['count_input'] = 0 # 需要输出的物料 @@ -969,35 +971,39 @@ class DoFormInit(CreateAPIView, GenericAPIView): # 排除主要产物, 因为已经放到半成品里了, 由半成品进行处理, 夹层可能需要特殊处理 o_objs = SubProductionProgress.objects.filter( subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True) - + else: # 此时显示所有子计划需要输出的物料 o_objs = SubProductionProgress.objects.filter( subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) - ret_0['output'] = list(o_objs.values('subproduction_plan', 'material', 'material__name', 'material__number')) + ret_0['output'] = list(o_objs.values( + 'subproduction_plan', 'material', 'material__name', 'material__number')) for i in ret_0['output']: - i['count_output']=0 + i['count_output'] = 0 ret['forms'] = [] ret_0['id'] = 0 ret_0['name'] = '基本信息' # 查询工具工装 - ret_0['tools'] = SubprodctionMaterialListSerializer(instance= - SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, - subproduction__subplan_subprod__in = splans), many=True).data + ret_0['tools'] = SubprodctionMaterialListSerializer( + instance=SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, + subproduction__subplan_subprod__in=splans), many=True).data # 查询技术文档 - ret_0['techdocs'] = TechDocListSerializer(instance = - TechDoc.objects.filter(subproduction__subplan_subprod__in = splans, enabled=True)\ + ret_0['techdocs'] = TechDocListSerializer( + instance=TechDoc.objects.filter( + subproduction__subplan_subprod__in=splans, enabled=True) .distinct(), many=True).data ret['forms'].append(ret_0) - forms = RecordForm.objects.filter(step=vdata['step'], type=RecordForm.RF_TYPE_DO) + forms = RecordForm.objects.filter( + step=vdata['step'], type=RecordForm.RF_TYPE_DO) if forms.exists(): - ret['forms'].extend(RecordFormDetailSerializer(instance=forms, many=True).data) + ret['forms'].extend(RecordFormDetailSerializer( + instance=forms, many=True).data) return Response(ret) class DoFormSubmit(CreateAPIView, GenericAPIView): - perms_map={'*':'*'} + perms_map = {'*': '*'} serializer_class = OperationSubmitSerializer @transaction.atomic @@ -1006,18 +1012,19 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): 提交操作表单 """ data = request.data - serializer = OperationSubmitSerializer(data=data, context={'request':self.request}) + serializer = OperationSubmitSerializer( + data=data, context={'request': self.request}) serializer.is_valid(raise_exception=True) - vdata = serializer.validated_data #校验之后的数据 + vdata = serializer.validated_data # 校验之后的数据 # 创建一个生产操作记录 action_obj = Operation() action_obj.step = vdata['step'] - action_obj.remark = vdata.get('remark', '') # 操作备注 + action_obj.remark = vdata.get('remark', '') # 操作备注 action_obj.create_by = request.user action_obj.use_scrap = vdata.get('use_scrap', False) action_obj.save() - + # 保存关联半成品 if 'wproducts' in data and data['wproducts']: owps = [] @@ -1034,45 +1041,46 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): # 保存物料消耗 for i in vdata['input']: - if i['count_input']: #如果有消耗 + if i['count_input']: # 如果有消耗 i_wmat = i['id'] OperationMaterial.objects.create(type=1, operation=action_obj, - wmaterial= i_wmat, count=i['count_input']) + wmaterial=i_wmat, count=i['count_input']) # 更新车间物料 - i_wmat.count = i_wmat.count- i['count_input'] + i_wmat.count = i_wmat.count - i['count_input'] i_wmat.save() # 更新子计划物料消耗情况 sp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan, - material=i_wmat.material) + material=i_wmat.material) sp.count_real = sp.count_real + i['count_input'] sp.save() - + # 物料产出 if 'output' in data and data['output']: - for i in vdata['output']: # 已经序列化好的数据 + for i in vdata['output']: # 已经序列化好的数据 ma = i['material'] - if i['subproduction_plan'].product == ma: # 如果是该计划主产物 + if i['subproduction_plan'].product == ma: # 如果是该计划主产物 # 如果是切割 # 获取下一步子工序 if vdata['step'].type == Step.STEP_TYPE_DIV: - newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step']) + newstep, _ = WpmServies.get_next_step( + i['subproduction_plan'], vdata['step']) wpr = dict(material=ma, step=newstep, - act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', - subproduction_plan=i['subproduction_plan']) + act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='', + subproduction_plan=i['subproduction_plan']) for x in range(i['count_output']): WProduct.objects.create(**wpr) else: # 更新操作产出物料表 OperationMaterial.objects.create(type=2, operation=action_obj, - material= ma, count=i['count_output']) + material=ma, count=i['count_output']) # 更新车间物料表 ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i['subproduction_plan'], - material=ma) + material=ma) ins.count = ins.count + i['count_output'] ins.save() # 更新子计划进度表 sp = SubProductionProgress.objects.get(subproduction_plan=i['subproduction_plan'], - material=ma) + material=ma) sp.count_real = sp.count_real + i['count_input'] sp.save() @@ -1081,31 +1089,33 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): if vdata['step'].type == Step.STEP_TYPE_COMB: wproducts = vdata['wproducts'] if 'suproduction_plan' in vdata: - wproducts.update(is_hidden=True) # 隐藏 - newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step']) + wproducts.update(is_hidden=True) # 隐藏 + newstep, hasNext = WpmServies.get_next_step( + i['subproduction_plan'], vdata['step']) wproduct = WProduct() wproduct.material = vdata['subproduction_plan'].product wproduct.step = newstep - wproduct.subproduction_plan=vdata['subproduction_plan'] + wproduct.subproduction_plan = vdata['subproduction_plan'] wproduct.parent = data['wproducts'] if hasNext: - wproduct.act_state=WProduct.WPR_ACT_STATE_DOWAIT + wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT else: - wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST + wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST wproduct.save() else: raise exceptions.APIException('请指定子计划') else: for wproduct in vdata['wproducts']: # 获取下一步子工序 - newstep, hasNext = WpmServies.get_next_step(wproduct.subproduction_plan, vdata['step']) + newstep, hasNext = WpmServies.get_next_step( + wproduct.subproduction_plan, vdata['step']) wproduct.step = newstep - wproduct.pre_step=vdata['step'] + wproduct.pre_step = vdata['step'] if hasNext: - wproduct.act_state=WProduct.WPR_ACT_STATE_DOWAIT + wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT else: - wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST - wproduct.material=wproduct.subproduction_plan.product + wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST + wproduct.material = wproduct.subproduction_plan.product wproduct.save() # 保存自定义表单结果 @@ -1116,7 +1126,7 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): wr.operation = action_obj wr.save() wrds = [] - for m in i['record_data']: # 保存记录详情 + for m in i['record_data']: # 保存记录详情 form_field = m['form_field'] m['field_name'] = form_field.field_name m['field_key'] = form_field.field_key @@ -1127,5 +1137,3 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): wrds.append(OperationRecordItem(**m)) OperationRecordItem.objects.bulk_create(wrds) return Response() - - \ No newline at end of file From 09a3581dcabf981141c19cc30697efe2a6bb3d27 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:15:40 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E6=89=B9=E9=87=8F=E5=85=A5=E5=BA=93remar?= =?UTF-8?q?k=E9=9D=9E=E5=BF=85=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index d9f09dd..5889aa4 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -418,12 +418,12 @@ class WplanPutInSerializer(serializers.Serializer): class WproductPutInSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") - remark = serializers.CharField(label="入库备注", required =False, default="") + remark = serializers.CharField(label="入库备注", required=False, allow_blank=True) class WproductPutInsSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID', many=True) - remark = serializers.CharField(label="入库备注", required =False, default="") + remark = serializers.CharField(label="入库备注", required=False, allow_blank=True) class OperationEquipListSerializer(serializers.Serializer): From 783a778d710b2ed9122c03f242e7ecaf7c4a7249 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:19:22 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=B6=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=8A=B6=E6=80=81=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/em/serializers.py | 2 +- hb_server/apps/inm/models.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index 677383b..be34bfc 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -27,7 +27,7 @@ class EquipmentSerializer(ModelSerializer): class EquipmentSimpleSerializer(ModelSerializer): class Meta: model = Equipment - fields = ['id', 'number', 'name'] + fields = ['id', 'number', 'name', 'state'] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index 0fe74a4..21105c0 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -84,7 +84,6 @@ class FIFOItem(BaseModel): """ 出入库详细条目 """ - need_test = models.BooleanField('是否需要检验', default=False) is_tested = models.BooleanField('是否已检验', default=False) is_testok = models.BooleanField('是否检验合格', default=False) warehouse = models.ForeignKey( From 62bd7423db07f90c7bfc8ad1f3650a43ccbab0a4 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:28:04 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E9=87=87=E8=B4=AD=E5=85=A5=E5=BA=93?= =?UTF-8?q?=E4=B8=8D=E9=9C=80=E8=A6=81=E5=A1=AB=E5=86=99=E5=85=A5=E5=BA=93?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/serializers.py | 54 ++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index a05e3c1..32abb80 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -1,78 +1,95 @@ from rest_framework import serializers -from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse,Inventory +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse, Inventory from apps.qm.models import TestRecord, TestRecordItem from apps.system.serializers import UserSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer from django.db import transaction -class WareHouseSerializer(serializers. ModelSerializer): - create_by_=UserSimpleSerializer('create_by', read_only=True) + +class WareHouseSerializer(serializers.ModelSerializer): + create_by_ = UserSimpleSerializer('create_by', read_only=True) + class Meta: model = WareHouse fields = '__all__' + class WareHouseCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = WareHouse fields = ['name', 'number', 'place'] + class WareHouseSimpleSerializer(serializers.ModelSerializer): class Meta: model = WareHouse fields = ['name', 'number', 'place'] -class InventorySerializer(serializers. ModelSerializer): - material_= MaterialSimpleSerializer(source='material', read_only=True) + +class InventorySerializer(serializers.ModelSerializer): + material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) + class Meta: model = Inventory fields = '__all__' -class MaterialBatchSerializer(serializers. ModelSerializer): - material_= MaterialSimpleSerializer(source='material', read_only=True) + +class MaterialBatchSerializer(serializers.ModelSerializer): + material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) + class Meta: model = MaterialBatch fields = '__all__' + class IProductListSerializer(serializers.ModelSerializer): - material_= MaterialSimpleSerializer(source='material', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) is_mtested = serializers.BooleanField(source='wproduct.is_mtested', read_only=True) is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True) remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True) + class Meta: model = IProduct fields = '__all__' - + class FIFOListSerializer(serializers.ModelSerializer): auditor_ = UserSimpleSerializer(source='auditor', read_only=True) create_by_ = UserSimpleSerializer(source='create_by', read_only=True) + class Meta: - model=FIFO + model = FIFO fields = '__all__' + class FIFOItemSerializer(serializers.ModelSerializer): warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) - material_= MaterialSimpleSerializer(source='material', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) + class Meta: - model= FIFOItem + model = FIFOItem fields = '__all__' + class IProductInPurSerializer(serializers.ModelSerializer): class Meta: model = IProduct fields = ['number'] - + + class FIFODetailInPurSerializer(serializers.ModelSerializer): details = IProductInPurSerializer(many=True, required=False) + class Meta: model = FIFOItem fields = ['material', 'count', 'batch', 'details', 'warehouse'] + class MaterialBatchQuerySerializer(serializers.Serializer): warehouse = serializers.IntegerField(label="仓库ID", required=False) materials = serializers.ListField(child=serializers.IntegerField(label="物料ID"), required=False) @@ -83,13 +100,14 @@ class FIFOInPurSerializer(serializers.ModelSerializer): 采购入库序列化 """ details = FIFODetailInPurSerializer(many=True) + class Meta: model = FIFO - fields = ['details', 'inout_date'] + fields = ['details'] def create(self, validated_data): details = validated_data.pop('details') - if len(details)>0: + if len(details) > 0: pass else: raise serializers.ValidationError('没有入库内容') @@ -103,7 +121,7 @@ class FIFOInPurSerializer(serializers.ModelSerializer): # raise serializers.ValidationError('批次号{}在其他仓库已存在'.format(i['batch'])) # except: # pass - + # 创建采购入库 with transaction.atomic(): validated_data['type'] = FIFO.FIFO_TYPE_PUR_IN @@ -137,17 +155,17 @@ class FIFOInPurSerializer(serializers.ModelSerializer): return obj - class InmTestRecordItemCreateSerializer(serializers.ModelSerializer): class Meta: model = TestRecordItem fields = ['form_field', 'field_value', 'is_testok'] + class InmTestRecordCreateSerializer(serializers.ModelSerializer): record_data = InmTestRecordItemCreateSerializer(many=True) fifo_item = serializers.PrimaryKeyRelatedField(queryset=FIFOItem.objects.all(), required=True) is_testok = serializers.BooleanField() + class Meta: model = TestRecord fields = ['form', 'record_data', 'is_testok', 'fifo_item'] - From 490440cad3d49b409f4e53f89c3c8df728996955 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:32:41 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0026_alter_fifo_inout_date.py | 18 ++++++++++++++++++ hb_server/apps/inm/models.py | 2 +- hb_server/apps/inm/views.py | 7 +++++-- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 hb_server/apps/inm/migrations/0026_alter_fifo_inout_date.py diff --git a/hb_server/apps/inm/migrations/0026_alter_fifo_inout_date.py b/hb_server/apps/inm/migrations/0026_alter_fifo_inout_date.py new file mode 100644 index 0000000..f086ed3 --- /dev/null +++ b/hb_server/apps/inm/migrations/0026_alter_fifo_inout_date.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-14 07:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inm', '0025_auto_20220113_0932'), + ] + + operations = [ + migrations.AlterField( + model_name='fifo', + name='inout_date', + field=models.DateField(blank=True, null=True, verbose_name='出入库日期'), + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index 21105c0..6d179f6 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -76,7 +76,7 @@ class FIFO(CommonADModel): is_audited = models.BooleanField('是否审核', default=False) auditor = models.ForeignKey( User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True) - inout_date = models.DateField('出入库日期') + inout_date = models.DateField('出入库日期', null=True, blank=True) remark = models.CharField('备注', max_length=1000, default='') diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 2b3af52..0aa9d0f 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -7,7 +7,9 @@ from rest_framework.viewsets import GenericViewSet, ModelViewSet from apps.inm.filters import IProductFilterSet, MbFilterSet from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse, Inventory -from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer, InventorySerializer +from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, \ + InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, \ + WareHouseCreateUpdateSerializer, InventorySerializer from apps.inm.signals import update_inm from apps.mtm.models import Material from apps.pm.services import PmService @@ -20,6 +22,7 @@ from django.utils import timezone from apps.wpm.services import WpmServies + # Create your views here. @@ -173,7 +176,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): with transaction.atomic(): obj.is_audited = True obj.auditor = request.user - obj.inout_date = timezone.now() # 也是审核日期 + obj.inout_date = timezone.now() # 也是审核日期 obj.save() update_inm(obj) # 更新库存 return Response() From 75ff28535a8ebe5d4956ca6d1832a0f0a9948c50 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 15:51:35 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E5=87=BA=E5=85=A5=E5=BA=93=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0need=5Ftest=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/filters.py | 11 ++++--- .../inm/migrations/0027_auto_20220114_1551.py | 33 +++++++++++++++++++ hb_server/apps/inm/models.py | 5 +-- hb_server/apps/inm/views.py | 11 ++----- hb_server/apps/sam/views.py | 3 +- hb_server/apps/wpm/serializers.py | 1 - hb_server/apps/wpm/views.py | 4 --- 7 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 hb_server/apps/inm/migrations/0027_auto_20220114_1551.py diff --git a/hb_server/apps/inm/filters.py b/hb_server/apps/inm/filters.py index c6beb53..db876ec 100644 --- a/hb_server/apps/inm/filters.py +++ b/hb_server/apps/inm/filters.py @@ -3,22 +3,25 @@ from django_filters import rest_framework as filters from apps.mtm.models import Material from .models import IProduct, MaterialBatch from django.utils import timezone + + class MbFilterSet(filters.FilterSet): material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all()) tag = filters.CharFilter(method="filter_tag") + class Meta: model = MaterialBatch fields = ['material', 'warehouse'] - + def filter_tag(self, queryset, name, value): if value == 'expired': - queryset = queryset.exclude(expiration_date=None).filter(expiration_date__lte = timezone.now()) + queryset = queryset.exclude(expiration_date=None).filter(expiration_date__lte=timezone.now()) return queryset class IProductFilterSet(filters.FilterSet): - order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order") + class Meta: model = IProduct - fields = ['material', 'warehouse', 'batch', 'order', 'material__type'] \ No newline at end of file + fields = ['material', 'warehouse', 'batch', 'order', 'material__type'] diff --git a/hb_server/apps/inm/migrations/0027_auto_20220114_1551.py b/hb_server/apps/inm/migrations/0027_auto_20220114_1551.py new file mode 100644 index 0000000..5f0ea85 --- /dev/null +++ b/hb_server/apps/inm/migrations/0027_auto_20220114_1551.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.9 on 2022-01-14 07:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0003_auto_20210812_0909'), + ('inm', '0026_alter_fifo_inout_date'), + ] + + operations = [ + migrations.RemoveField( + model_name='fifoitem', + name='is_tested', + ), + migrations.AddField( + model_name='fifoitem', + name='files', + field=models.ManyToManyField(to='system.File', verbose_name='上传材料'), + ), + migrations.AddField( + model_name='fifoitem', + name='need_test', + field=models.BooleanField(default=False, verbose_name='是否需要复验'), + ), + migrations.AlterField( + model_name='fifoitem', + name='is_testok', + field=models.BooleanField(blank=True, null=True, verbose_name='是否复验合格'), + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index 6d179f6..af1b84a 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -84,8 +84,8 @@ class FIFOItem(BaseModel): """ 出入库详细条目 """ - is_tested = models.BooleanField('是否已检验', default=False) - is_testok = models.BooleanField('是否检验合格', default=False) + need_test = models.BooleanField('是否需要复验', default=False) + is_testok = models.BooleanField('是否复验合格', null=True, blank=True) warehouse = models.ForeignKey( WareHouse, on_delete=models.CASCADE, verbose_name='仓库') material = models.ForeignKey( @@ -96,6 +96,7 @@ class FIFOItem(BaseModel): on_delete=models.CASCADE) subproduction_plan = models.ForeignKey( SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True) + files = models.ManyToManyField(File, verbose_name='上传材料') class IProduct(BaseModel): diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 0aa9d0f..d36b6ec 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -1,8 +1,7 @@ -from django.shortcuts import render from rest_framework import serializers from rest_framework import exceptions from rest_framework.exceptions import APIException -from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveModelMixin +from rest_framework.mixins import DestroyModelMixin, ListModelMixin from rest_framework.viewsets import GenericViewSet, ModelViewSet from apps.inm.filters import IProductFilterSet, MbFilterSet @@ -11,17 +10,13 @@ from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOLi InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, \ WareHouseCreateUpdateSerializer, InventorySerializer from apps.inm.signals import update_inm -from apps.mtm.models import Material -from apps.pm.services import PmService from apps.qm.models import TestRecordItem -from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin +from apps.system.mixins import CreateUpdateModelAMixin from rest_framework.decorators import action from rest_framework.response import Response from django.db import transaction from django.utils import timezone -from apps.wpm.services import WpmServies - # Create your views here. @@ -168,7 +163,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): 审核通过 """ obj = self.get_object() - for i in FIFOItem.objects.filter(fifo=obj): + for i in FIFOItem.objects.filter(fifo=obj, need_test=True): if not i.is_testok: raise APIException('未检验通过, 不可审核') if obj.is_audited: diff --git a/hb_server/apps/sam/views.py b/hb_server/apps/sam/views.py index 62fd081..a239d8e 100644 --- a/hb_server/apps/sam/views.py +++ b/hb_server/apps/sam/views.py @@ -150,8 +150,7 @@ class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, C warehouse = WareHouse.objects.get(id=i['warehouse']) material = Material.objects.get(id=i['material']) fifoitem = FIFOItem() - fifoitem.is_tested = True - fifoitem.is_testok = True + fifoitem.need_test = False fifoitem.warehouse = warehouse fifoitem.material = material fifoitem.count = i['total'] diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 5889aa4..8956eb3 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -69,7 +69,6 @@ class PickSerializer(serializers.Serializer): if isLowLevel: iproducts = i.pop('iproducts') i['fifo'] = fifo - i['is_testok'] = True # 默认检验合格 i['subproduction_plan'] = sp fifoitem = FIFOItem.objects.create(**i) # 创建再下一个层级 diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 0920983..28d8a12 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -248,8 +248,6 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): for i in wproducts_a: spi = SubProductionPlan.objects.get(pk=i['subproduction_plan']) fifoitem = FIFOItem() - fifoitem.is_tested = True - fifoitem.is_testok = True fifoitem.warehouse = warehouse fifoitem.material = Material.objects.get(pk=i['material']) fifoitem.count = i['total'] @@ -303,8 +301,6 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): create_by=request.user, remark=remark) # 创建入库明细 fifoitem = FIFOItem() - fifoitem.is_tested = True - fifoitem.is_testok = True fifoitem.warehouse = warehouse fifoitem.material = material fifoitem.count = 1 # 单个半成品入库 From 4257741c2d8f71be4477ac56ebd600d217ffa034 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 14 Jan 2022 16:34:20 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E9=87=87=E8=B4=AD=E8=AE=B0=E5=BD=95need?= =?UTF-8?q?=5Ftest=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/develop/urls.py | 6 ++++-- hb_server/apps/develop/views.py | 20 ++++++++++++++++++- .../migrations/0028_alter_fifoitem_files.py | 19 ++++++++++++++++++ hb_server/apps/inm/models.py | 2 +- hb_server/apps/inm/serializers.py | 17 ++++++++++++++++ hb_server/apps/inm/views.py | 14 ++++++++----- 6 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 hb_server/apps/inm/migrations/0028_alter_fifoitem_files.py diff --git a/hb_server/apps/develop/urls.py b/hb_server/apps/develop/urls.py index 8f6e395..b284243 100644 --- a/hb_server/apps/develop/urls.py +++ b/hb_server/apps/develop/urls.py @@ -2,11 +2,13 @@ from django.db.models import base from rest_framework import urlpatterns from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateLastTestResult +from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult urlpatterns = [ path('cleandata/', CleanDataView.as_view()), path('update_cutting/', UpdateCuttingView.as_view()), - path('update_last_result/', UpdateLastTestResult.as_view()) + path('update_last_result/', UpdateLastTestResult.as_view()), + path('update_last_result/', UpdateLastTestResult.as_view()), + path('update_fifoitem/', UpdateFIFOItem.as_view()) ] diff --git a/hb_server/apps/develop/views.py b/hb_server/apps/develop/views.py index 7ca4ca8..f02f55f 100644 --- a/hb_server/apps/develop/views.py +++ b/hb_server/apps/develop/views.py @@ -4,7 +4,7 @@ from rest_framework.decorators import permission_classes from rest_framework.views import APIView from rest_framework.permissions import IsAdminUser from rest_framework.response import Response -from apps.inm.models import FIFO, Inventory, MaterialBatch +from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch from apps.mtm.models import Material from apps.pm.models import ProductionPlan from apps.sam.models import Order @@ -62,3 +62,21 @@ class UpdateLastTestResult(APIView): i.last_test_result = tr.is_testok i.save() return Response() + +class UpdateFIFOItem(APIView): + + permission_classes = [IsAdminUser] + @transaction.atomic + def post(self, request, format=None): + """ + 更新出入库结果 + """ + for i in FIFOItem.objects.all(): + if i.fifo.type == FIFO.FIFO_TYPE_PUR_IN: + if i.is_testok: + i.need_test = True + i.save() + else: + i.is_testok = None + i.save() + return Response() diff --git a/hb_server/apps/inm/migrations/0028_alter_fifoitem_files.py b/hb_server/apps/inm/migrations/0028_alter_fifoitem_files.py new file mode 100644 index 0000000..df29017 --- /dev/null +++ b/hb_server/apps/inm/migrations/0028_alter_fifoitem_files.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.9 on 2022-01-14 08:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0003_auto_20210812_0909'), + ('inm', '0027_auto_20220114_1551'), + ] + + operations = [ + migrations.AlterField( + model_name='fifoitem', + name='files', + field=models.ManyToManyField(blank=True, to='system.File', verbose_name='上传材料'), + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index af1b84a..ee9d786 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -96,7 +96,7 @@ class FIFOItem(BaseModel): on_delete=models.CASCADE) subproduction_plan = models.ForeignKey( SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True) - files = models.ManyToManyField(File, verbose_name='上传材料') + files = models.ManyToManyField(File, verbose_name='上传材料', blank=True) class IProduct(BaseModel): diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index 32abb80..34d26f4 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -1,3 +1,4 @@ +from rest_framework import exceptions from rest_framework import serializers from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse, Inventory @@ -169,3 +170,19 @@ class InmTestRecordCreateSerializer(serializers.ModelSerializer): class Meta: model = TestRecord fields = ['form', 'record_data', 'is_testok', 'fifo_item'] + + + +class FIFOItemUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = FIFOItem + fields = ['need_test', 'files'] + + def validate(self, attrs): + ins = self.instance + fifo = ins.fifo + if fifo.is_audited: + raise exceptions.APIException('该记录已审核') + if ins.is_testok is not None: + attrs.pop('need_test') + return super().validate(attrs) \ No newline at end of file diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index d36b6ec..932a1d1 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -1,12 +1,12 @@ from rest_framework import serializers from rest_framework import exceptions from rest_framework.exceptions import APIException -from rest_framework.mixins import DestroyModelMixin, ListModelMixin +from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin from rest_framework.viewsets import GenericViewSet, ModelViewSet from apps.inm.filters import IProductFilterSet, MbFilterSet from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse, Inventory -from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, \ +from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOItemUpdateSerializer, FIFOListSerializer, IProductListSerializer, \ InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, \ WareHouseCreateUpdateSerializer, InventorySerializer from apps.inm.signals import update_inm @@ -77,7 +77,7 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet): return Response(MaterialBatchSerializer(instance=queryset, many=True).data) -class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): +class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet): """ 出入库记录详情表 """ @@ -85,11 +85,16 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): queryset = FIFOItem.objects.select_related('material', 'fifo').all() serializer_class = FIFOItemSerializer filterset_fields = ['material', 'fifo', - 'fifo__type', 'is_tested', 'is_testok'] + 'fifo__type', 'need_test', 'is_testok'] search_fields = [] ordering_fields = ['create_time'] ordering = ['-create_time'] + def get_serializer_class(self): + if self.action == 'update': + return FIFOItemUpdateSerializer + return super().get_serializer_class() + def perform_destroy(self, instance): if instance.fifo.is_audited: raise APIException('该出入库记录已通过审核, 无法删除') @@ -119,7 +124,6 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): # 如果检验合格 if obj.fifo_item: obj.fifo_item.is_testok = True if obj.is_testok else False - obj.fifo_item.is_tested = True obj.fifo_item.save() return Response() From b7b32b2320bbd16a82c6c3eb8572f743efd7d816 Mon Sep 17 00:00:00 2001 From: shilixia <2309368887@qq.com> Date: Fri, 14 Jan 2022 16:46:04 +0800 Subject: [PATCH 08/11] xiugai --- hb_client/src/router/index.js | 2 +- hb_client/src/views/inm/fifo.vue | 20 ++-- hb_client/src/views/pm/plan.vue | 1 + hb_client/src/views/pm/plandetails.vue | 121 +++++++++++++++++++--- hb_client/src/views/pm/work.vue | 7 +- hb_client/src/views/qm/producttest.vue | 4 +- hb_client/src/views/qm/taskdetails.vue | 2 +- hb_client/src/views/qm/taskrecordfrom.vue | 2 +- hb_client/src/views/wpm/operation.vue | 2 +- hb_client/src/views/wpm/operationdo.vue | 27 ++++- 10 files changed, 145 insertions(+), 43 deletions(-) diff --git a/hb_client/src/router/index.js b/hb_client/src/router/index.js index d794671..f849876 100644 --- a/hb_client/src/router/index.js +++ b/hb_client/src/router/index.js @@ -348,7 +348,7 @@ export const asyncRoutes = [ component: Layout, redirect: '/qm/product', name: 'qm', - meta: { title: '质量管理', icon: 'example', perms: ['equipment_set'] }, + meta: { title: '检验管理', icon: 'example', perms: ['equipment_set'] }, children: [ { path: 'product', diff --git a/hb_client/src/views/inm/fifo.vue b/hb_client/src/views/inm/fifo.vue index 1225521..f5f6982 100644 --- a/hb_client/src/views/inm/fifo.vue +++ b/hb_client/src/views/inm/fifo.vue @@ -100,6 +100,7 @@ - - - - +
- + - + - + - + { this.$refs["Form"].resetFields(); + this.value1=""; }); }, diff --git a/hb_client/src/views/pm/plandetails.vue b/hb_client/src/views/pm/plandetails.vue index b0499d3..fdcf322 100644 --- a/hb_client/src/views/pm/plandetails.vue +++ b/hb_client/src/views/pm/plandetails.vue @@ -75,7 +75,7 @@ - + + + + + @@ -123,12 +137,14 @@ import { getProductionplan,getsubproductionplanList } from "@/api/pm"; import { getwproductList,getrecordList} from "@/api/wpm"; import checkPermission from "@/utils/permission"; +import customForm from '@/components/customForm/index' +import {getrffieldList} from "@/api/mtm"; -import {getTestRecord} from "@/api/qm"; +import { getTestRecord ,getTestRecordItem} from "@/api/qm"; import Pagination from "@/components/Pagination"; // secondary package based on el-pagination - +const defaultrecordform = {enabled:false}; export default { - components: { Pagination }, + components: { Pagination,customForm }, data() { return { productionplan:{ @@ -136,6 +152,7 @@ export default { }, activeName:"1", wproduct:[], + recordList:[], limitedCheckRecord:false, listQuery: { page: 1, @@ -162,6 +179,30 @@ export default { }, process_json:null, productionplanID:null, + dialogVisibleForm: false, + tableForm:{ + name:'', + }, + + recordform: defaultrecordform, + dialogType: "new", + dialogVisible: false, + dialogType1: "new", + dialogVisible1: false, + tableForm: defaultrecordform, + checkForm: { + hhh: '', + }, + + recordVisible: false, + customfieldList: [], + recordform: null, + recordId: null, + fifo_detail: "", + formName: "项目检查表", + hasPicture: false, + fieldList: [], + }; }, computed: {}, @@ -217,10 +258,56 @@ export default { this.limitedCheckRecord=true; getrecordList({wproduct: scope.row.id,page:0}).then(res => { if (res.code == 200) { - that.recordList = res.data.results; + this.recordList = res.data; } }) - } + }, + + //点击记录里的查看 + handleRecordDetail(scope) { + let that = this; + that.recordVisible = false; + that.recordId = scope.row.id; + that.recordform = scope.row.form; + that.formName = scope.row.form_.name; + getrffieldList({ form: this.recordform, page: 1, page_size: 100 }).then( + (response) => { + if (response.data) { + that.hasPicture = false; + let fieldList = response.data.results; + that.fieldList = [...fieldList]; + let arr = fieldList.filter((item) => { + return item.field_type === "draw"; + }); + if (arr.length > 0) { + that.hasPicture = true; + } + getTestRecordItem(scope.row.id).then((res) => { + let arr = []; + let fieldList = res.data.record_data; + for (let i = 0; i < that.fieldList.length; i++) { + let obj = that.fieldList[i]; + obj.is_testok = null; + for (let j = 0; j < fieldList.length; j++) { + if (that.fieldList[i].field_key === fieldList[j].field_key) { + obj.id = fieldList[j].id; + obj.is_testok = fieldList[j].is_testok; + obj.field_value = fieldList[j].field_value; + } + } + arr.push(obj); + } + that.fieldList = arr; + that.$nextTick(() => { + that.isDisabled = true; + that.recordVisible = true; + }); + }); + } + } + ); + }, + }, }; diff --git a/hb_client/src/views/pm/work.vue b/hb_client/src/views/pm/work.vue index 666212f..c80ed45 100644 --- a/hb_client/src/views/pm/work.vue +++ b/hb_client/src/views/pm/work.vue @@ -165,7 +165,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -309,7 +309,8 @@ export default { { this.xhwl.push(item); } - else{ + else if(item.type==2) + { this.ccwl.push(item); } diff --git a/hb_client/src/views/qm/producttest.vue b/hb_client/src/views/qm/producttest.vue index 6ad92aa..4e858c8 100644 --- a/hb_client/src/views/qm/producttest.vue +++ b/hb_client/src/views/qm/producttest.vue @@ -153,14 +153,12 @@ import { getfifodetailList } from "@/api/inm"; import checkPermission from "@/utils/permission"; import { mtest,getwproductList } from "@/api/wpm"; - - import customForm from '@/components/customForm/index'; import { getrecordformList, getrffieldList} from "@/api/mtm"; import {getTestRecord,getTestRecordItem} from "@/api/qm"; import Pagination from "@/components/Pagination"; // secondary package based on el-pagination export default { - components: { Pagination,customForm }, + components: { Pagination }, data() { return { wproductList: { diff --git a/hb_client/src/views/qm/taskdetails.vue b/hb_client/src/views/qm/taskdetails.vue index 61ea1d3..37a1a93 100644 --- a/hb_client/src/views/qm/taskdetails.vue +++ b/hb_client/src/views/qm/taskdetails.vue @@ -6,7 +6,7 @@ {{productionplan.product_.name}} {{productionplan.product_.specification}} {{state_[productionplan.state]}} - 不合格数没有 + {{productionplan.count_notok}}
diff --git a/hb_client/src/views/qm/taskrecordfrom.vue b/hb_client/src/views/qm/taskrecordfrom.vue index fec8201..83a6aa4 100644 --- a/hb_client/src/views/qm/taskrecordfrom.vue +++ b/hb_client/src/views/qm/taskrecordfrom.vue @@ -6,7 +6,7 @@ {{productionplan.product_.name}} {{productionplan.product_.specification}} {{state_[productionplan.state]}} - 不合格数没有 + {{productionplan.count_notok}} {{wproductnumber}} {{process}} diff --git a/hb_client/src/views/wpm/operation.vue b/hb_client/src/views/wpm/operation.vue index cc8d5f8..37671c8 100644 --- a/hb_client/src/views/wpm/operation.vue +++ b/hb_client/src/views/wpm/operation.vue @@ -136,7 +136,7 @@ export default { handleoperation(scope) { - this.$router.push({name: "operationdo", params: { id: scope.row.id,submited:scope.row.is_submited }, }) + this.$router.push({name: "operationdo", params: { id: scope.row.id}, }) }, //大工序工序渲染 getProcessList() { diff --git a/hb_client/src/views/wpm/operationdo.vue b/hb_client/src/views/wpm/operationdo.vue index bbf317f..d6806ca 100644 --- a/hb_client/src/views/wpm/operationdo.vue +++ b/hb_client/src/views/wpm/operationdo.vue @@ -132,6 +132,23 @@ + + + +