增加工具工装接口

This commit is contained in:
caoqianming 2021-11-01 15:23:37 +08:00
parent bed00aaaea
commit d655e78625
11 changed files with 207 additions and 67 deletions

View File

@ -0,0 +1,86 @@
# Generated by Django 3.2.6 on 2021-11-01 07:22
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),
('mtm', '0025_outputmaterial_is_main'),
]
operations = [
migrations.CreateModel(
name='SubplanMaterial',
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='删除标记')),
('is_main', models.BooleanField(default=False, verbose_name='是否主产出')),
('count', models.FloatField(default=1, verbose_name='消耗量/产出量')),
('type', models.IntegerField(default=1, verbose_name='物料应用类型')),
('sort', models.IntegerField(default=1, verbose_name='排序号')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subplanmaterial_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
],
options={
'abstract': False,
},
),
migrations.RemoveField(
model_name='outputmaterial',
name='create_by',
),
migrations.RemoveField(
model_name='outputmaterial',
name='material',
),
migrations.RemoveField(
model_name='outputmaterial',
name='subproduction',
),
migrations.RemoveField(
model_name='outputmaterial',
name='update_by',
),
migrations.AlterField(
model_name='material',
name='name',
field=models.CharField(max_length=100, verbose_name='物料名称'),
),
migrations.AlterField(
model_name='material',
name='type',
field=models.CharField(choices=[(1, '成品'), (2, '半成品'), (3, '主要原料'), (4, '辅助材料'), (5, '加工工具'), (6, '辅助工装')], default=1, max_length=20, verbose_name='物料类型'),
),
migrations.AlterField(
model_name='material',
name='unit',
field=models.CharField(choices=[('', ''), ('', ''), ('', ''), ('m2', 'm2'), ('', '')], default='', max_length=10, verbose_name='基准计量单位'),
),
migrations.DeleteModel(
name='InputMaterial',
),
migrations.DeleteModel(
name='OutputMaterial',
),
migrations.AddField(
model_name='subplanmaterial',
name='material',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subplan_material', to='mtm.material', verbose_name='物料'),
),
migrations.AddField(
model_name='subplanmaterial',
name='subproduction',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.subproduction', verbose_name='关联生产分解'),
),
migrations.AddField(
model_name='subplanmaterial',
name='update_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subplanmaterial_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'),
),
]

View File

