Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
9997d41b52
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card>
|
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span>基本信息</span>
|
<span>基本信息</span>
|
||||||
|
|
@ -465,7 +464,7 @@
|
||||||
>提交本次操作</el-button
|
>提交本次操作</el-button
|
||||||
>
|
>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-card>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,4 @@ celerybeat-schedule.dir
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
temp/
|
temp/
|
||||||
nohup.out
|
nohup.out
|
||||||
|
server/settings_pro.py
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-12-01 02:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inm', '0018_alter_fifoitem_subproduction_plan'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='fifoitem',
|
||||||
|
name='count',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='数量'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='inventory',
|
||||||
|
name='count',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='仓库物料存量'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='materialbatch',
|
||||||
|
name='count',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='存量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -29,7 +29,7 @@ class Inventory(BaseModel):
|
||||||
库存物料
|
库存物料
|
||||||
"""
|
"""
|
||||||
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
||||||
count = models.IntegerField('仓库物料存量', default=0, validators=[MinValueValidator(0)])
|
count = models.PositiveIntegerField('仓库物料存量', default=0)
|
||||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '库存表'
|
verbose_name = '库存表'
|
||||||
|
|
@ -41,7 +41,7 @@ class MaterialBatch(BaseModel):
|
||||||
"""
|
"""
|
||||||
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
||||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||||
count = models.IntegerField('存量', default=0, validators=[MinValueValidator(0)])
|
count = models.PositiveIntegerField('存量', default=0)
|
||||||
batch = models.CharField('批次号', max_length=100, default='')
|
batch = models.CharField('批次号', max_length=100, default='')
|
||||||
expiration_date = models.DateField('有效期', null=True, blank=True)
|
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -79,7 +79,7 @@ class FIFOItem(BaseModel):
|
||||||
is_testok = models.BooleanField('是否检测合格', default=False)
|
is_testok = models.BooleanField('是否检测合格', default=False)
|
||||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||||
count = models.IntegerField('数量', default=0, validators=[MinValueValidator(0)])
|
count = models.PositiveIntegerField('数量', default=0)
|
||||||
batch = models.CharField('批次号', max_length=100, default='')
|
batch = models.CharField('批次号', max_length=100, default='')
|
||||||
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-29 06:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0036_auto_20211123_1052'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='recordform',
|
||||||
|
name='type',
|
||||||
|
field=models.IntegerField(choices=[(1, '生产记录模板'), (2, '检验记录模板')], default=1, verbose_name='表格类型'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='step',
|
||||||
|
name='need_test',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否需要检验'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-12-01 02:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0037_auto_20211129_1456'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='process',
|
||||||
|
name='type',
|
||||||
|
field=models.IntegerField(default=30, verbose_name='类型'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-12-01 02:16
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0038_process_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='recordform',
|
||||||
|
name='enabled',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否启用'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='recordform',
|
||||||
|
name='number',
|
||||||
|
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='编号'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-12-01 02:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0039_auto_20211201_1016'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='material',
|
||||||
|
name='piece_count',
|
||||||
|
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='单片玻璃数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -40,6 +40,7 @@ class Material(CommonAModel):
|
||||||
sort_str = models.CharField('排序字符', max_length=100, null=True, blank=True)
|
sort_str = models.CharField('排序字符', max_length=100, null=True, blank=True)
|
||||||
unit = models.CharField('基准计量单位', choices=unit_choices, default='块', max_length=10)
|
unit = models.CharField('基准计量单位', choices=unit_choices, default='块', max_length=10)
|
||||||
count = models.IntegerField('物料总数', default=0)
|
count = models.IntegerField('物料总数', default=0)
|
||||||
|
piece_count = models.PositiveSmallIntegerField('单片玻璃数量', null=True, blank=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '物料表'
|
verbose_name = '物料表'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
@ -51,8 +52,17 @@ class Process(CommonAModel):
|
||||||
"""
|
"""
|
||||||
工序
|
工序
|
||||||
"""
|
"""
|
||||||
|
PROCESS_TYPE_SPEC = 10
|
||||||
|
PROCESS_TYPE_KEY = 20
|
||||||
|
PROCESS_TYPE_NOMAL = 30
|
||||||
|
type_choices = (
|
||||||
|
(PROCESS_TYPE_SPEC, '特殊'),
|
||||||
|
(PROCESS_TYPE_KEY, '关键'),
|
||||||
|
(PROCESS_TYPE_NOMAL, '普通'),
|
||||||
|
)
|
||||||
name = models.CharField('工序名称', max_length=100, unique=True)
|
name = models.CharField('工序名称', max_length=100, unique=True)
|
||||||
number = models.CharField('编号', max_length=100, unique=True)
|
number = models.CharField('编号', max_length=100, unique=True)
|
||||||
|
type = models.IntegerField('类型', default=30)
|
||||||
instruction = models.ForeignKey(File, verbose_name='指导书', on_delete=models.SET_NULL, null=True, blank=True)
|
instruction = models.ForeignKey(File, verbose_name='指导书', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
instruction_content = models.TextField('指导书内容', null=True, blank=True)
|
instruction_content = models.TextField('指导书内容', null=True, blank=True)
|
||||||
workshop = models.ForeignKey(Organization, verbose_name='生产车间', on_delete=models.CASCADE, null=True, blank=True)
|
workshop = models.ForeignKey(Organization, verbose_name='生产车间', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
@ -81,7 +91,7 @@ class Step(CommonAModel):
|
||||||
name = models.CharField('工序步骤名称', max_length=100)
|
name = models.CharField('工序步骤名称', max_length=100)
|
||||||
number = models.CharField('步骤编号', max_length=100, null=True, blank=True)
|
number = models.CharField('步骤编号', max_length=100, null=True, blank=True)
|
||||||
instruction_content = models.TextField('相应操作指导', null=True, blank=True)
|
instruction_content = models.TextField('相应操作指导', null=True, blank=True)
|
||||||
need_test = models.BooleanField('是否需要过程检验', default=False)
|
need_test = models.BooleanField('是否需要检验', default=False)
|
||||||
sort = models.IntegerField('排序号', default=1)
|
sort = models.IntegerField('排序号', default=1)
|
||||||
equipments = models.ManyToManyField(Equipment, verbose_name='使用设备', related_name='step_equips')
|
equipments = models.ManyToManyField(Equipment, verbose_name='使用设备', related_name='step_equips')
|
||||||
|
|
||||||
|
|
@ -99,13 +109,15 @@ class RecordForm(CommonAModel):
|
||||||
RF_TYPE_DO = 1
|
RF_TYPE_DO = 1
|
||||||
RF_TYPE_TEST = 2
|
RF_TYPE_TEST = 2
|
||||||
type_choices=(
|
type_choices=(
|
||||||
(RF_TYPE_DO, '生产记录'),
|
(RF_TYPE_DO, '生产记录模板'),
|
||||||
(RF_TYPE_TEST, '检验记录')
|
(RF_TYPE_TEST, '检验记录模板')
|
||||||
)
|
)
|
||||||
name = models.CharField('表格名称', max_length=100)
|
name = models.CharField('表格名称', max_length=100)
|
||||||
type = models.IntegerField('表格类型', choices=type_choices, default=1)
|
type = models.IntegerField('表格类型', choices=type_choices, default=1)
|
||||||
step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE, null=True, blank=True)
|
step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE, null=True, blank=True)
|
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
enabled = models.BooleanField('是否启用', default=False)
|
||||||
|
number = models.CharField('编号', null=True, blank=True, max_length=32)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '记录表格'
|
verbose_name = '记录表格'
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class ProcessSerializer(serializers.ModelSerializer):
|
||||||
class ProcessSimpleSerializer(serializers.ModelSerializer):
|
class ProcessSimpleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Process
|
model = Process
|
||||||
fields = ['id', 'name', 'number']
|
fields = ['id', 'name', 'number', 'type']
|
||||||
|
|
||||||
class StepSerializer(serializers.ModelSerializer):
|
class StepSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -160,7 +160,7 @@ class RecordFormSimpleSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecordForm
|
model = RecordForm
|
||||||
fields = ['id', 'name']
|
fields = ['id', 'name', 'number', 'enabled']
|
||||||
class RecordFormSerializer(serializers.ModelSerializer):
|
class RecordFormSerializer(serializers.ModelSerializer):
|
||||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||||
|
|
@ -180,12 +180,12 @@ class RecordFormSerializer(serializers.ModelSerializer):
|
||||||
class RecordFormCreateSerializer(serializers.ModelSerializer):
|
class RecordFormCreateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecordForm
|
model = RecordForm
|
||||||
fields = ['name', 'type', 'step', 'material']
|
fields = ['name', 'type', 'step', 'material', 'number', 'enabled']
|
||||||
|
|
||||||
class RecordFormUpdateSerializer(serializers.ModelSerializer):
|
class RecordFormUpdateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecordForm
|
model = RecordForm
|
||||||
fields = ['name', 'type']
|
fields = ['name', 'type', 'number', 'enabled']
|
||||||
|
|
||||||
class RecordFormFieldSerializer(serializers.ModelSerializer):
|
class RecordFormFieldSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class ProcessViewSet(PageOrNot, CreateUpdateModelAMixin, ModelViewSet):
|
||||||
queryset = Process.objects.select_related('instruction', 'workshop').all()
|
queryset = Process.objects.select_related('instruction', 'workshop').all()
|
||||||
serializer_class = ProcessSerializer
|
serializer_class = ProcessSerializer
|
||||||
search_fields = ['name', 'number']
|
search_fields = ['name', 'number']
|
||||||
filterset_fields = ['number', 'workshop']
|
filterset_fields = ['number', 'workshop', 'type']
|
||||||
ordering_fields = ['number']
|
ordering_fields = ['number']
|
||||||
ordering = ['number']
|
ordering = ['number']
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ class RecordFormViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet
|
||||||
"""
|
"""
|
||||||
perms_map = {'*':'*'}
|
perms_map = {'*':'*'}
|
||||||
queryset = RecordForm.objects.all()
|
queryset = RecordForm.objects.all()
|
||||||
filterset_fields = ['step', 'type', 'material']
|
filterset_fields = ['step', 'type', 'material', 'number', 'enabled']
|
||||||
search_fields = ['name']
|
search_fields = ['name']
|
||||||
ordering='id'
|
ordering='id'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from apps.sam.serializers import OrderSerializer
|
from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, SubProductionSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, SubProductionSimpleSerializer
|
||||||
from apps.system.serializers import OrganizationSimpleSerializer
|
from apps.system.serializers import OrganizationSimpleSerializer
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ class ProductionPlanCreateFromOrderSerializer(serializers.ModelSerializer):
|
||||||
fields = ['order', 'count', 'start_date', 'end_date']
|
fields = ['order', 'count', 'start_date', 'end_date']
|
||||||
|
|
||||||
class ProductionPlanSerializer(serializers.ModelSerializer):
|
class ProductionPlanSerializer(serializers.ModelSerializer):
|
||||||
order_ = OrderSerializer(source='order', read_only=True)
|
order_ = OrderSimpleSerializer(source='order', read_only=True)
|
||||||
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProductionPlan
|
model = ProductionPlan
|
||||||
|
|
@ -29,10 +29,14 @@ class SubProductionPlanListSerializer(serializers.ModelSerializer):
|
||||||
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
||||||
subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True)
|
subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True)
|
||||||
main_product_ = MaterialSimpleSerializer(source='main_product', read_only=True)
|
main_product_ = MaterialSimpleSerializer(source='main_product', read_only=True)
|
||||||
|
product_ = serializers.SerializerMethodField()
|
||||||
class Meta:
|
class Meta:
|
||||||
model=SubProductionPlan
|
model=SubProductionPlan
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
def get_product_(self, obj):
|
||||||
|
return MaterialSimpleSerializer(instance=obj.production_plan.product).data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
子生产计划-列表/修改
|
子生产计划-列表/修改
|
||||||
"""
|
"""
|
||||||
perms_map = {'*': '*'}
|
perms_map = {'*': '*'}
|
||||||
queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'main_product')
|
queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'main_product', 'production_plan__product')
|
||||||
search_fields = []
|
search_fields = []
|
||||||
serializer_class = SubProductionPlanListSerializer
|
serializer_class = SubProductionPlanListSerializer
|
||||||
filterset_fields = ['production_plan', 'process', 'state', 'main_product', 'workshop']
|
filterset_fields = ['production_plan', 'process', 'state', 'main_product', 'workshop']
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-29 06:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0011_auto_20211119_0848'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='testrecorditem',
|
||||||
|
name='field_type',
|
||||||
|
field=models.CharField(choices=[(1, '生产记录模板'), (2, '检验记录模板')], max_length=50, verbose_name='字段类型'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -48,3 +48,9 @@ class OrderSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Order
|
model = Order
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
class OrderSimpleSerializer(serializers.ModelSerializer):
|
||||||
|
contract_ = ContractSimpleSerializer(source='contract', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = Order
|
||||||
|
fields = '__all__'
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,4 @@ from .permission import get_permission_list
|
||||||
@receiver(m2m_changed, sender=User.roles.through)
|
@receiver(m2m_changed, sender=User.roles.through)
|
||||||
def update_perms_cache_user(sender, instance, action, **kwargs):
|
def update_perms_cache_user(sender, instance, action, **kwargs):
|
||||||
if action in ['post_remove', 'post_add']:
|
if action in ['post_remove', 'post_add']:
|
||||||
if cache.get(instance.username+'__perms', None):
|
get_permission_list(instance)
|
||||||
get_permission_list(instance)
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-29 06:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0023_alter_operationmaterial_count'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationrecorditem',
|
||||||
|
name='field_type',
|
||||||
|
field=models.CharField(choices=[(1, '生产记录模板'), (2, '检验记录模板')], max_length=50, verbose_name='字段类型'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='act_state',
|
||||||
|
field=models.IntegerField(choices=[(6, '待复检'), (10, '生产中'), (20, '待检验'), (30, '已合格'), (40, '库存中'), (50, '不合格'), (60, '待成品检验')], default=0, verbose_name='进行状态'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-12-01 02:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0024_auto_20211129_1456'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='wmaterial',
|
||||||
|
name='count',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='当前数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -17,21 +17,28 @@ class WMaterial(BaseModel):
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE)
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE)
|
||||||
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
|
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
|
||||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||||
count = models.IntegerField('当前数量', default=0, validators=[MinValueValidator(0)])
|
count = models.PositiveIntegerField('当前数量', default=0)
|
||||||
|
|
||||||
|
|
||||||
class WProduct(CommonAModel):
|
class WProduct(CommonAModel):
|
||||||
"""
|
"""
|
||||||
动态半成品/成品表
|
动态半成品/成品表
|
||||||
"""
|
"""
|
||||||
WPR_ACT_STATE_DOING = 1
|
WPR_ACT_STATE_TORETEST = 6
|
||||||
WPR_ACT_STATE_TOTEST = 2
|
WPR_ACT_STATE_DOING = 10
|
||||||
WPR_ACT_STATE_OK = 3
|
WPR_ACT_STATE_TOTEST = 20
|
||||||
WPR_ACT_STATE_INM = 4
|
WPR_ACT_STATE_OK = 30
|
||||||
|
WPR_ACT_STATE_INM = 40
|
||||||
|
WPR_ACT_STATE_NOTOK = 50
|
||||||
|
WPR_ACT_STATE_TOFINALTEST = 60
|
||||||
act_state_choices=(
|
act_state_choices=(
|
||||||
|
(WPR_ACT_STATE_TORETEST, '待复检'),
|
||||||
(WPR_ACT_STATE_DOING, '生产中'),
|
(WPR_ACT_STATE_DOING, '生产中'),
|
||||||
(WPR_ACT_STATE_TOTEST, '待检测'),
|
(WPR_ACT_STATE_TOTEST, '待检验'),
|
||||||
(WPR_ACT_STATE_OK, '已合格'),
|
(WPR_ACT_STATE_OK, '已合格'),
|
||||||
(WPR_ACT_STATE_INM, '库存中'),
|
(WPR_ACT_STATE_INM, '库存中'),
|
||||||
|
(WPR_ACT_STATE_NOTOK, '不合格'),
|
||||||
|
(WPR_ACT_STATE_TOFINALTEST, '待成品检验')
|
||||||
)
|
)
|
||||||
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||||
material = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
material = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ class PickHalfSerializer(serializers.Serializer):
|
||||||
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||||
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
|
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
|
||||||
required=False) # 从半成品表里直接修改状态
|
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)
|
||||||
|
|
@ -37,16 +38,16 @@ class PickSerializer(serializers.Serializer):
|
||||||
sp = validated_data.pop('subproduction_plan')
|
sp = validated_data.pop('subproduction_plan')
|
||||||
if sp.state not in [SubProductionPlan.SUBPLAN_STATE_ASSGINED, SubProductionPlan.SUBPLAN_STATE_ACCEPTED,
|
if sp.state not in [SubProductionPlan.SUBPLAN_STATE_ASSGINED, SubProductionPlan.SUBPLAN_STATE_ACCEPTED,
|
||||||
SubProductionPlan.SUBPLAN_STATE_WORKING]:
|
SubProductionPlan.SUBPLAN_STATE_WORKING]:
|
||||||
raise exceptions.ValidationError('该子计划状态错误')
|
raise exceptions.APIException('该子计划状态错误')
|
||||||
# if sp.is_picked:
|
# if sp.is_picked:
|
||||||
# raise exceptions.ValidationError('该子计划已领料')
|
# raise exceptions.APIException('该子计划已领料')
|
||||||
# for i in picks:
|
# for i in picks:
|
||||||
# try:
|
# try:
|
||||||
# instance = MaterialBatch.objects.get(material=i['material'], batch=i['batch'])
|
# instance = MaterialBatch.objects.get(material=i['material'], batch=i['batch'])
|
||||||
# if instance.count < i['pick_count']:
|
# if instance.count < i['pick_count']:
|
||||||
# raise exceptions.ValidationError('物料不足')
|
# raise exceptions.APIException('物料不足')
|
||||||
# except:
|
# except:
|
||||||
# raise exceptions.ValidationError('物料不存在')
|
# raise exceptions.APIException('物料不存在')
|
||||||
# 创建出库记录
|
# 创建出库记录
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
|
@ -100,7 +101,7 @@ class PickSerializer(serializers.Serializer):
|
||||||
wproducts = WProduct.objects.filter(pk__in=wids)
|
wproducts = WProduct.objects.filter(pk__in=wids)
|
||||||
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
||||||
wproducts.update(step=first_step, is_executed=False,
|
wproducts.update(step=first_step, is_executed=False,
|
||||||
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
|
act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None,
|
||||||
subproduction_plan=sp)
|
subproduction_plan=sp)
|
||||||
sp.is_picked=True
|
sp.is_picked=True
|
||||||
sp.state = SubProductionPlan.SUBPLAN_STATE_WORKING #生产中
|
sp.state = SubProductionPlan.SUBPLAN_STATE_WORKING #生产中
|
||||||
|
|
@ -173,21 +174,23 @@ class OperationCreateSerializer(serializers.Serializer):
|
||||||
|
|
||||||
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
||||||
# if step.id not in stepIds:
|
# if step.id not in stepIds:
|
||||||
# raise exceptions.ValidationError('请选择正确的子工序操作')
|
# raise exceptions.APIException('请选择正确的子工序操作')
|
||||||
|
|
||||||
if 'wproducts' in data and data['wproducts']:
|
if 'wproducts' in data and data['wproducts']:
|
||||||
if step.type == Step.STEP_TYPE_DIV:
|
if step.type == Step.STEP_TYPE_DIV:
|
||||||
raise exceptions.ValidationError(_('不可进行此操作'))
|
raise exceptions.APIException(_('不可进行此操作'))
|
||||||
for i in data['wproducts']:
|
for i in data['wproducts']:
|
||||||
|
if i.act_state != WProduct.WPR_ACT_STATE_DOING:
|
||||||
|
raise exceptions.APIException('半成品不在生产状态')
|
||||||
if i.is_executed:
|
if i.is_executed:
|
||||||
raise exceptions.ValidationError('不可进行操作')
|
raise exceptions.APIException('不可进行操作')
|
||||||
# if i.subproduction_plan != subproduction_plan:
|
# if i.subproduction_plan != subproduction_plan:
|
||||||
# raise exceptions.ValidationError('半成品所属子计划不一致')
|
# raise exceptions.APIException('半成品所属子计划不一致')
|
||||||
if i.step != step:
|
if i.step != step:
|
||||||
raise exceptions.ValidationError('半成品所属子工序不一致')
|
raise exceptions.APIException('半成品所属子工序不一致')
|
||||||
else:
|
else:
|
||||||
if step.type != Step.STEP_TYPE_DIV:
|
if step.type != Step.STEP_TYPE_DIV:
|
||||||
raise exceptions.ValidationError(_('请选择半成品进行操作'))
|
raise exceptions.APIException(_('请选择半成品进行操作'))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -208,21 +211,21 @@ class OperationInitSerializer(serializers.Serializer):
|
||||||
|
|
||||||
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
||||||
# if step.id not in stepIds:
|
# if step.id not in stepIds:
|
||||||
# raise exceptions.ValidationError('请选择正确的子工序操作')
|
# raise exceptions.APIException('请选择正确的子工序操作')
|
||||||
|
|
||||||
if 'wproducts' in data and data['wproducts']:
|
if 'wproducts' in data and data['wproducts']:
|
||||||
if step.type == Step.STEP_TYPE_DIV:
|
if step.type == Step.STEP_TYPE_DIV:
|
||||||
raise exceptions.ValidationError(_('不可进行此操作'))
|
raise exceptions.APIException(_('不可进行此操作'))
|
||||||
for i in data['wproducts']:
|
for i in data['wproducts']:
|
||||||
if i.is_executed:
|
if i.is_executed:
|
||||||
raise exceptions.ValidationError('不可进行操作')
|
raise exceptions.APIException('不可进行操作')
|
||||||
# if i.subproduction_plan != subproduction_plan:
|
# if i.subproduction_plan != subproduction_plan:
|
||||||
# raise exceptions.ValidationError('半成品所属子计划不一致')
|
# raise exceptions.APIException('半成品所属子计划不一致')
|
||||||
if i.step != step:
|
if i.step != step:
|
||||||
raise exceptions.ValidationError('半成品所属子工序不一致')
|
raise exceptions.APIException('半成品所属子工序不一致')
|
||||||
else:
|
else:
|
||||||
if step.type != Step.STEP_TYPE_DIV:
|
if step.type != Step.STEP_TYPE_DIV:
|
||||||
raise exceptions.ValidationError(_('请选择半成品进行操作'))
|
raise exceptions.APIException(_('请选择半成品进行操作'))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||||
spp.save()
|
spp.save()
|
||||||
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
|
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
|
||||||
wps.update(step=first_step, is_executed=False,
|
wps.update(step=first_step, is_executed=False,
|
||||||
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
|
act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None,
|
||||||
subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
|
subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
|
||||||
sp.is_picked = True
|
sp.is_picked = True
|
||||||
sp.save()
|
sp.save()
|
||||||
|
|
@ -178,12 +178,13 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
record_data = vdata.pop('record_data')
|
record_data = vdata.pop('record_data')
|
||||||
wproduct = vdata['wproduct']
|
wproduct = vdata['wproduct']
|
||||||
if wproduct.act_state != WProduct.WPR_ACT_STATE_TOTEST:
|
if wproduct.act_state not in [WProduct.WPR_ACT_STATE_TOTEST, WProduct.WPR_ACT_STATE_TORETEST]:
|
||||||
raise exceptions.APIException('该半成品不可检测')
|
raise exceptions.APIException('该产品当前状态不可检验')
|
||||||
if 'is_testok' not in vdata:
|
if 'is_testok' not in vdata:
|
||||||
raise exceptions.APIException('未填写检测结论')
|
raise exceptions.APIException('未填写检测结论')
|
||||||
|
|
||||||
obj = serializer.save(create_by = self.request.user, material=wproduct.material)
|
obj = serializer.save(create_by = self.request.user,
|
||||||
|
material=wproduct.material, number=wproduct.number, subproduction_plan=wproduct.subproduction_plan)
|
||||||
tris = []
|
tris = []
|
||||||
for m in record_data: # 保存记录详情
|
for m in record_data: # 保存记录详情
|
||||||
form_field = m['form_field']
|
form_field = m['form_field']
|
||||||
|
|
@ -212,10 +213,53 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
instance.count_ok = instance.count_ok + 1 # 这个地方可能会有问题
|
instance.count_ok = instance.count_ok + 1 # 这个地方可能会有问题
|
||||||
instance.save()
|
instance.save()
|
||||||
else:# 如果不合格
|
else:# 如果不合格
|
||||||
pass
|
wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK
|
||||||
|
wproduct.save()
|
||||||
|
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def retest(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
复检
|
||||||
|
"""
|
||||||
|
serializer = WpmTestRecordCreateSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
record_data = vdata.pop('record_data')
|
||||||
|
wproduct = vdata['wproduct']
|
||||||
|
if wproduct.act_state != WProduct.WPR_ACT_STATE_TORETEST:
|
||||||
|
raise exceptions.APIException('该产品当前状态不可检验')
|
||||||
|
if 'is_testok' not in vdata:
|
||||||
|
raise exceptions.APIException('未填写检测结论')
|
||||||
|
|
||||||
|
obj = serializer.save(create_by = self.request.user,
|
||||||
|
material=wproduct.material, number=wproduct.number, subproduction_plan=wproduct.subproduction_plan)
|
||||||
|
tris = []
|
||||||
|
for m in record_data: # 保存记录详情
|
||||||
|
form_field = m['form_field']
|
||||||
|
m['field_name'] = form_field.field_name
|
||||||
|
m['field_key'] = form_field.field_key
|
||||||
|
m['field_type'] = form_field.field_type
|
||||||
|
m['field_value'] = m['field_value']
|
||||||
|
m['sort'] = form_field.sort
|
||||||
|
m['need_judge'] = form_field.need_judge
|
||||||
|
m['is_testok'] = m['is_testok'] if 'is_testok' in m else None
|
||||||
|
m['test_record'] = obj
|
||||||
|
tris.append(TestRecordItem(**m))
|
||||||
|
TestRecordItem.objects.bulk_create(tris)
|
||||||
|
|
||||||
|
# 如果检测合格, 变更动态产品进行状态
|
||||||
|
|
||||||
|
if obj.is_testok:
|
||||||
|
wproduct.act_state = WProduct.WPR_ACT_STATE_DOING
|
||||||
|
wproduct.save()
|
||||||
|
else:# 如果不合格
|
||||||
|
wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK
|
||||||
|
wproduct.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer)
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer)
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def putin(self, request, pk=None):
|
def putin(self, request, pk=None):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue