Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
9df7d39e05
|
@ -4,4 +4,5 @@ deploy.sh
|
||||||
package-lock.json
|
package-lock.json
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.idea/
|
||||||
server/static/
|
server/static/
|
|
@ -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())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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='设备状态'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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='最后编辑人'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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='预计下次校准检查日期'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
# """
|
||||||
出勤记录
|
# 出勤记录
|
||||||
"""
|
# """
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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='需要质检'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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='关联订单'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
@ -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)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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='当前设备状态'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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='当前设备状态'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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='指派的订单'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
|
@ -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())
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue