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

This commit is contained in:
shijing 2022-01-20 15:45:38 +08:00
commit 9df7d39e05
31 changed files with 500 additions and 106 deletions

1
.gitignore vendored
View File

@ -4,4 +4,5 @@ deploy.sh
package-lock.json package-lock.json
.idea/ .idea/
.vscode/ .vscode/
.idea/
server/static/ server/static/

View File

@ -2,13 +2,14 @@ from django.db.models import base
from rest_framework import urlpatterns from rest_framework import urlpatterns
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult, UpdateSpg
urlpatterns = [ urlpatterns = [
path('cleandata/', CleanDataView.as_view()), path('cleandata/', CleanDataView.as_view()),
path('update_cutting/', UpdateCuttingView.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_last_result/', UpdateLastTestResult.as_view()),
path('update_fifoitem/', UpdateFIFOItem.as_view()) path('update_fifoitem/', UpdateFIFOItem.as_view()),
path('update_spg/', UpdateSpg.as_view())
] ]

View File

@ -6,7 +6,7 @@ from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response from rest_framework.response import Response
from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch
from apps.mtm.models import Material from apps.mtm.models import Material
from apps.pm.models import ProductionPlan from apps.pm.models import ProductionPlan, SubProductionPlan
from apps.sam.models import Order from apps.sam.models import Order
from apps.wf.models import Ticket from apps.wf.models import Ticket
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
@ -80,3 +80,14 @@ class UpdateFIFOItem(APIView):
i.is_testok = None i.is_testok = None
i.save() i.save()
return Response() return Response()
class UpdateSpg(APIView):
permission_classes = [IsAdminUser]
@transaction.atomic
def post(self, request, format=None):
"""
冷加工重新计算合格率
"""
for i in SubProductionPlan.objects.filter(subproduction__process__id=1):
WpmServies.update_subproduction_progress_main(sp=i)
return Response()

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-18 00:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('em', '0009_auto_20210916_1108'),
]
operations = [
migrations.AlterField(
model_name='equipment',
name='state',
field=models.PositiveIntegerField(choices=[(0, '完好'), (1, '限用'), (2, '在修'), (3, '禁用')], default=0, verbose_name='设备状态'),
),
]

View File

@ -0,0 +1,63 @@
# Generated by Django 3.2.9 on 2022-01-20 01:56
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('em', '0010_alter_equipment_state'),
]
operations = [
migrations.CreateModel(
name='ECheckRecord',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('check_date', models.DateField(blank=True, null=True, verbose_name='校准检查日期')),
('description', models.CharField(blank=True, max_length=200, null=True, verbose_name='描述')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
],
options={
'abstract': False,
},
),
migrations.RemoveField(
model_name='equipment',
name='belong_dept',
),
migrations.RemoveField(
model_name='equipment',
name='statedm',
),
migrations.AddField(
model_name='equipment',
name='next_check_date',
field=models.DateField(blank=True, null=True, verbose_name='下次校准检查日期'),
),
migrations.AlterField(
model_name='equipment',
name='state',
field=models.PositiveIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用')], default=0, verbose_name='设备状态'),
),
migrations.DeleteModel(
name='Equipmentrecord',
),
migrations.AddField(
model_name='echeckrecord',
name='equipment',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='校准检定设备'),
),
migrations.AddField(
model_name='echeckrecord',
name='update_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'),
),
]

View File

@ -0,0 +1,43 @@
# Generated by Django 3.2.9 on 2022-01-20 02:48
import datetime
from django.db import migrations, models
import django.db.models.deletion
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('em', '0011_auto_20220120_0956'),
]
operations = [
migrations.AddField(
model_name='equipment',
name='check_date',
field=models.DateField(blank=True, null=True, verbose_name='最近校准检查日期'),
),
migrations.AlterField(
model_name='echeckrecord',
name='check_date',
field=models.DateField(default=datetime.datetime(2022, 1, 20, 2, 48, 20, 706844, tzinfo=utc), verbose_name='校准检查日期'),
preserve_default=False,
),
migrations.AlterField(
model_name='echeckrecord',
name='equipment',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='校准检定设备'),
preserve_default=False,
),
migrations.AlterField(
model_name='equipment',
name='cycle',
field=models.IntegerField(blank=True, null=True, verbose_name='校准或检定周期(月)'),
),
migrations.AlterField(
model_name='equipment',
name='next_check_date',
field=models.DateField(blank=True, null=True, verbose_name='预计下次校准检查日期'),
),
]

View File

