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/views.py b/hb_server/apps/inm/views.py index 244118e..c05693e 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'] + 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/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index b9c4474..5c9a3e0 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -183,7 +183,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..a1875a3 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -116,63 +116,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): """ 半成品 @@ -235,6 +178,63 @@ class WProductViewSet(ListModelMixin, GenericViewSet): 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 OperationViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): """ 生产操作记录