采购入库bug,领料需求
This commit is contained in:
parent
2a79fa9f2b
commit
1e361b5a6a
|
@ -0,0 +1,9 @@
|
|||
from django_filters import rest_framework as filters
|
||||
|
||||
from apps.mtm.models import Material
|
||||
from .models import MaterialBatch
|
||||
class MbFilterSet(filters.FilterSet):
|
||||
material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all())
|
||||
class Meta:
|
||||
model = MaterialBatch
|
||||
fields = ['material', 'warehouse']
|
|
@ -10,7 +10,6 @@ class Migration(migrations.Migration):
|
|||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('wpm', '__first__'),
|
||||
('mtm', '0025_outputmaterial_is_main'),
|
||||
('pm', '0007_auto_20211025_1533'),
|
||||
('inm', '0004_auto_20210929_0842'),
|
||||
|
@ -57,7 +56,6 @@ class Migration(migrations.Migration):
|
|||
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='所属批次号')),
|
||||
('fifos', models.JSONField(blank=True, default=list, verbose_name='关联出入库记录')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='iproduct_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('d_product', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='wpm.product', verbose_name='关联的动态产品')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料类型')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='iproduct_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.warehouse', verbose_name='所在仓库')),
|
||||
|
|
|
@ -7,7 +7,6 @@ import django.db.models.deletion
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wpm', '__first__'),
|
||||
('inm', '0005_auto_20211025_1533'),
|
||||
]
|
||||
|
||||
|
@ -18,9 +17,4 @@ class Migration(migrations.Migration):
|
|||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='inm.fifo', verbose_name='关联出入库'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='iproduct',
|
||||
name='d_product',
|
||||
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='wpm.product', verbose_name='关联的动态产品'),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -91,7 +91,7 @@ class IProduct(BaseModel):
|
|||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
batch = models.CharField('所属批次号', max_length=100, null=True, blank=True)
|
||||
d_product = models.ForeignKey('wpm.product', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True)
|
||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True)
|
||||
fifos = models.JSONField('关联出入库记录', default=list, blank=True)
|
||||
|
||||
|
||||
|
|
|
@ -59,6 +59,11 @@ class FIFODetailInPurSerializer(serializers.ModelSerializer):
|
|||
model = FIFODetail
|
||||
fields = ['material', 'count', 'batch', 'details']
|
||||
|
||||
class MaterialBatchQuerySerializer(serializers.Serializer):
|
||||
warehouse = serializers.IntegerField(label="仓库ID", required=False)
|
||||
materials = serializers.ListField(child=serializers.IntegerField(label="物料ID"), required=False)
|
||||
|
||||
|
||||
class FIFOInPurSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
采购入库序列化
|
||||
|
|
|
@ -18,6 +18,7 @@ def update_by_fifodetail(sender, instance, created, **kwargs):
|
|||
o1.save()
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=instance.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
|
||||
o2.count = o2.count + instance.count
|
||||
o2.save()
|
||||
material.count = material.count + 1
|
||||
material.save()
|
||||
|
|
|
@ -2,9 +2,10 @@ from django.shortcuts import render
|
|||
from rest_framework import serializers
|
||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.inm.filters import MbFilterSet
|
||||
|
||||
from apps.inm.models import FIFO, FIFODetail, MaterialBatch, WareHouse,Inventory
|
||||
from apps.inm.serializers import FIFODetailSerializer, FIFOInPurSerializer, FIFOListSerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
|
||||
from apps.inm.serializers import FIFODetailSerializer, FIFOInPurSerializer, FIFOListSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
@ -43,11 +44,22 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
|
|||
perms_map = {'*': '*'}
|
||||
queryset = MaterialBatch.objects.select_related('material', 'warehouse').all()
|
||||
serializer_class = MaterialBatchSerializer
|
||||
filterset_fields = ['material', 'warehouse']
|
||||
# filterset_fields = ['material', 'warehouse']
|
||||
filterset_class = MbFilterSet
|
||||
search_fields = []
|
||||
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()
|
||||
|
||||
class FIFODetailViewSet(ListModelMixin, GenericViewSet):
|
||||
"""
|
||||
出入库记录详情表
|
||||
|
@ -66,11 +78,13 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
|
|||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = FIFO.objects.select_related('warehouse', 'operator')
|
||||
serializer_class = FIFOListSerializer
|
||||
filterset_fields = ['warehouse']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'list':
|
||||
return FIFOListSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=FIFOInPurSerializer)
|
||||
def in_pur(self, request, pk=None):
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-29 02:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0008_subproductionprogress_count_current'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='subproductionprogress',
|
||||
name='count_current',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subproductionplan',
|
||||
name='is_picked',
|
||||
field=models.BooleanField(default=False, verbose_name='是否已领料'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subproductionprogress',
|
||||
name='count',
|
||||
field=models.FloatField(verbose_name='应出入数'),
|
||||
),
|
||||
]
|
|
@ -49,6 +49,7 @@ class SubProductionPlan(CommonAModel):
|
|||
state = models.IntegerField('状态', default=0)
|
||||
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
|
||||
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
||||
is_picked = models.BooleanField('是否已领料', default=False)
|
||||
class Meta:
|
||||
verbose_name = '子生产计划'
|
||||
verbose_name_plural = verbose_name
|
||||
|
@ -64,6 +65,5 @@ class SubProductionProgress(BaseModel):
|
|||
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)
|
||||
type = models.IntegerField('物料应用类型', default=1)
|
||||
count = models.IntegerField('应出入数')
|
||||
count = models.FloatField('应出入数')
|
||||
count_real = models.IntegerField('实际出入数', default=0)
|
||||
count_current = models.IntegerField('当前数量', default=0)
|
||||
|
|
|
@ -44,3 +44,6 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = SubProductionProgress
|
||||
fields = '__all__'
|
||||
|
||||
class PickNeedSerializer(serializers.Serializer):
|
||||
warehouse = serializers.IntegerField(label="仓库ID")
|
||||
|
|
|
@ -3,9 +3,11 @@ from rest_framework import serializers
|
|||
from rest_framework.views import APIView
|
||||
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.system.mixins import CreateUpdateModelAMixin
|
||||
from apps.pm.serializers import GenSubPlanSerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, 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
|
||||
|
@ -78,9 +80,9 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
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, subproduction_plan=instance)
|
||||
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, subproduction_plan=instance)
|
||||
SubProductionProgress.objects.create(material=m.material, type=2, count=m.count*production_plan.count, subproduction_plan=instance)
|
||||
production_plan.is_planed=True
|
||||
production_plan.save()
|
||||
return Response()
|
||||
|
@ -92,6 +94,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
perms_map = {'*': '*'}
|
||||
queryset = SubProductionPlan.objects.select_related('process', 'workshop')
|
||||
search_fields = []
|
||||
serializer_class = SubProductionPlanListSerializer
|
||||
filterset_fields = ['production_plan']
|
||||
ordering_fields = ['process__number']
|
||||
ordering = ['process__number']
|
||||
|
@ -101,7 +104,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
return SubProductionPlanListSerializer
|
||||
elif self.action == 'update':
|
||||
return SubProductionPlanUpdateSerializer
|
||||
return SubProductionPlanListSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get':'*'}, serializer_class=SubProductionProgressSerializer)
|
||||
def progress(self, request, pk=None):
|
||||
|
@ -137,15 +140,21 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
return Response()
|
||||
raise APIException('计划状态有误')
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickNeedSerializer)
|
||||
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)
|
||||
need = serializer.data
|
||||
materials = []
|
||||
for i in need:
|
||||
materials.append(i['material'])
|
||||
objs = MaterialBatch.objects.filter(warehouse=request.data['warehouse'], material__id__in=materials)
|
||||
have = MaterialBatchSerializer(instance=objs, many=True).data
|
||||
return Response({'need':need, 'have':have})
|
||||
|
||||
|
||||
class ResourceViewSet(GenericViewSet):
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-29 02:19
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('pm', '0009_auto_20211029_1017'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('mtm', '0025_outputmaterial_is_main'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='WProduct',
|
||||
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='删除标记')),
|
||||
('number', models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='物品编号')),
|
||||
('act_state', models.IntegerField(default=0, verbose_name='进行状态')),
|
||||
('remark', 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='wproduct_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('m_state', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='所属物料状态')),
|
||||
('p_state', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.step', verbose_name='所在步骤')),
|
||||
('parent', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='上一级')),
|
||||
('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子生产计划')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproduct_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WProductForm',
|
||||
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='删除标记')),
|
||||
('data', models.JSONField(blank=True, default=dict, verbose_name='记录的数据')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproductform_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('record_form', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.recordform', verbose_name='所用表格')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproductform_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WProductFlow',
|
||||
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='删除标记')),
|
||||
('wproduct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='产品')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WMaterial',
|
||||
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='删除标记')),
|
||||
('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,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -8,9 +8,18 @@ from utils.model import SoftModel, BaseModel
|
|||
from simple_history.models import HistoricalRecords
|
||||
from apps.mtm.models import Material, Step, RecordForm
|
||||
|
||||
class Product(CommonAModel):
|
||||
class WMaterial(BaseModel):
|
||||
"""
|
||||
产品(所有生产过程中出现过的)
|
||||
车间生产物料
|
||||
"""
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, 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)
|
||||
|
||||
class WProduct(CommonAModel):
|
||||
"""
|
||||
半成品/成品
|
||||
"""
|
||||
act_state_choices=(
|
||||
(0, '待执行'),
|
||||
|
@ -25,7 +34,7 @@ class Product(CommonAModel):
|
|||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE)
|
||||
|
||||
class ProductForm(CommonAModel):
|
||||
class WProductForm(CommonAModel):
|
||||
"""
|
||||
记录表格
|
||||
"""
|
||||
|
@ -33,8 +42,8 @@ class ProductForm(CommonAModel):
|
|||
data = models.JSONField('记录的数据', default=dict, blank=True)
|
||||
|
||||
|
||||
class ProductFlow(BaseModel):
|
||||
class WProductFlow(BaseModel):
|
||||
"""
|
||||
产品流转日志
|
||||
"""
|
||||
product = models.ForeignKey(Product, verbose_name='产品', on_delete=models.CASCADE)
|
||||
wproduct = models.ForeignKey(WProduct, verbose_name='产品', on_delete=models.CASCADE)
|
|
@ -1,6 +1,10 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
|
||||
class PickDetailSerializer(serializers.Serializer):
|
||||
material = serializers.IntegerField(label='物料ID')
|
||||
batch = serializers.CharField(label='物料批次')
|
||||
pick_count = serializers.IntegerField(label="领料数量")
|
||||
|
||||
class PickSerializer(serializers.Serializer):
|
||||
warehouse = serializers.IntegerField()
|
||||
warehouse = serializers.IntegerField(label="仓库ID")
|
Loading…
Reference in New Issue