@ -3,32 +3,34 @@ from django.contrib.auth.models import AbstractUser
from django.db.models.base import Model from django.db.models.base import Model
import django.utils.timezone as timezone import django.utils.timezone as timezone
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
#from apps.mtm.models import Process
from utils.model import SoftModel, BaseModel from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords from simple_history.models import HistoricalRecords
class Equipment(CommonBModel): class Equipment(CommonAModel):
""" """
设备台账信息 设备台账信息
""" """
EQUIP_STATE_OK = 10
EQUIP_STATE_LIMIT = 20
EQUIP_STATE_FIX = 30
EQUIP_STATE_DISABLE = 40
state_choices = ( state_choices = (
(0, '完好'), (EQUIP_STATE_OK, '完好'),
(1, '限用'), (EQUIP_STATE_LIMIT, '限用'),
(2, '在修'), (EQUIP_STATE_FIX, '在修'),
(3, '禁用') (EQUIP_STATE_DISABLE, '禁用')
) )
statedm_choices = ( state2_choices = (
(0, '合格'), (EQUIP_STATE_OK, '合格'),
(1, '准用'), (EQUIP_STATE_DISABLE, '禁用')
(2, '限用'),
(3, '禁用'),
(4, '停用'),
(5, '封存')
) )
EQUIP_TYPE_PRO = 1
EQUIP_TYPE_TEST = 2
type_choices = ( type_choices = (
(1, '生产设备'), (1, '生产设备'),
(2, '检验工具') (2, '检验工具')
@ -54,20 +56,21 @@ class Equipment(CommonBModel):
factory = models.CharField('生产厂', max_length=50, null=True, blank=True) factory = models.CharField('生产厂', max_length=50, null=True, blank=True)
production_date = models.DateField('生产日期', null=True, blank=True) production_date = models.DateField('生产日期', null=True, blank=True)
buy_date = models.DateField('购置日期', null=True, blank=True) buy_date = models.DateField('购置日期', null=True, blank=True)
state = models.CharField('设备状态', max_length=11, choices=state_choices, default=0) state = models.PositiveIntegerField('设备状态', choices=state_choices, default=0)
parameter = models.TextField('技术参数', null=True, blank=True) parameter = models.TextField('技术参数', null=True, blank=True)
place = models.CharField('存放位置', max_length=50, null=True, blank=True) place = models.CharField('存放位置', max_length=50, null=True, blank=True)
count = models.IntegerField('数量', default=0) count = models.IntegerField('数量', default=0)
keeper = models.ForeignKey(User, verbose_name='保管人', on_delete=models.CASCADE, null=True, blank=True) keeper = models.ForeignKey(User, verbose_name='保管人', on_delete=models.CASCADE, null=True, blank=True)
description = models.CharField('描述', max_length=200, blank=True, null=True) description = models.CharField('描述', max_length=200, blank=True, null=True)
#process = models.ForeignKey(Process, verbose_name='工序', on_delete=models.CASCADE, null=True, blank=True) # 以下是监视测量设备单独字段
mgmtype = models.IntegerField('管理类别', choices=mgmtype_choices, default=1)#监视,测量设备 mgmtype = models.IntegerField('管理类别', choices=mgmtype_choices, default=1)
way = models.IntegerField('校准或检定方式', choices=way_choices, default=1)#监视,测量设备 way = models.IntegerField('校准或检定方式', choices=way_choices, default=1)
standard = models.CharField('溯源标准或依据', max_length=200, blank=True, null=True)#监视,测量设备 standard = models.CharField('溯源标准或依据', max_length=200, blank=True, null=True)
cycle = models.IntegerField('校准或检定周期', default=0)#监视,测量设备 cycle = models.IntegerField('校准或检定周期(月)', null=True, blank=True)
usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1)#监视,测量设备 usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1)
statedm = models.IntegerField('设备状态', choices=statedm_choices, default=0)#监视,测量设备
check_date = models.DateField('最近校准检查日期', blank=True, null=True)
next_check_date = models.DateField('预计下次校准检查日期',blank=True, null=True)
class Meta: class Meta:
verbose_name = '设备信息' verbose_name = '设备信息'
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
@ -75,8 +78,10 @@ class Equipment(CommonBModel):
def __str__(self): def __str__(self):
return self.number + '-' + self.name return self.number + '-' + self.name
class Equipmentrecord(CommonBModel): class ECheckRecord(CommonADModel):
equipment = models.ForeignKey(Equipment, verbose_name='校准检定设备', on_delete=models.CASCADE, null=True, blank=True) """
recentlydate = models.DateField('最近一次校准/检定日期',blank=True, null=True) 校准鉴定记录
nextdate = models.DateField('下次应校准或检定日期',blank=True, null=True) """
equipment = models.ForeignKey(Equipment, verbose_name='校准检定设备', on_delete=models.CASCADE)
check_date = models.DateField('校准检查日期')
description = models.CharField('描述', max_length=200, blank=True, null=True) description = models.CharField('描述', max_length=200, blank=True, null=True)

View File

@ -1,13 +1,12 @@
from apps.mtm.models import Step from apps.mtm.models import Step
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework import exceptions
from .models import Equipment,Equipmentrecord from .models import Equipment, ECheckRecord
from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer
class EquipmentSerializer(ModelSerializer): class EquipmentListSerializer(ModelSerializer):
belong_dept_ = OrganizationSimpleSerializer(source='belong_dept', read_only=True)
keeper_ = UserSimpleSerializer(source='keeper', read_only=True) keeper_ = UserSimpleSerializer(source='keeper', read_only=True)
step_ = serializers.SerializerMethodField() step_ = serializers.SerializerMethodField()
class Meta: class Meta:
@ -17,24 +16,35 @@ class EquipmentSerializer(ModelSerializer):
@staticmethod @staticmethod
def setup_eager_loading(queryset): def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """ """ Perform necessary eager loading of data. """
queryset = queryset.select_related('belong_dept','keeper') queryset = queryset.select_related('keeper')
return queryset return queryset
def get_step_(self, obj): def get_step_(self, obj):
return Step.objects.filter(equipments=obj).values('id', 'name', 'number') return Step.objects.filter(equipments=obj).values('id', 'name', 'number')
class EquipmentCreateUpdateSerializer(ModelSerializer):
class Meta:
model = Equipment
exclude = ['create_by', 'update_by', 'create_time', 'update_time', 'check_date', 'next_check_date']
def validate(self, attrs):
if attrs['type'] == Equipment.EQUIP_TYPE_TEST:
if attrs['state'] not in [Equipment.EQUIP_STATE_OK, Equipment.EQUIP_STATE_DISABLE]:
raise exceptions.APIException('设备状态错误')
return super().validate(attrs)
class EquipmentSimpleSerializer(ModelSerializer): class EquipmentSimpleSerializer(ModelSerializer):
class Meta: class Meta:
model = Equipment model = Equipment
fields = ['id', 'number', 'name', 'state'] fields = ['id', 'number', 'name', 'state', 'model']
class EquipmentrecordSerializer(ModelSerializer): class ECheckRecordListSerializer(ModelSerializer):
equipment_ = EquipmentSerializer(source='equipment', read_only=True) equipment_ = EquipmentSimpleSerializer(source='equipment', read_only=True)
class Meta: class Meta:
model = Equipmentrecord model = ECheckRecord
fields = '__all__' fields = '__all__'
@staticmethod @staticmethod
@ -43,6 +53,11 @@ class EquipmentrecordSerializer(ModelSerializer):
queryset = queryset.select_related('equipment') queryset = queryset.select_related('equipment')
return queryset return queryset
class EChcekRecordCreateSerializer(ModelSerializer):
class Meta:
model = ECheckRecord
fields = ['equipment', 'check_date', 'description']
class DaqCreateSerializer(serializers.Serializer): class DaqCreateSerializer(serializers.Serializer):
number = serializers.CharField() number = serializers.CharField()
file = serializers.FileField() file = serializers.FileField()

View File

@ -0,0 +1,20 @@
from tabnanny import check
from apps.em.models import ECheckRecord, Equipment
from dateutil.relativedelta import relativedelta
from django.utils import timezone
class EmService:
@classmethod
def update_check_date(cls, equip:Equipment):
# 根据校准检定记录变更下次日期
check = ECheckRecord.objects.filter(equipment=equip).order_by('id').last()
if check:
equip.check_date = check.check_date
if equip.cycle:
equip.next_check_date = equip.check_date + relativedelta(months=equip.cycle)
else:
equip.next_check_date = None
else:
equip.check_date = None
equip.next_check_date = None
equip.save()

View File

@ -1,12 +1,12 @@
from django.db.models import base from django.db.models import base
from rest_framework import urlpatterns from rest_framework import urlpatterns
from apps.em.views import DaqView, EquipmentViewSet,EquipmentrecordViewSet from apps.em.views import DaqView, EquipmentViewSet, EChcekRecordViewSet
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
router = DefaultRouter() router = DefaultRouter()
router.register('equipment', EquipmentViewSet, basename='equipment') router.register('equipment', EquipmentViewSet, basename='equipment')
router.register('equipmentrecord', EquipmentrecordViewSet, basename='equipmentrecord') router.register('echeck_record', EChcekRecordViewSet, basename='echeck_record')
urlpatterns = [ urlpatterns = [
path('daq/', DaqView.as_view()), path('daq/', DaqView.as_view()),
path('', include(router.urls)), path('', include(router.urls)),

View File

@ -1,14 +1,20 @@
from datetime import timedelta
from django.shortcuts import render from django.shortcuts import render
from numpy import delete
from rest_framework.exceptions import APIException from rest_framework.exceptions import APIException
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet, GenericViewSet
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, ListModelMixin, DestroyModelMixin
from rest_framework import serializers, status from rest_framework import serializers, status
from rest_framework.response import Response from rest_framework.response import Response
from apps.em.models import Equipment,Equipmentrecord from apps.em.models import Equipment, ECheckRecord
from apps.em.serializers import DaqCreateSerializer, EquipmentSerializer,EquipmentrecordSerializer from apps.em.serializers import DaqCreateSerializer, EChcekRecordCreateSerializer, ECheckRecordListSerializer, \
EquipmentCreateUpdateSerializer, EquipmentListSerializer
from apps.em.services import EmService
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from django.utils import timezone
from django.db import transaction
# Create your views here. # Create your views here.
class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet):
@ -18,48 +24,48 @@ class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet)
perms_map = {'get': '*', 'post': 'equipment_create', perms_map = {'get': '*', 'post': 'equipment_create',
'put': 'equipment_update', 'delete': 'equipment_delete'} 'put': 'equipment_update', 'delete': 'equipment_delete'}
queryset = Equipment.objects.all() queryset = Equipment.objects.all()
serializer_class = EquipmentSerializer serializer_class = EquipmentListSerializer
search_fields = ['number', 'name','description'] search_fields = ['number', 'name','description']
filterset_fields = ['belong_dept', 'keeper', 'type'] filterset_fields = ['keeper', 'type']
ordering_fields = ['create_time'] ordering_fields = ['create_time']
ordering = ['-create_time'] ordering = ['-create_time']
def get_serializer_class(self):
if self.action in ['create', 'update']:
return EquipmentCreateUpdateSerializer
return super().get_serializer_class()
# Create your views here. # Create your views here.
class EquipmentrecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): class EChcekRecordViewSet(CreateUpdateModelAMixin, OptimizationMixin,
CreateModelMixin, RetrieveModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet):
""" """
设备校准-增删改查 设备校准-增删改查
""" """
perms_map = {'get': '*', 'post': 'equipmentrecord_create', perms_map = {'get': '*', 'post': 'echeckrecord_create', 'delete': 'echeckrecord_delete'}
'put': 'equipmentrecord_update', 'delete': 'equipmentrecord_delete'} queryset = ECheckRecord.objects.all()
queryset = Equipmentrecord.objects.all() serializer_class = ECheckRecordListSerializer
serializer_class = EquipmentrecordSerializer
filterset_fields = ['equipment'] filterset_fields = ['equipment']
ordering_fields = ['create_time'] ordering = ['-id']
ordering = ['-create_time']
def get_serializer_class(self):
if self.action in ['create']:
return EChcekRecordCreateSerializer
return super().get_serializer_class()
@transaction.atomic
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
data = request.data
if data.get('equipment', None):
equipment = Equipment.objects.get(pk=data['equipment'])
equipment.statedm = data['state']
equipment.save()
serializer = self.get_serializer(data=request.data) serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
serializer.save() instance = serializer.save(create_by=request.user)
return Response(status=status.HTTP_200_OK) EmService.update_check_date(equip=instance.equipment)
def update(self, request, *args, **kwargs): return Response()
data = request.data
if data.get('equipment', None): @transaction.atomic
equipment = Equipment.objects.get(pk=data['equipment']) def destroy(self, request, *args, **kwargs):
equipment.statedm = data['state'] instance = self.get_object()
equipment.save() instance.delete()
id = self.get_object() EmService.update_check_date(equip=instance.equipment)
serializer = self.get_serializer(id, data=data) return Response()
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=status.HTTP_200_OK)
import uuid import uuid
import os import os

View File

@ -36,8 +36,8 @@ class Employee(CommonAModel):
def __str__(self): def __str__(self):
return self.name return self.name
class Attendance(CommonADModel): # class Attendance(CommonADModel):
""" # """
出勤记录 # 出勤记录
""" # """

View File

@ -21,7 +21,8 @@ class MbFilterSet(filters.FilterSet):
class IProductFilterSet(filters.FilterSet): class IProductFilterSet(filters.FilterSet):
order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order") order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order")
update_time_start = filters.DateFilter(field_name="update_time", lookup_expr='gte')
update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte')
class Meta: class Meta:
model = IProduct model = IProduct
fields = ['material', 'warehouse', 'batch', 'order', 'material__type'] fields = ['material', 'warehouse', 'batch', 'order', 'material__type', 'is_saled', 'update_time_start', 'update_time_end']

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-19 07:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mtm', '0043_auto_20220106_0942'),
]
operations = [
migrations.AddField(
model_name='subproduction',
name='need_combtest',
field=models.BooleanField(default=False, verbose_name='需要质检'),
),
]

