Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
bde43946f6
|
@ -79,6 +79,17 @@ class FIFOInPurSerializer(serializers.ModelSerializer):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise serializers.ValidationError('没有入库内容')
|
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
|
validated_data['type'] = 3
|
||||||
obj = FIFO(**validated_data)
|
obj = FIFO(**validated_data)
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
|
@ -20,6 +20,16 @@ def update_by_fifodetail(sender, instance, created, **kwargs):
|
||||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
|
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
|
||||||
o2.count = o2.count + instance.count
|
o2.count = o2.count + instance.count
|
||||||
o2.save()
|
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()
|
material.save()
|
||||||
|
|
||||||
|
|
|
@ -50,15 +50,16 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
|
||||||
ordering_fields = ['create_time']
|
ordering_fields = ['create_time']
|
||||||
ordering = ['-create_time']
|
ordering = ['-create_time']
|
||||||
|
|
||||||
# @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer)
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer)
|
||||||
# def query(self, request, pk=None):
|
def query(self, request, pk=None):
|
||||||
# """
|
"""
|
||||||
# 复杂查询
|
复杂查询
|
||||||
# """
|
"""
|
||||||
# serializer = MaterialBatchQuerySerializer(data=request.data)
|
data = request.data
|
||||||
# serializer.is_valid(raise_exception=True)
|
serializer = MaterialBatchQuerySerializer(data=data)
|
||||||
# queryset = self.queryset.filter()
|
serializer.is_valid(raise_exception=True)
|
||||||
# return Response()
|
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):
|
class FIFODetailViewSet(ListModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -22,7 +22,10 @@ class Material(CommonAModel):
|
||||||
)
|
)
|
||||||
unit_choices =(
|
unit_choices =(
|
||||||
('块', '块'),
|
('块', '块'),
|
||||||
('套', '套')
|
('套', '套'),
|
||||||
|
('个', '个'),
|
||||||
|
('m2', 'm2'),
|
||||||
|
('瓶', '瓶')
|
||||||
)
|
)
|
||||||
name = models.CharField('物料名称', max_length=100, unique=True)
|
name = models.CharField('物料名称', max_length=100, unique=True)
|
||||||
number = models.CharField('编号', max_length=100, unique=True)
|
number = models.CharField('编号', max_length=100, unique=True)
|
||||||
|
|
|
@ -47,3 +47,6 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class PickNeedSerializer(serializers.Serializer):
|
class PickNeedSerializer(serializers.Serializer):
|
||||||
warehouse = serializers.IntegerField(label="仓库ID")
|
warehouse = serializers.IntegerField(label="仓库ID")
|
||||||
|
|
||||||
|
class PlanDestorySerializer(serializers.Serializer):
|
||||||
|
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')
|
||||||
|
|
|
@ -7,7 +7,7 @@ from apps.inm.models import MaterialBatch
|
||||||
from apps.inm.serializers import MaterialBatchSerializer
|
from apps.inm.serializers import MaterialBatchSerializer
|
||||||
from apps.mtm.models import InputMaterial, OutputMaterial, Step, SubProduction, UsedStep
|
from apps.mtm.models import InputMaterial, OutputMaterial, Step, SubProduction, UsedStep
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin
|
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 rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
|
||||||
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
|
@ -63,6 +63,14 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
||||||
updateOrderPlanedCount(instance.order)
|
updateOrderPlanedCount(instance.order)
|
||||||
return Response()
|
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)
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=GenSubPlanSerializer)
|
||||||
def gen_subplan(self, request, pk=None):
|
def gen_subplan(self, request, pk=None):
|
||||||
"""
|
"""
|
||||||
|
@ -95,7 +103,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
queryset = SubProductionPlan.objects.select_related('process', 'workshop')
|
queryset = SubProductionPlan.objects.select_related('process', 'workshop')
|
||||||
search_fields = []
|
search_fields = []
|
||||||
serializer_class = SubProductionPlanListSerializer
|
serializer_class = SubProductionPlanListSerializer
|
||||||
filterset_fields = ['production_plan']
|
filterset_fields = ['production_plan', 'process', 'state']
|
||||||
ordering_fields = ['process__number']
|
ordering_fields = ['process__number']
|
||||||
ordering = ['process__number']
|
ordering = ['process__number']
|
||||||
|
|
||||||
|
@ -140,6 +148,16 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
return Response()
|
return Response()
|
||||||
raise APIException('计划状态有误')
|
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)
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickNeedSerializer)
|
||||||
def pick_need(self, request, pk=None):
|
def pick_need(self, request, pk=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -77,7 +77,6 @@ class Migration(migrations.Migration):
|
||||||
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
|
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
|
||||||
('count', models.IntegerField(default=0, verbose_name='当前数量')),
|
('count', models.IntegerField(default=0, verbose_name='当前数量')),
|
||||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', 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={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
|
|
|
@ -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,
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,13 +6,14 @@ from apps.pm.models import SubProductionPlan
|
||||||
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
|
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||||
from utils.model import SoftModel, BaseModel
|
from utils.model import SoftModel, BaseModel
|
||||||
from simple_history.models import HistoricalRecords
|
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):
|
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)
|
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
|
||||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||||
count = models.IntegerField('当前数量', default=0)
|
count = models.IntegerField('当前数量', default=0)
|
||||||
|
|
|
@ -1,10 +1,37 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.serializers import ModelSerializer
|
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):
|
class PickDetailSerializer(serializers.Serializer):
|
||||||
material = serializers.IntegerField(label='物料ID')
|
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
|
||||||
batch = serializers.CharField(label='物料批次')
|
batch = serializers.CharField(label='物料批次')
|
||||||
pick_count = serializers.IntegerField(label="领料数量")
|
pick_count = serializers.IntegerField(label="领料数量")
|
||||||
|
|
||||||
class PickSerializer(serializers.Serializer):
|
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
|
|
@ -3,8 +3,10 @@ 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
|
||||||
|
|
||||||
router = DefaultRouter()
|
from apps.wpm.views import WMaterialViewSet
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from rest_framework.generics import CreateAPIView, GenericAPIView
|
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 rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
|
from apps.pm.serializers import SubProductionPlanUpdateSerializer
|
||||||
|
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
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.
|
# 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()
|
|
@ -68,6 +68,8 @@ urlpatterns = [
|
||||||
path('api/sam/', include('apps.sam.urls')),
|
path('api/sam/', include('apps.sam.urls')),
|
||||||
path('api/qm/', include('apps.qm.urls')),
|
path('api/qm/', include('apps.qm.urls')),
|
||||||
path('api/pm/', include('apps.pm.urls')),
|
path('api/pm/', include('apps.pm.urls')),
|
||||||
|
path('api/wpm/', include('apps.wpm.urls')),
|
||||||
|
|
||||||
# 工具
|
# 工具
|
||||||
path('api/utils/signature/', GenSignature.as_view()),
|
path('api/utils/signature/', GenSignature.as_view()),
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue