车间操作重新梳理

This commit is contained in:
caoqianming 2021-11-19 10:40:09 +08:00
parent b8495ee431
commit bd179c20b1
13 changed files with 216 additions and 25 deletions

View File

@ -26,7 +26,7 @@ class MaterialDetailSerializer(serializers.ModelSerializer):
class MaterialSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Material
fields = ['id', 'name', 'number', 'unit','specification']
fields = ['id', 'name', 'number', 'unit','specification', 'type']
class ProcessSerializer(serializers.ModelSerializer):
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2021-11-19 02:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pm', '0013_alter_subproductionplan_subproduction'),
]
operations = [
migrations.AddField(
model_name='subproductionplan',
name='number',
field=models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='子计划编号'),
),
]

View File

@ -44,6 +44,7 @@ class SubProductionPlan(CommonAModel):
(SUBPLAN_STATE_WORKING, '生产中'),
(SUBPLAN_STATE_DONE, '已完成')
)
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
start_date = models.DateField('计划开工日期')

View File

@ -55,3 +55,8 @@ class PickNeedSerializer(serializers.Serializer):
class PlanDestorySerializer(serializers.Serializer):
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')
class SubproductionPlanSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = SubProductionPlan
fields = ['id', 'number']

View File

@ -62,7 +62,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
pass
else:
raise APIException('排产数量错误')
instance = serializer.save(create_by=request.user, product=order.product, number='JH-'+ranstr(7))
instance = serializer.save(create_by=request.user, product=order.product, number='JH'+ranstr(7))
updateOrderPlanedCount(instance.order)
return Response()
@ -83,13 +83,13 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
if production_plan.is_planed:
raise APIException('已生成子计划')
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
for i in subps:
for index, i in enumerate(subps):
steps = Step.objects.filter(usedstep__subproduction=i, usedstep__subproduction__is_deleted=False,
usedstep__is_deleted=False, is_deleted=False).values('id', 'number', 'name', 'usedstep__remark')
instance = SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i,
start_date=production_plan.start_date, end_date=production_plan.end_date,
workshop=i.process.workshop, process=i.process, create_by=request.user,
steps = list(steps))
steps = list(steps), number=production_plan.number + '-' + str(index+1))
# 生成子计划物料需求/进度
for m in SubprodctionMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
spro = SubProductionProgress.objects.create(material=m.material, type=m.type,

View File

@ -0,0 +1,35 @@
# Generated by Django 3.2.9 on 2021-11-19 00:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('pm', '0013_alter_subproductionplan_subproduction'),
('qm', '0010_rename_m_state_testrecord_material'),
]
operations = [
migrations.AddField(
model_name='testrecord',
name='is_testok_robot',
field=models.BooleanField(default=True, verbose_name='自动判定的是否合格'),
),
migrations.AddField(
model_name='testrecord',
name='number',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='产品编号'),
),
migrations.AddField(
model_name='testrecord',
name='subproduction_plan',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联的生产子计划'),
),
migrations.AddField(
model_name='testrecorditem',
name='is_testok_robot',
field=models.BooleanField(blank=True, null=True, verbose_name='自动判定的是否合格'),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 3.2.9 on 2021-11-19 00:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wpm', '0015_auto_20211117_2332'),
]
operations = [
migrations.RemoveField(
model_name='operation',
name='wproducts',
),
migrations.AddField(
model_name='operation',
name='is_submited',
field=models.BooleanField(default=True, verbose_name='是否提交'),
),
migrations.AddField(
model_name='wproduct',
name='operation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_operation', to='wpm.operation', verbose_name='关联操作'),
),
]

View File