View File

@ -210,6 +210,7 @@ class SubProduction(CommonAModel):
name = models.CharField('命名', max_length=50, null=True, blank=True) name = models.CharField('命名', max_length=50, null=True, blank=True)
product = models.ForeignKey(Material, verbose_name='产品', on_delete=models.CASCADE) product = models.ForeignKey(Material, verbose_name='产品', on_delete=models.CASCADE)
process = models.ForeignKey(Process, verbose_name='隶属大工序', on_delete=models.CASCADE, related_name='subproduction_process') process = models.ForeignKey(Process, verbose_name='隶属大工序', on_delete=models.CASCADE, related_name='subproduction_process')
need_combtest = models.BooleanField('需要质检', default=False)
sort = models.IntegerField('排序号', default=1) sort = models.IntegerField('排序号', default=1)
class Meta: class Meta:

View File

@ -72,6 +72,11 @@ class SubProductionSerializer(serializers.ModelSerializer):
model = SubProduction model = SubProduction
fields = '__all__' fields = '__all__'
class SubProductionCreateUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = SubProduction
fields = ['name', 'product', 'process', 'need_combtest', 'sort']
class OtherMaterialSerializer(serializers.ModelSerializer): class OtherMaterialSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = SubprodctionMaterial model = SubprodctionMaterial

