Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shijing 2021-11-22 14:08:30 +08:00
commit d0f9030cfc
35 changed files with 1024 additions and 154 deletions

View File

@ -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,

View File

@ -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>

View File

@ -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) {

View File

@ -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("成功!");

View File

@ -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='关联子生产计划'),
),
]

View File

@ -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):
"""

View File

@ -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='关联生产分解'),
),
]

View File

@ -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 = '技术文件'

View File

@ -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']

View File

@ -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':

View File

@ -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='关联生产分解'),
),
]

View File

@ -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='子计划编号'),
),
]

View File

@ -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)

View File

@ -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']

View File

@ -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()

View File

@ -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()

View File

@ -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',
),
]

View File

@ -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='自动判定的是否合格'),
),
]

View File

@ -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')

View File

@ -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

View File

@ -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='关联半成品'),
),
]

View File

@ -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='所在步骤'),
),
]

View File

@ -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='关联操作'),
),
]

View File

@ -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,
},
),
]

View File

@ -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='关联操作'),
),
]

View File

@ -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='当前子生产计划'),
),
]

View File

@ -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)

View File

@ -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']

View File

@ -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

View File

@ -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()),

View File

@ -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()
# 保存自定义表单结果

View File

@ -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

View File

@ -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"))

View File

@ -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)

View File

@ -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())