增加采购入库功能
This commit is contained in:
parent
ee09543227
commit
3bd4cb014e
|
@ -0,0 +1,86 @@
|
||||||
|
# Generated by Django 3.2.6 on 2021-10-25 07:33
|
||||||
|
|
||||||
|
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),
|
||||||
|
('wpm', '__first__'),
|
||||||
|
('mtm', '0025_outputmaterial_is_main'),
|
||||||
|
('pm', '0007_auto_20211025_1533'),
|
||||||
|
('inm', '0004_auto_20210929_0842'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='inout_date',
|
||||||
|
field=models.DateField(default=django.utils.timezone.now, verbose_name='出入库日期'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='operator',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='system.user', verbose_name='操作人'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='subproduction_plan',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='pm.subproductionplan', verbose_name='关联子生产计划'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='warehouse',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='inm.warehouse', verbose_name='仓库'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='materialbatch',
|
||||||
|
name='batch',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True, unique=True, verbose_name='批次号'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='IProduct',
|
||||||
|
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='删除标记')),
|
||||||
|
('state', models.IntegerField(default=1, verbose_name='物品状态')),
|
||||||
|
('number', models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='物品编号')),
|
||||||
|
('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='所在仓库')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='FIFODetail',
|
||||||
|
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='删除标记')),
|
||||||
|
('count', models.IntegerField(default=0, verbose_name='数量')),
|
||||||
|
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
|
||||||
|
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fifodetail_create_by', to=settings.AUTH_USER_MODEL, 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='fifodetail_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Generated by Django 3.2.6 on 2021-10-27 01:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '__first__'),
|
||||||
|
('inm', '0005_auto_20211025_1533'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifodetail',
|
||||||
|
name='fifo',
|
||||||
|
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='关联的动态产品'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -41,7 +41,7 @@ class MaterialBatch(BaseModel):
|
||||||
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
||||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||||
count = models.IntegerField('存量', default=0)
|
count = models.IntegerField('存量', default=0)
|
||||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
batch = models.CharField('批次号', max_length=100, null=True, blank=True, unique=True)
|
||||||
expiration_date = models.DateField('有效期', null=True, blank=True)
|
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '库存表'
|
verbose_name = '库存表'
|
||||||
|
@ -60,22 +60,37 @@ class FIFO(CommonAModel):
|
||||||
(4, '生产入库')
|
(4, '生产入库')
|
||||||
)
|
)
|
||||||
type = models.IntegerField('出入库类型', default=1)
|
type = models.IntegerField('出入库类型', default=1)
|
||||||
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||||
operator = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE)
|
operator = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE)
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True)
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True)
|
||||||
|
inout_date = models.DateField('出入库日期')
|
||||||
|
|
||||||
# class FIFODetail(CommonAModel):
|
|
||||||
# """
|
|
||||||
# 领料详细记录
|
|
||||||
# """
|
|
||||||
|
|
||||||
class Product(CommonAModel):
|
class FIFODetail(BaseModel):
|
||||||
"""
|
"""
|
||||||
具体产品
|
出入库详细记录
|
||||||
"""
|
"""
|
||||||
|
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||||
|
count = models.IntegerField('数量', default=0)
|
||||||
|
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||||
|
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
|
class IProduct(BaseModel):
|
||||||
|
"""
|
||||||
|
具体产品条目
|
||||||
|
"""
|
||||||
|
inm_product_state_choices = (
|
||||||
|
(1, '可用'),
|
||||||
|
(2, '锁定'),
|
||||||
|
(3, '已消耗')
|
||||||
|
)
|
||||||
|
state = models.IntegerField('物品状态', default=1)
|
||||||
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||||
batch = models.CharField('所属批次号', max_length=100, null=True, blank=True)
|
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)
|
||||||
fifos = models.JSONField('关联出入库记录', default=list, blank=True)
|
fifos = models.JSONField('关联出入库记录', default=list, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from apps.inm.models import WareHouse,Inventory
|
from apps.inm.models import FIFO, FIFODetail, IProduct, WareHouse,Inventory
|
||||||
|
|
||||||
from apps.system.serializers import UserSimpleSerializer
|
from apps.system.serializers import UserSimpleSerializer
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||||
|
@ -32,3 +32,53 @@ class InventoryCreateUpdateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Inventory
|
model = Inventory
|
||||||
fields = ['material', 'count', 'warehouse']
|
fields = ['material', 'count', 'warehouse']
|
||||||
|
|
||||||
|
class IProductInPurSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = IProduct
|
||||||
|
fields = ['number']
|
||||||
|
|
||||||
|
class FIFODetailInPurSerializer(serializers.ModelSerializer):
|
||||||
|
details = IProductInPurSerializer(many=True, required=False)
|
||||||
|
class Meta:
|
||||||
|
model = FIFODetail
|
||||||
|
fields = ['material', 'count', 'batch', 'details']
|
||||||
|
|
||||||
|
class FIFOInPurSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
采购入库序列化
|
||||||
|
"""
|
||||||
|
details = FIFODetailInPurSerializer(many=True)
|
||||||
|
class Meta:
|
||||||
|
model = FIFO
|
||||||
|
fields = ['warehouse', 'operator', 'details', 'inout_date']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
details = validated_data.pop('details')
|
||||||
|
if len(details)>0:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise serializers.ValidationError('没有入库内容')
|
||||||
|
validated_data['type'] = 3
|
||||||
|
obj = FIFO(**validated_data)
|
||||||
|
obj.save()
|
||||||
|
for i in details:
|
||||||
|
if 'details' in i:
|
||||||
|
p_details = i.pop('details')
|
||||||
|
if len(p_details) != i['count']:
|
||||||
|
raise serializers.ValidationError('数目对不上')
|
||||||
|
else:
|
||||||
|
serialier = FIFODetailInPurSerializer(data=i)
|
||||||
|
fifod = serialier.save(fifo=obj)
|
||||||
|
p_list = []
|
||||||
|
for x in p_details:
|
||||||
|
x['state'] = 1
|
||||||
|
x['material'] = i['material']
|
||||||
|
x['warehouse'] = validated_data['warehouse']
|
||||||
|
x['batch'] = i['batch']
|
||||||
|
x['fifos'] = [fifod.id]
|
||||||
|
p_list.append(IProduct(**x))
|
||||||
|
IProduct.objects.bulk_create(p_list)
|
||||||
|
else:
|
||||||
|
serialier = FIFODetailInPurSerializer(data=i)
|
||||||
|
serialier.save(fifo=obj)
|
|
@ -1,12 +1,13 @@
|
||||||
from django.db.models import base
|
from django.db.models import base
|
||||||
from rest_framework import urlpatterns
|
from rest_framework import urlpatterns
|
||||||
from apps.inm.views import WarehouseViewSet,InventoryViewSet
|
from apps.inm.views import FIFOViewSet, WarehouseViewSet,InventoryViewSet
|
||||||
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()
|
router = DefaultRouter()
|
||||||
router.register('warehouse', WarehouseViewSet, basename='warehouse')
|
router.register('warehouse', WarehouseViewSet, basename='warehouse')
|
||||||
router.register('inventory', InventoryViewSet, basename='inventory')
|
router.register('inventory', InventoryViewSet, basename='inventory')
|
||||||
|
router.register('fifo', FIFOViewSet, basename='fifo')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from rest_framework import serializers
|
||||||
from rest_framework.mixins import ListModelMixin
|
from rest_framework.mixins import ListModelMixin
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
|
|
||||||
from apps.inm.models import WareHouse,Inventory
|
from apps.inm.models import WareHouse,Inventory
|
||||||
from apps.inm.serializers import WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer,InventoryCreateUpdateSerializer
|
from apps.inm.serializers import FIFOInPurSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer,InventoryCreateUpdateSerializer
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||||
|
@ -27,11 +28,27 @@ class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||||
|
|
||||||
class InventoryViewSet(ListModelMixin, GenericViewSet):
|
class InventoryViewSet(ListModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
物料基本信息-增删改查
|
仓库物料表
|
||||||
"""
|
"""
|
||||||
perms_map = {'*': '*'}
|
perms_map = {'*': '*'}
|
||||||
queryset = Inventory.objects.select_related('create_by').all()
|
queryset = Inventory.objects.select_related('create_by').all()
|
||||||
serializer_class = InventorySerializer
|
serializer_class = InventorySerializer
|
||||||
filterset_fields = []
|
filterset_fields = []
|
||||||
|
search_fields = ['material', 'warehouse']
|
||||||
ordering_fields = ['create_time']
|
ordering_fields = ['create_time']
|
||||||
ordering = ['-create_time']
|
ordering = ['-create_time']
|
||||||
|
|
||||||
|
class FIFOViewSet(GenericViewSet):
|
||||||
|
"""
|
||||||
|
出入库记录
|
||||||
|
"""
|
||||||
|
perms_map = {'*': '*'}
|
||||||
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=FIFOInPurSerializer)
|
||||||
|
def in_pur(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
采购入库
|
||||||
|
"""
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
serializer.save()
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.6 on 2021-10-25 07:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pm', '0006_alter_subproductionprogress_count_real'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='end_date_real',
|
||||||
|
field=models.DateField(blank=True, null=True, verbose_name='实际完工日期'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='start_date_real',
|
||||||
|
field=models.DateField(blank=True, null=True, verbose_name='实际开工日期'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -57,7 +57,7 @@ INSTALLED_APPS = [
|
||||||
'apps.sam',
|
'apps.sam',
|
||||||
'apps.qm',
|
'apps.qm',
|
||||||
'apps.pm',
|
'apps.pm',
|
||||||
# 'apps.wpm'
|
'apps.wpm'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
Loading…
Reference in New Issue