@ -16,9 +16,9 @@ class Material(CommonAModel):
(1, '成品'),
(2, '半成品'),
(3, '主要原料'),
(4, '辅助') ,
(4, '辅助') ,
(5, '加工工具'),
(6, '辅助工')
(6, '辅助工')
)
unit_choices =(
('', ''),
@ -27,7 +27,7 @@ class Material(CommonAModel):
('m2', 'm2'),
('', '')
)
name = models.CharField('物料名称', max_length=100, unique=True)
name = models.CharField('物料名称', max_length=100)
number = models.CharField('编号', max_length=100, unique=True)
specification = models.CharField('型号', max_length=100, null=True, blank=True)
type = models.CharField('物料类型', choices= type_choices, max_length=20, default=1)
@ -159,35 +159,22 @@ class SubProduction(CommonAModel):
verbose_name = '产品生产工序'
verbose_name_plural = verbose_name
class InputMaterial(CommonAModel):
class SubplanMaterial(CommonAModel):
"""
输入物料
输入/输出物料/工具工装
"""
material = models.ForeignKey(Material, verbose_name='输入物料', on_delete=models.CASCADE, related_name='inputmaterial')
count = models.FloatField('消耗量', default=1)
type_choices=(
(1, '输入物料'),
(2, '输出物料'),
(3, '工具工装')
)
material = models.ForeignKey(Material, verbose_name='物料', on_delete=models.CASCADE, related_name='subplan_material')
is_main = models.BooleanField('是否主产出', default=False) # 以该产品完成度计算进度
count = models.FloatField('消耗量/产出量', default=1)
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE)
type = models.IntegerField('物料应用类型', default=1)
sort = models.IntegerField('排序号', default=1)
class Meta:
verbose_name = '输入物料'
verbose_name_plural = verbose_name
class OutputMaterial(CommonAModel):
"""
输出物料
"""
material = models.ForeignKey(Material, verbose_name='输出物料', on_delete=models.CASCADE, related_name='outputmaterial')
is_main = models.BooleanField('是否主产出', default=True) # 以该产品完成度计算进度
count = models.FloatField('产出量', default=1)
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE)
sort = models.IntegerField('排序号', default=1)
class Meta:
verbose_name = '输出物料'
verbose_name_plural = verbose_name
class UsedStep(CommonAModel):
"""

View File

@ -1,7 +1,7 @@
from apps.em.serializers import EquipmentSimpleSerializer
from rest_framework import serializers
from rest_framework.exceptions import ParseError, ValidationError
from .models import InputMaterial, Material, OutputMaterial, Process, RecordForm, RecordFormField, Step, TechDoc, UsedStep, SubProduction
from .models import Material, Process, RecordForm, RecordFormField, Step, SubplanMaterial, TechDoc, UsedStep, SubProduction
from apps.system.serializers import FileSimpleSerializer, OrganizationSimpleSerializer
@ -19,7 +19,7 @@ class MaterialDetailSerializer(serializers.ModelSerializer):
def get_processes_(self, obj):
# steps = UsedStep.objects.filter(subproduction__product=obj).values_list('step', flat=True)
# objs = Process.objects.filter(step_process__id__in=steps).distinct().order_by('number')
objs = Process.objects.filter(subproduction_process__product=obj, subproduction_process__is_deleted=False, is_deleted=False).order_by('number')
objs = Process.objects.filter(subproduction_process__product=obj, subproduction_process__is_deleted=False, is_deleted=False).distinct().order_by('number')
return ProcessSimpleSerializer(instance=objs, many=True).data
@ -51,7 +51,7 @@ class StepSimpleSerializer(serializers.ModelSerializer):
fields = ['id', 'name', 'sort']
class StepDetailSerializer(serializers.ModelSerializer):
equipments_ = EquipmentSimpleSerializer(source='equipments', many=True)
equipments_ = EquipmentSimpleSerializer(source='equipments', many=True, required=False)
class Meta:
model = Step
fields = '__all__'
@ -67,51 +67,59 @@ class SubProductionSerializer(serializers.ModelSerializer):
model = SubProduction
fields = '__all__'
class InputMaterialListSerializer(serializers.ModelSerializer):
class OtherMaterialSerializer(serializers.ModelSerializer):
class Meta:
model = SubplanMaterial
fields = ['sort', 'material', 'subproduction']
def create(self, validated_data):
if SubplanMaterial.objects.filter(material=validated_data['material'], subproduction=validated_data['subproduction'], is_deleted=False, type=3).exists():
raise ValidationError('该物料已存在')
validated_data['type']=3
return super().create(validated_data)
class SubplanMaterialListSerializer(serializers.ModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
class Meta:
model = InputMaterial
model = SubplanMaterial
fields = '__all__'
class OutputMaterialListSerializer(serializers.ModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
class Meta:
model = OutputMaterial
fields = '__all__'
class InputMaterialSerializer(serializers.ModelSerializer):
class Meta:
model = InputMaterial
model = SubplanMaterial
fields = ['count', 'sort', 'material', 'subproduction']
def create(self, validated_data):
if InputMaterial.objects.filter(material=validated_data['material'], subproduction=validated_data['subproduction'], is_deleted=False).exists():
if SubplanMaterial.objects.filter(material=validated_data['material'], subproduction=validated_data['subproduction'], is_deleted=False, type=1).exists():
raise ValidationError('该物料已存在')
validated_data['type']=1
return super().create(validated_data)
class InputMaterialUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = InputMaterial
model = SubplanMaterial
fields = ['count', 'sort']
class OutputMaterialSerializer(serializers.ModelSerializer):
class Meta:
model = OutputMaterial
model = SubplanMaterial
fields = ['count', 'sort', 'material', 'subproduction', 'is_main']
def create(self, validated_data):
if OutputMaterial.objects.filter(subproduction=validated_data['subproduction'], is_deleted=False, is_main=True).exists():
if SubplanMaterial.objects.filter(subproduction=validated_data['subproduction'], is_deleted=False, is_main=True, type=2).exists():
raise ValidationError('主产出只能有1个')
if OutputMaterial.objects.filter(material=validated_data['material'], subproduction=validated_data['subproduction'], is_deleted=False).exists():
if SubplanMaterial.objects.filter(material=validated_data['material'], subproduction=validated_data['subproduction'], is_deleted=False, type=2).exists():
raise ValidationError('该物料已存在')
validated_data['type']=2
return super().create(validated_data)
class OutputMaterialUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = OutputMaterial
model = SubplanMaterial
fields = ['count', 'sort', 'is_main']
class UsedStepCreateSerializer(serializers.ModelSerializer):
"""
产品生产子工序创建

View File