@ -0,0 +1,49 @@
# Generated by Django 3.2.9 on 2021-11-19 02:34
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('em', '0009_auto_20210916_1108'),
('wpm', '0016_auto_20211119_0848'),
]
operations = [
migrations.RemoveField(
model_name='operationrecord',
name='create_by',
),
migrations.RemoveField(
model_name='operationrecord',
name='update_by',
),
migrations.AddField(
model_name='operationrecord',
name='is_filled',
field=models.BooleanField(default=True, verbose_name='是否填写'),
),
migrations.AlterField(
model_name='operation',
name='is_submited',
field=models.BooleanField(default=False, verbose_name='是否提交'),
),
migrations.CreateModel(
name='OperationEquip',
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='删除标记')),
('remark', models.TextField(blank=True, null=True, verbose_name='备注')),
('equip', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='生产设备')),
('operation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.operation', verbose_name='关联操作')),
],
options={
'abstract': False,
},
),
]

View File

@ -9,6 +9,7 @@ from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm
from django.core.validators import MinValueValidator
from apps.em.models import Equipment
class WMaterial(BaseModel):
"""
车间生产物料
@ -44,17 +45,17 @@ class WProduct(CommonAModel):
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
# operation = models.ForeignKey('wpm.operation', verbose_name='关联操作',
# on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation')
operation = models.ForeignKey('wpm.operation', verbose_name='关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation')
class Operation(CommonADModel):
"""
生产操作
"""
wproducts = models.ManyToManyField(WProduct, verbose_name='关联半成品', through='wpm.operationwproduct')
step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True)
use_scrap = models.BooleanField('是否使用的边角料', default=False)
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
is_submited = models.BooleanField('是否提交', default=False)
class OperationWproduct(BaseModel):
"""
@ -82,13 +83,13 @@ class OperationMaterial(BaseModel):
material = models.ForeignKey(Material, verbose_name='可能产出的副产品', on_delete=models.CASCADE, null=True, blank=True)
count = models.IntegerField('消耗或产出数量', validators=[MinValueValidator(0)])
class OperationRecord(CommonAModel):
class OperationRecord(BaseModel):
"""
记录表格
"""
form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', on_delete=models.CASCADE)
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
is_filled = models.BooleanField('是否填写', default=True)
class OperationRecordItem(BaseModel):
"""
@ -102,3 +103,7 @@ class OperationRecordItem(BaseModel):
sort = models.IntegerField('排序号', default=1)
operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE)
class OperationEquip(BaseModel):
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE)
equip = models.ForeignKey(Equipment, verbose_name='生产设备', on_delete=models.CASCADE)
remark = models.TextField('备注', null=True, blank=True)

View File

@ -8,9 +8,10 @@ from apps.mtm.serializers import MaterialSimpleSerializer, StepSimpleSerializer
from apps.pm.models import SubProductionPlan, SubProductionProgress
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from apps.pm.serializers import SubproductionPlanSimpleSerializer
from apps.qm.models import TestRecord, TestRecordItem
from apps.system.serializers import UserSimpleSerializer
from apps.wpm.models import Operation, WMaterial, WProduct, OperationRecord, OperationRecordItem
from apps.wpm.models import Operation, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem
from django.db import transaction
class PickHalfSerializer(serializers.Serializer):
@ -130,20 +131,14 @@ class WProductListSerializer(serializers.ModelSerializer):
fields = '__all__'
class OperationDetailSerializer(serializers.ModelSerializer):
wproducts_ = serializers.SerializerMethodField()
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
material_ = MaterialSimpleSerializer(source='material', read_only=True)
step_ = StepSimpleSerializer(source='step', read_only=True)
class Meta:
model = Operation
fields = '__all__'
def get_wproducts_(self, obj):
return list(WProduct.objects.filter(id__in=obj.wproducts).values('id', 'number'))
class OperationListSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
material_ = MaterialSimpleSerializer(source='material', read_only=True)
step_ = StepSimpleSerializer(source='step', read_only=True)
class Meta:
model = Operation
@ -231,6 +226,12 @@ class OperationRecordSerializer(serializers.ModelSerializer):
model = OperationRecord
fields = ['form', 'record_data']
class OperationWproductListSerializer(serializers.ModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
class Meta:
model = OperationWproduct
fields = '__all__'
class OperationSubmitSerializer(serializers.Serializer):

View File

@ -3,12 +3,13 @@ from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
router = DefaultRouter()
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
router.register('wproduct', WProductViewSet, basename='wproduct')
router.register('operation', OperationViewSet, basename='operation')
router.register('operation_wproduct', OperationWproductViewSet, basename='operation_wproduct')
router.register('subplan', WPlanViewSet, basename='wplan')
urlpatterns = [
path('do/init/', DoFormInit.as_view()),

View File

@ -15,9 +15,9 @@ from apps.qm.models import TestRecordItem
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from apps.wpm.models import OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
from apps.wpm.serializers import OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
from apps.wpm.serializers import OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
@ -67,7 +67,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
wps.update(step=first_step, is_executed=False,
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
subproduction_plan=sp, production_plan=sp.production_plan)
subproduction_plan=sp, production_plan=sp.production_plan, update_by=request.user, update_time=timezone.now())
return Response()
@ -125,7 +125,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
IProduct.objects.bulk_create(ips2)
# 更新库存并修改半成品进行状态
update_inm(fifo)
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse)
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user, update_time=timezone.now())
return Response()
@ -156,7 +156,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
半成品
"""
perms_map={'*':'*'}
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False)
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False).exclude(operation=None)
serializer_class = WProductListSerializer
filterset_fields = ['step', 'subproduction_plan', 'material', 'production_plan', 'step__process', 'act_state']
search_fields = ['number']
@ -199,7 +199,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
if obj.is_testok:
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
if wproduct.number is None: # 产生半成品编号
wproduct.number = 'WP-'+ranstr(7)
wproduct.number = 'WP'+ranstr(7)
wproduct.save()
# 更新子计划状态
# 更新子计划主产品数
@ -266,7 +266,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Gen
perms_map={'*':'*'}
queryset = Operation.objects.select_related('step', 'material').all()
serializer_class = OperationListSerializer
filterset_fields = ['step', 'step__process']
filterset_fields = ['step', 'step__process', 'is_submited']
ordering_fields = ['id']
ordering = ['-id']
@ -283,8 +283,56 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Gen
serializer = OperationCreateSerializer(data=data, context={'request':self.request})
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data #校验之后的数据
step = Step.objects.get(pk=vdata['step'])
op = Operation()
op.step = step
op.is_submited = False
op.save()
# 创建操作所用半成品关联记录
if 'wproducts' in vdata:
owps = []
for i in vdata['wproducts']:
owp = {}
wpd = WProduct.objects.get(pk=i)
owp['operation'] = op
owp['wproduct'] = wpd
owp['number'] = wpd.number
owp['material'] = wpd.material
owp['subproduction_plan'] = wpd.subproduction_plan
owp['production_plan'] = wpd.production_plan
owps.append(OperationWproduct(**owp))
OperationWproduct.objects.bulk_create(owps)
# 查询需要填写的自定义表格
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO)
for i in forms:
opr = OperationRecord()
opr.operation = op
opr.form = i
opr.is_filled = False
opr.save()
# 查询需要使用的生产设备
equips = step.equipements
for i in equips:
ope = OperationEquip()
ope.operation = op
ope.equip = i
ope.save()
return Response()
class OperationWproductViewSet(ListModelMixin, GenericViewSet):
"""
操作使用的半成品
"""
perms_map={'*':'*'}
queryset = OperationWproduct.objects.select_related('subproduction_plan', 'material').all()
serializer_class = OperationWproductListSerializer
filterset_fields = ['material', 'subproduction_plan', 'operation']
ordering_fields = ['id']
ordering = ['-id']
class DoFormInit(CreateAPIView, GenericAPIView):
perms_map={'*':'*'}
serializer_class=OperationInitSerializer

View File

@ -2,6 +2,6 @@ import random
import string
def ranstr(num):
salt = ''.join(random.sample(string.ascii_letters + string.digits, num))
salt = ''.join(random.sample(string.ascii_lowercase + string.digits, num))
return salt
ranstr(10)