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

This commit is contained in:
shilixia 2021-11-17 15:14:05 +08:00
commit eaea0cdb7c
16 changed files with 248 additions and 86 deletions

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.6 on 2021-11-17 06:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inm', '0016_auto_20211112_1124'),
]
operations = [
migrations.AlterField(
model_name='iproduct',
name='number',
field=models.CharField(default=1, max_length=50, unique=True, verbose_name='物品编号'),
preserve_default=False,
),
]

View File

@ -97,7 +97,7 @@ class IProduct(BaseModel):
"""
具体产品条目
"""
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
number = models.CharField('物品编号', unique=True, max_length=50)
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, default='')

View File

@ -37,6 +37,14 @@ class MaterialBatchSerializer(serializers. ModelSerializer):
model = MaterialBatch
fields = '__all__'
class IProductListSerializer(serializers.ModelSerializer):
material_= MaterialSimpleSerializer(source='material', read_only=True)
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
class Meta:
model = IProduct
fields = '__all__'
class FIFOListSerializer(serializers.ModelSerializer):
auditor_ = UserSimpleSerializer(source='auditor', read_only=True)
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)

View File

@ -1,7 +1,7 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from apps.inm.models import FIFOItemProduct, Inventory, MaterialBatch, FIFO, FIFOItem
from apps.inm.models import FIFOItemProduct, IProduct, Inventory, MaterialBatch, FIFO, FIFOItem
def update_inm(instance:FIFO, type:int=1):
@ -23,6 +23,19 @@ def update_inm(instance:FIFO, type:int=1):
o2.save()
material.count = material.count + i.count
material.save()
# 创建IProduct
ips2 = []
for m in FIFOItemProduct.objects.filter(fifoitem=i):
ip = {}
ip['warehouse'] = warehouse
ip['batch'] = i.batch
ip['wproduct'] = m.wproduct
ip['number'] = m.number
ip['material'] = m.material
ips2.append(IProduct(**ip))
IProduct.objects.bulk_create(ips2)
elif instance.type in [FIFO.FIFO_TYPE_DO_OUT]: # 生产领料
# 更新相关表
for i in FIFOItem.objects.filter(fifo=instance):
@ -37,3 +50,7 @@ def update_inm(instance:FIFO, type:int=1):
material.count = material.count - i.count
material.save()
# 删除IProduct
numbers = FIFOItemProduct.objects.filter(fifoitem=i).values_list('number', flat=True)
IProduct.objects.filter(number__in=numbers).delete()

View File

@ -1,6 +1,6 @@
from django.db.models import base
from rest_framework import urlpatterns
from apps.inm.views import FIFOItemViewSet, FIFOViewSet, MaterialBatchViewSet, WarehouseViewSet,InventoryViewSet
from apps.inm.views import FIFOItemViewSet, FIFOViewSet, IProductViewSet, MaterialBatchViewSet, WarehouseViewSet,InventoryViewSet
from django.urls import path, include
from rest_framework.routers import DefaultRouter
@ -10,6 +10,7 @@ router.register('inventory', InventoryViewSet, basename='inventory')
router.register('materialbatch', MaterialBatchViewSet, basename='materialbatch')
router.register('fifo', FIFOViewSet, basename='fifo'),
router.register('fifoitem', FIFOItemViewSet, basename='fifoitem')
router.register('iproduct', IProductViewSet, basename='iproduct')
urlpatterns = [
path('', include(router.urls)),
]

View File

@ -5,8 +5,8 @@ from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveMod
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from apps.inm.filters import MbFilterSet
from apps.inm.models import FIFO, FIFOItem, MaterialBatch, WareHouse,Inventory
from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse,Inventory
from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
from apps.inm.signals import update_inm
from apps.qm.models import TestRecordItem
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
@ -161,3 +161,15 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
update_inm(obj) # 更新库存
return Response()
class IProductViewSet(ListModelMixin, GenericViewSet):
"""
半成品库存表
"""
perms_map = {'*': '*'}
queryset = IProduct.objects.select_related('material', 'warehouse').all()
serializer_class = IProductListSerializer
filterset_fields = ['material', 'warehouse', 'batch']
search_fields = []
ordering_fields = ['create_time']
ordering = ['-create_time']

