Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
37b874036f
|
@ -0,0 +1,61 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function getPuorderList(query) {
|
||||
return request({
|
||||
url: '/pum/pu_order/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function createPuorder(data) {
|
||||
return request({
|
||||
url: '/pum/pu_order/',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function updatePuorder(id, data) {
|
||||
return request({
|
||||
url: `/pum/pu_order/${id}/`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function deletePuorder(id, data) {
|
||||
return request({
|
||||
url: `/pum/pu_order/${id}/`,
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
//采购订单审核
|
||||
export function createPuorderAudit(id,data) {
|
||||
return request({
|
||||
url: `/pum/pu_order/${id}/audit/`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//采购订单条目
|
||||
export function getPuorderItemList(query) {
|
||||
return request({
|
||||
url: '/pum/pu_order_item/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function createPuorderItem(data) {
|
||||
return request({
|
||||
url: '/pum/pu_order_item/',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//采购订单条目删除
|
||||
export function deletePuorderItem(id, data) {
|
||||
return request({
|
||||
url: `/pum/pu_order_item/${id}/`,
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
|
@ -501,10 +501,17 @@ export const asyncRoutes = [
|
|||
meta: { title: '供应商', icon: 'example', perms: ['vendor_manage'] }
|
||||
},
|
||||
{
|
||||
path: 'vendor',
|
||||
name: 'vendor',
|
||||
component: () => import('@/views/procurement/vendor'),
|
||||
path: 'puorder',
|
||||
name: 'puorder',
|
||||
component: () => import('@/views/procurement/puorder'),
|
||||
meta: { title: '采购订单', icon: 'example', perms: ['vendor_manage'] }
|
||||
},
|
||||
{
|
||||
path: 'puorderitem/:id',
|
||||
name: 'puorderitem',
|
||||
component: () => import('@/views/procurement/puorderitem'),
|
||||
meta: { title: '采购订单项', perms: ['vendor_manage'] },
|
||||
hidden: true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<div>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleCreate"
|
||||
>新增采购订单</el-button
|
||||
>
|
||||
|
||||
<el-input
|
||||
v-model="listQuery.search"
|
||||
placeholder="采购订单编号、供应商名称"
|
||||
style="width: 300px"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="handleFilter"
|
||||
/>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
@click="handleFilter"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
type="primary"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="resetFilter"
|
||||
>重置</el-button
|
||||
>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 2px">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="puorderList.results"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
highlight-current-row
|
||||
max-height="700"
|
||||
height="100"
|
||||
v-el-height-adaptive-table="{ bottomOffset: 43 }"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column label="采购订单编号">
|
||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="供应商">
|
||||
<template slot-scope="scope" v-if="scope.row.vendor_">{{
|
||||
scope.row.vendor_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核情况" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.is_audited == false">未审核</el-tag>
|
||||
<el-tag v-else-if="scope.row.is_audited == true">已审核</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="操作" width="220px">
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
v-if="checkPermission(['vendor_update'])"
|
||||
type="primary"
|
||||
@click="handlePuOrderItem(scope)"
|
||||
>订单项</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
checkPermission(['vendor_update']) &&
|
||||
scope.row.is_audited == false
|
||||
"
|
||||
type="primary"
|
||||
@click="handleAudit(scope)"
|
||||
>审核</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="checkPermission(['vendor_update'])"
|
||||
type="primary"
|
||||
@click="handleEdit(scope)"
|
||||
>编辑</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="checkPermission(['vendor_delete'])"
|
||||
type="danger"
|
||||
@click="handleDelete(scope)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="puorderList.count > 0"
|
||||
:total="puorderList.count"
|
||||
:page.sync="listQuery.page"
|
||||
:limit.sync="listQuery.page_size"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
:title="dialogType === 'edit' ? '编辑采购订单' : '新增采购订单'"
|
||||
>
|
||||
<el-form
|
||||
ref="Form"
|
||||
:model="puorder"
|
||||
label-width="120px"
|
||||
label-position="right"
|
||||
:rules="rule1"
|
||||
>
|
||||
<el-form-item label="订单编号" prop="number">
|
||||
<el-input v-model="puorder.number" placeholder="订单编号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="供应商" prop="vendor">
|
||||
<el-select
|
||||
style="width: 100%"
|
||||
v-model="puorder.vendor"
|
||||
placeholder="请选择"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in vendorList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align: right">
|
||||
<el-button type="danger" @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirm('Form')">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getpVendorList } from "@/api/vendor";
|
||||
import { getUserList } from "@/api/user";
|
||||
import {
|
||||
getPuorderList,
|
||||
createPuorder,
|
||||
updatePuorder,
|
||||
deletePuorder,
|
||||
createPuorderAudit,
|
||||
createPuorderItem,
|
||||
deletePuorderItem,
|
||||
} from "@/api/pum";
|
||||
import checkPermission from "@/utils/permission";
|
||||
|
||||
import { genTree } from "@/utils";
|
||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||
const defaultpuorder = {
|
||||
number: "",
|
||||
};
|
||||
export default {
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
puorder: defaultpuorder,
|
||||
puorderList: {
|
||||
count: 0,
|
||||
},
|
||||
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
},
|
||||
vendorList: [],
|
||||
dialogVisible: false,
|
||||
dialogType: "new",
|
||||
rule1: {
|
||||
number: [{ required: true, message: "请输入", trigger: "blur" }],
|
||||
vendor: [
|
||||
{ required: true, message: "请选择供应商", trigger: "change" },
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getVendorList();
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
//采购订单
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
getPuorderList(this.listQuery).then((response) => {
|
||||
if (response.data) {
|
||||
this.puorderList = response.data;
|
||||
}
|
||||
this.listLoading = false;
|
||||
});
|
||||
},
|
||||
//供应商列表
|
||||
getVendorList() {
|
||||
getpVendorList({ page: 0 }).then((response) => {
|
||||
if (response.data) {
|
||||
this.vendorList = response.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
resetFilter() {
|
||||
this.listQuery = {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
};
|
||||
this.getList();
|
||||
},
|
||||
handleCreate() {
|
||||
this.puorder = Object.assign({}, defaultpuorder);
|
||||
this.dialogType = "new";
|
||||
this.dialogVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["Form"].clearValidate();
|
||||
});
|
||||
},
|
||||
|
||||
handleEdit(scope) {
|
||||
this.puorder = Object.assign({}, scope.row); // copy obj
|
||||
this.dialogType = "edit";
|
||||
this.dialogVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["Form"].clearValidate();
|
||||
});
|
||||
},
|
||||
handleDelete(scope) {
|
||||
this.$confirm("确认删除?", "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
await deletePuorder(scope.row.id);
|
||||
this.getList();
|
||||
this.$message.success("成功");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
|
||||
async confirm(form) {
|
||||
this.$refs[form].validate((valid) => {
|
||||
if (valid) {
|
||||
const isEdit = this.dialogType === "edit";
|
||||
if (isEdit) {
|
||||
updatePuorder(this.puorder.id, this.puorder).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$message.success("成功");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
createPuorder(this.puorder).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$message.success("成功");
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
handlePuOrderItem(scope) {
|
||||
this.$router.push({ name: "puorderitem", params: { id: scope.row.id } });
|
||||
},
|
||||
handleAudit(scope) {
|
||||
|
||||
createPuorderAudit(scope.row.id).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getList();
|
||||
|
||||
this.$message.success("审核成功!");
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,197 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<div>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleCreate"
|
||||
>新增采购订单项</el-button
|
||||
>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card style="margin-top: 2px">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="puorderTtemList.results"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
highlight-current-row
|
||||
max-height="700"
|
||||
height="100"
|
||||
v-el-height-adaptive-table="{ bottomOffset: 43 }"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column label="物料名称">
|
||||
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="物料型号">
|
||||
<template slot-scope="scope">{{ scope.row.material_.specification }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="采购数量">
|
||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已到货数量">
|
||||
<template slot-scope="scope">{{ scope.row.delivered_count }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="截止到货时间">
|
||||
<template slot-scope="scope">{{ scope.row.delivery_date }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="操作" width="220px">
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
v-if="checkPermission(['vendor_delete'])"
|
||||
type="danger"
|
||||
@click="handleDelete(scope)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="puorderTtemList.count > 0"
|
||||
:total="puorderTtemList.count"
|
||||
:page.sync="listQuery.page"
|
||||
:limit.sync="listQuery.page_size"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
<el-dialog :visible.sync="dialogVisible" title="新增采购订单项">
|
||||
<el-form
|
||||
ref="Form"
|
||||
:model="puorderTtem"
|
||||
label-width="120px"
|
||||
label-position="right"
|
||||
:rules="rule1"
|
||||
>
|
||||
<el-form-item label="所需数量" prop="number">
|
||||
<el-input v-model="puorderTtem.count" placeholder="所需数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="截止到货时间" prop="delivery_date">
|
||||
<el-date-picker
|
||||
v-model="puorderTtem.delivery_date"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 100%"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item class="material" label="采购物料:" :prop="material">
|
||||
<el-select v-model="puorderTtem.material" filterable size="small">
|
||||
<el-option
|
||||
v-for="item in materialoptions"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align: right">
|
||||
<el-button type="danger" @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirm">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getpVendorList } from "@/api/vendor";
|
||||
import { getMaterialList } from "@/api/mtm";
|
||||
|
||||
import {
|
||||
getPuorderItemList,
|
||||
createPuorderItem,
|
||||
deletePuorderItem,
|
||||
} from "@/api/pum";
|
||||
import checkPermission from "@/utils/permission";
|
||||
|
||||
import { genTree } from "@/utils";
|
||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||
const defaultpuorderItem = {
|
||||
pu_order:null,
|
||||
};
|
||||
export default {
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
puorderTtem: defaultpuorderItem,
|
||||
puorderTtemList: {
|
||||
count: 0,
|
||||
},
|
||||
materialoptions: [],
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
},
|
||||
dialogVisible:false,
|
||||
rule1: {
|
||||
delivery_date: [{ required: true, message: "请选择日期", trigger: "blur" }],
|
||||
material: [
|
||||
{ required: true, message: "请选择物料", trigger: "change" },
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
created() {
|
||||
this.id = this.$route.params.id;
|
||||
this.getList();
|
||||
this.getmaterialList();
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
//采购订单列表
|
||||
getList() {
|
||||
this.listQuery.pu_order= this.id;
|
||||
getPuorderItemList(this.listQuery).then((response) => {
|
||||
if (response.data) {
|
||||
this.puorderTtemList = response.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
//物料
|
||||
getmaterialList() {
|
||||
getMaterialList({ page: 0 }).then((response) => {
|
||||
if (response.data) {
|
||||
this.materialoptions = response.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleCreate() {
|
||||
this.puorderTtem = Object.assign({}, defaultpuorderItem);
|
||||
this.dialogVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["Form"].clearValidate();
|
||||
});
|
||||
},
|
||||
async confirm() {
|
||||
this.puorderTtem.pu_order=this.id
|
||||
createPuorderItem(this.puorderTtem).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.getList();
|
||||
this.dialogVisible = false;
|
||||
this.$message.success("成功");
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDelete(scope) {
|
||||
this.$confirm("确认删除?", "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
})
|
||||
.then(async () => {
|
||||
await deletePuorderItem(scope.row.id);
|
||||
this.getList();
|
||||
this.$message.success("成功");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -75,6 +75,7 @@
|
|||
|
||||
<el-link
|
||||
v-if="checkPermission(['vendor_update'])"
|
||||
type="primary"
|
||||
@click="handleEdit(scope)"
|
||||
>编辑</el-link
|
||||
>
|
||||
|
|
|
@ -10,7 +10,7 @@ from apps.pm.models import ProductionPlan, SubProductionPlan
|
|||
from apps.sam.models import Order
|
||||
from apps.wf.models import Ticket
|
||||
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
from apps.em.tasks import update_equip_state_by_next_check_date
|
||||
# Create your views here.
|
||||
|
||||
|
@ -46,7 +46,7 @@ class UpdateCuttingView(APIView):
|
|||
i.coperation = op
|
||||
i.save()
|
||||
WproductFlow.objects.filter(wproduct=i).update(coperation=op)
|
||||
WpmServies.update_cutting_list_with_operation(op)
|
||||
WpmService.update_cutting_list_with_operation(op)
|
||||
return Response()
|
||||
|
||||
from apps.qm.models import TestRecord
|
||||
|
@ -90,7 +90,7 @@ class UpdateSpg(APIView):
|
|||
冷加工重新计算合格率
|
||||
"""
|
||||
for i in SubProductionPlan.objects.filter(subproduction__process__id=1):
|
||||
WpmServies.update_subproduction_progress_main(sp=i)
|
||||
WpmService.update_subproduction_progress_main(sp=i)
|
||||
return Response()
|
||||
|
||||
|
||||
|
|
|
@ -67,11 +67,13 @@ class FIFO(CommonADModel):
|
|||
FIFO_TYPE_SALE_OUT = 2
|
||||
FIFO_TYPE_PUR_IN = 3
|
||||
FIFO_TYPE_DO_IN = 4
|
||||
FIFO_TYPE_OTHER_IN = 5
|
||||
type_choices = (
|
||||
(FIFO_TYPE_DO_OUT, '生产领料'),
|
||||
(FIFO_TYPE_SALE_OUT, '销售提货'),
|
||||
(FIFO_TYPE_PUR_IN, '采购入库'),
|
||||
(FIFO_TYPE_DO_IN, '生产入库')
|
||||
(FIFO_TYPE_DO_IN, '生产入库'),
|
||||
(FIFO_TYPE_OTHER_IN, '其他入库')
|
||||
)
|
||||
number = models.CharField('记录编号', max_length=100)
|
||||
type = models.IntegerField('出入库类型', default=1)
|
||||
|
|
|
@ -80,7 +80,7 @@ class FIFOItemCreateSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = FIFOItem
|
||||
fields = ['warehouse',
|
||||
'material', 'batch', 'fifo', 'files', 'pu_order_item']
|
||||
'material', 'batch', 'fifo', 'files', 'pu_order_item', 'count']
|
||||
|
||||
def create(self, validated_data):
|
||||
fifo = validated_data['fifo']
|
||||
|
@ -97,7 +97,7 @@ class FIFOItemCreateSerializer(serializers.ModelSerializer):
|
|||
class FIFOItemUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FIFOItem
|
||||
fields = ['warehouse', 'batch', 'files']
|
||||
fields = ['warehouse', 'batch', 'files', 'count']
|
||||
|
||||
class FIFOItemSerializer(serializers.ModelSerializer):
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
|
|
|
@ -25,7 +25,8 @@ class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
"""
|
||||
仓库-增删改查
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*', 'post':'warehouse_create',
|
||||
'put':'warehouse_update', 'delete':'warehouse_delete'}
|
||||
queryset = WareHouse.objects.select_related('create_by').all()
|
||||
serializer_class = WareHouseSerializer
|
||||
search_fields = ['name', 'number', 'place']
|
||||
|
@ -43,7 +44,7 @@ class InventoryViewSet(ListModelMixin, GenericViewSet):
|
|||
"""
|
||||
仓库物料表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*'}
|
||||
queryset = Inventory.objects.select_related(
|
||||
'material', 'warehouse').filter(count__gt=0).all()
|
||||
serializer_class = InventorySerializer
|
||||
|
@ -54,7 +55,7 @@ class InventoryViewSet(ListModelMixin, GenericViewSet):
|
|||
|
||||
|
||||
class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*'}
|
||||
queryset = MaterialBatch.objects.select_related(
|
||||
'material', 'warehouse').filter(count__gt=0).all()
|
||||
serializer_class = MaterialBatchSerializer
|
||||
|
@ -81,7 +82,8 @@ class FIFOItemViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, Updat
|
|||
"""
|
||||
出入库记录详情表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*', 'post':'fifoitem_create',
|
||||
'put':'fifoitem_update', 'delete':'fifoitem_delete'}
|
||||
queryset = FIFOItem.objects.select_related('material', 'fifo').prefetch_related('files').all()
|
||||
serializer_class = FIFOItemSerializer
|
||||
filterset_fields = ['material', 'fifo',
|
||||
|
@ -115,7 +117,7 @@ class FIFOItemViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, Updat
|
|||
raise ValidationError('该出入库记录已审核')
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=InmTestRecordCreateSerializer)
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'fifoitem_test'}, serializer_class=InmTestRecordCreateSerializer)
|
||||
def test(self, request, pk=None):
|
||||
"""
|
||||
检验
|
||||
|
@ -147,7 +149,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
"""
|
||||
出入库记录
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*', 'delete':'fifo_delete'}
|
||||
queryset = FIFO.objects.select_related('auditor', 'create_by')
|
||||
serializer_class = FIFOListSerializer
|
||||
filterset_fields = '__all__'
|
||||
|
@ -166,7 +168,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
raise exceptions.APIException('该记录已审核,不可删除')
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=FIFOInPurSerializer)
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'fifo_in_pur'}, serializer_class=FIFOInPurSerializer)
|
||||
def in_pur(self, request, pk=None):
|
||||
"""
|
||||
采购入库
|
||||
|
@ -176,7 +178,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
serializer.save(create_by=request.user)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'fifo_in_other'},
|
||||
serializer_class=FIFOInOtherSerializer)
|
||||
def in_other(self, request, pk=None):
|
||||
"""
|
||||
|
@ -187,7 +189,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
serializer.save(create_by=request.user)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=serializers.Serializer)
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'fifo_audit'}, serializer_class=serializers.Serializer)
|
||||
def audit(self, request, pk=None):
|
||||
"""
|
||||
审核通过
|
||||
|
@ -213,7 +215,7 @@ class IProductViewSet(ListModelMixin, GenericViewSet):
|
|||
"""
|
||||
半成品库存表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
perms_map = {'get': '*'}
|
||||
queryset = IProduct.objects.select_related(
|
||||
'material', 'warehouse',
|
||||
'wproduct__subproduction_plan__production_plan__order',
|
||||
|
|
|
@ -45,7 +45,7 @@ def get_file_list(file_path):
|
|||
return dir_list
|
||||
|
||||
class LogView(APIView):
|
||||
|
||||
permission_classes = [IsAuthenticated]
|
||||
@swagger_auto_schema(manual_parameters=[
|
||||
openapi.Parameter('name', openapi.IN_QUERY, description='日志文件名', type=openapi.TYPE_STRING)
|
||||
])
|
||||
|
@ -82,7 +82,7 @@ class LogView(APIView):
|
|||
|
||||
|
||||
class LogDetailView(APIView):
|
||||
|
||||
permission_classes = [IsAuthenticated]
|
||||
def get(self, request, name):
|
||||
"""
|
||||
查看日志详情
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-29 07:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0044_subproduction_need_combtest'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='usedstep',
|
||||
name='need_test',
|
||||
field=models.BooleanField(default=False, verbose_name='工序内检验'),
|
||||
),
|
||||
]
|
|
@ -242,6 +242,7 @@ class UsedStep(CommonADModel):
|
|||
涉及的生产子工序
|
||||
"""
|
||||
step = models.ForeignKey(Step, verbose_name='子工序', on_delete=models.CASCADE, related_name='usedstep')
|
||||
need_test = models.BooleanField('工序内检验', default=False)
|
||||
remark = models.TextField('生产备注', null=True, blank=True)
|
||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='usedstep_subproduction')
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from apps.mtm.models import Material, Step
|
|||
from apps.pm.models import ProductionPlan, SubProductionProgress
|
||||
from apps.wpm.models import Operation, WProduct
|
||||
from datetime import *
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
from django.db.models import F
|
||||
|
||||
from utils.mixins import DynamicFieldsFilterMixin
|
||||
|
@ -52,9 +52,9 @@ class SubproductionProgressFilterSet(filters.FilterSet):
|
|||
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
|
||||
step = operation.step
|
||||
if wproducts.exists():
|
||||
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
|
||||
subplans = WpmService.get_subplans_queryset_from_wproducts(wproducts)
|
||||
else:
|
||||
subplans = WpmServies.get_subplans_queyset_from_step(step)
|
||||
subplans = WpmService.get_subplans_queyset_from_step(step)
|
||||
queryset = queryset.filter(subproduction_plan__in=subplans)
|
||||
if step.type == Step.STEP_TYPE_NOM:
|
||||
queryset = queryset.exclude(material__type__in =[Material.MA_TYPE_HALFGOOD, Material.MA_TYPE_GOOD])
|
||||
|
|
|
@ -89,7 +89,8 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
|
||||
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')
|
||||
usedstep__is_deleted=False, is_deleted=False
|
||||
).values('id', 'number', 'name', 'usedstep__remark', need_test=F('usedstep__need_test'))
|
||||
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,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-29 07:12
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('qm', '0022_auto_20211216_1401'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='testrecord',
|
||||
name='is_midtesing',
|
||||
field=models.BooleanField(default=False, verbose_name='是否子工序检验中'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testrecorditem',
|
||||
name='create_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='testrecorditem_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='testrecorditem',
|
||||
name='update_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='testrecorditem_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='testrecord',
|
||||
name='type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(20, '工序检验'), (30, '工序复检'), (36, '夹层检验'), (40, '成品检验')], default=20),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-29 07:24
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('qm', '0023_auto_20220129_1512'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='testrecord',
|
||||
old_name='is_midtesing',
|
||||
new_name='is_midtesting',
|
||||
),
|
||||
]
|
|
@ -47,13 +47,11 @@ class TestRecord(CommonADModel):
|
|||
"""
|
||||
检验记录
|
||||
"""
|
||||
TEST_STEP = 10
|
||||
TEST_PROCESS = 20
|
||||
TEST_PROCESS_RE = 30
|
||||
TEST_COMB = 36
|
||||
TEST_FINAL = 40
|
||||
type_choice = (
|
||||
(TEST_STEP, '子工序检验'),
|
||||
(TEST_PROCESS, '工序检验'),
|
||||
(TEST_PROCESS_RE, '工序复检'),
|
||||
(TEST_COMB, '夹层检验'),
|
||||
|
@ -70,6 +68,7 @@ class TestRecord(CommonADModel):
|
|||
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
||||
origin_test = models.ForeignKey('self', verbose_name='原检验记录', on_delete=models.CASCADE, null=True, blank=True)
|
||||
is_submited = models.BooleanField('是否提交', default=False)
|
||||
is_midtesting = models.BooleanField('是否子工序检验中', default=False)
|
||||
remark = models.TextField('备注', default='')
|
||||
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ class TestRecordUpdateSerializer(serializers.ModelSerializer):
|
|||
if i['field_value'] != tri.field_value:
|
||||
tri.field_value = i['field_value']
|
||||
tri.update_by = update_by
|
||||
tri.is_testok = i['is_testok']
|
||||
tri.is_hidden = i['is_hidden']
|
||||
tri.save()
|
||||
tri.is_testok = i['is_testok']
|
||||
tri.is_hidden = i['is_hidden']
|
||||
tri.save()
|
||||
return instance
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.db import transaction
|
|||
from rest_framework.decorators import action
|
||||
|
||||
from apps.wpm.models import WProduct
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
# Create your views here.
|
||||
class StandardViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||
"""
|
||||
|
@ -69,7 +69,7 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
|
|||
|
||||
def update(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.is_submited:
|
||||
if obj.is_submited and obj.is_midtesting is False:
|
||||
raise exceptions.APIException('该记录已提交不可编辑')
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
|
@ -77,20 +77,22 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
|
|||
obj = self.get_object()
|
||||
if obj.is_submited:
|
||||
raise exceptions.APIException('该记录已提交不可删除')
|
||||
WpmServies.add_wproduct_flow_log(obj.wproduct, 'test_delete')
|
||||
WpmService.add_wproduct_flow_log(obj.wproduct, 'test_delete')
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=TestRecordUpdateSerializer)
|
||||
def submit(self, request, pk=None):
|
||||
obj = self.get_object()
|
||||
if obj.is_submited and obj.is_midtesting is False:
|
||||
raise exceptions.APIException('该记录已提交')
|
||||
# 校验是否有未填项目
|
||||
if obj.type != TestRecord.TEST_PROCESS_RE:
|
||||
if obj.type != TestRecord.TEST_PROCESS_RE and obj.is_midtesting is False:
|
||||
if TestRecordItem.objects.filter(field_value__isnull=True, is_hidden=False, test_record=obj).exists():
|
||||
raise exceptions.APIException('存在未填写项目')
|
||||
with transaction.atomic():
|
||||
obj.is_submited=True
|
||||
obj.save()
|
||||
WpmServies.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
||||
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
||||
return Response()
|
||||
|
||||
# def create(self, request, *args, **kwargs):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django_filters import rest_framework as filters
|
||||
from apps.mtm.models import Material, Step
|
||||
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
from utils.mixins import DynamicFieldsFilterMixin
|
||||
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
|
||||
|
||||
|
@ -20,10 +20,10 @@ class WMaterialFilterSet(filters.FilterSet):
|
|||
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
|
||||
step = operation.step
|
||||
if wproducts.exists():
|
||||
subplans = WpmServies.get_subplans_queryset_from_wproducts(
|
||||
subplans = WpmService.get_subplans_queryset_from_wproducts(
|
||||
wproducts)
|
||||
else:
|
||||
subplans = WpmServies.get_subplans_queyset_from_step(step)
|
||||
subplans = WpmService.get_subplans_queyset_from_step(step)
|
||||
queryset = queryset.filter(subproduction_plan__in=subplans).exclude(
|
||||
material__type=Material.MA_TYPE_HALFGOOD)
|
||||
return queryset
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-29 07:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0045_usedstep_need_test'),
|
||||
('wpm', '0052_auto_20220125_1116'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='wproduct',
|
||||
name='material_check',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_material_check', to='mtm.material', verbose_name='按物料状态检查'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='wproductflow',
|
||||
name='material_check',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_material_check', to='mtm.material', verbose_name='按物料状态检查'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='child',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_child', to='wpm.wproduct'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='material',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wp_material', to='mtm.material', verbose_name='所属物料状态'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='pre_step',
|
||||
field=models.ForeignKey(blank=True, help_text='已执行完的步骤', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_pre_step', to='mtm.step', verbose_name='已执行到'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproduct',
|
||||
name='step',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wp_step', to='mtm.step', verbose_name='所在步骤'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproductflow',
|
||||
name='child',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_child', to='wpm.wproductflow'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproductflow',
|
||||
name='material',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wpf_material', to='mtm.material', verbose_name='所属物料状态'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproductflow',
|
||||
name='pre_step',
|
||||
field=models.ForeignKey(blank=True, help_text='已执行完的步骤', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_pre_step', to='mtm.step', verbose_name='已执行到'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wproductflow',
|
||||
name='step',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wpf_step', to='mtm.step', verbose_name='所在步骤'),
|
||||
),
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
import re
|
||||
|
||||
from rest_framework import exceptions
|
||||
from django.db import models
|
||||
from django.db.models.base import Model
|
||||
|
@ -88,16 +89,20 @@ class WProduct(CommonAModel):
|
|||
number = models.CharField(
|
||||
'物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||
Material, verbose_name='所属物料状态', on_delete=models.CASCADE,
|
||||
related_name='wp_material')
|
||||
material_check = models.ForeignKey(
|
||||
Material, verbose_name='按物料状态检查', on_delete=models.CASCADE,
|
||||
null=True, blank=True, related_name='wp_material_check')
|
||||
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
|
||||
on_delete=models.CASCADE, related_name='w_pre_step')
|
||||
on_delete=models.CASCADE, related_name='wp_pre_step')
|
||||
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
|
||||
related_name='w_step')
|
||||
related_name='wp_step')
|
||||
act_state = models.IntegerField(
|
||||
'进行状态', default=0, choices=act_state_choices)
|
||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
||||
child = models.ForeignKey('self', blank=True, null=True,
|
||||
on_delete=models.CASCADE, related_name='wproduct_child')
|
||||
on_delete=models.CASCADE, related_name='wp_child')
|
||||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE,
|
||||
related_name='wproduct_subplan')
|
||||
|
@ -164,16 +169,19 @@ class WproductFlow(CommonAModel):
|
|||
WProduct, on_delete=models.CASCADE, verbose_name='关联产品', null=True, blank=True)
|
||||
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||
Material, verbose_name='所属物料状态', on_delete=models.CASCADE, related_name='wpf_material')
|
||||
material_check = models.ForeignKey(
|
||||
Material, verbose_name='按物料状态检查', on_delete=models.CASCADE,
|
||||
null=True, blank=True, related_name='wpf_material_check')
|
||||
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
|
||||
on_delete=models.CASCADE, related_name='wl_pre_step')
|
||||
on_delete=models.CASCADE, related_name='wpf_pre_step')
|
||||
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
|
||||
related_name='wl_step')
|
||||
related_name='wpf_step')
|
||||
act_state = models.IntegerField(
|
||||
'进行状态', default=0, choices=WProduct.act_state_choices)
|
||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
||||
child = models.ForeignKey('self', blank=True, null=True,
|
||||
on_delete=models.CASCADE, related_name='wproduct_child')
|
||||
on_delete=models.CASCADE, related_name='wpf_child')
|
||||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(
|
||||
SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
||||
|
|
|
@ -9,19 +9,21 @@ from apps.system.models import User
|
|||
from apps.wf.models import State, TicketFlow, Transition
|
||||
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow, WprouctTicket
|
||||
from utils.tools import ranstr
|
||||
class WpmServies(object):
|
||||
class WpmService(object):
|
||||
|
||||
@classmethod
|
||||
def get_next_step(cls, subproduction_plan:SubProductionPlan, nowstep:Step):
|
||||
"""
|
||||
获取下一步骤
|
||||
"""
|
||||
stepIds = [i['id'] for i in subproduction_plan.steps]
|
||||
steps_list = subproduction_plan.steps
|
||||
stepIds = [i['id'] for i in steps_list]
|
||||
pindex = stepIds.index(nowstep.id)
|
||||
need_test = steps_list[pindex].get('need_test', False)
|
||||
if pindex + 1 < len(stepIds):
|
||||
return Step.objects.get(pk=stepIds[pindex+1]), True
|
||||
return Step.objects.get(pk=stepIds[pindex+1]), need_test
|
||||
else:
|
||||
return nowstep, False
|
||||
return nowstep, need_test
|
||||
|
||||
@classmethod
|
||||
def get_subplans_queryset_from_wproducts(cls, wproducts:List):
|
||||
|
@ -47,9 +49,15 @@ class WpmServies(object):
|
|||
"""
|
||||
is_testok = test.is_testok
|
||||
wproduct = test.wproduct
|
||||
test_i = None
|
||||
if is_testok:
|
||||
if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 复检
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
|
||||
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \
|
||||
test.is_midtesing is True:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
test_i = test
|
||||
|
||||
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST
|
||||
|
@ -97,7 +105,7 @@ class WpmServies(object):
|
|||
|
||||
wproduct.update_by = user
|
||||
wproduct.update_time = timezone.now()
|
||||
wproduct.test = None
|
||||
wproduct.test = test_i
|
||||
wproduct.last_test_result = is_testok
|
||||
wproduct.save()
|
||||
# 添加日志
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.dispatch import receiver
|
|||
from rest_framework import exceptions
|
||||
from apps.wpm.models import WProduct, WproductFlow, WprouctTicket
|
||||
from apps.wpm.models import OperationWproduct
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
|
||||
|
||||
@receiver(post_save, sender=Ticket)
|
||||
|
@ -34,7 +34,7 @@ def handleTicket(sender, instance, created, **kwargs):
|
|||
# 工单绑定半成品
|
||||
wproduct.ticket = instance
|
||||
wproduct.save()
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'ticket_create')
|
||||
WpmService.add_wproduct_flow_log(wproduct, 'ticket_create')
|
||||
|
||||
|
||||
elif instance.act_state == Ticket.TICKET_ACT_STATE_FINISH:
|
||||
|
@ -77,7 +77,7 @@ def handleTicket(sender, instance, created, **kwargs):
|
|||
wp.save()
|
||||
|
||||
# 添加日志
|
||||
WpmServies.add_wproduct_flow_log(wp, 'ticket_finish')
|
||||
WpmService.add_wproduct_flow_log(wp, 'ticket_finish')
|
||||
# 更新子计划合格进度
|
||||
WpmServies.update_subproduction_progress_main(sp=wp.subproduction_plan)
|
||||
WpmService.update_subproduction_progress_main(sp=wp.subproduction_plan)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework import urlpatterns
|
|||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.wpm.views import CuttingListViewSet, DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
|
||||
from apps.wpm.views import CuttingListViewSet, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||
|
@ -19,8 +19,6 @@ router.register('operation_tool', OperationMaterialToolViewSet, basename='operat
|
|||
router.register('subplan', WPlanViewSet, basename='wplan')
|
||||
router.register('cutting_list', CuttingListViewSet, basename='cutting_list')
|
||||
urlpatterns = [
|
||||
path('do/init/', DoFormInit.as_view()),
|
||||
path('do/submit/', DoFormSubmit.as_view()),
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerial
|
|||
from rest_framework.response import Response
|
||||
from django.db import transaction
|
||||
from rest_framework import exceptions, serializers
|
||||
from apps.wpm.services import WpmServies
|
||||
from apps.wpm.services import WpmService
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from django.db.models import Count
|
||||
|
@ -105,7 +105,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
|||
m.update_by = request.user
|
||||
m.update_time = timezone.now()
|
||||
m.save()
|
||||
WpmServies.add_wproduct_flow_log(
|
||||
WpmService.add_wproduct_flow_log(
|
||||
instance=m, change_str='pick_half')
|
||||
pw = PickWproduct()
|
||||
pw.pick = pick
|
||||
|
@ -151,7 +151,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
perms_map = {'*': '*'}
|
||||
queryset = WProduct.objects.select_related('step', 'material',
|
||||
'subproduction_plan', 'warehouse', 'subproduction_plan__production_plan__order',
|
||||
'to_order').prefetch_related('wproduct_child')
|
||||
'to_order').prefetch_related('wp_child')
|
||||
serializer_class = WProductListSerializer
|
||||
filterset_class = WProductFilterSet
|
||||
search_fields = ['number']
|
||||
|
@ -188,7 +188,6 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
WProduct.WPR_ACT_STATE_TORETEST, WProduct.WPR_ACT_STATE_TOFINALTEST,
|
||||
WProduct.WPR_ACT_STATE_TOCOMBTEST]:
|
||||
raise exceptions.APIException('该产品当前状态不可检验')
|
||||
|
||||
savedict = dict(
|
||||
create_by=request.user,
|
||||
wproduct=wproduct,
|
||||
|
@ -208,13 +207,16 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
savedict['type'] = TestRecord.TEST_FINAL
|
||||
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOCOMBTEST:
|
||||
savedict['type'] = TestRecord.TEST_COMB
|
||||
elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and\
|
||||
wproduct.step != wproduct.pre_step: # 如果是工序内检验
|
||||
savedict['is_midtesting'] = True
|
||||
tr = TestRecord.objects.create(**savedict)
|
||||
# 更新wproduct
|
||||
wproduct.test = tr
|
||||
wproduct.update_by = request.user
|
||||
wproduct.update_time = timezone.now()
|
||||
wproduct.save()
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'test_init')
|
||||
WpmService.add_wproduct_flow_log(wproduct, 'test_init')
|
||||
# 创建检验条目
|
||||
for i in RecordFormField.objects.filter(form=form, is_deleted=False):
|
||||
tri = TestRecordItem()
|
||||
|
@ -224,6 +226,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
tri.create_by = request.user
|
||||
tri.save()
|
||||
return Response(TestRecordDetailSerializer(instance=tr).data)
|
||||
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductPutInsSerializer)
|
||||
@transaction.atomic
|
||||
|
@ -281,7 +284,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
i.update_by = request.user
|
||||
i.update_time = timezone.now()
|
||||
i.save()
|
||||
WpmServies.add_wproduct_flow_log(i, 'putins')
|
||||
WpmService.add_wproduct_flow_log(i, 'putins')
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=WproductPutInSerializer)
|
||||
|
@ -328,7 +331,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
wproduct.act_state = WProduct.WPR_ACT_STATE_INM
|
||||
wproduct.warehouse = warehouse
|
||||
wproduct.save()
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'putin')
|
||||
WpmService.add_wproduct_flow_log(wproduct, 'putin')
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=ScrapSerializer)
|
||||
|
@ -354,9 +357,9 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
obj.update_by = request.user
|
||||
obj.update_time = timezone.now()
|
||||
obj.save()
|
||||
WpmServies.add_wproduct_flow_log(obj, 'scrap')
|
||||
WpmService.add_wproduct_flow_log(obj, 'scrap')
|
||||
if obj.step.process.id == 1: # 如果是冷加工
|
||||
WpmServies.update_cutting_list_with_operation(obj.coperation)
|
||||
WpmService.update_cutting_list_with_operation(obj.coperation)
|
||||
return Response()
|
||||
|
||||
# @action(methods=['get'], detail=False, perms_map={'get':'*'})
|
||||
|
@ -411,14 +414,14 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
is_mtestok = request.data.get('is_mtestok')
|
||||
obj.is_mtestok = is_mtestok
|
||||
if is_mtestok:
|
||||
WpmServies.update_plan_state_by_mtestok(
|
||||
WpmService.update_plan_state_by_mtestok(
|
||||
obj.subproduction_plan.production_plan)
|
||||
obj.update_by = request.user
|
||||
obj.save()
|
||||
change_str = 'mtest_notok'
|
||||
if is_mtestok:
|
||||
change_str = 'mtest_ok'
|
||||
WpmServies.add_wproduct_flow_log(instance=obj, change_str=change_str)
|
||||
WpmService.add_wproduct_flow_log(instance=obj, change_str=change_str)
|
||||
return Response()
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get': '*'})
|
||||
|
@ -461,7 +464,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
i.need_to_order = True
|
||||
i.update_by = request.user
|
||||
i.save()
|
||||
WpmServies.add_wproduct_flow_log(i, change_str='need_to_order')
|
||||
WpmService.add_wproduct_flow_log(i, change_str='need_to_order')
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductToOrderSerializer)
|
||||
|
@ -486,7 +489,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
i.to_order = order
|
||||
i.update_by = request.user
|
||||
i.save()
|
||||
WpmServies.add_wproduct_flow_log(i,change_str='to_order')
|
||||
WpmService.add_wproduct_flow_log(i,change_str='to_order')
|
||||
return Response()
|
||||
|
||||
class WproductTicketViewSet(ListModelMixin, GenericViewSet):
|
||||
|
@ -544,7 +547,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
i.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
i.update_by = request.user
|
||||
i.save()
|
||||
WpmServies.add_wproduct_flow_log(i, 'operation_delete')
|
||||
WpmService.add_wproduct_flow_log(i, 'operation_delete')
|
||||
self.perform_destroy(instance)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
@ -565,14 +568,14 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
# 创建操作所用半成品关联记录
|
||||
if 'wproducts' in vdata:
|
||||
owps = []
|
||||
splans = WpmServies.get_subplans_queryset_from_wproducts(
|
||||
splans = WpmService.get_subplans_queryset_from_wproducts(
|
||||
vdata['wproducts'])
|
||||
for wpd in vdata['wproducts']:
|
||||
wpd.operation = op
|
||||
wpd.act_state = WProduct.WPR_ACT_STATE_DOING
|
||||
wpd.update_by = request.user
|
||||
wpd.save()
|
||||
WpmServies.add_wproduct_flow_log(wpd, 'operation_create')
|
||||
WpmService.add_wproduct_flow_log(wpd, 'operation_create')
|
||||
owp = {}
|
||||
owp['operation'] = op
|
||||
owp['wproduct'] = wpd
|
||||
|
@ -583,7 +586,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
owps.append(OperationWproduct(**owp))
|
||||
OperationWproduct.objects.bulk_create(owps)
|
||||
else:
|
||||
splans = WpmServies.get_subplans_queryset_from_wproducts(
|
||||
splans = WpmService.get_subplans_queryset_from_wproducts(
|
||||
vdata['wproducts'])
|
||||
# 查询需要填写的自定义表格
|
||||
forms = RecordForm.objects.filter(
|
||||
|
@ -677,22 +680,31 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
wsp = i.subproduction_plan
|
||||
|
||||
# 获取下一步子工序
|
||||
newstep, hasNext = WpmServies.get_next_step(wsp, step)
|
||||
newstep, needTest = WpmService.get_next_step(wsp, step)
|
||||
wp.step = newstep
|
||||
wp.pre_step = step
|
||||
if hasNext:
|
||||
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
else:
|
||||
|
||||
if step == newstep:
|
||||
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
wp.material = wsp.product
|
||||
if wp.test:# 如果有正在进行的工序中检验
|
||||
wp.test.is_midtesting = False
|
||||
wp.test.is_submited = False
|
||||
wp.test.save()
|
||||
else:
|
||||
wp.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
if needTest:
|
||||
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
wp.material_check = wsp.product
|
||||
|
||||
wp.operation = None
|
||||
wp.update_by = request.user
|
||||
wp.save()
|
||||
WpmServies.add_wproduct_flow_log(wp, 'operation_submit')
|
||||
WpmService.add_wproduct_flow_log(wp, 'operation_submit')
|
||||
|
||||
for i in ows.values('subproduction_plan').distinct():
|
||||
# 更新进度
|
||||
WpmServies.update_subproduction_progress_main(sp=wsp)
|
||||
WpmService.update_subproduction_progress_main(sp=wsp)
|
||||
|
||||
elif step.type == Step.STEP_TYPE_DIV:
|
||||
# 更新物料产出情况
|
||||
|
@ -700,7 +712,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
raise exceptions.APIException('请选择物料产出')
|
||||
for i in omos:
|
||||
if i.subproduction_progress.is_main:
|
||||
newstep, _ = WpmServies.get_next_step(
|
||||
newstep, _ = WpmService.get_next_step(
|
||||
i.subproduction_plan, step)
|
||||
wpr = dict(material=i.material, step=newstep,
|
||||
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
|
||||
|
@ -709,33 +721,41 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
for x in range(i.count):
|
||||
ins = WProduct.objects.create(**wpr)
|
||||
# 添加日志
|
||||
WpmServies.add_wproduct_flow_log(
|
||||
WpmService.add_wproduct_flow_log(
|
||||
ins, 'wproduct_create')
|
||||
# 更新进度
|
||||
WpmServies.update_subproduction_progress_main(
|
||||
WpmService.update_subproduction_progress_main(
|
||||
sp=i.subproduction_plan)
|
||||
elif step.type == Step.STEP_TYPE_COMB:
|
||||
oms_w = omos.filter(subproduction_progress__is_main=True)
|
||||
if len(oms_w) == 1:
|
||||
oms_w = oms_w[0]
|
||||
# 校验单片数量是否正确, 暂时未写
|
||||
newstep, hasNext = WpmServies.get_next_step(
|
||||
newstep, needTest = WpmService.get_next_step(
|
||||
oms_w.subproduction_plan, step)
|
||||
wproduct = WProduct()
|
||||
wproduct.material = oms_w.material
|
||||
wproduct.step = newstep
|
||||
wproduct.subproduction_plan = oms_w.subproduction_plan
|
||||
if hasNext:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
else:
|
||||
if step == newstep:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
# 更新子计划进度
|
||||
WpmServies.update_subproduction_progress_main(
|
||||
sp=oms_w.subproduction_plan)
|
||||
if wproduct.test:# 如果有正在进行的工序中检验
|
||||
wproduct.test.is_midtesting = False
|
||||
wproduct.test.is_submited = False
|
||||
wproduct.test.save()
|
||||
else:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
if needTest:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
wproduct.material_check = wproduct.product
|
||||
|
||||
# 更新子计划进度
|
||||
WpmService.update_subproduction_progress_main(
|
||||
sp=oms_w.subproduction_plan)
|
||||
wproduct.create_by = request.user
|
||||
wproduct.coperation = op
|
||||
wproduct.save()
|
||||
WpmServies.add_wproduct_flow_log(wproduct, 'wproduct_create')
|
||||
WpmService.add_wproduct_flow_log(wproduct, 'wproduct_create')
|
||||
# 隐藏原半成品
|
||||
wps = WProduct.objects.filter(ow_wproduct__operation=op)
|
||||
wps.update(is_hidden=True, child=wproduct,
|
||||
|
@ -747,7 +767,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
|||
|
||||
# 如果是冷加工
|
||||
if step.process.id == 1:
|
||||
WpmServies.update_cutting_list_with_operation(op=op)
|
||||
WpmService.update_cutting_list_with_operation(op=op)
|
||||
return Response()
|
||||
|
||||
|
||||
|
@ -971,213 +991,3 @@ class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyMode
|
|||
return Response()
|
||||
|
||||
|
||||
class DoFormInit(CreateAPIView, GenericAPIView):
|
||||
perms_map = {'*': '*'}
|
||||
serializer_class = OperationInitSerializer
|
||||
|
||||
def post(self, request, format=None):
|
||||
"""
|
||||
调用操作表单
|
||||
"""
|
||||
data = request.data
|
||||
serializer = OperationInitSerializer(data=data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.validated_data
|
||||
ret = {}
|
||||
ret_0 = {}
|
||||
ret_0['step'] = data['step']
|
||||
splans = []
|
||||
ret_0['input'] = []
|
||||
# ret_0['subproduction_plan'] = data['subproduction_plan']
|
||||
if 'wproducts' in data and data['wproducts']:
|
||||
ret_0['wproducts'] = data['wproducts']
|
||||
splans = WProduct.objects.filter(id__in=data['wproducts']).values_list(
|
||||
'subproduction_plan', flat=True)
|
||||
# 调出所属子计划现有物料
|
||||
ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(
|
||||
subproduction_plan__in=splans), many=True).data
|
||||
else:
|
||||
if 'subproduction_plan' in vdata:
|
||||
splans = [vdata['subproduction_plan']]
|
||||
else:
|
||||
splans = SubProductionPlan.objects.filter(is_deleted=False,
|
||||
subproduction__usedstep_subproduction__step=vdata[
|
||||
'step'],
|
||||
state=3)
|
||||
ret_0['wproducts'] = []
|
||||
ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(
|
||||
subproduction_plan__in=splans), many=True).data
|
||||
|
||||
for i in ret_0['input']:
|
||||
i['count_input'] = 0
|
||||
# 需要输出的物料
|
||||
if ret_0['wproducts']:
|
||||
# 排除主要产物, 因为已经放到半成品里了, 由半成品进行处理, 夹层可能需要特殊处理
|
||||
o_objs = SubProductionProgress.objects.filter(
|
||||
subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True)
|
||||
|
||||
else:
|
||||
# 此时显示所有子计划需要输出的物料
|
||||
o_objs = SubProductionProgress.objects.filter(
|
||||
subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||
ret_0['output'] = list(o_objs.values(
|
||||
'subproduction_plan', 'material', 'material__name', 'material__number'))
|
||||
for i in ret_0['output']:
|
||||
i['count_output'] = 0
|
||||
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():
|
||||
ret['forms'].extend(RecordFormDetailSerializer(
|
||||
instance=forms, many=True).data)
|
||||
return Response(ret)
|
||||
|
||||
|
||||
class DoFormSubmit(CreateAPIView, GenericAPIView):
|
||||
perms_map = {'*': '*'}
|
||||
serializer_class = OperationSubmitSerializer
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request, format=None):
|
||||
"""
|
||||
提交操作表单
|
||||
"""
|
||||
data = request.data
|
||||
serializer = OperationSubmitSerializer(
|
||||
data=data, context={'request': self.request})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.validated_data # 校验之后的数据
|
||||
|
||||
# 创建一个生产操作记录
|
||||
action_obj = Operation()
|
||||
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
|
||||
owps.append(OperationWproduct(**owp))
|
||||
OperationWproduct.objects.bulk_create(owps)
|
||||
|
||||
# 保存物料消耗
|
||||
for i in vdata['input']:
|
||||
if i['count_input']: # 如果有消耗
|
||||
i_wmat = i['id']
|
||||
OperationMaterial.objects.create(type=1, operation=action_obj,
|
||||
wmaterial=i_wmat, count=i['count_input'])
|
||||
# 更新车间物料
|
||||
i_wmat.count = i_wmat.count - i['count_input']
|
||||
i_wmat.save()
|
||||
# 更新子计划物料消耗情况
|
||||
sp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan,
|
||||
material=i_wmat.material)
|
||||
sp.count_real = sp.count_real + i['count_input']
|
||||
sp.save()
|
||||
|
||||
# 物料产出
|
||||
if 'output' in data and data['output']:
|
||||
for i in vdata['output']: # 已经序列化好的数据
|
||||
ma = i['material']
|
||||
if i['subproduction_plan'].product == ma: # 如果是该计划主产物
|
||||
# 如果是切割
|
||||
# 获取下一步子工序
|
||||
if vdata['step'].type == Step.STEP_TYPE_DIV:
|
||||
newstep, _ = WpmServies.get_next_step(
|
||||
i['subproduction_plan'], vdata['step'])
|
||||
wpr = dict(material=ma, step=newstep,
|
||||
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
|
||||
subproduction_plan=i['subproduction_plan'])
|
||||
for x in range(i['count_output']):
|
||||
WProduct.objects.create(**wpr)
|
||||
else:
|
||||
# 更新操作产出物料表
|
||||
OperationMaterial.objects.create(type=2, operation=action_obj,
|
||||
material=ma, count=i['count_output'])
|
||||
# 更新车间物料表
|
||||
ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i['subproduction_plan'],
|
||||
material=ma)
|
||||
ins.count = ins.count + i['count_output']
|
||||
ins.save()
|
||||
# 更新子计划进度表
|
||||
sp = SubProductionProgress.objects.get(subproduction_plan=i['subproduction_plan'],
|
||||
material=ma)
|
||||
sp.count_real = sp.count_real + i['count_input']
|
||||
sp.save()
|
||||
|
||||
# 更新动态产品表
|
||||
if 'wproducts' in vdata and vdata['wproducts']:
|
||||
if vdata['step'].type == Step.STEP_TYPE_COMB:
|
||||
wproducts = vdata['wproducts']
|
||||
if 'suproduction_plan' in vdata:
|
||||
wproducts.update(is_hidden=True) # 隐藏
|
||||
newstep, hasNext = WpmServies.get_next_step(
|
||||
i['subproduction_plan'], vdata['step'])
|
||||
wproduct = WProduct()
|
||||
wproduct.material = vdata['subproduction_plan'].product
|
||||
wproduct.step = newstep
|
||||
wproduct.subproduction_plan = vdata['subproduction_plan']
|
||||
wproduct.parent = data['wproducts']
|
||||
if hasNext:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
else:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
wproduct.save()
|
||||
else:
|
||||
raise exceptions.APIException('请指定子计划')
|
||||
else:
|
||||
for wproduct in vdata['wproducts']:
|
||||
# 获取下一步子工序
|
||||
newstep, hasNext = WpmServies.get_next_step(
|
||||
wproduct.subproduction_plan, vdata['step'])
|
||||
wproduct.step = newstep
|
||||
wproduct.pre_step = vdata['step']
|
||||
if hasNext:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
|
||||
else:
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||
wproduct.material = wproduct.subproduction_plan.product
|
||||
wproduct.save()
|
||||
|
||||
# 保存自定义表单结果
|
||||
for i in vdata['forms']:
|
||||
wr = OperationRecord()
|
||||
wr.form = i['form']
|
||||
wr.create_by = request.user
|
||||
wr.operation = action_obj
|
||||
wr.save()
|
||||
wrds = []
|
||||
for m in i['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'] = wr
|
||||
wrds.append(OperationRecordItem(**m))
|
||||
OperationRecordItem.objects.bulk_create(wrds)
|
||||
return Response()
|
||||
|
|
Loading…
Reference in New Issue