@ -1,6 +1,6 @@
from django.db.models import base
from rest_framework import urlpatterns
from apps.mtm.views import InputMaterialViewSet, MaterialViewSet, OutputMaterialViewSet, ProcessViewSet, RecordFormFieldViewSet, RecordFormViewSet, StepViewSet, SubProductionViewSet, TechDocViewSet, UsedStepViewSet
from apps.mtm.views import InputMaterialViewSet, MaterialViewSet, OtherMaterialViewSet, OutputMaterialViewSet, ProcessViewSet, RecordFormFieldViewSet, RecordFormViewSet, StepViewSet, SubProductionViewSet, TechDocViewSet, UsedStepViewSet
from django.urls import path, include
from rest_framework.routers import DefaultRouter
@ -11,6 +11,7 @@ router.register('step', StepViewSet, basename='step')
router.register('subproducation', SubProductionViewSet, basename='subproducation')
router.register('inputmaterial', InputMaterialViewSet, basename='inputmaterial')
router.register('outputmaterial', OutputMaterialViewSet, basename='outputmaterial')
router.register('othermaterial', OtherMaterialViewSet, basename='othermaterial')
router.register('usedstep', UsedStepViewSet, basename='usedstep')
router.register('recordform', RecordFormViewSet, basename='recordform')
router.register('recordform-field', RecordFormFieldViewSet, basename='recordform-field')

View File

@ -2,8 +2,8 @@ from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin
from apps.mtm.models import InputMaterial, Material, OutputMaterial, Process, RecordForm, RecordFormField, Step, TechDoc, UsedStep, SubProduction
from apps.mtm.serializers import InputMaterialListSerializer, InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OutputMaterialListSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer
from apps.mtm.models import Material, Process, RecordForm, RecordFormField, Step, SubplanMaterial, TechDoc, UsedStep, SubProduction
from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, SubplanMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from rest_framework.response import Response
@ -85,14 +85,14 @@ class InputMaterialViewSet(CreateUpdateModelAMixin, ModelViewSet):
输入物料-增删改查
"""
perms_map = {'*':'*'}
queryset = InputMaterial.objects.select_related('material').all()
queryset = SubplanMaterial.objects.select_related('material').filter(type=1)
serializer_class = InputMaterialSerializer
filterset_fields = ['subproduction']
ordering = ['sort', '-create_time']
def get_serializer_class(self):
if self.action == 'list':
return InputMaterialListSerializer
return SubplanMaterialListSerializer
elif self.action == 'update':
return InputMaterialUpdateSerializer
return InputMaterialSerializer
@ -102,18 +102,33 @@ class OutputMaterialViewSet(CreateUpdateModelAMixin, ModelViewSet):
输出物料-增删改查
"""
perms_map = {'*':'*'}
queryset = OutputMaterial.objects.select_related('material').all()
queryset = SubplanMaterial.objects.select_related('material').filter(type=2)
serializer_class = OutputMaterialSerializer
filterset_fields = ['subproduction']
ordering = ['sort', '-create_time']
def get_serializer_class(self):
if self.action == 'list':
return OutputMaterialListSerializer
return SubplanMaterialListSerializer
elif self.action == 'update':
return OutputMaterialUpdateSerializer
return OutputMaterialSerializer
class OtherMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, DestroyModelMixin, GenericViewSet):
"""
其他物料-增删改查
"""
perms_map = {'*':'*'}
queryset = SubplanMaterial.objects.select_related('material').filter(type=3)
serializer_class = OutputMaterialSerializer
filterset_fields = ['subproduction']
ordering = ['sort', '-create_time']
def get_serializer_class(self):
if self.action == 'list':
return SubplanMaterialListSerializer
return OtherMaterialSerializer
class UsedStepViewSet(OptimizationMixin, CreateModelMixin, DestroyModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
"""
产品生产子工序表

View File

@ -60,7 +60,8 @@ class SubProductionProgress(BaseModel):
"""
type_choices=(
(1, '输入物料'),
(2, '输出物料')
(2, '输出物料'),
(3, '工具工装')
)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, related_name='progress_subplan')
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)

View File

