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) 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, default='') batch = models.CharField('所属批次号', max_length=100, default='')

View File

@ -37,6 +37,14 @@ class MaterialBatchSerializer(serializers. ModelSerializer):
model = MaterialBatch model = MaterialBatch
fields = '__all__' 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): class FIFOListSerializer(serializers.ModelSerializer):
auditor_ = UserSimpleSerializer(source='auditor', read_only=True) auditor_ = UserSimpleSerializer(source='auditor', read_only=True)
create_by_ = UserSimpleSerializer(source='create_by', 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.db.models.signals import post_save
from django.dispatch import receiver 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): def update_inm(instance:FIFO, type:int=1):
@ -23,6 +23,19 @@ def update_inm(instance:FIFO, type:int=1):
o2.save() o2.save()
material.count = material.count + i.count material.count = material.count + i.count
material.save() 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]: # 生产领料 elif instance.type in [FIFO.FIFO_TYPE_DO_OUT]: # 生产领料
# 更新相关表 # 更新相关表
for i in FIFOItem.objects.filter(fifo=instance): for i in FIFOItem.objects.filter(fifo=instance):
@ -36,4 +49,8 @@ def update_inm(instance:FIFO, type:int=1):
o2.save() o2.save()
material.count = material.count - i.count material.count = material.count - i.count
material.save() 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 django.db.models import base
from rest_framework import urlpatterns 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 django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
@ -10,6 +10,7 @@ router.register('inventory', InventoryViewSet, basename='inventory')
router.register('materialbatch', MaterialBatchViewSet, basename='materialbatch') router.register('materialbatch', MaterialBatchViewSet, basename='materialbatch')
router.register('fifo', FIFOViewSet, basename='fifo'), router.register('fifo', FIFOViewSet, basename='fifo'),
router.register('fifoitem', FIFOItemViewSet, basename='fifoitem') router.register('fifoitem', FIFOItemViewSet, basename='fifoitem')
router.register('iproduct', IProductViewSet, basename='iproduct')
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), 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 rest_framework.viewsets import GenericViewSet, ModelViewSet
from apps.inm.filters import MbFilterSet from apps.inm.filters import MbFilterSet
from apps.inm.models import FIFO, FIFOItem, MaterialBatch, WareHouse,Inventory from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse,Inventory
from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOListSerializer, IProductListSerializer, InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
from apps.inm.signals import update_inm from apps.inm.signals import update_inm
from apps.qm.models import TestRecordItem from apps.qm.models import TestRecordItem
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
@ -160,4 +160,16 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
obj.save() obj.save()
update_inm(obj) # 更新库存 update_inm(obj) # 更新库存
return Response() 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_type = models.CharField('类型', max_length=50, choices=field_type_choices)
field_key = models.CharField('字段标识', max_length=50, help_text='字段类型请尽量特殊,避免与系统中关键字冲突') field_key = models.CharField('字段标识', max_length=50, help_text='字段类型请尽量特殊,避免与系统中关键字冲突')
field_name = models.CharField('字段名称', max_length=50) field_name = models.CharField('字段名称', max_length=50)
boolean_field_display = models.JSONField('布尔类型显示名', default=dict, blank=True, null=True, field_choice = models.JSONField('radio、checkbox、select的选项', default=list, blank=True, null=True,
help_text='当为布尔类型时候,可以支持自定义显示形式。{"1":"","0":""}或{"1":"需要","0":"不需要"},注意数字也需要引号')
field_choice = models.JSONField('radio、checkbox、select的选项', default=dict, blank=True, null=True,
help_text='radio,checkbox,select,multiselect类型可供选择的选项格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号') help_text='radio,checkbox,select,multiselect类型可供选择的选项格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号')
help_text = models.TextField('说明', null=True, blank=True)
sort = models.IntegerField('排序号', default=1) sort = models.IntegerField('排序号', default=1)
need_judge = models.BooleanField('需要判定项目', default=False)
high_limit = models.FloatField('上限值', null=True, blank=True) high_limit = models.FloatField('上限值', null=True, blank=True)
high_rule = models.IntegerField('上限规则', choices=high_rule_choices, 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_limit = models.FloatField('下限值', null=True, blank=True)
low_rule = models.IntegerField('下限规则', choices=low_rule_choices, 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) 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: class Meta:
verbose_name = '记录表格字段' verbose_name = '记录表格字段'

View File

@ -215,7 +215,7 @@ class RecordFormDetailSerializer(serializers.ModelSerializer):
class RecordFormFieldCreateSerializer(serializers.ModelSerializer): class RecordFormFieldCreateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = RecordFormField 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): def validate(self, data):
if RecordFormField.objects.filter(field_key=data['field_key'], form=data['form'], is_deleted=False).exists(): 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 RecordFormFieldUpdateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = RecordFormField 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 RecordFormFieldSimpleSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -57,6 +57,8 @@ class SubProductionPlan(CommonAModel):
start_date_real = models.DateField('实际开工日期', null=True, blank=True) start_date_real = models.DateField('实际开工日期', null=True, blank=True)
end_date_real = models.DateField('实际完工日期', null=True, blank=True) end_date_real = models.DateField('实际完工日期', null=True, blank=True)
is_picked = models.BooleanField('是否已领料', default=False) is_picked = models.BooleanField('是否已领料', default=False)
# wproducts = models.JSONField('半成品表', default=list, blank=True)
class Meta: class Meta:
verbose_name = '子生产计划' verbose_name = '子生产计划'
verbose_name_plural = 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_product = instance.material
subplan.main_count = instance.count subplan.main_count = instance.count
subplan.main_count_real = instance.count_real 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.state = 4
subplan.save() subplan.save()

