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

This commit is contained in:
shilixia 2021-11-01 09:41:47 +08:00
commit bde43946f6
13 changed files with 140 additions and 21 deletions

View File

@ -79,6 +79,17 @@ class FIFOInPurSerializer(serializers.ModelSerializer):
pass
else:
raise serializers.ValidationError('没有入库内容')
for i in details:
# 校验批次
try:
obj = MaterialBatch.objects.get(batch=i['batch'])
if obj.warehouse != validated_data['warehouse']:
raise serializers.ValidationError('批次号{}在其他仓库已存在'.format(i['batch']))
except:
pass
# 创建采购入库
validated_data['type'] = 3
obj = FIFO(**validated_data)
obj.save()

View File

@ -20,6 +20,16 @@ def update_by_fifodetail(sender, instance, created, **kwargs):
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
o2.count = o2.count + instance.count
o2.save()
material.count = material.count + 1
material.count = material.count + instance.count
material.save()
elif fifo.type in [1]: # 生产领料
# 更新相关表
o1 = Inventory.objects.get(material=material, warehouse=warehouse)
o1.count = o1.count - instance.count
o1.save()
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=instance.batch)
o2.count = o2.count - instance.count
o2.save()
material.count = material.count - instance.count
material.save()

View File

@ -50,15 +50,16 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
ordering_fields = ['create_time']
ordering = ['-create_time']
# @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer)
# def query(self, request, pk=None):
# """
# 复杂查询
# """
# serializer = MaterialBatchQuerySerializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# queryset = self.queryset.filter()
# return Response()
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer)
def query(self, request, pk=None):
"""
复杂查询
"""
data = request.data
serializer = MaterialBatchQuerySerializer(data=data)
serializer.is_valid(raise_exception=True)
queryset = self.queryset.filter(warehouse__id=data['warehouse'], material__id__in=data['materials'])
return Response(MaterialBatchSerializer(instance=queryset, many=True).data)
class FIFODetailViewSet(ListModelMixin, GenericViewSet):
"""

View File

@ -22,7 +22,10 @@ class Material(CommonAModel):
)
unit_choices =(
('', ''),
('', '')
('', ''),
('', ''),
('m2', 'm2'),
('', '')
)
name = models.CharField('物料名称', max_length=100, unique=True)
number = models.CharField('编号', max_length=100, unique=True)

View File

@ -47,3 +47,6 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
class PickNeedSerializer(serializers.Serializer):
warehouse = serializers.IntegerField(label="仓库ID")
class PlanDestorySerializer(serializers.Serializer):
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')

View File

@ -7,7 +7,7 @@ from apps.inm.models import MaterialBatch
from apps.inm.serializers import MaterialBatchSerializer
from apps.mtm.models import InputMaterial, OutputMaterial, Step, SubProduction, UsedStep
from apps.system.mixins import CreateUpdateModelAMixin
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
from rest_framework.viewsets import GenericViewSet, ModelViewSet
@ -63,6 +63,14 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
updateOrderPlanedCount(instance.order)
return Response()
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PlanDestorySerializer)
def destory(self, request, pk=None):
"""
批量物理删除
"""
ProductionPlan.objects.filter(id__in=request.data.get('ids', [])).delete(soft=False)
return Response()
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=GenSubPlanSerializer)
def gen_subplan(self, request, pk=None):
"""
@ -95,7 +103,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
queryset = SubProductionPlan.objects.select_related('process', 'workshop')
search_fields = []
serializer_class = SubProductionPlanListSerializer
filterset_fields = ['production_plan']
filterset_fields = ['production_plan', 'process', 'state']
ordering_fields = ['process__number']
ordering = ['process__number']
@ -140,6 +148,16 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
return Response()
raise APIException('计划状态有误')
@action(methods=['get'], detail=True, perms_map={'get':'*'}, serializer_class=serializers.Serializer)
def pick_need_(self, request, pk=None):
"""
领料需求清单
"""
obj = self.get_object()
instance = SubProductionProgress.objects.filter(subproduction_plan=obj, type=1)
serializer = SubProductionProgressSerializer(instance=instance, many=True)
return Response(serializer.data)
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickNeedSerializer)
def pick_need(self, request, pk=None):
"""

View File

@ -77,7 +77,6 @@ class Migration(migrations.Migration):
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
('count', models.IntegerField(default=0, verbose_name='当前数量')),
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='关联物料')),
('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子计划')),
],
options={
'abstract': False,

View File

@ -0,0 +1,28 @@
# Generated by Django 3.2.6 on 2021-10-29 05:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('system', '0003_auto_20210812_0909'),
('mtm', '0025_outputmaterial_is_main'),
('wpm', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='wmaterial',
name='process',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mtm.process', verbose_name='关联大工序'),
preserve_default=False,
),
migrations.AddField(
model_name='wmaterial',
name='workshop',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='system.organization', verbose_name='生产车间'),
preserve_default=False,
),
]

View File

@ -6,13 +6,14 @@ from apps.pm.models import SubProductionPlan
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
from apps.mtm.models import Material, Step, RecordForm
from apps.mtm.models import Material, Process, Step, RecordForm
class WMaterial(BaseModel):
"""
车间生产物料
"""
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE)
workshop = models.ForeignKey(Organization, verbose_name='生产车间', on_delete=models.CASCADE)
process = models.ForeignKey(Process, verbose_name='关联大工序', on_delete=models.CASCADE)
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
count = models.IntegerField('当前数量', default=0)

View File

@ -1,10 +1,37 @@
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.pm.models import SubProductionPlan
from django.utils import timezone
class PickDetailSerializer(serializers.Serializer):
material = serializers.IntegerField(label='物料ID')
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
batch = serializers.CharField(label='物料批次')
pick_count = serializers.IntegerField(label="领料数量")
class PickSerializer(serializers.Serializer):
warehouse = serializers.IntegerField(label="仓库ID")
subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID")
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
picks = PickDetailSerializer(many=True)
def create(self, validated_data):
picks = validated_data.pop('picks')
for i in picks:
try:
instance = MaterialBatch.objects.get(material=i['material'], batch=i['batch'])
if instance.count < i['pick_count']:
raise serializers.ValidationError('物料不足')
except:
raise serializers.ValidationError('物料不存在')
operator = self.context['request'].user
validated_data['create_by'] = operator
validated_data['operator'] = operator
validated_data['type'] = 1
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

View File

@ -3,8 +3,10 @@ from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
from apps.wpm.views import WMaterialViewSet
router = DefaultRouter()
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
urlpatterns = [
path('', include(router.urls)),
]

View File

@ -1,12 +1,26 @@
from django.shortcuts import render
from rest_framework.generics import CreateAPIView, GenericAPIView
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.serializers import PickSerializer
from rest_framework.response import Response
# Create your views here.
class WpmPickView(CreateUpdateModelAMixin, CreateAPIView):
class WMaterialViewSet(CreateUpdateModelAMixin, GenericViewSet):
"""
领料
"""
pass
perms_map={'*':'*'}
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickSerializer)
def pick(self, request, pk=None):
"""
领料
"""
serializer= PickSerializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
serializer.save()
return Response()

View File

@ -68,6 +68,8 @@ urlpatterns = [
path('api/sam/', include('apps.sam.urls')),
path('api/qm/', include('apps.qm.urls')),
path('api/pm/', include('apps.pm.urls')),
path('api/wpm/', include('apps.wpm.urls')),
# 工具
path('api/utils/signature/', GenSignature.as_view()),