View File

@ -4,7 +4,7 @@ from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelM
from apps.mtm.filters import MaterialFilterSet, TechDocFilterset from apps.mtm.filters import MaterialFilterSet, TechDocFilterset
from apps.mtm.models import Material, Process, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep, SubProduction from apps.mtm.models import Material, Process, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep, SubProduction
from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, SubprodctionMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionCreateUpdateSerializer, SubProductionSerializer, SubprodctionMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
@ -80,6 +80,10 @@ class SubProductionViewSet(CreateUpdateModelAMixin, ModelViewSet):
search_fields = ['name'] search_fields = ['name']
serializer_class = SubProductionSerializer serializer_class = SubProductionSerializer
ordering = ['sort'] ordering = ['sort']
def get_serializer_class(self):
if self.action in ['create', 'update']:
return SubProductionCreateUpdateSerializer
return super().get_serializer_class()
class InputMaterialViewSet(CreateUpdateModelAMixin, ModelViewSet): class InputMaterialViewSet(CreateUpdateModelAMixin, ModelViewSet):
""" """

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.9 on 2022-01-18 00:39
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sam', '0010_auto_20211208_1408'),
('pm', '0022_auto_20211229_1429'),
]
operations = [
migrations.AlterField(
model_name='productionplan',
name='order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='plan_order', to='sam.order', verbose_name='关联订单'),
),
]

