diff --git a/hb_server/apps/inm/migrations/0017_alter_iproduct_number.py b/hb_server/apps/inm/migrations/0017_alter_iproduct_number.py new file mode 100644 index 0000000..0e3931c --- /dev/null +++ b/hb_server/apps/inm/migrations/0017_alter_iproduct_number.py @@ -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, + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index c3902bf..57e3e17 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -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='') diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index f398159..7f050fc 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -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) diff --git a/hb_server/apps/inm/signals.py b/hb_server/apps/inm/signals.py index 66870a4..79d5a19 100644 --- a/hb_server/apps/inm/signals.py +++ b/hb_server/apps/inm/signals.py @@ -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): @@ -36,4 +49,8 @@ def update_inm(instance:FIFO, type:int=1): o2.save() 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() diff --git a/hb_server/apps/inm/urls.py b/hb_server/apps/inm/urls.py index 908d9b6..b0dbbd1 100644 --- a/hb_server/apps/inm/urls.py +++ b/hb_server/apps/inm/urls.py @@ -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)), ] diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 244118e..eccb166 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -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 @@ -160,4 +160,16 @@ class FIFOViewSet(ListModelMixin, GenericViewSet): obj.save() update_inm(obj) # 更新库存 return Response() - \ No newline at end of file + + +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'] \ No newline at end of file diff --git a/hb_server/apps/mtm/migrations/0034_auto_20211116_1603.py b/hb_server/apps/mtm/migrations/0034_auto_20211116_1603.py new file mode 100644 index 0000000..f20ef44 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0034_auto_20211116_1603.py @@ -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的选项'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index 050ff6f..6a92190 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -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 = '记录表格字段' diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 0d9b82f..b07ccb7 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -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: diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index bc59ec9..ddddd78 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -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 diff --git a/hb_server/apps/pm/signals.py b/hb_server/apps/pm/signals.py index 9d6cd6c..b07a67c 100644 --- a/hb_server/apps/pm/signals.py +++ b/hb_server/apps/pm/signals.py @@ -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() diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index a718880..2128aab 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -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() diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 83dfcf1..7424783 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -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): """ 生产操作 diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index b9c4474..c5bae06 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -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'] diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 3f61a0d..7a5f9c3 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -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): """ 生产操作记录 diff --git a/hb_server/utils/tools.py b/hb_server/utils/tools.py new file mode 100644 index 0000000..786b8f2 --- /dev/null +++ b/hb_server/utils/tools.py @@ -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) \ No newline at end of file