View File

@ -0,0 +1,43 @@
# Generated by Django 3.2.6 on 2021-11-16 08:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0033_alter_recordformfield_rule_expression'),
]
operations = [
migrations.RemoveField(
model_name='recordformfield',
name='boolean_field_display',
),
migrations.AddField(
model_name='recordformfield',
name='display_expression',
field=models.TextField(blank=True, null=True, verbose_name='字段展现表达式'),
),
migrations.AddField(
model_name='recordformfield',
name='help_text',
field=models.TextField(blank=True, null=True, verbose_name='说明'),
),
migrations.AddField(
model_name='recordformfield',
name='is_hidden',
field=models.BooleanField(default=False, verbose_name='是否隐藏'),
),
migrations.AddField(
model_name='recordformfield',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.recordformfield', verbose_name=''),
),
migrations.AlterField(
model_name='recordformfield',
name='field_choice',
field=models.JSONField(blank=True, default=list, help_text='radio,checkbox,select,multiselect类型可供选择的选项格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号', null=True, verbose_name='radio、checkbox、select的选项'),
),
]

View File

@ -144,17 +144,23 @@ class RecordFormField(CommonAModel):
field_type = models.CharField('类型', max_length=50, choices=field_type_choices)
field_key = models.CharField('字段标识', max_length=50, help_text='字段类型请尽量特殊,避免与系统中关键字冲突')
field_name = models.CharField('字段名称', max_length=50)
boolean_field_display = models.JSONField('布尔类型显示名', default=dict, blank=True, null=True,
help_text='当为布尔类型时候,可以支持自定义显示形式。{"1":"","0":""}或{"1":"需要","0":"不需要"},注意数字也需要引号')
field_choice = models.JSONField('radio、checkbox、select的选项', default=dict, blank=True, null=True,
field_choice = models.JSONField('radio、checkbox、select的选项', default=list, blank=True, null=True,
help_text='radio,checkbox,select,multiselect类型可供选择的选项格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号')
help_text = models.TextField('说明', null=True, blank=True)
sort = models.IntegerField('排序号', default=1)
need_judge = models.BooleanField('需要判定项目', default=False)
high_limit = models.FloatField('上限值', null=True, blank=True)
high_rule = models.IntegerField('上限规则', choices=high_rule_choices, null=True, blank=True)
low_limit = models.FloatField('下限值', null=True, blank=True)
low_rule = models.IntegerField('下限规则', choices=low_rule_choices, null=True, blank=True)
need_judge = models.BooleanField('需要判定项目', default=False)
rule_expression = models.TextField('判定表达式', null=True, blank=True)
display_expression = models.TextField('字段展现表达式', null=True, blank=True)
is_hidden = models.BooleanField('是否隐藏', default=False)
parent = models.ForeignKey('self', verbose_name='', on_delete=models.CASCADE, null=True, blank=True)
class Meta:
verbose_name = '记录表格字段'

View File

@ -215,7 +215,7 @@ class RecordFormDetailSerializer(serializers.ModelSerializer):
class RecordFormFieldCreateSerializer(serializers.ModelSerializer):
class Meta:
model = RecordFormField
fields = ['form', 'field_type', 'field_key', 'field_name', 'boolean_field_display', 'field_choice', 'sort', 'need_judge', 'high_limit', 'high_rule', 'low_limit', 'low_rule', 'rule_expression']
fields = '__all__'
def validate(self, data):
if RecordFormField.objects.filter(field_key=data['field_key'], form=data['form'], is_deleted=False).exists():
@ -225,7 +225,7 @@ class RecordFormFieldCreateSerializer(serializers.ModelSerializer):
class RecordFormFieldUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = RecordFormField
fields = ['field_type', 'field_name', 'boolean_field_display', 'field_choice', 'sort', 'need_judge', 'high_limit', 'high_rule', 'low_limit', 'low_rule', 'rule_expression']
exclude = ['field_key']
class RecordFormFieldSimpleSerializer(serializers.ModelSerializer):
class Meta:

View File

@ -57,6 +57,8 @@ class SubProductionPlan(CommonAModel):
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
is_picked = models.BooleanField('是否已领料', default=False)
# wproducts = models.JSONField('半成品表', default=list, blank=True)
class Meta:
verbose_name = '子生产计划'
verbose_name_plural = verbose_name

View File

@ -13,7 +13,7 @@ def update_subplan_main(sender, instance, created, **kwargs):
subplan.main_product = instance.material
subplan.main_count = instance.count
subplan.main_count_real = instance.count_real
if subplan.main_count == instance.count_real:
if subplan.main_count >= instance.count_real:
subplan.state = 4
subplan.save()

View File

@ -17,6 +17,7 @@ from rest_framework.exceptions import APIException
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import F
from utils.tools import ranstr
# Create your views here.
def updateOrderPlanedCount(order):
@ -59,7 +60,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
pass
else:
raise APIException('排产数量错误')
instance = serializer.save(create_by=request.user, product=order.product)
instance = serializer.save(create_by=request.user, product=order.product, number='JH-'+ranstr(7))
updateOrderPlanedCount(instance.order)
return Response()

View File

@ -20,7 +20,7 @@ class WMaterial(BaseModel):
class WProduct(CommonAModel):
"""
半成品/成品
动态半成品/成品
"""
WPR_ACT_STATE_DOING = 1
WPR_ACT_STATE_TOTEST = 2
@ -45,7 +45,6 @@ class WProduct(CommonAModel):
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
class Operation(CommonAModel):
"""
生产操作

View File

@ -1,6 +1,6 @@
from rest_framework import serializers, exceptions
from rest_framework.serializers import ModelSerializer
from apps.inm.models import FIFO, FIFOItem, MaterialBatch, WareHouse
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse
from apps.inm.signals import update_inm
from apps.mtm.models import Material, RecordForm, Step
from apps.mtm.serializers import MaterialSimpleSerializer, StepSimpleSerializer
@ -13,15 +13,21 @@ from apps.system.serializers import UserSimpleSerializer
from apps.wpm.models import Operation, WMaterial, WProduct, OperationRecord, OperationRecordItem
from django.db import transaction
class PickHalfSerializer(serializers.Serializer):
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
required=False) # 从半成品表里直接修改状态
class PickDetailSerializer(serializers.Serializer):
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
batch = serializers.CharField(label='物料批次', allow_blank=True)
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
pick_count = serializers.IntegerField(label="领料数量", required=False)
iproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), label='库存半成品ID'),
required=False)
class PickSerializer(serializers.Serializer):
subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID")
picks = PickDetailSerializer(many=True)
picks = PickDetailSerializer(many=True) # 从库存里拿
def create(self, validated_data):
picks = validated_data.pop('picks')
@ -38,16 +44,33 @@ class PickSerializer(serializers.Serializer):
# except:
# raise exceptions.ValidationError('物料不存在')
# 创建出库记录
with transaction.atomic():
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user)
for i in picks:
# 更新出库详情
i['count'] = i.pop('pick_count', 0)
# 是否勾选每一个
if 'iproducts' in i and len(i['iproducts'])>0:
i['count'] = len(i['iproducts'])
isLowLevel = True
if i['count']>0:
i['fifo'] = fifo
i['is_testok'] = True # 默认检测合格
i['subproduction_plan'] = sp
FIFOItem.objects.create(**i)
fifoitem = FIFOItem.objects.create(**i)
# 创建再下一个层级
if isLowLevel:
mls = []
for m in i['iproducts']:
ml = {}
ml['material'] = m.material
ml['number'] = m.number
ml['wproduct'] = m.wproduct
ml['fifoitem'] = fifoitem
mls.append(FIFOItemProduct(**ml))
FIFOItemProduct.objects.bulk_create(mls)
# 更新车间物料
wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \
subproduction_plan=sp,defaults={
@ -62,6 +85,12 @@ class PickSerializer(serializers.Serializer):
spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1)
spp.count_pick = spp.count_pick + i['count']
spp.save()
# 更新半成品表
wproducts = WProduct.objects.filter(pk__in=[x.wproduct for x in i['iproducts']])
first_step = Step.objects.get(pk=sp.steps[0].id)
wproducts.update(p_state=first_step, is_executed=False,
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
subproduction_plan=sp, production_plan=sp.production_plan)
sp.is_picked=True
sp.state = 3 #生产中
sp.state_date_real = timezone.now() #实际开工日期
@ -183,7 +212,7 @@ class WpmTestRecordItemCreateSerializer(serializers.ModelSerializer):
class WpmTestRecordCreateSerializer(serializers.ModelSerializer):
record_data = WpmTestRecordItemCreateSerializer(many=True)
wproduct = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), required=True)
is_testok = serializers.BooleanField()
is_testok = serializers.BooleanField(required=False)
class Meta:
model = TestRecord
fields = ['form', 'record_data', 'is_testok', 'wproduct']

View File

@ -5,7 +5,7 @@ from rest_framework.utils import serializer_helpers
from rest_framework.utils.field_mapping import get_relation_kwargs
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
from apps.inm.signals import update_inm
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial
from apps.mtm.serializers import RecordFormDetailSerializer
@ -17,13 +17,14 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from apps.wpm.models import WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
from apps.wpm.services import WpmServies
from django.utils import timezone
from utils.tools import ranstr
# Create your views here.
class WPlanViewSet(ListModelMixin, GenericViewSet):
"""
@ -37,6 +38,33 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
ordering_fields = []
ordering = ['-id']
@action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfSerializer)
@transaction.atomic
def pick_half(self, request, pk=None):
"""
领半成品
"""
sp = self.get_object()
if request.method=='GET':
"""
领半成品
"""
mIds = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
material__type=Material.MA_TYPE_HALFGOOD).values_list('material', flat=True)
queyset = WProduct.objects.filter(is_hidden=False, m_state__in=mIds, act_state=WProduct.WPR_ACT_STATE_OK)
return Response(WProductListSerializer(instance=queyset, many=True).data)
elif request.method=='POST':
serializer= PickHalfSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.data
wps = WProduct.objects.filter(pk__in=[x for x in vdata['wproducts']])
first_step = Step.objects.get(pk=sp.steps[0].id)
wps.update(p_state=first_step, is_executed=False,
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
subproduction_plan=sp, production_plan=sp.production_plan)
return Response()
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer)
@transaction.atomic
def putin(self, request, pk=None):
@ -49,6 +77,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
subplan = self.get_object()
material = subplan.main_product
batch = subplan.production_plan.number
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
wproducts = WProduct.objects.filter(subproduction_plan=subplan,
act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False)
if wproducts.exists():
@ -60,7 +89,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
fifoitem = FIFOItem()
fifoitem.is_tested = True
fifoitem.is_testok = True
fifoitem.warehouse = vdata['warehouse']
fifoitem.warehouse = warehouse
fifoitem.material = material
fifoitem.count = wproducts.count()
fifoitem.batch = batch
@ -81,7 +110,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
ips2 = []
for i in wproducts:
ip = {}
ip['warehouse'] = vdata['warehouse']
ip['warehouse'] = warehouse
ip['batch'] = batch
ip['wproduct'] = i
ip['number'] = i.number
@ -90,7 +119,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
IProduct.objects.bulk_create(ips2)
# 更新库存并修改半成品进行状态
update_inm(fifo)
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=vdata['warehouse'])
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse)
return Response()
@ -116,63 +145,6 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
serializer.save()
return Response()
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer)
@transaction.atomic
def putin(self, request, pk=None):
"""
半成品入库
"""
serializer= WproductPutInSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.data
wproduct = self.get_object()
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
raise exceptions.APIException('半成品不可入库')
material = wproduct.m_state
batch = wproduct.production_plan.number
# 创建入库记录
remark = vdata.get('remark', '')
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark)
# 创建入库明细
fifoitem = FIFOItem()
fifoitem.is_tested = True
fifoitem.is_testok = True
fifoitem.warehouse = vdata['warehouse']
fifoitem.material = material
fifoitem.count = 1 # 单个半成品入库
fifoitem.batch = batch
fifoitem.fifo = fifo
fifoitem.subproduction_plan = wproduct.subproduction_plan
fifoitem.save()
# 创建入库明细半成品
ips = []
for i in [wproduct]:
ip = {}
ip['fifoitem'] = fifoitem
ip['wproduct'] = i
ip['number'] = i.number
ip['material'] = material
ips.append(FIFOItemProduct(**ip))
FIFOItemProduct.objects.bulk_create(ips)
# 创建IProduct
ips2 = []
for i in [wproduct]:
ip = {}
ip['warehouse'] = vdata['warehouse']
ip['batch'] = batch
ip['wproduct'] = i
ip['number'] = i.number
ip['material'] = material
ips2.append(IProduct(**ip))
IProduct.objects.bulk_create(ips2)
# 更新库存并修改半成品进行状态
update_inm(fifo)
wproduct.act_state=WProduct.WPR_ACT_STATE_INM
wproduct.warehouse=vdata['warehouse']
wproduct.save()
return Response()
class WProductViewSet(ListModelMixin, GenericViewSet):
"""
半成品
@ -221,20 +193,66 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
if obj.is_testok:
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
if wproduct.number is None: # 产生半成品编号
wproduct.number = 'BCP' + str(timezone.now())
wproduct.number = 'WP-'+ranstr(7)
wproduct.save()
# 更新子计划状态
# 获取该子计划主产品数, 更新进度
main_count = WProduct.objects.filter(subproduction_plan=wproduct.subproduction_plan, act_stae=WProduct.WPR_ACT_STATE_OK).count()
# 更新子计划主产品数
instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
instance.count_real = main_count
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题
instance.save()
else:# 如果不合格
pass
return Response()
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer)
@transaction.atomic
def putin(self, request, pk=None):
"""
半成品入库
"""
serializer= WproductPutInSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.data
wproduct = self.get_object()
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
raise exceptions.APIException('半成品不可入库')
material = wproduct.m_state
batch = wproduct.production_plan.number
# 创建入库记录
remark = vdata.get('remark', '')
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark)
# 创建入库明细
fifoitem = FIFOItem()
fifoitem.is_tested = True
fifoitem.is_testok = True
fifoitem.warehouse = warehouse
fifoitem.material = material
fifoitem.count = 1 # 单个半成品入库
fifoitem.batch = batch
fifoitem.fifo = fifo
fifoitem.subproduction_plan = wproduct.subproduction_plan
fifoitem.save()
# 创建入库明细半成品
ips = []
for i in [wproduct]:
ip = {}
ip['fifoitem'] = fifoitem
ip['wproduct'] = i
ip['number'] = i.number
ip['material'] = material
ips.append(FIFOItemProduct(**ip))
FIFOItemProduct.objects.bulk_create(ips)
# 更新库存并修改半成品进行状态
update_inm(fifo)
wproduct.act_state=WProduct.WPR_ACT_STATE_INM
wproduct.warehouse=warehouse
wproduct.save()
return Response()
class OperationViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
"""
生产操作记录

7
hb_server/utils/tools.py Normal file
View File

@ -0,0 +1,7 @@
import random
import string
def ranstr(num):
salt = ''.join(random.sample(string.ascii_letters + string.digits, num))
return salt
ranstr(10)