View File

@ -4,7 +4,7 @@ from django.db import transaction
from rest_framework import serializers from rest_framework import serializers
from rest_framework.views import APIView from rest_framework.views import APIView
from apps.em.models import Equipment from apps.em.models import Equipment
from apps.em.serializers import EquipmentSerializer from apps.em.serializers import EquipmentSimpleSerializer
from apps.inm.models import MaterialBatch from apps.inm.models import MaterialBatch
from apps.inm.serializers import MaterialBatchSerializer from apps.inm.serializers import MaterialBatchSerializer
from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep
@ -248,5 +248,5 @@ class ResourceViewSet(GenericViewSet):
subproductions = SubProduction.objects.filter(product__id__in=rdata_l, is_deleted=False) subproductions = SubProduction.objects.filter(product__id__in=rdata_l, is_deleted=False)
steps = Step.objects.filter(usedstep__is_deleted=False, usedstep__subproduction__in=subproductions) steps = Step.objects.filter(usedstep__is_deleted=False, usedstep__subproduction__in=subproductions)
equips = Equipment.objects.filter(step_equips__in=steps, is_deleted=False).distinct() equips = Equipment.objects.filter(step_equips__in=steps, is_deleted=False).distinct()
serializer = EquipmentSerializer(instance=equips, many=True) serializer = EquipmentSimpleSerializer(instance=equips, many=True)
return Response(serializer.data) return Response(serializer.data)

