Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
168c8df4fd
|
@ -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,
|
||||
|
|
|
@ -226,6 +226,36 @@ export function deleteOutputmaterial(id, data) {
|
|||
data
|
||||
})
|
||||
}
|
||||
//其他材料
|
||||
export function getOthermaterialList(query) {
|
||||
return request({
|
||||
url: '/mtm/othermaterial/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function createOthermaterial(data) {
|
||||
return request({
|
||||
url: '/mtm/othermaterial/',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function updateOthermaterial(id, data) {
|
||||
return request({
|
||||
url: `/mtm/othermaterial/${id}/`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function deleteOthermaterial(id, data) {
|
||||
return request({
|
||||
url: `/mtm/othermaterial/${id}/`,
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//子工序
|
||||
|
||||
export function getUsedstepList(query) {
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="技术指标">
|
||||
<el-table-column label="技术指标" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.parameter }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="保管人">
|
||||
|
@ -208,8 +208,13 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术指标" prop="parameter">
|
||||
<el-input v-model="equipment.parameter" placeholder="技术指标" />
|
||||
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
v-model="equipment.parameter"
|
||||
placeholder="技术指标"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="存放位置" prop="place">
|
||||
<el-input v-model="equipment.place" placeholder="存放位置" />
|
||||
|
|
|
@ -232,13 +232,16 @@
|
|||
</el-form-item>
|
||||
|
||||
<el-form-item label="输入物料" prop="unit">
|
||||
<el-select filterable style="width: 100%" v-model="inputmaterial.material" placeholder="请选择">
|
||||
<el-select filterable style="width: 50%" v-model="inputmaterial.material" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in materialoptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.specification }}</span>
|
||||
</el-option>
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
|
@ -330,12 +333,14 @@
|
|||
</el-form-item>
|
||||
|
||||
<el-form-item label="输出物料" prop="unit">
|
||||
<el-select style="width: 100%" v-model="outputmaterial.material" placeholder="请选择">
|
||||
<el-select style="width: 50%" v-model="outputmaterial.material" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in materialoptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.specification }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
@ -359,6 +364,103 @@
|
|||
</div>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="工具工装">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleotherCreate"
|
||||
>新增</el-button>
|
||||
|
||||
<el-table
|
||||
|
||||
:data="othertableData"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column label="物料编号" min-width="100">
|
||||
<template slot-scope="scope">{{scope.row.material_.number}}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="物料名称" min-width="100">
|
||||
<template slot-scope="scope"> {{scope.row.material_.name}}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="计量单位" min-width="100">
|
||||
<template slot-scope="scope">{{ scope.row.material_.unit }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="单位消耗量" min-width="100">
|
||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
|
||||
<el-link
|
||||
v-if="checkPermission(['material_update'])"
|
||||
@click="handleotherEdit(scope)"
|
||||
>编辑</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="checkPermission(['material_delete'])"
|
||||
type="danger"
|
||||
@click="handleotherDelete(scope)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisibleother"
|
||||
:title="dialogTypeother === 'edit' ? '编辑工具工装' : '新增工具工装'"
|
||||
>
|
||||
<el-form
|
||||
ref="Formother"
|
||||
:model="othermaterial"
|
||||
label-width="80px"
|
||||
label-position="right"
|
||||
>
|
||||
|
||||
<el-form-item label="消耗量" prop="count">
|
||||
<el-input-number v-model="othermaterial.count" :min="0" placeholder="输入整数或小数" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="输入物料" prop="unit">
|
||||
<el-select filterable style="width: 50%" v-model="othermaterial.material" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in materialoptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.specification }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number
|
||||
v-model="othermaterial.sort"
|
||||
:min="-2147483648"
|
||||
:max="2147483647"
|
||||
></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-form>
|
||||
<div style="text-align: right">
|
||||
<el-button type="danger" @click="dialogVisibleother = false">取消</el-button>
|
||||
<el-button type="primary" @click="otherconfirm('Formother')">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="子工序列表">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleusedstepCreate"
|
||||
>新增</el-button>
|
||||
|
@ -532,7 +634,8 @@
|
|||
import { getMaterialList,getMaterial,getInputmaterialList,createInputmaterial,updateInputmaterial
|
||||
,deleteInputmaterial,getOutputmaterialList,createOutputmaterial,updateOutputmaterial,deleteOutputmaterial,
|
||||
getUsedstepList,createUsedstep,deleteUsedstep,getStepList,gettechdocList,createtechdoc,updatetechdoc,deletetechdoc
|
||||
,getsubproducationList,createsubproducation,updatesubproducation,deletesubproducation,getProcessList } from "@/api/mtm";
|
||||
,getsubproducationList,createsubproducation,updatesubproducation,deletesubproducation,getProcessList ,
|
||||
getOthermaterialList,createOthermaterial,deleteOthermaterial} from "@/api/mtm";
|
||||
import { quillEditor } from 'vue-quill-editor'
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
|
@ -548,6 +651,7 @@ const defaultinputmaterial = {
|
|||
const defaultoutputmaterial = {
|
||||
|
||||
};
|
||||
const defaultother = {};
|
||||
const defaultusedstep = {
|
||||
|
||||
};
|
||||
|
@ -569,11 +673,13 @@ export default {
|
|||
editorOption: {} ,
|
||||
processOptions:[],
|
||||
is_main:false,
|
||||
othermaterial:defaultother,
|
||||
techdoc: defaulttechdoc,
|
||||
subproducation:defaultsubproducation,
|
||||
inputmaterial: defaultinputmaterial,
|
||||
techdoctableData:"",
|
||||
outputtableData:"",
|
||||
othertableData:"",
|
||||
outputmaterial: defaultoutputmaterial,
|
||||
usedsteptableData:"",
|
||||
usedstep: defaultusedstep,
|
||||
|
@ -601,6 +707,9 @@ export default {
|
|||
listQueryusedstep: {
|
||||
page: 0,
|
||||
},
|
||||
listQueryother: {
|
||||
page: 0,
|
||||
},
|
||||
listQuerytechdoc:{
|
||||
page: 0,
|
||||
},
|
||||
|
@ -619,6 +728,8 @@ export default {
|
|||
dialogVisibleusedstep:false,
|
||||
dialogTypet: "new",
|
||||
dialogVisiblet:false,
|
||||
dialogVisibleother:false,
|
||||
dialogTypeother: "new",
|
||||
listLoading: true,
|
||||
|
||||
};
|
||||
|
@ -648,7 +759,7 @@ export default {
|
|||
this.listLoading = true;
|
||||
getMaterialList({pageoff:true}).then((response) => {
|
||||
if (response.data) {
|
||||
this.materialoptions = genTree(response.data);
|
||||
this.materialoptions = response.data;
|
||||
}
|
||||
this.listLoading = false;
|
||||
});
|
||||
|
@ -680,29 +791,16 @@ export default {
|
|||
handlespChange(row){
|
||||
this.subproduction = row.id;
|
||||
this.processes = row.process;
|
||||
this.getmaterialList();//物料列表
|
||||
|
||||
this.getInputmaterialLists();//输入物料
|
||||
|
||||
this.getOutputmaterialLists();//输出物料
|
||||
this.getOthermaterialLists();//辅助工装
|
||||
this.getstepList();//子工序
|
||||
this. getUsedstepLists();//
|
||||
this.gettechdocLists();//技术文件
|
||||
},
|
||||
//工艺点击信息
|
||||
|
||||
stepclick(id)
|
||||
{
|
||||
this.process = id;
|
||||
// alert(this.process)
|
||||
this.getmaterialList();//物料列表
|
||||
this.getInputmaterialLists();//输入物料
|
||||
|
||||
this.getOutputmaterialLists();//输出物料
|
||||
this.getstepList();//子工序
|
||||
this. getUsedstepLists();//
|
||||
this.gettechdocLists();//技术文件
|
||||
|
||||
},
|
||||
|
||||
//产品分解
|
||||
getsubproducationList(){
|
||||
|
@ -798,6 +896,7 @@ export default {
|
|||
this.$nextTick(() => {
|
||||
this.$refs["Form"].clearValidate();
|
||||
});
|
||||
this.getmaterialList();//物料列表
|
||||
},
|
||||
handleinputEdit(scope) {
|
||||
this.inputmaterial = Object.assign({}, scope.row); // copy obj
|
||||
|
@ -878,6 +977,7 @@ export default {
|
|||
this.$nextTick(() => {
|
||||
this.$refs["Forms"].clearValidate();
|
||||
});
|
||||
this.getmaterialList();//物料列表
|
||||
},
|
||||
handleoutputEdit(scope) {
|
||||
this.outputmaterial = Object.assign({}, scope.row); // copy obj
|
||||
|
@ -931,6 +1031,84 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
//输入其他物料列表
|
||||
|
||||
getOthermaterialLists(){
|
||||
|
||||
this.listQueryother.subproduction=this.subproduction;
|
||||
getOthermaterialList(this.listQueryother).then((response) => {
|
||||
if (response.data) {
|
||||
|
||||
this.othertableData = response.data;//工装列表
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
//输入其他物料
|
||||
handleotherCreate() {
|
||||
this.othermaterial = Object.assign({}, defaultother);
|
||||
this.dialogTypeother = "new";
|
||||
this.dialogVisibleother = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["Formother"].clearValidate();
|
||||
});
|
||||
this.getmaterialList();//物料列表
|
||||
},
|
||||
handleotherEdit(scope) {
|
||||
this.othermaterial = Object.assign({}, scope.row); // copy obj
|
||||
this.dialogTypeother = "edit";
|
||||
this.dialogVisibleother = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["Formother"].clearValidate();
|
||||
});
|
||||
},
|
||||
handleotherDelete(scope) {
|
||||
this.$confirm("确认删除?", "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
await deleteOthermaterial(scope.row.id);
|
||||
this.getOthermaterialLists()
|
||||
this.$message.success("成功");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
async otherconfirm(form) {
|
||||
this.$refs[form].validate((valid) => {
|
||||
if (valid) {
|
||||
const isEdit = this.dialogTypeother === "edit";
|
||||
if (isEdit) {
|
||||
this.othermaterial.subproduction=this.subproduction;
|
||||
updateOthermaterial(this.othermaterial.id, this.othermaterial).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getOthermaterialLists()
|
||||
this.dialogVisibleother = false;
|
||||
this.$message.success("成功");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.othermaterial.subproduction=this.subproduction;
|
||||
createOthermaterial(this.othermaterial).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getOthermaterialLists()
|
||||
this.dialogVisibleother = false;
|
||||
this.$message.success("成功");
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
//子工序列表
|
||||
|
||||
getUsedstepLists(){
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-02 01:35
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wpm', '0002_auto_20211029_1336'),
|
||||
('inm', '0007_auto_20211028_1331'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='iproduct',
|
||||
name='wproduct',
|
||||
field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='关联的动态产品'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='materialbatch',
|
||||
name='batch',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-02 03:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inm', '0008_auto_20211102_0935'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='is_audited',
|
||||
field=models.BooleanField(default=False, verbose_name='是否审核'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifodetail',
|
||||
name='is_tested',
|
||||
field=models.BooleanField(default=False, verbose_name='是否检测'),
|
||||
),
|
||||
]
|
|
@ -41,7 +41,7 @@ class MaterialBatch(BaseModel):
|
|||
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
count = models.IntegerField('存量', default=0)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True, unique=True)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||
class Meta:
|
||||
verbose_name = '库存表'
|
||||
|
@ -60,6 +60,7 @@ class FIFO(CommonAModel):
|
|||
(4, '生产入库')
|
||||
)
|
||||
type = models.IntegerField('出入库类型', default=1)
|
||||
is_audited = models.BooleanField('是否审核', default=False)
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||
operator = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True)
|
||||
|
@ -71,6 +72,8 @@ class FIFODetail(BaseModel):
|
|||
"""
|
||||
出入库详细记录
|
||||
"""
|
||||
is_tested = models.BooleanField('是否已检测', default=False)
|
||||
is_testok = models.BooleanField('是否检测合格', default=False)
|
||||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
count = models.IntegerField('数量', default=0)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
|
|
|
@ -83,7 +83,8 @@ class FIFOInPurSerializer(serializers.ModelSerializer):
|
|||
for i in details:
|
||||
# 校验批次
|
||||
try:
|
||||
obj = MaterialBatch.objects.get(batch=i['batch'])
|
||||
if i['batch']:
|
||||
obj = MaterialBatch.objects.get(batch=i['batch'], material=i['material'])
|
||||
if obj.warehouse != validated_data['warehouse']:
|
||||
raise serializers.ValidationError('批次号{}在其他仓库已存在'.format(i['batch']))
|
||||
except:
|
||||
|
|
|
@ -1,35 +1,38 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from apps.inm.models import FIFODetail, Inventory, MaterialBatch
|
||||
from apps.inm.models import Inventory, MaterialBatch, FIFO, FIFODetail
|
||||
|
||||
|
||||
@receiver(post_save, sender=FIFODetail)
|
||||
def update_by_fifodetail(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
fifo = instance.fifo
|
||||
material = instance.material
|
||||
warehouse = fifo.warehouse
|
||||
if fifo.type in [3]: # 采购入库
|
||||
def update_inm(instance:FIFO, type:int):
|
||||
"""
|
||||
更新库存(正反)
|
||||
"""
|
||||
warehouse = instance.warehouse
|
||||
if instance.type in [3]: # 采购入库
|
||||
# 更新相关表
|
||||
for i in FIFODetail.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
o1, _ = Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0})
|
||||
o1.count = o1.count + instance.count
|
||||
o1.count = o1.count + i.count
|
||||
o1.save()
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=instance.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
|
||||
o2.count = o2.count + instance.count
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
||||
o2.count = o2.count + i.count
|
||||
o2.save()
|
||||
material.count = material.count + instance.count
|
||||
material.count = material.count + i.count
|
||||
material.save()
|
||||
elif fifo.type in [1]: # 生产领料
|
||||
elif instance.type in [1]: # 生产领料
|
||||
# 更新相关表
|
||||
for i in FIFODetail.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
o1 = Inventory.objects.get(material=material, warehouse=warehouse)
|
||||
o1.count = o1.count - instance.count
|
||||
o1.count = o1.count - i.count
|
||||
o1.save()
|
||||
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=instance.batch)
|
||||
o2.count = o2.count - instance.count
|
||||
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=i.batch)
|
||||
o2.count = o2.count - i.count
|
||||
o2.save()
|
||||
material.count = material.count - instance.count
|
||||
material.count = material.count - i.count
|
||||
material.save()
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.inm.filters import MbFilterSet
|
||||
|
||||
from apps.inm.models import FIFO, FIFODetail, MaterialBatch, WareHouse,Inventory
|
||||
from apps.inm.serializers import FIFODetailSerializer, FIFOInPurSerializer, FIFOListSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
@ -80,7 +82,10 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
|
|||
perms_map = {'*': '*'}
|
||||
queryset = FIFO.objects.select_related('warehouse', 'operator')
|
||||
serializer_class = FIFOListSerializer
|
||||
filterset_fields = ['warehouse', 'type']
|
||||
filterset_fields = '__all__'
|
||||
ordering_fields = '__all__'
|
||||
search_fields = ['warehouse__name', 'warehouse__number']
|
||||
ordering = ['-pk']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'list':
|
||||
|
@ -97,3 +102,17 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
|
|||
serializer.save(create_by=request.user)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
|
||||
def audit(self, request, pk=None):
|
||||
"""
|
||||
审核通过
|
||||
"""
|
||||
obj = self.get_object()
|
||||
for i in FIFODetail.objects.filter(fifo=obj):
|
||||
if not i.is_testok:
|
||||
raise APIException('未检验通过, 不可审核')
|
||||
obj.is_audited = True
|
||||
obj.save()
|
||||
update_inm(obj) # 更新库存
|
||||
return Response()
|
||||
|
|
@ -88,6 +88,7 @@ class RecordForm(CommonAModel):
|
|||
type = models.IntegerField('表格类型', choices=type_choices, default=1)
|
||||
step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE, null=True, blank=True)
|
||||
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '记录表格'
|
||||
verbose_name_plural = verbose_name
|
||||
|
@ -130,7 +131,7 @@ class RecordFormField(CommonAModel):
|
|||
field_choice = models.JSONField('radio、checkbox、select的选项', default=dict, blank=True, null=True,
|
||||
help_text='radio,checkbox,select,multiselect类型可供选择的选项,格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号')
|
||||
sort = models.IntegerField('排序号', default=1)
|
||||
need_judge = models.BooleanField('需要判定', default=False)
|
||||
need_judge = models.BooleanField('需要判定项目', default=False)
|
||||
high_limit = models.FloatField('上限值', null=True, blank=True)
|
||||
high_rule = models.IntegerField('上限规则', choices=high_rule_choices, null=True, blank=True)
|
||||
low_limit = models.FloatField('下限值', null=True, blank=True)
|
||||
|
|
|
@ -151,6 +151,11 @@ class UsedStepListSerializer(serializers.ModelSerializer):
|
|||
queryset = queryset.select_related('step')
|
||||
return queryset
|
||||
|
||||
class RecordFormSimpleSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = RecordForm
|
||||
fields = ['id', 'name']
|
||||
class RecordFormSerializer(serializers.ModelSerializer):
|
||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
|
@ -182,6 +187,26 @@ class RecordFormFieldSerializer(serializers.ModelSerializer):
|
|||
model = RecordFormField
|
||||
fields = '__all__'
|
||||
|
||||
class RecordFormDetailSerializer(serializers.ModelSerializer):
|
||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
form_fields = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = RecordForm
|
||||
fields = '__all__'
|
||||
|
||||
@staticmethod
|
||||
def setup_eager_loading(queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.select_related('step', 'material')
|
||||
return queryset
|
||||
|
||||
def get_form_fields(self, obj):
|
||||
serializer = RecordFormFieldSerializer(instance=RecordFormField.objects.filter(form=obj, is_deleted=False), many=True)
|
||||
return serializer.data
|
||||
|
||||
|
||||
class RecordFormFieldCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = RecordFormField
|
||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
|||
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin
|
||||
|
||||
from apps.mtm.models import Material, Process, RecordForm, RecordFormField, Step, SubplanMaterial, TechDoc, UsedStep, SubProduction
|
||||
from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, SubplanMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer
|
||||
from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, SubplanMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
@ -159,6 +159,8 @@ class RecordFormViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet
|
|||
return RecordFormCreateSerializer
|
||||
elif self.action == 'update':
|
||||
return RecordFormUpdateSerializer
|
||||
elif self.action == 'retrieve':
|
||||
return RecordFormDetailSerializer
|
||||
return RecordFormSerializer
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get':'*'}, pagination_class=None, serializer_class=RecordFormFieldSerializer)
|
||||
|
@ -171,6 +173,8 @@ class RecordFormViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet
|
|||
return Response(serializer.data)
|
||||
|
||||
|
||||
|
||||
|
||||
class RecordFormFieldViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelViewSet):
|
||||
"""
|
||||
表格字段表 增删改查
|
||||
|
|
|
@ -18,7 +18,6 @@ class Vendor(CommonAModel):
|
|||
contact_phone = models.CharField('联系电话', max_length=11, unique=True)
|
||||
address = models.CharField('地址', max_length=200, null=True, blank=True)
|
||||
description = models.CharField('描述', max_length=200, blank=True, null=True)
|
||||
material = models.CharField('供应的物料', max_length=200, blank=True, null=True)
|
||||
class Meta:
|
||||
verbose_name = '供应商信息'
|
||||
verbose_name_plural = verbose_name
|
||||
|
|
|
@ -39,3 +39,14 @@ class AnalysisItem(CommonAModel):
|
|||
|
||||
class Meta:
|
||||
verbose_name = '检验分析项'
|
||||
|
||||
class TestRecord(CommonAModel):
|
||||
"""
|
||||
检验记录
|
||||
"""
|
||||
|
||||
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
||||
record_data = models.JSONField('记录数据', default=dict, blank=True)
|
||||
is_testok = models.BooleanField('是否合格', default=True)
|
||||
fifo_detail = models.ForeignKey('inm.fifodetail', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
from rest_framework import serializers
|
||||
from apps.mtm.models import RecordForm, RecordFormField
|
||||
from apps.mtm.serializers import RecordFormFieldSerializer, RecordFormSimpleSerializer
|
||||
from apps.system.serializers import FileSimpleSerializer
|
||||
from .models import Standard, TestItem
|
||||
from .models import Standard, TestItem, TestRecord
|
||||
|
||||
class StandardCreateUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
@ -31,3 +33,41 @@ class TestItemSerializer(serializers.ModelSerializer):
|
|||
|
||||
class AnalysisItemSerializer(serializers.ModelSerializer):
|
||||
pass
|
||||
|
||||
|
||||
class TestRecordCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TestRecord
|
||||
fields = ['form', 'record_data', 'is_testok', 'fifo_detail']
|
||||
|
||||
def create(self, validated_data):
|
||||
if 'is_testok' not in validated_data:
|
||||
raise serializers.ValidationError('未填写检测结论')
|
||||
return super().create(validated_data)
|
||||
|
||||
class TestRecordListSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TestRecord
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TestRecordDetailSerializer(serializers.ModelSerializer):
|
||||
form_ = RecordFormSimpleSerializer(source='form', read_only=True)
|
||||
record_data_ = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = TestRecord
|
||||
fields = '__all__'
|
||||
|
||||
@staticmethod
|
||||
def setup_eager_loading(queryset):
|
||||
queryset = queryset.select_related('form','fifo_detail')
|
||||
return queryset
|
||||
|
||||
def get_record_data_(self, obj):
|
||||
record_data = obj.record_data
|
||||
all_fields = RecordFormField.objects.filter(form=obj.form, is_deletd=False).order_by('sort')
|
||||
all_fields_l = RecordFormFieldSerializer(instance=all_fields, many=True).data
|
||||
for i in all_fields_l:
|
||||
key = i['field_key']
|
||||
i['field_value'] = record_data.get(key, None)
|
||||
return all_fields_l
|
|
@ -1,4 +1,4 @@
|
|||
from apps.qm.views import StandardViewSet, TestItemViewSet
|
||||
from apps.qm.views import StandardViewSet, TestItemViewSet, TestRecordViewSet
|
||||
from django.db.models import base
|
||||
from rest_framework import urlpatterns
|
||||
from django.urls import path, include
|
||||
|
@ -7,6 +7,7 @@ from rest_framework.routers import DefaultRouter
|
|||
router = DefaultRouter()
|
||||
router.register('standard', StandardViewSet, basename='standard')
|
||||
router.register('testitem', TestItemViewSet, basename='testitem')
|
||||
router.register('testrecord', TestRecordViewSet, basename='testrecord')
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from apps.qm.serializers import StandardCreateUpdateSerializer, StandardSerializer, TestItemCreateUpdateSerializer, TestItemSerializer
|
||||
from apps.qm.models import Standard, TestItem
|
||||
from apps.qm.serializers import StandardCreateUpdateSerializer, StandardSerializer, TestItemCreateUpdateSerializer, TestItemSerializer, TestRecordCreateSerializer, TestRecordDetailSerializer, TestRecordListSerializer
|
||||
from apps.qm.models import Standard, TestItem, TestRecord
|
||||
from django.shortcuts import render
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from apps.system.mixins import CreateUpdateModelAMixin
|
||||
|
@ -37,3 +37,29 @@ class TestItemViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
if self.action in ['create', 'update']:
|
||||
return TestItemCreateUpdateSerializer
|
||||
return TestItemSerializer
|
||||
|
||||
class TestRecordViewSet(ModelViewSet):
|
||||
"""
|
||||
检测记录
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = TestRecord.objects.select_related('fifo_detail', 'form').all()
|
||||
serializer_class = TestRecordListSerializer
|
||||
ordering = ['-id']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return TestRecordCreateSerializer
|
||||
elif self.action == 'list':
|
||||
return TestRecordListSerializer
|
||||
elif self.action == 'retrieve':
|
||||
return TestRecordDetailSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
def perform_create(self, serializer):
|
||||
obj = serializer.save(create_by = self.request.user)
|
||||
# 如果检测合格
|
||||
if obj.fifo_detail:
|
||||
obj.fifo_detail.is_testok = True if obj.is_testok else False
|
||||
obj.fifo_detail.is_tested = True
|
||||
obj.fifo_detail.save()
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 3.2.6 on 2021-11-02 01:35
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0009_auto_20211029_1017'),
|
||||
('wpm', '0002_auto_20211029_1336'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='production_plan',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='pm.productionplan', verbose_name='关联主生产计划'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='当前子生产计划'),
|
||||
),
|
||||
]
|
|
@ -1,6 +1,7 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from apps.inm.models import FIFO, FIFODetail, MaterialBatch, WareHouse
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.mtm.models import Material
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
|
||||
|
@ -37,7 +38,7 @@ class PickSerializer(serializers.Serializer):
|
|||
validated_data['operator'] = operator
|
||||
validated_data['type'] = 1
|
||||
validated_data['inout_date'] = timezone.now()
|
||||
fifo = FIFO.objects.create(validated_data)
|
||||
fifo = FIFO.objects.create(**validated_data)
|
||||
for i in picks:
|
||||
# 更新出库详情
|
||||
i['fifo'] = fifo
|
||||
|
@ -53,12 +54,16 @@ class PickSerializer(serializers.Serializer):
|
|||
})
|
||||
wm.count = wm.count + i['pick_count']
|
||||
wm.save()
|
||||
# 更新子计划进度
|
||||
# 更新子计划物料情况
|
||||
spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1)
|
||||
spp.count_real = spp.count_real + i['pick_count']
|
||||
spp.save()
|
||||
sp.is_picked=True
|
||||
sp.save()
|
||||
# 更新库存
|
||||
fifo.is_audited = True
|
||||
fifo.save()
|
||||
update_inm(fifo)
|
||||
return fifo
|
||||
|
||||
class WMaterialListSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -32,3 +32,9 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
|
|||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return Response()
|
||||
|
||||
class DoFormInit(CreateAPIView):
|
||||
"""
|
||||
生产操作表单创建
|
||||
"""
|
||||
perms_map={'*':'*'}
|
|
@ -0,0 +1,6 @@
|
|||
from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
class MyGenericViewSet(GenericViewSet):
|
||||
filterset_fields = '__all__'
|
||||
ordering_fields = '__all__'
|
||||
ordering = ['-pk']
|
Loading…
Reference in New Issue