@ -5,7 +5,7 @@ from apps.em.models import Equipment
from apps.em.serializers import EquipmentSerializer
from apps.inm.models import MaterialBatch
from apps.inm.serializers import MaterialBatchSerializer
from apps.mtm.models import InputMaterial, OutputMaterial, Step, SubProduction, UsedStep
from apps.mtm.models import Step, SubProduction, UsedStep
from apps.system.mixins import CreateUpdateModelAMixin
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
@ -87,10 +87,8 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
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))
for m in InputMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
SubProductionProgress.objects.create(material=m.material, type=1, count=m.count*production_plan.count, subproduction_plan=instance)
for m in OutputMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
SubProductionProgress.objects.create(material=m.material, type=2, count=m.count*production_plan.count, subproduction_plan=instance)
for m in SubProduction.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
SubProductionProgress.objects.create(material=m.material, type=m.type, count=m.count*production_plan.count, subproduction_plan=instance)
production_plan.is_planed=True
production_plan.save()
return Response()

View File

@ -1,4 +1,5 @@
from django.db.models import query
from rest_framework.utils import serializer_helpers
from rest_framework.views import APIView
from apps.system.models import User
from apps.wf.filters import TicketFilterSet

View File

@ -2,7 +2,7 @@ from django.db import models
from django.db.models.base import Model
import django.utils.timezone as timezone
from django.db.models.query import QuerySet
from apps.pm.models import SubProductionPlan
from apps.pm.models import ProductionPlan, SubProductionPlan
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
@ -33,7 +33,8 @@ class WProduct(CommonAModel):
act_state = models.IntegerField('进行状态', default=0)
parent = models.ForeignKey('self', verbose_name='上一级', on_delete=models.CASCADE, db_constraint=False)
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
class WProductForm(CommonAModel):
"""

View File

@ -2,10 +2,13 @@ from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from apps.inm.models import FIFO, FIFODetail, MaterialBatch, WareHouse
from apps.mtm.models import Material
from apps.mtm.serializers import MaterialSimpleSerializer
from apps.pm.models import SubProductionPlan
from apps.pm.models import SubProductionPlan, SubProductionProgress
from django.utils import timezone
from apps.wpm.models import WMaterial
class PickDetailSerializer(serializers.Serializer):
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
batch = serializers.CharField(label='物料批次')
@ -18,6 +21,9 @@ class PickSerializer(serializers.Serializer):
def create(self, validated_data):
picks = validated_data.pop('picks')
sp = validated_data['subproduction_plan']
if sp.is_picked:
raise serializers.ValidationError('该子计划已领料')
for i in picks:
try:
instance = MaterialBatch.objects.get(material=i['material'], batch=i['batch'])
@ -25,6 +31,7 @@ class PickSerializer(serializers.Serializer):
raise serializers.ValidationError('物料不足')
except:
raise serializers.ValidationError('物料不存在')
# 创建出库记录
operator = self.context['request'].user
validated_data['create_by'] = operator
validated_data['operator'] = operator
@ -32,6 +39,33 @@ class PickSerializer(serializers.Serializer):
validated_data['inout_date'] = timezone.now()
fifo = FIFO.objects.create(validated_data)
for i in picks:
# 更新出库详情
i['fifo'] = fifo
FIFODetail.objects.create(**i)
return fifo
# 更新车间物料
wm = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \
process=validated_data['process'],defaults={
'material':i['material'],
'batch':i['batch'],
'process':validated_data['process'],
'workshop':validated_data['workshop'],
'count':0
})
wm.count = wm.count + i['pick_count']
wm.save()
# 更新子计划进度
spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1)
spp.count_real = spp.count_real + i['pick_count']
spp.save()
sp.is_picked=True
sp.save()
return fifo
class WMaterialListSerializer(serializers.ModelSerializer):
"""
车间物料
"""
material_ = MaterialSimpleSerializer(source='material', read_only=True)
class Meta:
model = Material
fields = '__all__'

View File

@ -1,21 +1,29 @@
from django.shortcuts import render
from rest_framework.generics import CreateAPIView, GenericAPIView
from rest_framework.mixins import ListModelMixin
from rest_framework.utils.field_mapping import get_relation_kwargs
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from apps.pm.serializers import SubProductionPlanUpdateSerializer
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from apps.wpm.models import WMaterial
from apps.wpm.serializers import PickSerializer
from apps.wpm.serializers import PickSerializer, WMaterialListSerializer
from rest_framework.response import Response
# Create your views here.
class WMaterialViewSet(CreateUpdateModelAMixin, GenericViewSet):
class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
"""
领料
车间物料表
"""
perms_map={'*':'*'}
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickSerializer)
queryset = WMaterial.objects.select_related('material').all()
serializer_class = WMaterialListSerializer
filterset_fields = ['material', 'process', 'workshop']
ordering_fields = ['material__number']
ordering = ['material__number']
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PickSerializer)
def pick(self, request, pk=None):
"""
领料