View File

@ -19,4 +19,8 @@ class PlanGanttSerializer(serializers.ModelSerializer):
def get_children(self, obj): def get_children(self, obj):
subplans = SubProductionPlan.objects.filter(production_plan=obj).order_by('process__number') subplans = SubProductionPlan.objects.filter(production_plan=obj).order_by('process__number')
return SubplanGanttSerializer(instance=subplans, many=True).data return SubplanGanttSerializer(instance=subplans, many=True).data
class ProcessYieldSerializer(serializers.Serializer):
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)

View File

@ -3,11 +3,12 @@ from rest_framework import urlpatterns
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from apps.srm.views import GanttPlan from apps.srm.views import GanttPlan, ProcessYieldView
router = DefaultRouter() router = DefaultRouter()
urlpatterns = [ urlpatterns = [
path('gantt/plan/', GanttPlan.as_view()), path('gantt/plan/', GanttPlan.as_view()),
path('process/yield/', ProcessYieldView.as_view()),
path('', include(router.urls)), path('', include(router.urls)),
] ]

View File

@ -1,9 +1,14 @@
from django.shortcuts import render from django.shortcuts import render
from rest_framework import serializers from rest_framework import serializers
from rest_framework.generics import ListAPIView from rest_framework.generics import ListAPIView, CreateAPIView
from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from apps.mtm.models import Process, Step
from apps.pm.models import ProductionPlan, SubProductionPlan from apps.pm.models import ProductionPlan, SubProductionPlan
from apps.srm.serializers import PlanGanttSerializer from apps.srm.serializers import PlanGanttSerializer, ProcessYieldSerializer
from apps.wpm.models import WProduct, WproductFlow
from django.db.models import Count
# Create your views here. # Create your views here.
class GanttPlan(ListAPIView): class GanttPlan(ListAPIView):
@ -15,4 +20,48 @@ class GanttPlan(ListAPIView):
queryset = ProductionPlan.objects.filter(is_deleted=False, is_planed=True).prefetch_related('subplan_plan', 'subplan_plan__process') queryset = ProductionPlan.objects.filter(is_deleted=False, is_planed=True).prefetch_related('subplan_plan', 'subplan_plan__process')
ordering = ['-id'] ordering = ['-id']
class ProcessYieldView(CreateAPIView):
"""
工序成品率统计
"""
perms_map = {'get':'*'}
serializer_class = ProcessYieldSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
wpfs = WproductFlow.objects.filter(is_lastlog=True)
if vdata.get('datetime_start', None):
wpfs = wpfs.filter(update_time__gte = vdata.get('datetime_start'))
if vdata.get('datetime_end', None):
wpfs = wpfs.filter(update_time__lte = vdata.get('datetime_end'))
# 根据产品日志记录进行聚合
count_ok_g = list(wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM,
WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).values('step__process__id').annotate(count_ok=Count('id')))
count_notok_g = list(
(
wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).exclude(step__process__id=1)
| wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP],
step__process__id=1).exclude(number=None)
)\
.values('step__process__id',
).annotate(count_notok=Count('id')))
ret = []
process_l = list(Process.objects.filter(is_deleted=False).order_by('number').values('id', 'name'))
for i in process_l:
ret_item = {'id':i['id'], 'name':i['name'], 'count_ok':0, 'count_notok':0, 'rate':1}
for m in count_ok_g:
if m['step__process__id'] == ret_item['id']:
ret_item['count_ok'] = m['count_ok']
for n in count_notok_g:
if n['step__process__id'] == ret_item['id']:
ret_item['count_notok'] = n['count_notok']
rate = (ret_item['count_ok']/(ret_item['count_ok']+ret_item['count_notok'])) \
if ret_item['count_ok']+ret_item['count_notok']>0 else 1
ret_item['rate'] = rate
ret.append(ret_item)
return Response(ret)

View File