View File

@ -17,6 +17,7 @@ from rest_framework.exceptions import APIException
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.decorators import action from rest_framework.decorators import action
from django.db.models import F from django.db.models import F
from utils.tools import ranstr
# Create your views here. # Create your views here.
def updateOrderPlanedCount(order): def updateOrderPlanedCount(order):
@ -59,7 +60,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
pass pass
else: else:
raise APIException('排产数量错误') 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) updateOrderPlanedCount(instance.order)
return Response() return Response()

View File

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

View File

@ -1,6 +1,6 @@
from rest_framework import serializers, exceptions from rest_framework import serializers, exceptions
from rest_framework.serializers import ModelSerializer 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.inm.signals import update_inm
from apps.mtm.models import Material, RecordForm, Step from apps.mtm.models import Material, RecordForm, Step
from apps.mtm.serializers import MaterialSimpleSerializer, StepSimpleSerializer 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 apps.wpm.models import Operation, WMaterial, WProduct, OperationRecord, OperationRecordItem
from django.db import transaction 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): class PickDetailSerializer(serializers.Serializer):
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID") material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
batch = serializers.CharField(label='物料批次', allow_blank=True) batch = serializers.CharField(label='物料批次', allow_blank=True)
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
pick_count = serializers.IntegerField(label="领料数量", required=False) 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): class PickSerializer(serializers.Serializer):
subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID") subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID")
picks = PickDetailSerializer(many=True) picks = PickDetailSerializer(many=True) # 从库存里拿
def create(self, validated_data): def create(self, validated_data):
picks = validated_data.pop('picks') picks = validated_data.pop('picks')
@ -38,16 +44,33 @@ class PickSerializer(serializers.Serializer):
# except: # except:
# raise exceptions.ValidationError('物料不存在') # raise exceptions.ValidationError('物料不存在')
# 创建出库记录 # 创建出库记录
with transaction.atomic(): with transaction.atomic():
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user) fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user)
for i in picks: for i in picks:
# 更新出库详情 # 更新出库详情
i['count'] = i.pop('pick_count', 0) 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: if i['count']>0:
i['fifo'] = fifo i['fifo'] = fifo
i['is_testok'] = True # 默认检测合格 i['is_testok'] = True # 默认检测合格
i['subproduction_plan'] = sp 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'], \ wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \
subproduction_plan=sp,defaults={ 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 = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1)
spp.count_pick = spp.count_pick + i['count'] spp.count_pick = spp.count_pick + i['count']
spp.save() 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.is_picked=True
sp.state = 3 #生产中 sp.state = 3 #生产中
sp.state_date_real = timezone.now() #实际开工日期 sp.state_date_real = timezone.now() #实际开工日期
@ -183,7 +212,7 @@ class WpmTestRecordItemCreateSerializer(serializers.ModelSerializer):
class WpmTestRecordCreateSerializer(serializers.ModelSerializer): class WpmTestRecordCreateSerializer(serializers.ModelSerializer):
record_data = WpmTestRecordItemCreateSerializer(many=True) record_data = WpmTestRecordItemCreateSerializer(many=True)
wproduct = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), required=True) wproduct = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), required=True)
is_testok = serializers.BooleanField() is_testok = serializers.BooleanField(required=False)
class Meta: class Meta:
model = TestRecord model = TestRecord
fields = ['form', 'record_data', 'is_testok', 'wproduct'] 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.utils.field_mapping import get_relation_kwargs
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet 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.inm.signals import update_inm
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial
from apps.mtm.serializers import RecordFormDetailSerializer from apps.mtm.serializers import RecordFormDetailSerializer
@ -17,13 +17,14 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action from rest_framework.decorators import action
from apps.wpm.models import WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem 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 rest_framework.response import Response
from django.db import transaction from django.db import transaction
from rest_framework import exceptions, serializers from rest_framework import exceptions, serializers
from apps.wpm.services import WpmServies from apps.wpm.services import WpmServies
from django.utils import timezone from django.utils import timezone
from utils.tools import ranstr
# Create your views here. # Create your views here.
class WPlanViewSet(ListModelMixin, GenericViewSet): class WPlanViewSet(ListModelMixin, GenericViewSet):
""" """
@ -37,6 +38,33 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
ordering_fields = [] ordering_fields = []
ordering = ['-id'] 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) @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer)
@transaction.atomic @transaction.atomic
def putin(self, request, pk=None): def putin(self, request, pk=None):
@ -49,6 +77,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
subplan = self.get_object() subplan = self.get_object()
material = subplan.main_product material = subplan.main_product
batch = subplan.production_plan.number batch = subplan.production_plan.number
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
wproducts = WProduct.objects.filter(subproduction_plan=subplan, wproducts = WProduct.objects.filter(subproduction_plan=subplan,
act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False) act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False)
if wproducts.exists(): if wproducts.exists():
@ -60,7 +89,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
fifoitem = FIFOItem() fifoitem = FIFOItem()
fifoitem.is_tested = True fifoitem.is_tested = True
fifoitem.is_testok = True fifoitem.is_testok = True
fifoitem.warehouse = vdata['warehouse'] fifoitem.warehouse = warehouse
fifoitem.material = material fifoitem.material = material
fifoitem.count = wproducts.count() fifoitem.count = wproducts.count()
fifoitem.batch = batch fifoitem.batch = batch
@ -81,7 +110,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
ips2 = [] ips2 = []
for i in wproducts: for i in wproducts:
ip = {} ip = {}
ip['warehouse'] = vdata['warehouse'] ip['warehouse'] = warehouse
ip['batch'] = batch ip['batch'] = batch
ip['wproduct'] = i ip['wproduct'] = i
ip['number'] = i.number ip['number'] = i.number
@ -90,7 +119,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
IProduct.objects.bulk_create(ips2) IProduct.objects.bulk_create(ips2)
# 更新库存并修改半成品进行状态 # 更新库存并修改半成品进行状态
update_inm(fifo) 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() return Response()
@ -116,63 +145,6 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
serializer.save() serializer.save()
return Response() 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): class WProductViewSet(ListModelMixin, GenericViewSet):
""" """
半成品 半成品
@ -221,20 +193,66 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
if obj.is_testok: if obj.is_testok:
wproduct.act_state = WProduct.WPR_ACT_STATE_OK wproduct.act_state = WProduct.WPR_ACT_STATE_OK
if wproduct.number is None: # 产生半成品编号 if wproduct.number is None: # 产生半成品编号
wproduct.number = 'BCP' + str(timezone.now()) wproduct.number = 'WP-'+ranstr(7)
wproduct.save() 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, instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
instance.count_real = main_count instance.count_real = instance.count_real + 1 # 这个地方可能会有问题
instance.save() instance.save()
else:# 如果不合格 else:# 如果不合格
pass pass
return Response() 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): 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)