Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
d0f9030cfc
|
@ -2,8 +2,8 @@
|
|||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
#VUE_APP_BASE_API = 'http://127.0.0.1:8000/api'
|
||||
VUE_APP_BASE_API = 'http://47.95.0.242:2222/api'
|
||||
VUE_APP_BASE_API = 'http://127.0.0.1:8000/api'
|
||||
#VUE_APP_BASE_API = 'http://47.95.0.242:2222/api'
|
||||
|
||||
|
||||
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
|
||||
|
|
|
@ -167,9 +167,7 @@
|
|||
label-position="right"
|
||||
:rules="rule1"
|
||||
>
|
||||
<el-form-item label="生产计划编号" prop="number">
|
||||
<el-input v-model="orderplan.number" placeholder="生产计划编号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="排产数量" prop="count">
|
||||
<el-input-number v-model="orderplan.count" :min="0"></el-input-number>
|
||||
</el-form-item>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column label="半成品名称">
|
||||
<template slot-scope="scope">{{ scope.row.m_state_.name }}</template>
|
||||
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="半成品编号">
|
||||
|
@ -27,7 +27,7 @@
|
|||
</el-table-column>
|
||||
|
||||
<el-table-column label="所在子工序">
|
||||
<template slot-scope="scope">{{ scope.row.p_state_.name }}</template>
|
||||
<template slot-scope="scope">{{ scope.row.step_.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="操作" width="220px">
|
||||
|
@ -62,7 +62,7 @@
|
|||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column label="半成品名称">
|
||||
<template slot-scope="scope">{{ scope.row.m_state_.name }}</template>
|
||||
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="半成品编号">
|
||||
|
@ -75,7 +75,7 @@
|
|||
</el-table-column>
|
||||
|
||||
<el-table-column label="所在子工序">
|
||||
<template slot-scope="scope">{{ scope.row.p_state_.name }}</template>
|
||||
<template slot-scope="scope">{{ scope.row.step_.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="操作" width="220px">
|
||||
|
@ -389,7 +389,7 @@ export default {
|
|||
//调该物料对应的检查表
|
||||
this.outerVisible = true;
|
||||
this.wproduct=scope.row.id;//半成品ID
|
||||
this.listQueryrecordform.material = scope.row.m_state;//
|
||||
this.listQueryrecordform.material = scope.row.material;//
|
||||
this.listQueryrecordform.type = 2;
|
||||
getrecordformList(this.listQueryrecordform).then((response) => {
|
||||
if (response.data) {
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
|
||||
<el-table-column align="center" label="操作" width="130px">
|
||||
<template slot-scope="scope">
|
||||
<el-link v-if="scope.row.state == 1" @click="handleNeed(scope)"
|
||||
<el-link @click="handleNeed(scope)"
|
||||
>领料</el-link
|
||||
>
|
||||
</template>
|
||||
|
@ -132,13 +132,13 @@
|
|||
|
||||
<el-table-column label="半成品状态">
|
||||
<template slot-scope="scope">{{
|
||||
scope.row.m_state_.name
|
||||
scope.row.material_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="所在子工序">
|
||||
<template slot-scope="scope">{{
|
||||
scope.row.p_state_.name
|
||||
scope.row.step_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所在子工序执行状态">
|
||||
|
@ -227,8 +227,8 @@
|
|||
>
|
||||
</div>
|
||||
<template>
|
||||
<el-table :data="havewl" style="width: 100%" ref="multipleTable">
|
||||
<el-table-column type="selection" width="55"> </el-table-column>
|
||||
<el-table :data="havewl" style="width: 100%" >
|
||||
|
||||
<el-table-column prop="batch" label="物料批次"> </el-table-column>
|
||||
<el-table-column prop="material_.name" label="物料名称">
|
||||
</el-table-column>
|
||||
|
@ -627,7 +627,8 @@ export default {
|
|||
from: [],
|
||||
workdata: {},
|
||||
wproductdata: {},
|
||||
iproducts: []
|
||||
workData:{},
|
||||
|
||||
};
|
||||
},
|
||||
process: "",
|
||||
|
@ -719,7 +720,7 @@ export default {
|
|||
this.listLoading = false;
|
||||
});
|
||||
//半成品
|
||||
getwproductList({page:0,p_state__process:this.process}).then((response) => {
|
||||
getwproductList({page:0,step__process:this.process}).then((response) => {
|
||||
if (response.data) {
|
||||
this.wproductData = response.data;
|
||||
//console.log( this.wproductData)
|
||||
|
@ -731,7 +732,7 @@ export default {
|
|||
//大工序下子工序产出的半成品
|
||||
getwproductLists() {
|
||||
this.wproductdata.page = 0;
|
||||
this.wproductdata.p_state__process = this.process;
|
||||
this.wproductdata.step__process = this.process;
|
||||
if (this.subproduction_plan != "") {
|
||||
this.wproductdata.subproduction_plan = this.subproduction_plan;
|
||||
}
|
||||
|
@ -746,22 +747,37 @@ export default {
|
|||
handlewproduct(scope){
|
||||
|
||||
this.dialogTableVisible = true;
|
||||
this.pcId=scope.row.id;
|
||||
getiproductList({page:0,material:scope.row.material,warehouse:scope.row.warehouse,batch:scope.row.batch}).then((response) => {
|
||||
if (response.data) {
|
||||
this.iproductData= response.data;
|
||||
}
|
||||
this.listLoading = false;
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
//勾选半成品
|
||||
handleSelectionChanges(val){
|
||||
let _this = this;
|
||||
_this.wpID = [];
|
||||
this.iproducts= [];
|
||||
val.forEach((item) => {
|
||||
_this.wpID.push(item.id);
|
||||
this.iproducts.push(item.id);
|
||||
});
|
||||
},
|
||||
//提交半成品
|
||||
iproductsSubmit(){
|
||||
|
||||
this.dialogTableVisible = false;
|
||||
this.havewl.forEach((item) => {
|
||||
if(item.id== this.pcId)
|
||||
{
|
||||
item.iproducts=this.iproducts;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
//领料
|
||||
handleNeed(scope) {
|
||||
this.need = Object.assign({}, defaulteneed);
|
||||
|
@ -778,17 +794,18 @@ export default {
|
|||
//确认领料
|
||||
handlePick() {
|
||||
this.pickData.subproduction_plan = this.id;
|
||||
this.pickData.picks = this.havewl;
|
||||
|
||||
// console.log(this.pickData);
|
||||
|
||||
|
||||
this.pickData.picks = this.havewl;
|
||||
|
||||
|
||||
createPick(this.pickData).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.dialogVisiblenw = false;
|
||||
|
||||
this.$message.success("领料成功!");
|
||||
this.$message.success("领料成功!");
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
prev() {
|
||||
--this.values;
|
||||
|
@ -865,18 +882,21 @@ export default {
|
|||
record_data: _this.field1,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.workData.step=this.step;
|
||||
this.workData.wproducts=this.wproducts;
|
||||
this.workData.input=this.input;
|
||||
this.workData.output=this.output;
|
||||
this.workData.forms=this.from;
|
||||
this.workData.remark=this.remark;
|
||||
if (this.subproduction_plan != "") {
|
||||
this.wproductdata.subproduction_plan = this.subproduction_plan;
|
||||
}
|
||||
console.log(this.remark);
|
||||
|
||||
|
||||
submitWork({
|
||||
step: this.step,
|
||||
subproduction_plan: this.subproduction_plan,
|
||||
wproducts: this.wproducts,
|
||||
input: this.input,
|
||||
output: this.output,
|
||||
forms: this.from,
|
||||
remark: this.remark,
|
||||
}).then((res) => {
|
||||
submitWork(this.workData).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.dialogVisiblework = false;
|
||||
this.$message.success("成功!");
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 15:06
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||
('inm', '0017_alter_iproduct_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='fifoitem',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子生产计划'),
|
||||
),
|
||||
]
|
|
@ -82,7 +82,7 @@ class FIFOItem(BaseModel):
|
|||
count = models.IntegerField('数量', default=0, validators=[MinValueValidator(0)])
|
||||
batch = models.CharField('批次号', max_length=100, default='')
|
||||
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
class FIFOItemProduct(BaseModel):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 08:37
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0034_auto_20211116_1603'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='techdoc',
|
||||
name='enabled',
|
||||
field=models.BooleanField(default=True, verbose_name='是否启用'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='step',
|
||||
name='type',
|
||||
field=models.IntegerField(choices=[(1, '常规'), (2, '分割'), (3, '结合')], default=1, verbose_name='操作类型'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subprodctionmaterial',
|
||||
name='subproduction',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subm_subprod', to='mtm.subproduction', verbose_name='关联生产分解'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='techdoc',
|
||||
name='subproduction',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tech_subprod', to='mtm.subproduction', verbose_name='关联生产分解'),
|
||||
),
|
||||
]
|
|
@ -72,7 +72,7 @@ class Step(CommonAModel):
|
|||
STEP_TYPE_DIV = 2
|
||||
STEP_TYPE_COMB = 3
|
||||
step_type_choices=(
|
||||
(STEP_TYPE_NOM, '普通'),
|
||||
(STEP_TYPE_NOM, '常规'),
|
||||
(STEP_TYPE_DIV, '分割'),
|
||||
(STEP_TYPE_COMB, '结合')
|
||||
)
|
||||
|
@ -199,7 +199,7 @@ class SubprodctionMaterial(CommonADModel):
|
|||
material = models.ForeignKey(Material, verbose_name='物料', on_delete=models.CASCADE, related_name='subplan_material')
|
||||
is_main = models.BooleanField('是否主产出', default=False) # 以该产品完成度计算进度
|
||||
count = models.FloatField('消耗量/产出量', default=0)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subm_subprod')
|
||||
type = models.IntegerField('物料应用类型', default=1)
|
||||
sort = models.IntegerField('排序号', default=1)
|
||||
|
||||
|
@ -223,8 +223,9 @@ class TechDoc(CommonADModel):
|
|||
"""
|
||||
name = models.CharField('名称', max_length=50)
|
||||
file = models.ForeignKey(File, verbose_name='技术文件', on_delete=models.CASCADE)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='tech_subprod')
|
||||
content = models.TextField('内容', null=True, blank=True)
|
||||
enabled = models.BooleanField('是否启用', default=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '技术文件'
|
||||
|
|
|
@ -26,7 +26,7 @@ class MaterialDetailSerializer(serializers.ModelSerializer):
|
|||
class MaterialSimpleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Material
|
||||
fields = ['id', 'name', 'number', 'unit','specification']
|
||||
fields = ['id', 'name', 'number', 'unit','specification', 'type']
|
||||
|
||||
class ProcessSerializer(serializers.ModelSerializer):
|
||||
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
||||
|
@ -209,6 +209,12 @@ class RecordFormDetailSerializer(serializers.ModelSerializer):
|
|||
|
||||
def get_form_fields(self, obj):
|
||||
serializer = RecordFormFieldSerializer(instance=RecordFormField.objects.filter(form=obj, is_deleted=False), many=True)
|
||||
vdata = serializer.data
|
||||
if obj.type == RecordForm.RF_TYPE_TEST:
|
||||
for i in vdata:
|
||||
if i['need_judge']:
|
||||
i['is_testok'] = False
|
||||
i['is_teskok_robot'] = False
|
||||
return serializer.data
|
||||
|
||||
|
||||
|
@ -241,9 +247,9 @@ class TechDocListSerializer(serializers.ModelSerializer):
|
|||
class TechDocCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TechDoc
|
||||
fields = ['file', 'subproduction', 'name', 'content']
|
||||
fields = ['file', 'subproduction', 'name', 'content', 'enabled']
|
||||
|
||||
class TechDocUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TechDoc
|
||||
fields = ['file', 'name', 'content']
|
||||
fields = ['file', 'name', 'content', 'enabled']
|
||||
|
|
|
@ -154,6 +154,7 @@ class RecordFormViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet
|
|||
filterset_fields = ['step', 'type', 'material']
|
||||
search_fields = ['name']
|
||||
ordering='id'
|
||||
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action =='create':
|
||||
|
@ -184,6 +185,8 @@ class RecordFormFieldViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelVi
|
|||
queryset = RecordFormField.objects.all()
|
||||
filterset_fields = ['field_type', 'form']
|
||||
search_fields = ['field_name', 'field_key']
|
||||
ordering = 'id'
|
||||
ordering_fields = ['sort', 'id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action =='create':
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 08:37
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0035_auto_20211117_1637'),
|
||||
('pm', '0012_alter_subproductionprogress_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='subproductionplan',
|
||||
name='subproduction',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subplan_subprod', to='mtm.subproduction', verbose_name='关联生产分解'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-19 02:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subproductionplan',
|
||||
name='number',
|
||||
field=models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='子计划编号'),
|
||||
),
|
||||
]
|
|
@ -32,15 +32,21 @@ class SubProductionPlan(CommonAModel):
|
|||
"""
|
||||
子生产计划
|
||||
"""
|
||||
SUBPLAN_STATE_PLANING = 0
|
||||
SUBPLAN_STATE_ASSGINED = 1
|
||||
SUBPLAN_STATE_ACCEPTED = 2
|
||||
SUBPLAN_STATE_WORKING = 3
|
||||
SUBPLAN_STATE_DONE = 4
|
||||
state_choices=(
|
||||
(0, '制定中'),
|
||||
(1, '已下达'),
|
||||
(2, '已接收'),
|
||||
(3, '生产中'),
|
||||
(4, '已完成')
|
||||
(SUBPLAN_STATE_PLANING, '制定中'),
|
||||
(SUBPLAN_STATE_ASSGINED, '已下达'),
|
||||
(SUBPLAN_STATE_ACCEPTED, '已接收'),
|
||||
(SUBPLAN_STATE_WORKING, '生产中'),
|
||||
(SUBPLAN_STATE_DONE, '已完成')
|
||||
)
|
||||
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
|
||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
|
||||
start_date = models.DateField('计划开工日期')
|
||||
end_date = models.DateField('计划完工日期')
|
||||
|
||||
|
@ -53,7 +59,7 @@ class SubProductionPlan(CommonAModel):
|
|||
|
||||
steps = models.JSONField('工艺步骤', default=list)
|
||||
|
||||
state = models.IntegerField('状态', default=0)
|
||||
state = models.IntegerField('状态', default=SUBPLAN_STATE_PLANING)
|
||||
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
|
||||
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
||||
is_picked = models.BooleanField('是否已领料', default=False)
|
||||
|
|
|
@ -8,7 +8,7 @@ from apps.system.serializers import OrganizationSimpleSerializer
|
|||
class ProductionPlanCreateFromOrderSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProductionPlan
|
||||
fields = ['order', 'number', 'count', 'start_date', 'end_date']
|
||||
fields = ['order', 'count', 'start_date', 'end_date']
|
||||
|
||||
class ProductionPlanSerializer(serializers.ModelSerializer):
|
||||
order_ = OrderSerializer(source='order', read_only=True)
|
||||
|
@ -55,3 +55,8 @@ class PickNeedSerializer(serializers.Serializer):
|
|||
|
||||
class PlanDestorySerializer(serializers.Serializer):
|
||||
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')
|
||||
|
||||
class SubproductionPlanSimpleSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SubProductionPlan
|
||||
fields = ['id', 'number']
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from apps.pm.models import SubProductionProgress
|
||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||
|
||||
@receiver(post_save, sender=SubProductionProgress)
|
||||
def update_subplan_main(sender, instance, created, **kwargs):
|
||||
|
@ -13,8 +13,8 @@ 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:
|
||||
subplan.state = 4
|
||||
if instance.count_real>= instance.count and instance.count_real != 0:
|
||||
subplan.state = SubProductionPlan.SUBPLAN_STATE_DONE
|
||||
subplan.save()
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from datetime import timezone
|
||||
from django.db import transaction
|
||||
from rest_framework import serializers
|
||||
from rest_framework.views import APIView
|
||||
from apps.em.models import Equipment
|
||||
|
@ -49,7 +50,8 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
elif self.action == 'list':
|
||||
return ProductionPlanSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
|
||||
@transaction.atomic()
|
||||
def create(self, request, *args, **kwargs):
|
||||
data = request.data
|
||||
serializer = self.get_serializer(data=data)
|
||||
|
@ -60,7 +62,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
pass
|
||||
else:
|
||||
raise APIException('排产数量错误')
|
||||
instance = serializer.save(create_by=request.user, product=order.product, number='JH-'+ranstr(7))
|
||||
instance = serializer.save(create_by=request.user, product=order.product, number='JH'+ranstr(7))
|
||||
updateOrderPlanedCount(instance.order)
|
||||
return Response()
|
||||
|
||||
|
@ -81,13 +83,13 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
if production_plan.is_planed:
|
||||
raise APIException('已生成子计划')
|
||||
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
|
||||
for i in subps:
|
||||
for index, i in enumerate(subps):
|
||||
steps = Step.objects.filter(usedstep__subproduction=i, usedstep__subproduction__is_deleted=False,
|
||||
usedstep__is_deleted=False, is_deleted=False).values('id', 'number', 'name', 'usedstep__remark')
|
||||
instance = SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i,
|
||||
start_date=production_plan.start_date, end_date=production_plan.end_date,
|
||||
workshop=i.process.workshop, process=i.process, create_by=request.user,
|
||||
steps = list(steps))
|
||||
steps = list(steps), number=production_plan.number + '-' + str(index+1))
|
||||
# 生成子计划物料需求/进度
|
||||
for m in SubprodctionMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
|
||||
spro = SubProductionProgress.objects.create(material=m.material, type=m.type,
|
||||
|
@ -131,8 +133,8 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
下达任务
|
||||
"""
|
||||
obj = self.get_object()
|
||||
if obj.state == 0:
|
||||
obj.state = 1
|
||||
if obj.state == SubProductionPlan.SUBPLAN_STATE_PLANING:
|
||||
obj.state = SubProductionPlan.SUBPLAN_STATE_ASSGINED
|
||||
obj.save()
|
||||
return Response()
|
||||
raise APIException('计划状态有误')
|
||||
|
@ -143,8 +145,8 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
开始生产
|
||||
"""
|
||||
obj = self.get_object()
|
||||
if obj.state in [1,2]:
|
||||
obj.state = 3
|
||||
if obj.state in [SubProductionPlan.SUBPLAN_STATE_ASSGINED, SubProductionPlan.SUBPLAN_STATE_ACCEPTED]:
|
||||
obj.state = SubProductionPlan.SUBPLAN_STATE_WORKING
|
||||
obj.start_date_real = timezone.now()
|
||||
obj.save()
|
||||
return Response()
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 15:32
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('qm', '0009_alter_testrecorditem_is_testok'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='testrecord',
|
||||
old_name='m_state',
|
||||
new_name='material',
|
||||
),
|
||||
]
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-19 00:48
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||
('qm', '0010_rename_m_state_testrecord_material'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='testrecord',
|
||||
name='is_testok_robot',
|
||||
field=models.BooleanField(default=True, verbose_name='自动判定的是否合格'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testrecord',
|
||||
name='number',
|
||||
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='产品编号'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testrecord',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联的生产子计划'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testrecorditem',
|
||||
name='is_testok_robot',
|
||||
field=models.BooleanField(blank=True, null=True, verbose_name='自动判定的是否合格'),
|
||||
),
|
||||
]
|
|
@ -49,8 +49,11 @@ class TestRecord(CommonAModel):
|
|||
"""
|
||||
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
||||
is_testok = models.BooleanField('是否合格', default=True)
|
||||
is_testok_robot = models.BooleanField('自动判定的是否合格', default=True)
|
||||
number = models.CharField('产品编号', null=True, blank=True, max_length=50)
|
||||
wproduct = models.ForeignKey('wpm.wproduct', verbose_name='关联的动态产品', on_delete=models.CASCADE, null=True, blank=True)
|
||||
m_state = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
||||
material = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey('pm.subproductionplan', verbose_name='关联的生产子计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
||||
remark = models.TextField('备注', default='')
|
||||
|
||||
|
@ -66,5 +69,6 @@ class TestRecordItem(BaseModel):
|
|||
field_value = models.JSONField('录入值', default=dict, blank=True)
|
||||
need_judge = models.BooleanField('是否需要判定', default=False)
|
||||
sort = models.IntegerField('排序号', default=1)
|
||||
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
||||
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
||||
is_testok_robot = models.BooleanField('自动判定的是否合格', null=True, blank=True)
|
||||
test_record = models.ForeignKey(TestRecord, verbose_name='关联的检测记录', on_delete=models.CASCADE, related_name='item_test_record')
|
|
@ -0,0 +1,17 @@
|
|||
from django_filters import rest_framework as filters
|
||||
from .models import Operation, WMaterial, WProduct
|
||||
|
||||
class WMaterialFilterSet(filters.FilterSet):
|
||||
|
||||
operation = filters.NumberFilter(method='filter_operation')
|
||||
class Meta:
|
||||
model = WMaterial
|
||||
fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop']
|
||||
|
||||
def filter_operation(self, queryset, name, value):
|
||||
operation = Operation.objects.get(pk=value)
|
||||
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
|
||||
if wproducts.exists():
|
||||
pass
|
||||
else:
|
||||
pass
|
|
@ -0,0 +1,53 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 14:54
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0035_auto_20211117_1637'),
|
||||
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||
('wpm', '0013_auto_20211116_0841'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='operation',
|
||||
old_name='p_state',
|
||||
new_name='step',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='operation',
|
||||
name='m_state',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='operation',
|
||||
name='wproducts',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OperationWproduct',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('number', models.CharField(blank=True, max_length=50, null=True, verbose_name='物品编号')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='操作时的物料状态')),
|
||||
('operation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.operation', verbose_name='关联操作')),
|
||||
('production_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.productionplan', verbose_name='当前主生产计划')),
|
||||
('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='当前子生产计划')),
|
||||
('wproduct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='关联半成品')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operation',
|
||||
name='wproducts',
|
||||
field=models.ManyToManyField(through='wpm.OperationWproduct', to='wpm.WProduct', verbose_name='关联半成品'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,38 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-17 15:32
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0035_auto_20211117_1637'),
|
||||
('wpm', '0014_auto_20211117_2254'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='wproduct',
|
||||
old_name='m_state',
|
||||
new_name='material',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='wproduct',
|
||||
name='p_state',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='wproduct',
|
||||
name='pre_pstate',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='pre_step',
|
||||
field=models.ForeignKey(blank=True, help_text='已执行完的步骤', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='w_pre_step', to='mtm.step', verbose_name='已执行到'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='step',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='w_step', to='mtm.step', verbose_name='所在步骤'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-19 00:48
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wpm', '0015_auto_20211117_2332'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='operation',
|
||||
name='wproducts',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operation',
|
||||
name='is_submited',
|
||||
field=models.BooleanField(default=True, verbose_name='是否提交'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='operation',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,49 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-19 02:34
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('em', '0009_auto_20210916_1108'),
|
||||
('wpm', '0016_auto_20211119_0848'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='operationrecord',
|
||||
name='create_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='operationrecord',
|
||||
name='update_by',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationrecord',
|
||||
name='is_filled',
|
||||
field=models.BooleanField(default=True, verbose_name='是否填写'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operation',
|
||||
name='is_submited',
|
||||
field=models.BooleanField(default=False, verbose_name='是否提交'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='OperationEquip',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('remark', models.TextField(blank=True, null=True, verbose_name='备注')),
|
||||
('equip', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='生产设备')),
|
||||
('operation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.operation', verbose_name='关联操作')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-19 05:40
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wpm', '0017_auto_20211119_1034'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='operationequip',
|
||||
name='operation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='oe_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationrecord',
|
||||
name='operation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='or_operation', to='wpm.operation', verbose_name='关联的生产操作'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationwproduct',
|
||||
name='operation',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ow_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,46 @@
|
|||
# Generated by Django 3.2.9 on 2021-11-22 03:10
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0035_auto_20211117_1637'),
|
||||
('pm', '0014_subproductionplan_number'),
|
||||
('wpm', '0018_auto_20211119_1340'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='batch',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联的子计划'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='operationmaterial',
|
||||
name='subproduction_progress',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionprogress', verbose_name='关联的生产进度'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationmaterial',
|
||||
name='material',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='可能产出的产品'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operationmaterial',
|
||||
name='type',
|
||||
field=models.IntegerField(choices=[(1, '输入物料'), (2, '输出物料'), (3, '工具工装')], default=0, verbose_name='类型'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wproduct_subplan', to='pm.subproductionplan', verbose_name='当前子生产计划'),
|
||||
),
|
||||
]
|
|
@ -3,12 +3,13 @@ from django.db.models.base import Model
|
|||
import django.utils.timezone as timezone
|
||||
from django.db.models.query import QuerySet
|
||||
from apps.inm.models import WareHouse
|
||||
from apps.pm.models import ProductionPlan, SubProductionPlan
|
||||
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
||||
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||
from utils.model import SoftModel, BaseModel
|
||||
from simple_history.models import HistoricalRecords
|
||||
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm
|
||||
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm, SubprodctionMaterial
|
||||
from django.core.validators import MinValueValidator
|
||||
from apps.em.models import Equipment
|
||||
class WMaterial(BaseModel):
|
||||
"""
|
||||
车间生产物料
|
||||
|
@ -33,49 +34,64 @@ class WProduct(CommonAModel):
|
|||
(WPR_ACT_STATE_INM, '库存中'),
|
||||
)
|
||||
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||
m_state = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||
pre_pstate = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, on_delete=models.CASCADE, related_name='w_pre_pstate')
|
||||
p_state = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, related_name='w_ptate')
|
||||
material = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True, on_delete=models.CASCADE, related_name='w_pre_step')
|
||||
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True, related_name='w_step')
|
||||
act_state = models.IntegerField('进行状态', default=0, choices=act_state_choices)
|
||||
is_executed = models.BooleanField('子工序是否已执行', default=False)
|
||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
||||
parent = models.JSONField('父', default=list, blank=True)
|
||||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='wproduct_subplan')
|
||||
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)
|
||||
operation = models.ForeignKey('wpm.operation', verbose_name='关联操作',
|
||||
on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation')
|
||||
|
||||
class Operation(CommonAModel):
|
||||
class Operation(CommonADModel):
|
||||
"""
|
||||
生产操作
|
||||
"""
|
||||
wproducts = models.JSONField('关联产品ID列表', default=list, blank=True)
|
||||
m_state = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
||||
p_state = 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)
|
||||
use_scrap = models.BooleanField('是否使用的边角料', default=False)
|
||||
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
|
||||
is_submited = models.BooleanField('是否提交', default=False)
|
||||
|
||||
class OperationWproduct(BaseModel):
|
||||
"""
|
||||
生产操作半成品关联表
|
||||
"""
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='ow_operation')
|
||||
wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='ow_wproduct')
|
||||
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
|
||||
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='当前主生产计划', on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class OperationMaterial(BaseModel):
|
||||
"""
|
||||
生产操作物料消耗产出表
|
||||
"""
|
||||
type_choices=(
|
||||
(1, '消耗'),
|
||||
(2, '产出')
|
||||
)
|
||||
type = models.IntegerField('类型', default=0, choices=type_choices)
|
||||
type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices)
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
||||
wmaterial = models.ForeignKey(WMaterial, 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)
|
||||
count = models.IntegerField('消耗或产出数量', validators=[MinValueValidator(0)])
|
||||
|
||||
class OperationRecord(CommonAModel):
|
||||
wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
|
||||
subproduction_progress = models.ForeignKey(SubProductionProgress, 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)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
|
||||
class OperationRecord(BaseModel):
|
||||
"""
|
||||
记录表格
|
||||
"""
|
||||
form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', on_delete=models.CASCADE)
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
||||
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, related_name='or_operation')
|
||||
is_filled = models.BooleanField('是否填写', default=True)
|
||||
|
||||
class OperationRecordItem(BaseModel):
|
||||
"""
|
||||
|
@ -89,3 +105,7 @@ class OperationRecordItem(BaseModel):
|
|||
sort = models.IntegerField('排序号', default=1)
|
||||
operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE)
|
||||
|
||||
class OperationEquip(BaseModel):
|
||||
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation')
|
||||
equip = models.ForeignKey(Equipment, verbose_name='生产设备', on_delete=models.CASCADE)
|
||||
remark = models.TextField('备注', null=True, blank=True)
|
|
@ -1,19 +1,22 @@
|
|||
from rest_framework import serializers, exceptions
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from apps.em.serializers import EquipmentSimpleSerializer
|
||||
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
|
||||
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer, RecordFormSimpleSerializer, StepSimpleSerializer
|
||||
|
||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from apps.pm.serializers import SubproductionPlanSimpleSerializer
|
||||
from apps.qm.models import TestRecord, TestRecordItem
|
||||
from apps.system.serializers import UserSimpleSerializer
|
||||
from apps.wpm.models import Operation, WMaterial, WProduct, OperationRecord, OperationRecordItem
|
||||
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem
|
||||
from django.db import transaction
|
||||
|
||||
class PickHalfSerializer(serializers.Serializer):
|
||||
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
|
||||
required=False) # 从半成品表里直接修改状态
|
||||
class PickDetailSerializer(serializers.Serializer):
|
||||
|
@ -32,10 +35,11 @@ class PickSerializer(serializers.Serializer):
|
|||
def create(self, validated_data):
|
||||
picks = validated_data.pop('picks')
|
||||
sp = validated_data.pop('subproduction_plan')
|
||||
if sp.state not in [1,2]:
|
||||
if sp.state not in [SubProductionPlan.SUBPLAN_STATE_ASSGINED, SubProductionPlan.SUBPLAN_STATE_ACCEPTED,
|
||||
SubProductionPlan.SUBPLAN_STATE_WORKING]:
|
||||
raise exceptions.ValidationError('该子计划状态错误')
|
||||
if sp.is_picked:
|
||||
raise exceptions.ValidationError('该子计划已领料')
|
||||
# if sp.is_picked:
|
||||
# raise exceptions.ValidationError('该子计划已领料')
|
||||
# for i in picks:
|
||||
# try:
|
||||
# instance = MaterialBatch.objects.get(material=i['material'], batch=i['batch'])
|
||||
|
@ -48,6 +52,7 @@ class PickSerializer(serializers.Serializer):
|
|||
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:
|
||||
isLowLevel = False
|
||||
# 更新出库详情
|
||||
i['count'] = i.pop('pick_count', 0)
|
||||
# 是否勾选每一个
|
||||
|
@ -55,6 +60,8 @@ class PickSerializer(serializers.Serializer):
|
|||
i['count'] = len(i['iproducts'])
|
||||
isLowLevel = True
|
||||
if i['count']>0:
|
||||
if isLowLevel:
|
||||
iproducts = i.pop('iproducts')
|
||||
i['fifo'] = fifo
|
||||
i['is_testok'] = True # 默认检测合格
|
||||
i['subproduction_plan'] = sp
|
||||
|
@ -62,7 +69,7 @@ class PickSerializer(serializers.Serializer):
|
|||
# 创建再下一个层级
|
||||
if isLowLevel:
|
||||
mls = []
|
||||
for m in i['iproducts']:
|
||||
for m in iproducts:
|
||||
ml = {}
|
||||
ml['material'] = m.material
|
||||
ml['number'] = m.number
|
||||
|
@ -82,17 +89,21 @@ class PickSerializer(serializers.Serializer):
|
|||
wm.count = wm.count + i['count']
|
||||
wm.save()
|
||||
# 更新子计划物料情况
|
||||
spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1)
|
||||
spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=SubprodctionMaterial.SUB_MA_TYPE_IN)
|
||||
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)
|
||||
if spp.count_pick > spp.count:
|
||||
raise exceptions.APIException('超过计划需求数')
|
||||
if isLowLevel:
|
||||
# 更新半成品表
|
||||
wids = IProduct.objects.filter(pk__in=[x.id for x in iproducts]).values_list('wproduct', flat=True)
|
||||
wproducts = WProduct.objects.filter(pk__in=wids)
|
||||
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
||||
wproducts.update(step=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 = SubProductionPlan.SUBPLAN_STATE_WORKING #生产中
|
||||
sp.state_date_real = timezone.now() #实际开工日期
|
||||
sp.save()
|
||||
# 更新库存
|
||||
|
@ -114,32 +125,75 @@ class WProductListSerializer(serializers.ModelSerializer):
|
|||
"""
|
||||
半成品列表
|
||||
"""
|
||||
m_state_ = MaterialSimpleSerializer(source='m_state', read_only=True)
|
||||
p_state_ = StepSimpleSerializer(source='p_state', read_only=True)
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||
class Meta:
|
||||
model = WProduct
|
||||
fields = '__all__'
|
||||
|
||||
class OperationDetailSerializer(serializers.ModelSerializer):
|
||||
wproducts_ = serializers.SerializerMethodField()
|
||||
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
||||
m_state_ = MaterialSimpleSerializer(source='m_state', read_only=True)
|
||||
p_state_ = StepSimpleSerializer(source='p_state', read_only=True)
|
||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||
class Meta:
|
||||
model = Operation
|
||||
fields = '__all__'
|
||||
|
||||
def get_wproducts_(self, obj):
|
||||
return list(WProduct.objects.filter(id__in=obj.wproducts).values('id', 'number'))
|
||||
|
||||
class OperationListSerializer(serializers.ModelSerializer):
|
||||
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
||||
m_state_ = MaterialSimpleSerializer(source='m_state', read_only=True)
|
||||
p_state_ = StepSimpleSerializer(source='p_state', read_only=True)
|
||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||
wproduct_count = serializers.SerializerMethodField()
|
||||
equip_count = serializers.SerializerMethodField()
|
||||
record_count = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = Operation
|
||||
fields = '__all__'
|
||||
|
||||
def get_wproduct_count(self, obj):
|
||||
return obj.ow_operation.count()
|
||||
|
||||
def get_equip_count(self, obj):
|
||||
return obj.oe_operation.count()
|
||||
|
||||
def get_record_count(self, obj):
|
||||
return obj.or_operation.count()
|
||||
|
||||
class OperationCreateSerializer(serializers.Serializer):
|
||||
"""
|
||||
操作创建
|
||||
"""
|
||||
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
|
||||
# subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False)
|
||||
wproducts = serializers.ListField(child=
|
||||
serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label="半成品ID列表", required=False)
|
||||
|
||||
def validate(self, data):
|
||||
# subproduction_plan = data['subproduction_plan']
|
||||
step = data['step']
|
||||
|
||||
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
||||
# if step.id not in stepIds:
|
||||
# raise exceptions.ValidationError('请选择正确的子工序操作')
|
||||
|
||||
if 'wproducts' in data and data['wproducts']:
|
||||
if step.type == Step.STEP_TYPE_DIV:
|
||||
raise exceptions.ValidationError(_('不可进行此操作'))
|
||||
for i in data['wproducts']:
|
||||
if i.is_executed:
|
||||
raise exceptions.ValidationError('不可进行操作')
|
||||
# if i.subproduction_plan != subproduction_plan:
|
||||
# raise exceptions.ValidationError('半成品所属子计划不一致')
|
||||
if i.step != step:
|
||||
raise exceptions.ValidationError('半成品所属子工序不一致')
|
||||
else:
|
||||
if step.type != Step.STEP_TYPE_DIV:
|
||||
raise exceptions.ValidationError(_('请选择半成品进行操作'))
|
||||
return data
|
||||
|
||||
|
||||
class OperationUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Operation
|
||||
fields =['use_scrap', 'remark']
|
||||
|
||||
class OperationInitSerializer(serializers.Serializer):
|
||||
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
|
||||
|
@ -163,7 +217,7 @@ class OperationInitSerializer(serializers.Serializer):
|
|||
raise exceptions.ValidationError('不可进行操作')
|
||||
# if i.subproduction_plan != subproduction_plan:
|
||||
# raise exceptions.ValidationError('半成品所属子计划不一致')
|
||||
if i.p_state != step:
|
||||
if i.step != step:
|
||||
raise exceptions.ValidationError('半成品所属子工序不一致')
|
||||
else:
|
||||
if step.type != Step.STEP_TYPE_DIV:
|
||||
|
@ -191,6 +245,19 @@ class OperationRecordSerializer(serializers.ModelSerializer):
|
|||
model = OperationRecord
|
||||
fields = ['form', 'record_data']
|
||||
|
||||
|
||||
class OperationRecordSubmitSerializer(serializers.ModelSerializer):
|
||||
record_data = OperationRecordItemSerializer(many=True)
|
||||
class Meta:
|
||||
model = OperationRecord
|
||||
fields = ['record_data']
|
||||
|
||||
class OperationWproductListSerializer(serializers.ModelSerializer):
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||
class Meta:
|
||||
model = OperationWproduct
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class OperationSubmitSerializer(serializers.Serializer):
|
||||
|
@ -229,6 +296,60 @@ class WplanPutInSerializer(serializers.Serializer):
|
|||
class WproductPutInSerializer(serializers.Serializer):
|
||||
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
|
||||
remark = serializers.CharField(label="入库备注", required =False)
|
||||
|
||||
class OperationEquipListSerializer(serializers.Serializer):
|
||||
equip_ = EquipmentSimpleSerializer(source='equip', read_only=True)
|
||||
class Meta:
|
||||
model = OperationEquip
|
||||
fields = '__all__'
|
||||
|
||||
class OperationEquipUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = OperationEquip
|
||||
fields = ['remark']
|
||||
|
||||
class OperationRecordListSerializer(serializers.ModelSerializer):
|
||||
form_ = RecordFormSimpleSerializer(source='form', read_only=True)
|
||||
class Meta:
|
||||
model = OperationRecord
|
||||
fields = '__all__'
|
||||
|
||||
class OperationMaterialListSerializer(serializers.ModelSerializer):
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = '__all__'
|
||||
|
||||
class OperationMaterialCreate1Serailizer(serializers.ModelSerializer):
|
||||
wmaterial = serializers.PrimaryKeyRelatedField(required=True, queryset=WMaterial.objects.all())
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = ['operation', 'wmaterial', 'count']
|
||||
|
||||
def create(self, validated_data):
|
||||
wmaterial = validated_data['wmaterial']
|
||||
validated_data['material'] = wmaterial.material
|
||||
validated_data['subproduction_plan'] = wmaterial.subproduction_plan
|
||||
validated_data['batch'] = wmaterial.batch
|
||||
return super().create(validated_data)
|
||||
|
||||
class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
|
||||
subproduction_progress = serializers.PrimaryKeyRelatedField(required=True, queryset=SubProductionProgress.objects.all())
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = ['operation', 'subproduction_progress', 'count']
|
||||
|
||||
def create(self, validated_data):
|
||||
subproduction_progress = validated_data['subproduction_progress']
|
||||
validated_data['material'] = subproduction_progress.material
|
||||
validated_data['subproduction_plan'] = subproduction_progress.subproduction_plan
|
||||
return super().create(validated_data)
|
||||
|
||||
class OperationMaterialCreate3Serializer(serializers.ModelSerializer):
|
||||
material = serializers.PrimaryKeyRelatedField(required=True, queryset=Material.objects.all())
|
||||
class Meta:
|
||||
model = OperationMaterial
|
||||
fields = ['operation', 'material']
|
||||
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
from typing import List
|
||||
from apps.pm.models import SubProductionPlan
|
||||
from apps.mtm.models import Step
|
||||
from apps.mtm.models import Step, SubprodctionMaterial
|
||||
from apps.wpm.models import WProduct
|
||||
class WpmServies(object):
|
||||
|
||||
@classmethod
|
||||
|
@ -12,4 +14,21 @@ class WpmServies(object):
|
|||
if pindex + 1 < len(stepIds):
|
||||
return Step.objects.get(pk=stepIds[pindex+1]), True
|
||||
else:
|
||||
return nowstep, False
|
||||
return nowstep, False
|
||||
|
||||
@classmethod
|
||||
def get_subplans_queryset_from_wproducts(cls, wproducts:List):
|
||||
"""
|
||||
通过半成品列表获取所属子计划
|
||||
"""
|
||||
splans = SubProductionPlan.objects.filter(is_deleted=False, wproduct_subplan__in=wproducts)
|
||||
return splans
|
||||
|
||||
@classmethod
|
||||
def get_subplans_queyset_from_step(cls, step:Step):
|
||||
"""
|
||||
通过当前操作获取所有正在进行的子计划
|
||||
"""
|
||||
splans = SubProductionPlan.objects.filter(is_deleted=False,
|
||||
subproduction__usedstep_subproduction__step=step, state=SubProductionPlan.SUBPLAN_STATE_WORKING)
|
||||
return splans
|
|
@ -3,12 +3,18 @@ from rest_framework import urlpatterns
|
|||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
|
||||
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||
router.register('wproduct', WProductViewSet, basename='wproduct')
|
||||
router.register('operation', OperationViewSet, basename='operation')
|
||||
router.register('operation_wproduct', OperationWproductViewSet, basename='operation_wproduct')
|
||||
router.register('operation_equip', OperationEquipViewSet, basename='operation_equip')
|
||||
router.register('operation_record', OperationRecordViewSet, basename='operation_record')
|
||||
router.register('operation_input', OperationMaterialInputViewSet, basename='operation_input')
|
||||
router.register('operation_output', OperationMaterialOutputViewSet, basename='operation_output')
|
||||
router.register('operation_tool', OperationMaterialToolViewSet, basename='operation_tool')
|
||||
router.register('subplan', WPlanViewSet, basename='wplan')
|
||||
urlpatterns = [
|
||||
path('do/init/', DoFormInit.as_view()),
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.generics import CreateAPIView, GenericAPIView
|
||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||
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, WareHouse
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial
|
||||
from apps.mtm.serializers import RecordFormDetailSerializer
|
||||
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial, TechDoc
|
||||
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
|
||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer
|
||||
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||
from apps.qm.models import TestRecordItem
|
||||
|
||||
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.filters import WMaterialFilterSet
|
||||
from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
|
||||
|
||||
from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
|
||||
from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, 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
|
||||
|
@ -25,6 +26,7 @@ from rest_framework import exceptions, serializers
|
|||
from apps.wpm.services import WpmServies
|
||||
from django.utils import timezone
|
||||
from utils.tools import ranstr
|
||||
from rest_framework import status
|
||||
# Create your views here.
|
||||
class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||
"""
|
||||
|
@ -49,19 +51,25 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
|||
"""
|
||||
领半成品
|
||||
"""
|
||||
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)
|
||||
spps = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
|
||||
material__type=Material.MA_TYPE_HALFGOOD, subproduction_plan=sp).select_related('material')
|
||||
return Response(SubProductionProgressSerializer(instance=spps, many=True).data)
|
||||
elif request.method=='POST':
|
||||
serializer= PickHalfSerializer(data=request.data)
|
||||
serializer= PickHalfSerializer(data=request.data, many=True)
|
||||
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)
|
||||
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
||||
for i in vdata:
|
||||
if 'wproducts' in i and len(i['wproducts'])>0:
|
||||
spp = SubProductionProgress.objects.get(pk=i['id'])
|
||||
spp.count_pick = spp.count_pick + len(i['wproducts'])
|
||||
if spp.count_pick > spp.count:
|
||||
raise exceptions.APIException('超过计划数')
|
||||
spp.save()
|
||||
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
|
||||
wps.update(step=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, update_by=request.user, update_time=timezone.now())
|
||||
return Response()
|
||||
|
||||
|
||||
|
@ -79,7 +87,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
|||
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)
|
||||
act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False)
|
||||
if wproducts.exists():
|
||||
# 创建入库记录
|
||||
remark = vdata.get('remark', '')
|
||||
|
@ -119,7 +127,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
|||
IProduct.objects.bulk_create(ips2)
|
||||
# 更新库存并修改半成品进行状态
|
||||
update_inm(fifo)
|
||||
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse)
|
||||
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user, update_time=timezone.now())
|
||||
|
||||
return Response()
|
||||
|
||||
|
@ -131,7 +139,7 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
|
|||
perms_map={'*':'*'}
|
||||
queryset = WMaterial.objects.select_related('material').all()
|
||||
serializer_class = WMaterialListSerializer
|
||||
filterset_fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop']
|
||||
filterset_class = WMaterialFilterSet
|
||||
ordering_fields = ['material__number']
|
||||
ordering = ['material__number']
|
||||
|
||||
|
@ -150,9 +158,9 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
半成品
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = WProduct.objects.select_related('p_state', 'm_state').filter(is_hidden=False)
|
||||
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False).exclude(operation=None)
|
||||
serializer_class = WProductListSerializer
|
||||
filterset_fields = ['p_state', 'subproduction_plan', 'm_state', 'production_plan', 'p_state__process', 'act_state']
|
||||
filterset_fields = ['step', 'subproduction_plan', 'material', 'production_plan', 'step__process', 'act_state']
|
||||
search_fields = ['number']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['id']
|
||||
|
@ -173,7 +181,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
if 'is_testok' not in vdata:
|
||||
raise exceptions.APIException('未填写检测结论')
|
||||
|
||||
obj = serializer.save(create_by = self.request.user, m_state=wproduct.m_state)
|
||||
obj = serializer.save(create_by = self.request.user, material=wproduct.material)
|
||||
tris = []
|
||||
for m in record_data: # 保存记录详情
|
||||
form_field = m['form_field']
|
||||
|
@ -193,7 +201,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
if obj.is_testok:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
|
||||
if wproduct.number is None: # 产生半成品编号
|
||||
wproduct.number = 'WP-'+ranstr(7)
|
||||
wproduct.number = 'WP'+ranstr(7)
|
||||
wproduct.save()
|
||||
# 更新子计划状态
|
||||
# 更新子计划主产品数
|
||||
|
@ -219,7 +227,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
|
||||
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
|
||||
raise exceptions.APIException('半成品不可入库')
|
||||
material = wproduct.m_state
|
||||
material = wproduct.material
|
||||
batch = wproduct.production_plan.number
|
||||
# 创建入库记录
|
||||
remark = vdata.get('remark', '')
|
||||
|
@ -253,20 +261,225 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
|||
wproduct.save()
|
||||
return Response()
|
||||
|
||||
class OperationViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
||||
class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
生产操作记录
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = Operation.objects.select_related('p_state', 'm_state').all()
|
||||
queryset = Operation.objects.select_related('step').prefetch_related('ow_operation', 'oe_operation', 'or_operation').all()
|
||||
serializer_class = OperationListSerializer
|
||||
filterset_fields = ['p_state', 'm_state']
|
||||
filterset_fields = ['step', 'step__process', 'is_submited']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(create_by=self.request.user)
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'retrieve':
|
||||
return OperationDetailSerializer
|
||||
elif self.action == 'create':
|
||||
return OperationCreateSerializer
|
||||
elif self.action == 'update':
|
||||
return OperationUpdateSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.is_submited:
|
||||
raise exceptions.APIException('该操作已提交')
|
||||
self.perform_destroy(instance)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
@transaction.atomic
|
||||
def create(self, request, *args, **kwargs):
|
||||
data = request.data
|
||||
serializer = OperationCreateSerializer(data=data, context={'request':self.request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.validated_data #校验之后的数据
|
||||
step = vdata['step']
|
||||
op = Operation()
|
||||
op.step = step
|
||||
op.is_submited = False
|
||||
op.create_by = request.user
|
||||
op.save()
|
||||
splans = []
|
||||
# 创建操作所用半成品关联记录
|
||||
if 'wproducts' in vdata:
|
||||
owps = []
|
||||
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
||||
for wpd in vdata['wproducts']:
|
||||
owp = {}
|
||||
owp['operation'] = op
|
||||
owp['wproduct'] = wpd
|
||||
owp['number'] = wpd.number
|
||||
owp['material'] = wpd.material
|
||||
owp['subproduction_plan'] = wpd.subproduction_plan
|
||||
owp['production_plan'] = wpd.production_plan
|
||||
owps.append(OperationWproduct(**owp))
|
||||
OperationWproduct.objects.bulk_create(owps)
|
||||
else:
|
||||
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
||||
# 查询需要填写的自定义表格
|
||||
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO)
|
||||
for i in forms:
|
||||
opr = OperationRecord()
|
||||
opr.operation = op
|
||||
opr.form = i
|
||||
opr.is_filled = False
|
||||
opr.save()
|
||||
# 查询需要使用的生产设备
|
||||
for i in step.equipments.all():
|
||||
ope = OperationEquip()
|
||||
ope.operation = op
|
||||
ope.equip = i
|
||||
ope.save()
|
||||
# 查询所需的工具工装
|
||||
for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,
|
||||
subproduction__subplan_subprod__in = splans, is_deleted=False).distinct():
|
||||
opm = OperationMaterial()
|
||||
opm.operation = op
|
||||
opm.material = i.material
|
||||
opm.type = SubprodctionMaterial.SUB_MA_TYPE_TOOL
|
||||
opm.save()
|
||||
return Response()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
操作使用的半成品
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationWproduct.objects.select_related('subproduction_plan', 'material').all()
|
||||
serializer_class = OperationWproductListSerializer
|
||||
filterset_fields = ['material', 'subproduction_plan', 'operation']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
@transaction.atomic()
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.operation.is_submited:
|
||||
raise exceptions.APIException('该操作已提交')
|
||||
instance.delete()
|
||||
wp = instance.wproduct
|
||||
wp.operation = None
|
||||
wp.save()
|
||||
return Response()
|
||||
|
||||
class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
|
||||
"""
|
||||
操作使用的设备
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationEquip.objects.select_related('operation', 'equip').all()
|
||||
serializer_class = OperationEquipListSerializer
|
||||
filterset_fields = ['operation', 'equip']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'update':
|
||||
return OperationEquipUpdateSerializer
|
||||
return super().get_serializer_class()
|
||||
@transaction.atomic()
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.operation.is_submited:
|
||||
raise exceptions.APIException('该操作已提交')
|
||||
instance.delete()
|
||||
return Response()
|
||||
|
||||
class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
操作使用的自定义表格
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationRecord.objects.select_related('operation', 'form').all()
|
||||
serializer_class = OperationRecordListSerializer
|
||||
filterset_fields = ['operation', 'form']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
@transaction.atomic()
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if instance.operation.is_submited:
|
||||
raise exceptions.APIException('该操作已提交')
|
||||
instance.delete()
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=OperationRecordSubmitSerializer)
|
||||
def submit(self, request, pk=None):
|
||||
serializer = OperationRecordSubmitSerializer(data=request.data, context={'request':self.request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.data
|
||||
opr = self.get_object()
|
||||
wrds = []
|
||||
for m in vdata['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['operation_record'] = opr
|
||||
wrds.append(OperationRecordItem(**m))
|
||||
OperationRecordItem.objects.bulk_create(wrds)
|
||||
opr.is_filled = True
|
||||
opr.save()
|
||||
return Response()
|
||||
|
||||
|
||||
class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
消耗物料
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN)
|
||||
serializer_class = OperationMaterialListSerializer
|
||||
filterset_fields = ['operation', 'subproduction_plan']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return OperationMaterialCreate1Serailizer
|
||||
return super().get_serializer_class()
|
||||
|
||||
class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
产出物料
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||
serializer_class = OperationMaterialListSerializer
|
||||
filterset_fields = ['operation', 'subproduction_plan']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return OperationMaterialCreate2Serailizer
|
||||
return super().get_serializer_class()
|
||||
|
||||
class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
工具工装
|
||||
"""
|
||||
perms_map={'*':'*'}
|
||||
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL)
|
||||
serializer_class = OperationMaterialListSerializer
|
||||
filterset_fields = ['operation', 'subproduction_plan']
|
||||
ordering_fields = ['id']
|
||||
ordering = ['-id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return OperationMaterialCreate3Serializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
class DoFormInit(CreateAPIView, GenericAPIView):
|
||||
|
@ -319,6 +532,15 @@ class DoFormInit(CreateAPIView, GenericAPIView):
|
|||
ret['forms'] = []
|
||||
ret_0['id'] = 0
|
||||
ret_0['name'] = '基本信息'
|
||||
# 查询工具工装
|
||||
ret_0['tools'] = SubprodctionMaterialListSerializer(instance=
|
||||
SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,
|
||||
subproduction__subplan_subprod__in = splans), many=True).data
|
||||
# 查询技术文档
|
||||
ret_0['techdocs'] = TechDocListSerializer(instance =
|
||||
TechDoc.objects.filter(subproduction__subplan_subprod__in = splans, enabled=True)\
|
||||
.distinct(), many=True).data
|
||||
|
||||
ret['forms'].append(ret_0)
|
||||
forms = RecordForm.objects.filter(step=vdata['step'], type=RecordForm.RF_TYPE_DO)
|
||||
if forms.exists():
|
||||
|
@ -342,14 +564,26 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
|||
|
||||
# 创建一个生产操作记录
|
||||
action_obj = Operation()
|
||||
action_obj.p_state = vdata['step']
|
||||
if 'wproducts' in data and data['wproducts']:
|
||||
action_obj.wproducts = data['wproducts']
|
||||
action_obj.m_state = vdata['wproducts'][0].m_state
|
||||
action_obj.step = vdata['step']
|
||||
action_obj.remark = vdata.get('remark', '') # 操作备注
|
||||
action_obj.create_by = request.user
|
||||
action_obj.use_scrap = vdata.get('use_scrap', False)
|
||||
action_obj.save()
|
||||
|
||||
# 保存关联半成品
|
||||
if 'wproducts' in data and data['wproducts']:
|
||||
owps = []
|
||||
for i in data['wproducts']:
|
||||
owp = {}
|
||||
owp['operation'] = action_obj
|
||||
wp = WProduct.objects.get(pk=i)
|
||||
owp['wproduct'] = wp
|
||||
owp['number'] = wp.number
|
||||
owp['material'] = wp.material
|
||||
owp['subproduction_plan'] = wp.subproduction_plan
|
||||
owp['production_plan'] = wp.production_plan
|
||||
owps.append(OperationWproduct(**owp))
|
||||
OperationWproduct.objects.bulk_create(owps)
|
||||
|
||||
# 保存物料消耗
|
||||
for i in vdata['input']:
|
||||
|
@ -375,7 +609,7 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
|||
# 获取下一步子工序
|
||||
if vdata['step'].type == Step.STEP_TYPE_DIV:
|
||||
newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
|
||||
wpr = dict(m_state=ma, p_state=newstep,
|
||||
wpr = dict(material=ma, step=newstep,
|
||||
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
|
||||
subproduction_plan=i['subproduction_plan'],
|
||||
production_plan=i['subproduction_plan'].production_plan)
|
||||
|
@ -404,8 +638,8 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
|||
wproducts.update(is_hidden=True) # 隐藏
|
||||
newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
|
||||
wproduct = WProduct()
|
||||
wproduct.m_state = vdata['subproduction_plan'].main_product
|
||||
wproduct.p_state = newstep
|
||||
wproduct.material = vdata['subproduction_plan'].main_product
|
||||
wproduct.step = newstep
|
||||
wproduct.subproduction_plan=vdata['subproduction_plan']
|
||||
wproduct.production_plan=vdata['subproduction_plan'].production_plan
|
||||
wproduct.parent = data['wproducts']
|
||||
|
@ -421,15 +655,15 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
|||
else:
|
||||
for wproduct in vdata['wproducts']:
|
||||
# 获取下一步子工序
|
||||
newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
|
||||
wproduct.p_state = newstep
|
||||
wproduct.pre_pstate=vdata['step']
|
||||
newstep, hasNext = WpmServies.get_next_step(wproduct.subproduction_plan, vdata['step'])
|
||||
wproduct.step = newstep
|
||||
wproduct.pre_step=vdata['step']
|
||||
if hasNext:
|
||||
wproduct.is_executed= False
|
||||
else:
|
||||
wproduct.is_executed= True
|
||||
wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST
|
||||
wproduct.m_state=wproduct.subproduction_plan.main_product
|
||||
wproduct.material=wproduct.subproduction_plan.main_product
|
||||
wproduct.save()
|
||||
|
||||
# 保存自定义表单结果
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
celery==5.1.2
|
||||
Django==3.2.6
|
||||
Django==3.2.9
|
||||
django-celery-beat==2.2.1
|
||||
django-cors-headers==3.7.0
|
||||
django-filter==2.4.0
|
||||
|
|
|
@ -26,7 +26,7 @@ from rest_framework.documentation import include_docs_urls
|
|||
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
||||
TokenRefreshView)
|
||||
from django.views.generic import TemplateView
|
||||
from utils.view import GenSignature
|
||||
from utils.view import GenSignature, UpdateDevelop
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register('', FileViewSet, basename="file")
|
||||
|
@ -72,6 +72,7 @@ urlpatterns = [
|
|||
|
||||
# 工具
|
||||
path('api/utils/signature/', GenSignature.as_view()),
|
||||
path('api/utils/develop/', UpdateDevelop.as_view()),
|
||||
|
||||
# 前端页面入口
|
||||
path('',TemplateView.as_view(template_name="index.html"))
|
||||
|
|
|
@ -2,6 +2,6 @@ import random
|
|||
import string
|
||||
|
||||
def ranstr(num):
|
||||
salt = ''.join(random.sample(string.ascii_letters + string.digits, num))
|
||||
salt = ''.join(random.sample(string.ascii_lowercase + string.digits, num))
|
||||
return salt
|
||||
ranstr(10)
|
|
@ -49,3 +49,22 @@ class GenSignature(APIView):
|
|||
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
|
||||
cv2.imwrite(path,image)
|
||||
return Response(request.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class UpdateDevelop(APIView):
|
||||
"""
|
||||
更新开发服务器
|
||||
"""
|
||||
authentication_classes = ()
|
||||
permission_classes = ()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
import os
|
||||
# 更新后端
|
||||
os.chdir('/home/hberp')
|
||||
ret = os.popen('git pull https://caoqianming%40ctc.ac.cn:9093qqww@e.coding.net/ctcdevteam/hberp/hberp.git origin develop')
|
||||
# 打包前端
|
||||
# os.chdir('/home/hberp/hb_client')
|
||||
# os.system('npm run build:prod')
|
||||
# os.system('\cp -rf /home/hberp/hb_client/dist/* /home/hberp/hb_server/vuedist')
|
||||
return Response(ret.read())
|
||||
|
|
Loading…
Reference in New Issue