@ -41,6 +41,12 @@ class WProductFilterSet(filters.FilterSet):
def filter_tag(self, queryset, name, value): def filter_tag(self, queryset, name, value):
if value == 'no_scrap': if value == 'no_scrap':
queryset = queryset.exclude(act_state=WProduct.WPR_ACT_STATE_SCRAP) queryset = queryset.exclude(act_state=WProduct.WPR_ACT_STATE_SCRAP)
elif value == 'notok':
queryset = queryset.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP])\
.exclude(step__process__id = 1) # 不算冷加工的报废
elif value == 'ok':
queryset = queryset.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM,
WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED])
return queryset return queryset

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-18 00:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wpm', '0048_operationwproduct_place'),
]
operations = [
migrations.AddField(
model_name='operationequip',
name='state',
field=models.PositiveSmallIntegerField(choices=[(0, '完好'), (1, '限用'), (2, '在修'), (3, '禁用')], default=0, verbose_name='当前设备状态'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-20 02:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wpm', '0049_operationequip_state'),
]
operations = [
migrations.AlterField(
model_name='operationequip',
name='state',
field=models.PositiveSmallIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用')], default=10, verbose_name='当前设备状态'),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.9 on 2022-01-20 07:41
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sam', '0010_auto_20211208_1408'),
('wpm', '0050_alter_operationequip_state'),
]
operations = [
migrations.AddField(
model_name='wproduct',
name='to_order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.order', verbose_name='指派的订单'),
),
migrations.AddField(
model_name='wproductflow',
name='to_order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.order', verbose_name='指派的订单'),
),
]

View File

@ -118,7 +118,8 @@ class WProduct(CommonAModel):
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test') on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test')
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket') on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket')
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
is_mtested = models.BooleanField('是否军检', default=False) is_mtested = models.BooleanField('是否军检', default=False)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True)
@ -192,7 +193,7 @@ class WproductFlow(CommonAModel):
on_delete=models.SET_NULL, null=True, blank=True) on_delete=models.SET_NULL, null=True, blank=True)
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
on_delete=models.SET_NULL, null=True, blank=True) on_delete=models.SET_NULL, null=True, blank=True)
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
is_mtested = models.BooleanField('是否军检', default=False) is_mtested = models.BooleanField('是否军检', default=False)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True)
@ -336,4 +337,5 @@ class OperationEquip(BaseModel):
Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation') Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation')
equip = models.ForeignKey(Equipment, verbose_name='生产设备', equip = models.ForeignKey(Equipment, verbose_name='生产设备',
on_delete=models.CASCADE, related_name='oe_equip') on_delete=models.CASCADE, related_name='oe_equip')
state = models.PositiveSmallIntegerField('当前设备状态', choices=Equipment.state_choices, default=Equipment.EQUIP_STATE_OK)
remark = models.TextField('备注', null=True, blank=True) remark = models.TextField('备注', null=True, blank=True)

View File

@ -19,6 +19,7 @@ from apps.system.models import User
from apps.system.serializers import UserSimpleSerializer from apps.system.serializers import UserSimpleSerializer
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
from django.db import transaction from django.db import transaction
from apps.sam.models import Order
class PickHalfSerializer(serializers.Serializer): class PickHalfSerializer(serializers.Serializer):
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID') id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
@ -155,6 +156,7 @@ class WProductListSerializer(serializers.ModelSerializer):
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
children = serializers.SerializerMethodField() children = serializers.SerializerMethodField()
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
class Meta: class Meta:
model = WProduct model = WProduct
fields = '__all__' fields = '__all__'
@ -560,4 +562,8 @@ class CuttingListSerializer(serializers.ModelSerializer):
class WproductMtestSerializer(serializers.ModelSerializer): class WproductMtestSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = WProduct model = WProduct
fields = ['remark_mtest', 'is_mtestok'] fields = ['remark_mtest', 'is_mtestok']
class WproductToOrderSerializer(serializers.Serializer):
wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), many=True)
order = serializers.PrimaryKeyRelatedField(queryset=Order.objects.all())

View File

@ -54,7 +54,8 @@ class WpmServies(object):
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验 elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验
wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.step.type == Step.STEP_TYPE_COMB: # 夹层检验 elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \
wproduct.subproduction_plan.subproduction.need_combtest : # 配置中需要质检
wproduct.act_state = WProduct.WPR_ACT_STATE_TOCOMBTEST wproduct.act_state = WProduct.WPR_ACT_STATE_TOCOMBTEST
else: else:
wproduct.act_state = WProduct.WPR_ACT_STATE_OK wproduct.act_state = WProduct.WPR_ACT_STATE_OK
@ -113,7 +114,11 @@ class WpmServies(object):
objs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True) objs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM,
WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).count() WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).count()
count_notok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).count() count_notok = (
objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).exclude(step__process__id=1)
| objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP],
step__process__id=1).exclude(number=None)
).count()
count_real = objs.exclude(act_state__in=[WProduct.WPR_ACT_STATE_TORETEST, count_real = objs.exclude(act_state__in=[WProduct.WPR_ACT_STATE_TORETEST,
WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_DOING]).count() WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_DOING]).count()
ins = SubProductionProgress.objects.filter(subproduction_plan=sp, ins = SubProductionProgress.objects.filter(subproduction_plan=sp,

View File

@ -16,7 +16,7 @@ from rest_framework.decorators import action
from apps.wf.models import Workflow from apps.wf.models import Workflow
from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, \ from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, \
OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket OperationMaterial, OperationRecord, OperationRecordItem, WproductFlow, WprouctTicket
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, \ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, \
OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, \ OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, \
@ -27,7 +27,7 @@ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerial
PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \ PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \
WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \ WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \
WpmTestFormInitSerializer, WproductMtestSerializer, WproductPutInSerializer, \ WpmTestFormInitSerializer, WproductMtestSerializer, WproductPutInSerializer, \
WproductPutInsSerializer, WproductTicketListSerializer WproductPutInsSerializer, WproductTicketListSerializer, WproductToOrderSerializer
from rest_framework.response import Response from rest_framework.response import Response
from django.db import transaction from django.db import transaction
@ -148,7 +148,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
""" """
perms_map = {'*': '*'} perms_map = {'*': '*'}
queryset = WProduct.objects.select_related('step', 'material', queryset = WProduct.objects.select_related('step', 'material',
'subproduction_plan', 'warehouse').prefetch_related('wproduct_child') 'subproduction_plan', 'warehouse', 'order').prefetch_related('wproduct_child')
serializer_class = WProductListSerializer serializer_class = WProductListSerializer
filterset_class = WProductFilterSet filterset_class = WProductFilterSet
search_fields = ['number'] search_fields = ['number']
@ -441,7 +441,31 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
ret.append([str(index + 1), item['step_name'], item['actions']]) ret.append([str(index + 1), item['step_name'], item['actions']])
return Response(ret) return Response(ret)
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductToOrderSerializer)
@transaction.atomic
def to_order(self, request, pk=None):
"""
指派发货订单
"""
serializer = WproductToOrderSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')])
wp = wps.first()
order = vdata['order']
if wp.material != order.product:
raise exceptions.ValidationError('所选订单与产品不符')
for i in wps:
if i.material != wp.material and i.material.type != Material.MA_TYPE_GOOD and i.act_state \
not in [WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_INM]:
raise exceptions.ValidationError('所选产品错误')
for i in wps:
i.to_order = order
i.update_by = request.user
i.save()
WpmServies.add_wproduct_flow_log(i,change_str='to_order')
return Response()
class WproductTicketViewSet(ListModelMixin, GenericViewSet): class WproductTicketViewSet(ListModelMixin, GenericViewSet):
""" """
玻璃审批工单 玻璃审批工单
@ -559,6 +583,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
ope = OperationEquip() ope = OperationEquip()
ope.operation = op ope.operation = op
ope.equip = i ope.equip = i
ope.state = i.state
ope.save() ope.save()
# 查询所需的工具工装 # 查询所需的工具工装
for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,

View File

@ -47,17 +47,20 @@ class FitJSONRenderer(JSONRenderer):
""" """
response_body = BaseResponse() response_body = BaseResponse()
response = renderer_context.get("response") response = renderer_context.get("response")
response_body.code = response.status_code status_code = response.status_code # Http状态异常码
if response_body.code >= 400: # 响应异常 if status_code >= 400: # 如果http响应异常
response_body.data = data # data里是详细异常信息 if isinstance(data, dict) and 'code' in data: # 如果自定义了异常码
prefix = "" response_body = data
if isinstance(data, dict): else:
prefix = list(data.keys())[0] response_body.data = data # data里是详细异常信息
data = data[prefix] prefix = ""
if isinstance(data, list): if isinstance(data, dict):
data = data[0] prefix = list(data.keys())[0]
response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert data = data[prefix]
elif isinstance(data, list):
data = data[0]
response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert
else: else:
response_body.data = data response_body.data = data
renderer_context.get("response").status_code = 200 # 统一成200响应,用code区分 renderer_context.get("response").status_code = 200 # 统一成200响应,body里code区分业务异常
return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context) return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context)