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

This commit is contained in:
shilixia 2022-01-06 08:34:53 +08:00
commit 9fd1e20008
15 changed files with 1232 additions and 337 deletions

View File

@ -147,7 +147,9 @@ export default {
text-align: center;
line-height: 50px;
border-radius: 26px;
background: #ffffff;
border: 2px solid #409EFF;
box-shadow: 0 0 8px 3px rgba(0,0,0,0.1);
}
.typeWrap{
display: none;

View File

@ -521,6 +521,13 @@ export const asyncRoutes = [
meta: { title: '工单处理', icon: 'example',noCache: true,},
hidden: true
},
{
path: 'ticketDetail',
name: 'ticketDetail',
component: () => import('@/views/workflow/ticketDetail'),
meta: { title: '工单详情', icon: 'example',noCache: true,},
hidden: true
},
]
},
{

View File

@ -52,22 +52,24 @@
</div>
<el-table
v-loading="listLoading"
:data="list"
:data="planList"
border fit stripe
height="300"
>
>
<el-table-column type="index" width="50" />
<el-table-column label="任务编号">
<template slot-scope="scope">{{ scope.row.id }}</template>
<el-table-column label="任务编号" prop="number">
</el-table-column>
<el-table-column label="产品名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
<template slot-scope="scope">{{ scope.row.product_.name }}</template>
</el-table-column>
<el-table-column label="产品型号">
<template slot-scope="scope">{{ scope.row.card }}</template>
<template slot-scope="scope">{{ scope.row.product_.specification }}</template>
</el-table-column>
<el-table-column label="生产数量">
<template slot-scope="scope">{{ scope.row.sco }}</template>
<el-table-column label="生产数量" prop="count">
</el-table-column>
<el-table-column label="开始时间" prop="start_date">
</el-table-column>
<el-table-column label="结束时间" prop="end_date">
</el-table-column>
</el-table>
</el-card>
@ -102,7 +104,7 @@
<el-col :span="12">
<el-card>
<div class="dashboardCardHand">
<div class="dashboardCardTitle">库存列表</div>
<div class="dashboardCardTitle">库存列表 <span class="stockMore" @click="stockMore">更多>></span></div>
<div class="block">
<el-pagination
:current-page.sync="stockPage"
@ -119,30 +121,29 @@
</div>
<el-table
v-loading="listLoading"
:data="list"
:data="stockList"
border fit stripe
height="300"
>
<el-table-column label="物料编号">
<template slot-scope="scope">{{ scope.row.id }}</template>
<el-table-column label="物料编号" prop="material_">
<template slot-scope="scope">{{ scope.row.material_.number }}</template>
</el-table-column>
<el-table-column label="物料名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
<el-table-column label="物料名称" prop="material_">
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
</el-table-column>
<el-table-column label="规格型号">
<template slot-scope="scope">{{ scope.row.card }}</template>
<el-table-column label="规格型号" prop="material_">
<template slot-scope="scope">{{ scope.row.material_.specification }}</template>
</el-table-column>
<el-table-column label="物料类型">
<template slot-scope="scope">{{ scope.row.sco }}</template>
<el-table-column label="物料类型" prop="material_">
<template slot-scope="scope">{{options[scope.row.material_.type]}}</template>
</el-table-column>
<el-table-column label="单位">
<template slot-scope="scope">{{ scope.row.name }}</template>
<el-table-column label="单位" prop="material_">
<template slot-scope="scope">{{scope.row.material_.unit}}</template>
</el-table-column>
<el-table-column label="库存">
<template slot-scope="scope">{{ scope.row.card }}</template>
<el-table-column label="库存" prop="count">
</el-table-column>
<el-table-column label="仓库">
<template slot-scope="scope">{{ scope.row.sco }}</template>
<el-table-column label="仓库" prop="warehouse_">
<template slot-scope="scope">{{ scope.row.warehouse_.name }}</template>
</el-table-column>
</el-table>
</el-card>
@ -163,25 +164,25 @@
</el-pagination>
</div>
</div>
<div class="lists">
<ul style="padding-right: 40px">
<li style="height: 50px;line-height: 50px;font-size: 20px">
<div style="display: flex;justify-content: space-between">
<div>
<ul class="lists">
<li class="listItem">
<div class="itemText">
<span>玻璃低于安全库存</span><span>2021-12-30</span>
</div>
</li>
<li style="height: 50px;line-height: 50px;font-size: 20px">
<div style="display: flex;justify-content: space-between">
<li class="listItem">
<div class="itemText">
<span>某某批货临近交货日期</span><span>2021-12-20</span>
</div>
</li>
<li style="height: 50px;line-height: 50px;font-size: 20px">
<div style="display: flex;justify-content: space-between">
<li class="listItem">
<div class="itemText">
<span>玻璃低于安全库存</span><span>2021-11-30</span>
</div>
</li>
<li style="height: 50px;line-height: 50px;font-size: 20px">
<div style="display: flex;justify-content: space-between">
<li class="listItem">
<div class="itemText">
<span>某某批货临近交货日期</span><span>2021-11-20</span>
</div>
</li>
@ -204,6 +205,9 @@
<script>
import echarts from 'echarts'
import { mapGetters } from 'vuex';
import { getInventoryList } from "@/api/inm";
import { getProductionplanList} from "@/api/pm";
export default {
name: 'Dashboard',
data() {
@ -212,19 +216,31 @@ export default {
stockPage:1,
stockPageSize:10,
stockTotal:100,
remindPage:2,
remindPage:1,
remindPageSize:20,
remindTotal:100,
tableIndex:null,
chartIndex:null,
tableDate:'2021-12',
chartDate:'2021-12',
planList:[],
stockList:[],
remindList:[],
list:[
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'},
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'},
{id:1,name:'HIehd9',card:'3337',sco:'REF-32'}
],
options:{
"1":'成品',
"2":'半成品',
"3":'主要原料',
"4":'辅助材料',
"5":'加工工具',
"6":'辅助工装',
},
seriesData:[80,60,60, 70, 76, 80, 90, 70],
}
},
@ -244,6 +260,29 @@ export default {
this.$router.push({name:'ticket',params:{}})
}
},
//任务排期列表
getPlanList() {
let that = this;
this.listLoading = true;
getProductionplanList({page:0}).then((response) => {
if (response.data) {
that.planList = response.data;
}
this.listLoading = false;
});
},
//库存列表
getStockList() {
let that = this;
this.listLoading = true;
getInventoryList({page:this.stockPage,page_size:this.stockPageSize}).then((response) => {
if (response.data) {
that.stockList = response.data.results;
that.stockTotal = response.data.count;
}
this.listLoading = false;
});
},
//图标渲染
drawChart() {
this.chartColumn = echarts.init(document.getElementById('chartColumn'));
@ -274,7 +313,7 @@ export default {
}
},
xAxis: {
name:'工序',
// name:'工序',
axisTick: {
show: false
},
@ -328,6 +367,9 @@ export default {
}]
});
},
stockMore(){
this.$router.push({name:'warehouse',params:{}})
},
//便捷查询按钮
convenientClick(index,type){
let startTime = '',endTime = '',url='',activeIndex = '1',obj = new Object();
@ -377,7 +419,15 @@ export default {
this.stockPage = 1;
},
handleStockCurrentChange(val){
console.log(`当前页: ${val}`);
let that = this;
this.listLoading = true;
getInventoryList({page:val,page_size:this.stockPageSize}).then((response) => {
if (response.data) {
that.stockList = response.data.results;
that.stockTotal = response.data.count;
}
this.listLoading = false;
});
},
handleRemindSizeChange(val){
this.remindPageSize = val;
@ -389,7 +439,9 @@ export default {
},
mounted () {
this.drawChart()
this.drawChart();
this.getPlanList();
this.getStockList();
},
updated () {
this.drawChart()
@ -409,6 +461,7 @@ export default {
margin-bottom: 5px;
.cards{
width: 240px;
max-width: 18%;
color: #ffffff;
background: #abccec;
text-align: center;
@ -416,7 +469,7 @@ export default {
padding: 10px;
line-height: 30px;
float: left;
margin: 15px;
margin: 15px 1%;
.cardFirstText{
text-align: left;
padding-left: 20px;
@ -437,9 +490,15 @@ export default {
.dashboardCardTitle{
height: 35px;
line-height:35px;
font-size: 24px;
font-size: 20px;
font-weight: bold;
vertical-align: middle;
.stockMore{
font-size: 14px;
font-weight: normal;
color: #409EFF;
cursor: pointer;
}
}
.dashboardCardFilter{
display: flex;
@ -473,4 +532,16 @@ export default {
}
}
.lists{
padding-right: 40px;
.listItem{
height: 40px;
line-height: 40px;
font-size: 18px;
.itemText{
display: flex;
justify-content: space-between;
}
}
}
</style>

View File

@ -68,6 +68,7 @@
<el-link v-if="scope.row.state_.type==1&&userId==1" type="danger" @click="handleClose(scope,'2')">关闭</el-link>
<!--如果state_.retreat为可退回则显示撤回按钮 state_.type==1处于草稿状态 -->
<el-link v-if="scope.row.state_.enable_retreat&&userId==scope.row.create_by&&scope.row.state_.type!==1" type="danger" @click="handleClose(scope,'1')">撤回</el-link>
<el-link type="primary" @click="handleDetails(scope)">详情</el-link>
<el-link type="success" @click="handleDelete(scope)">删除</el-link>
<el-link type="success" @click="handlePicture(scope)">查看流程图</el-link>
<el-link type="success" @click="handleLogs(scope)">工单日志</el-link>
@ -117,6 +118,7 @@
<el-link v-else-if="(scope.row.act_state==1||scope.row.act_state==3)&&scope.row.participant_type!==2&&scope.row.state_.type===0" type="primary" @click="handleDetail(scope)">处理</el-link>
-->
<el-link v-if="scope.row.state_.type==1&&userId==1" type="danger" @click="handleClose(scope,'2')">关闭</el-link>
<el-link type="primary" @click="handleDetails(scope)">详情</el-link>
<el-link type="success" @click="handlePicture(scope)">查看流程图</el-link>
<el-link type="success" @click="handleLogs(scope)">工单日志</el-link>
</template>
@ -163,6 +165,7 @@
<template slot-scope="scope" v-if="scope.row.state_">
<el-link v-if="scope.row.state_.enable_retreat&&scope.row.state_.type!==1" type="danger" @click="handleClose(scope,'1')">撤回</el-link>
<el-link v-if="scope.row.state_.type==1" type="danger" @click="handleClose(scope,'2')">关闭</el-link>
<el-link type="primary" @click="handleDetails(scope)">详情</el-link>
<el-link type="success" @click="handleDelete(scope)">删除</el-link>
<el-link type="success" @click="handlePicture(scope)">查看流程图</el-link>
<el-link type="success" @click="handleLogs(scope)">工单日志</el-link>
@ -208,6 +211,7 @@
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-link type="primary" @click="handleDetails(scope)">详情</el-link>
<el-link type="danger" @click="handlePicture(scope)">查看流程图</el-link>
<el-link type="success" @click="handleLogs(scope)">工单日志</el-link>
</template>
@ -866,6 +870,10 @@
handleDetail(scope){
this.$router.push({name:"ticketHandle",params:{ticketId:scope.row.id,workflow:scope.row.workflow}})
},
//工单详情
handleDetails(scope){
this.$router.push({name:"ticketDetail",params:{ticketId:scope.row.id,workflow:scope.row.workflow}})
},
//接单
handleGetTicket(scope){
let ticketId = scope.row.id;

View File

@ -0,0 +1,563 @@
<template>
<div class="app-container">
<el-card style="margin-bottom: 10px">
<el-steps :active="actives" spac="400px" align-center="" style="padding-top: 20px;">
<el-step :title="item.name" v-for="item in flowSteps " :key="item.id"></el-step>
</el-steps>
</el-card>
<el-row>
<el-col :span="8">
<el-card>
<svg height=800 id="mySvg" style="width:100%!important;"></svg>
</el-card>
</el-col>
<el-col :span="16">
<el-card style="margin-left: 10px">
<p style="text-align: center;font-size: 20px">{{ticketDetail.title}}</p>
<el-col :span="12">
<div class="items">
<span class="itemLabel">工作流</span>
<span>{{ticketDetail.workflow_.name}}</span>
</div>
</el-col>
<el-col :span="12">
<div class="items">
<span class="itemLabel">流水号</span>
<span>{{ticketDetail.sn}}</span>
</div>
</el-col>
<el-col :span="12">
<div class="items">
<span class="itemLabel">创建时间</span>
<span>{{ticketDetail.create_time}}</span>
</div>
</el-col>
<el-col v-for="item in ticketDetail.ticket_data_" :key="item.id" :span="12">
<div class="items">
<span class="itemLabel">{{item.field_name}}</span>
<span>{{item.field_display}}</span>
</div>
</el-col>
</el-card>
<el-card style="margin-left: 10px">
<el-table :data="logs" fit stripe
style="width: 100%;border-top:1px solid #EBEEF5;"
height="500"
highlight-current-row
>
<el-table-column label="工单标题" min-width="100">
<template slot-scope="scope" v-if="scope.row.ticket_data">
<span>{{scope.row.ticket_data.title}}</span>
</template>
</el-table-column>
<el-table-column label="进行状态" min-width="100">
<template slot-scope="scope" v-if="scope.row.state_">
<span v-if="scope.row.state_.type==0">{{scope.row.state_.name}}</span>
<span v-else>{{scope.row.state_.name}}</span>
</template>
</el-table-column>
<el-table-column label="操作人" min-width="100">
<template slot-scope="scope" v-if="scope.row.participant_">{{ scope.row.participant_.name }}</template>
</el-table-column>
<el-table-column label="操作意见" min-width="100" prop="suggestion">
</el-table-column>
<el-table-column label="更新时间" min-width="100" prop="update_time">
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
import {getOrgAll} from "@/api/org";
import {upUrl, upHeaders} from "@/api/file";
import {getUserList} from "@/api/user";
import {
getWorkflowList, getWfCustomfieldList, getWfStateList, getWfTransitionList, ticketHandle
, getWfFlowSteps, getTicketDetail, getTicketTransitions, getTicketFlowlog, ticketRetreat,
ticketAddNode, ticketAddNodeEnd, ticketClose
} from "@/api/workflow";
import Pagination from "@/components/Pagination";
import dagreD3 from 'dagre-d3'
import * as d3 from 'd3'
export default {
name: "ticketDetail",
components: {Pagination},
inject: ['reload'],
data() {
return {
step: 4,
actives: 4,
ticketId: 0,
stateSteps: 0,
ticketForm: {
transition: '',
ticket_data: {},
suggestion: '',
},
handleType: '1',
handleLabel: '撤回原因',
handleTitle: '工单撤回',
handleForm: {
suggestion: '',
},
addForm: {
toadd_user: '',
suggestion: '',
},
tooltip: null,
handleRule: {},
upUrl: upUrl(),
upHeaders: upHeaders(),
userId: '',
workflow: '',
watchedName: '',
watchedCreateTime: '',
logs: [],
orgList: [],
staffs: [],
edges: [],
nodes: [],
tooltip: [],
fileList: [],
workflows: [],
flowSteps: [],
ticketDetail: {},
operationBtn: [],
customfields: [],
transitions: [],
limitedAdd: false,
limitedHandle: false,
ticketFormRule: {},
}
},
mounted() {
let that = this;
that.userId = sessionStorage.getItem('userId')
let ticketId = that.ticketId = this.$route.params.ticketId;
let workflow = that.workflow = this.$route.params.workflow;
let handleTicketId = sessionStorage.getItem('handleTicketId');
let handleTicketWorkflow = sessionStorage.getItem('handleTicketWorkflow');
if (ticketId && workflow) {
if (handleTicketId && handleTicketWorkflow) {
sessionStorage.removeItem('handleTicketId');
sessionStorage.removeItem('handleTicketWorkflow');
sessionStorage.setItem('handleTicketId', ticketId);
sessionStorage.setItem('handleTicketWorkflow', workflow);
} else {
sessionStorage.setItem('handleTicketId', ticketId);
sessionStorage.setItem('handleTicketWorkflow', workflow);
}
} else {
ticketId = that.ticketId = handleTicketId;
workflow = that.workflow = handleTicketWorkflow;
}
this.getTicketFlowlogs(ticketId);
getTicketTransitions(ticketId).then(res => {
this.operationBtn = res.data;
})
getOrgAll().then((orgRes) => {
that.orgList = orgRes.data;
getUserList({page: 0}).then(userRes => {
if (userRes.data) {
that.staffs = userRes.data;
getWfFlowSteps(ticketId).then((res) => {
if (res.data) {
//流程步骤数组
that.flowSteps = res.data;
getTicketDetail(ticketId).then((res) => {
if (res.data) {
that.tooltip = that.createTooltip();
that.ticketDetail = res.data;
for (let i = 0; i < that.ticketDetail.ticket_data_.length; i++) {
if (that.ticketDetail.ticket_data_[i].label === "sys_user") {
that.ticketDetail.ticket_data_[i].field_choice = that.staffs;
}
if (that.ticketDetail.ticket_data_[i].label === "deptSelect") {
that.ticketDetail.ticket_data_[i].field_choice = that.orgList;
}
}
console.log(that.ticketDetail.state_.enable_retreat);
let state = res.data.state;
let dat = that.flowSteps.filter((item) => {
return item.id == state;
})
debugger;
let state_fields = dat[0].state_fields;
if (state_fields !== {}) {
for (let labe in state_fields) {
for (let j = 0; j < that.ticketDetail.ticket_data_.length; j++) {
if (that.ticketDetail.ticket_data_[j].field_key === labe) {
debugger;
console.log(labe)
console.log(state_fields[labe])
if (state_fields[labe] !== 4) {
that.ticketDetail.ticket_data_[j].is_hidden = false
} else {
that.ticketDetail.ticket_data_[j].is_hidden = true
}
}
}
}
}
that.sort = dat[0].sort;
that.actives = that.flowSteps.indexOf(dat[0]);
if (that.flowSteps.length - that.actives > 1) {
} else {
that.actives = that.flowSteps.length;
}
var g = new dagreD3.graphlib.Graph().setGraph({
rankdir: 'DL',
nodesep: 100,
edgesep: 10,//两条线之间的距离
ranksep: 50,//节点之间的距离
marginx: 60,
marginy: 20,
});
//获取state得到节点
getWfStateList(workflow).then((response) => {
if (response.data) {
let nodes = response.data;
// 添加节点
nodes.forEach((item) => {
if (item.sort == that.sort) {
g.setNode(item.id, {
// 节点标签
label: item.name,
// 节点形状
shape: 'rect',
toolText: item.name,
//节点样式
style: "fill:#409EFF;stroke:#000",
labelStyle: "fill:#000;",
rx: 5,//矩形节点圆角度
ry: 5
});
} else {
g.setNode(item.id, {
// 节点标签
label: item.name,
// 节点形状
shape: 'rect',
toolText: item.name,
//节点样式
style: "fill:#fff;stroke:#000",
labelStyle: "fill:#000;",
rx: 5,//矩形节点圆角度
ry: 5
});
}
});
g.nodes().forEach(function (v) {
console.log("Node " + v + ": " + JSON.stringify(g.node(v)));
});
//获取流转得到线 链接关系
getWfTransitionList(workflow).then((res) => {
if (res.data) {
let transitionList = res.data;
transitionList.forEach((transitions) => {
let transition0 = transitions;
if (transition0.condition_expression.length > 0) {
g.setNode(transition0.source_state_.id + 100000, {
label: "条件表达式",
style: "fill: #a4d088",
shape: "diamond"
});
g.setEdge(transition0.source_state_.id, transition0.source_state_.id + 100000, {
// 边标签
label: transition0.name,
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px"
});
let condition_expression = transition0.condition_expression;
condition_expression.forEach(condition_expression0 => {
g.setEdge(transition0.source_state_.id + 100000, condition_expression0.target_state, {
label: condition_expression0.label,
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px"
})
})
} else {
g.setEdge(transition0.source_state_.id, transition0.destination_state_.id, {
// 边标签
label: transition0.name,
// 边样式
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px" // 根据后台数据来改变连线的颜色
});
}
})
g.nodes().length - 1
g.nodes().forEach(function (v) {
console.log("Node " + v + ": " + JSON.stringify(g.node(v)));
});
// 创建渲染器
let render = new dagreD3.render();
// 选择 svg 并添加一个g元素作为绘图容器.
let svg = d3.select('#mySvg');
let svgGroup = svg.append('g');
let zoom = d3.zoom()
.on("zoom", function () {
svgGroup.attr("transform", d3.event.transform);
});
svg.call(zoom);
// 在绘图容器上运行渲染器生成流程图.
render(d3.select("svg g"), g);
// this.getTicketFlowlogs(ticketId);
getTicketFlowlog(ticketId).then(res => {
if (res.data) {
that.logs = res.data;
svgGroup
.selectAll('g.node')
.on('mouseover', (v) => {
// 假如当前toolText为"",则不展示
//这里就是自定义tooltip的内容
let filList = [], strList = [];
filList = nodes.filter((ii) => {
return ii.name === g.node(v).label
})
if (!filList.length) {
return
}
filList.map((k) => {
let filte = that.logs.filter(item => {
return item.state == k.id;
})
//每个
let str = '处理人:' + filte[0].participant_.name;
strList.push(str)
})
that.tipVisible(strList)
})
.on('mouseout', () => {
this.tipHidden()
})
}
})
} else {
}
});
}
});
}
});
}
});
}
})
});
},
activated() {
},
methods: {
getUser() {
getUserList({}).then(res => {
if (res.data) {
this.staffs = res.data.results;
}
})
},
//工单流转记录
getTicketFlowlogs(id) {
getTicketFlowlog(id).then(res => {
if (res.data) {
this.logs = res.data;
}
})
},
handlePreview(file) {
if ("url" in file) {
window.open(file.url);
} else {
window.open(file.response.data.path);
}
},
handleUpSuccess(res, file, filelist) {
this.process.instruction = res.data.id;
},
handleRemove(file, filelist) {
this.process.instruction = null;
},
// 创建提示框
createTooltip() {
return d3
.select('body')
.append('div')
.classed('tooltip', true)
.style('opacity', 0)
.style('display', 'none')
},
// tooltip显示
tipVisible(textContent) {
this.tooltip
.transition()
.duration(400)
.style('opacity', 1)
.style('display', 'block')
.style('color', '#ffffff')
.style('z-index', '3999')
.style('padding', '20px 30px')
.style('border-radius', '5px')
.style('position', 'fixed')
.style('background', 'rgba(0,0,0,.7)')
this.tooltip
.html(textContent)
.style('left', `${d3.event.pageX + 15}px`)
.style('top', `${d3.event.pageY - 10}px`)
},
// tooltip隐藏
tipHidden() {
this.tooltip
.transition()
.duration(400)
.style('opacity', 0)
.style('display', 'none')
},
operationSubmit(id) {
this.ticketForm.transition = id;
this.ticketForm.ticket_data = this.ticketDetail.ticket_data;
let obj = new Object();
obj.transition = id;
obj.ticket_data = this.ticketDetail.ticket_data;
obj.suggestion = this.ticketForm.suggestion;
console.log(this.ticketForm);
ticketHandle(this.ticketId, obj).then(res => {
if (res.data) {
this.$store.dispatch("user/getCount", {})
this.$router.replace({name: "ticket"})
}
})
},
retreatCancel() {
this.limitedHandle = false;
},
handleSubmit() {
let text = '', url = '';
if (this.handleType === '1') {
text = "确认撤回工单吗?";
url = ticketRetreat;
} else if (this.handleType === '2') {
text = "确认关闭工单吗?";
url = ticketClose;
}
if (this.handleType === '3') {
text = "确认处理工单吗?";
url = ticketAddNodeEnd;
}
this.$confirm(text, "温馨提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
url(this.ticketId, this.handleForm).then(res => {
this.limitedHandle = false;
this.$store.dispatch("user/getCount", {})
this.$router.replace({name: "ticket"})
this.$message.success("成功");
})
})
.catch((err) => {
console.error(err);
});
},
handleClick(index) {
this.limitedHandle = true;
this.handleType = index;
if (index === '1') {
this.handleTitle = '工单撤回';
this.handleLabel = '撤回原因';
} else if (index === '2') {
this.handleTitle = '工单关闭';
this.handleLabel = '关闭原因';
} else if (index === '3') {
this.handleTitle = '加签处理';
this.handleLabel = '加签意见';
}
},
handleAdd() {
this.getUser();
this.limitedAdd = true;
},
addCancel() {
this.limitedAdd = false;
},
addSubmit() {
ticketAddNode(this.ticketId, this.addForm).then(res => {
if (res.data) {
this.limitedAdd = false;
this.$nextTick(function () {
this.limitedAdd = true;
this.$store.dispatch("user/getCount", {})
this.$router.replace({name: "ticket"})
})
}
})
},
}
}
</script>
<style scoped>
.svgWrapper {
background: #fff;
width: 800px;
margin: 10vh auto 0;
text-align: center;
border-radius: 2px;
}
.svgItem {
padding: 20px 40px 0;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
font-size: 18px;
display: flex;
justify-content: space-between;
}
svg {
font-size: 14px;
}
.node rect {
stroke: #606266;
fill: #fff;
}
.edgePath path {
stroke: #606266;
fill: #333;
stroke-width: 1.5px;
}
.el-icon-close {
cursor: pointer;
}
.listItem {
margin-top: 15px;
font-size: 16px;
}
.listItem > span {
width: 100px;
text-align: right;
margin-right: 10px;
display: inline-block;
}
.items {
height: 35px;
line-height: 35px;
padding-left: 20px;
}
.itemLabel {
font-size: 14px;
color: #606266;
font-weight: 600;
}
</style>

View File

@ -36,10 +36,159 @@
</el-col>
<el-row style="display: flex;flex-wrap: wrap;width:100%;">
<el-col v-for="item in ticketDetail.ticket_data_" :key="item.id" :span="12" v-show="!item.is_hidden">
<el-form-item :label="item.field_name" v-if="item.field_state==='1'">
<span>{{ticketDetail.ticket_data[item.field_key]}}</span>
<el-form-item v-if="item.field_state=='1'" :label="item.field_name">
<template v-if="item.field_type=='string'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" :placeholder="item.description" disabled="true"/>
</template>
<template v-if="item.field_type==='int'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" type="number" :placeholder="item.description" oninput="value=value.replace(/[^\d]/g,'')" disabled="true"/>
</template>
<template v-if="item.field_type==='float'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" type="number" :placeholder="item.description" disabled="true"/>
</template>
<template v-if="item.field_type==='date'">
<el-date-picker
disabled="true"
v-model="ticketDetail.ticket_data[item.field_key]"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
style="width: 100%"
>
</el-date-picker>
</template>
<template v-if="item.field_type==='datetime'">
<el-date-picker
disabled="true"
v-model="ticketDetail.ticket_data[item.field_key]"
type="datetime"
placeholder="选择日期"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
>
</el-date-picker>
</template>
<template v-if="item.field_type==='select'">
<el-select style="width: 100%" v-model="ticketDetail.ticket_data[item.field_key]" placeholder="请选择" disabled="true">
<el-option
v-for="item1 in item.field_choice"
:key="item1.id"
:label="item1.name"
:value="item1.id"
>
</el-option>
</el-select>
</template>
<template v-if="item.field_type==='selects'">
<el-select style="width: 100%" multiple v-model="ticketDetail.ticket_data[item.field_key]" placeholder="请选择" disabled="true">
<el-option
v-for="item1 in item.field_choice"
:key="item1.id"
:label="item1.name"
:value="item1.id"
>
</el-option>
</el-select>
</template>
<template v-if="item.field_type==='textarea'">
<el-input type="textarea" :rows="3" v-model="ticketDetail.ticket_data[item.field_key]" placeholder="内容" disabled="true"/>
</template>
<template v-if="item.field_type==='file'">
<el-upload
ref="upload"
:action="upUrl"
:on-preview="handlePreview"
:on-success="handleUpSuccess"
:headers="upHeaders"
:file-list="fileList"
:limit="1"
accept=".doc,.docx,.xls,.xlsx,.ppt,.pptx"
>
<el-button size="small" type="primary">上传文件</el-button>
</el-upload>
</template>
</el-form-item>
<el-form-item :label="item.field_name" v-else>
<el-form-item
v-if="item.field_state=='2'"
:label="item.field_name"
prop=""
:rules="{
required: true, message: '不能为空', trigger: 'blur'
}"
>
<template v-if="item.field_type=='string'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" :placeholder="item.description"/>
</template>
<template v-if="item.field_type==='int'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" type="number" :placeholder="item.description" oninput="value=value.replace(/[^\d]/g,'')" />
</template>
<template v-if="item.field_type==='float'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" type="number" :placeholder="item.description" />
</template>
<template v-if="item.field_type==='date'">
<el-date-picker
v-model="ticketDetail.ticket_data[item.field_key]"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
style="width: 100%"
>
</el-date-picker>
</template>
<template v-if="item.field_type==='datetime'">
<el-date-picker
v-model="ticketDetail.ticket_data[item.field_key]"
type="datetime"
placeholder="选择日期"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
>
</el-date-picker>
</template>
<template v-if="item.field_type==='select'">
<el-select style="width: 100%" v-model="ticketDetail.ticket_data[item.field_key]" placeholder="请选择">
<el-option
v-for="item1 in item.field_choice"
:key="item1.id"
:label="item1.name"
:value="item1.id"
>
</el-option>
</el-select>
</template>
<template v-if="item.field_type==='selects'">
<el-select style="width: 100%" multiple v-model="ticketDetail.ticket_data[item.field_key]" placeholder="请选择">
<el-option
v-for="item1 in item.field_choice"
:key="item1.id"
:label="item1.name"
:value="item1.id"
>
</el-option>
</el-select>
</template>
<template v-if="item.field_type==='textarea'">
<el-input type="textarea" :rows="3" v-model="ticketDetail.ticket_data[item.field_key]" placeholder="内容" />
</template>
<template v-if="item.field_type==='file'">
<el-upload
ref="upload"
:action="upUrl"
:on-preview="handlePreview"
:on-success="handleUpSuccess"
:headers="upHeaders"
:file-list="fileList"
:limit="1"
accept=".doc,.docx,.xls,.xlsx,.ppt,.pptx"
>
<el-button size="small" type="primary">上传文件</el-button>
</el-upload>
</template>
</el-form-item>
<el-form-item
v-if="item.field_state=='3'"
:label="item.field_name"
>
<template v-if="item.field_type=='string'">
<el-input v-model="ticketDetail.ticket_data[item.field_key]" :placeholder="item.description"/>
</template>

View File

@ -11,13 +11,11 @@
stripe
highlight-current-row
max-height="700"
>
<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.number }}</template>
</el-table-column>
@ -26,12 +24,9 @@
{{ actstate_[scope.row.act_state] }}
</template>
</el-table-column>
<el-table-column label="所在子工序">
<template slot-scope="scope">{{ scope.row.step_.name }}</template>
</el-table-column>
<el-table-column align="center" label="操作" width="220px">
<template slot-scope="scope">
<el-link
@ -41,11 +36,12 @@
</el-link>
<el-link
v-if="scope.row.test!==null"
@click="checkRecord(scope,'1')"
@click="checkRecord(scope,'1')"
>检验记录
</el-link>
<el-link
<el-link
v-if="checkPermission(['warehouse_update'])"
type="danger"
@click="handleScrapbcp(scope)"
>报废
</el-link>
@ -61,30 +57,28 @@
/>
<el-dialog title="半成品报废" :close-on-click-modal="false" :visible.sync="dialogFormVisiblebcp">
<el-form :model="formbcp">
<el-form-item label="甩片原因" :label-width="formLabelWidth">
<el-select
style="width: 80%"
v-model="formbcp.scrap_reason"
placeholder="请甩片原因"
>
<el-option
v-for="item in scrapreason"
:key="item.lable"
:label="item.lable"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisiblebcp = false"> </el-button>
<el-button type="primary" @click="scrapesubmit"> </el-button>
</div>
</el-dialog>
<el-form :model="formbcp">
<el-form-item label="甩片原因" :label-width="formLabelWidth">
<el-select
style="width: 80%"
v-model="formbcp.scrap_reason"
placeholder="请甩片原因"
>
<el-option
v-for="item in scrapreason"
:key="item.lable"
:label="item.lable"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisiblebcp = false"> </el-button>
<el-button type="primary" @click="scrapesubmit"> </el-button>
</div>
</el-dialog>
</el-card>
</el-tab-pane>
<el-tab-pane label="复检半成品">
@ -126,13 +120,6 @@
@click="checkRecord(scope,'2')"
>检验记录
</el-link>
<!--<el-link
v-if="checkPermission(['warehouse_update'])"
@click="handleInspection(scope,'2')"
>
检验
</el-link>-->
</template>
</el-table-column>
</el-table>
@ -207,19 +194,16 @@
/>
</el-card>
</el-tab-pane>
<el-tab-pane label="不合格半成品">
<el-tab-pane label="不合格半成品">
<el-card style="margin-top: 2px">
<el-table
v-loading="listLoading"
:data="wproductList4.results"
border
fit
stripe
highlight-current-row
max-height="600"
>
<el-table-column type="index" width="50"/>
<el-table-column label="半成品名称">
@ -234,27 +218,29 @@
{{ actstate_[scope.row.act_state] }}
</template>
</el-table-column>
<el-table-column label="所在子工序">
<template slot-scope="scope">{{ scope.row.step_.name }}</template>
</el-table-column>
<el-table-column label="不合格标记">
<el-table-column label="不合格标记">
<template slot-scope="scope">
{{ ng_sign_[scope.row.ng_sign] }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="220px">
<template slot-scope="scope">
<el-link
type="danger"
<el-link
v-if="checkPermission(['warehouse_update'])"
type="danger"
@click="handleScrap(scope)"
>报废
>
报废
</el-link>
<el-link type="primary"
v-if="!scope.row.ticket"
<el-link
v-if="!scope.row.ticket"
type="primary"
@click="handleRetrial(scope)"
>重审
>
审理
</el-link>
</template>
</el-table-column>
@ -332,40 +318,40 @@
>
</el-option>
</el-select>
<!-- &lt;!&ndash;第一次操作时的展示&ndash;&gt;
<el-dialog
width="60%"
:title="formName"
:visible.sync="innerVisible"
append-to-body
>
<customForm
:results="fieldList"
:hasPicture="hasPicture"
:formID="recordform"
:wproduct="wproduct"
:recordId="recordId"
@recordSubmit="recordSubmit"
@recordSave="recordSave"
/>
</el-dialog>
&lt;!&ndash;复检检验表单&ndash;&gt;
<el-dialog
width="60%"
:title="formName"
:visible.sync="limitedReview"
append-to-body
>
<reviewForm
:results="fieldList"
:originList="originList"
:formID="recordform"
:hasPicture="hasPicture"
:wproduct="wproduct"
:origintest="origintest"
@formFunc="formFunc"
/>
</el-dialog>-->
<!-- &lt;!&ndash;第一次操作时的展示&ndash;&gt;
<el-dialog
width="60%"
:title="formName"
:visible.sync="innerVisible"
append-to-body
>
<customForm
:results="fieldList"
:hasPicture="hasPicture"
:formID="recordform"
:wproduct="wproduct"
:recordId="recordId"
@recordSubmit="recordSubmit"
@recordSave="recordSave"
/>
</el-dialog>
&lt;!&ndash;复检检验表单&ndash;&gt;
<el-dialog
width="60%"
:title="formName"
:visible.sync="limitedReview"
append-to-body
>
<reviewForm
:results="fieldList"
:originList="originList"
:formID="recordform"
:hasPicture="hasPicture"
:wproduct="wproduct"
:origintest="origintest"
@formFunc="formFunc"
/>
</el-dialog>-->
<div slot="footer" class="dialog-footer">
<el-button @click="outerVisible = false">
@ -520,13 +506,14 @@
<el-form label-width="130px" label-position="right">
<el-form-item :label="item.field_name" v-for="item in customfieldList" :key="item.id" v-show="!item.is_hidden">
<template v-if="item.field_type=='string'">
<el-input v-model="item.default_value" :placeholder="item.description" />
<el-input v-model="item.default_value" :placeholder="item.description"/>
</template>
<template v-if="item.field_type==='int'">
<el-input v-model="item.default_value" type="number" :placeholder="item.description" oninput="value=value.replace(/[^\d]/g,'')" />
<el-input v-model="item.default_value" type="number" :placeholder="item.description"
oninput="value=value.replace(/[^\d]/g,'')"/>
</template>
<template v-if="item.field_type==='float'">
<el-input v-model="item.default_value" type="number" :placeholder="item.description" />
<el-input v-model="item.default_value" type="number" :placeholder="item.description"/>
</template>
<template v-if="item.field_type==='date'">
<el-date-picker
@ -560,7 +547,7 @@
</el-select>
</template>
<template v-if="item.field_type==='selects'">
<el-select style="width: 100%" multiple v-model="item.default_value" placeholder="请选择">
<el-select style="width: 100%" multiple v-model="item.default_value" placeholder="请选择">
<el-option
v-for="item1 in item.field_choice"
:key="item1.id"
@ -571,7 +558,7 @@
</el-select>
</template>
<template v-if="item.field_type==='textarea'">
<el-input type="textarea" :rows="3" v-model="item.default_value" placeholder="内容" />
<el-input type="textarea" :rows="3" v-model="item.default_value" placeholder="内容"/>
</template>
<template v-if="item.field_type==='file'">
<el-upload
@ -598,26 +585,26 @@
</div>
</template>
<script>
import { getOrgAll } from "@/api/org";
import { getUserList } from "@/api/user";
import {getOrgAll} from "@/api/org";
import {getUserList} from "@/api/user";
import {getWarehouseList} from "@/api/inm";
import checkPermission from "@/utils/permission";
import customForm from '@/components/customForm/index';
import reviewForm from '@/components/customForm/review';
import {getWfCustomfieldList,createTicket ,getWorkflowInit} from "@/api/workflow";
import {getMaterialList, getrecordformList, getrffieldList} from "@/api/mtm";
import {getwproductList, wproductTest, wproductPutin, createputins,testInit,scrap,getRetrial} from "@/api/wpm";
import {getTestRecord,getTestRecordItem,putTestRecordItem,delTestRecordItem,subTestRecordItem} from "@/api/qm";
import {genTree} from "@/utils";
import { createTicket, getWorkflowInit} from "@/api/workflow";
import { getrecordformList, getrffieldList} from "@/api/mtm";
import {getwproductList, wproductPutin, createputins, testInit, scrap, getRetrial} from "@/api/wpm";
import {getTestRecord, getTestRecordItem, putTestRecordItem, delTestRecordItem, subTestRecordItem} from "@/api/qm";
// import {genTree} from "@/utils";
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
const defaultetestitem = {};
export default {
inject:['reload'],
components: {Pagination, customForm,reviewForm},
inject: ['reload'],
components: {Pagination, customForm, reviewForm},
data() {
return {
testitem: defaultetestitem,
formbcp:{},
formbcp: {},
form: {remark: "", warehouse: ""},
wproductList: {
count: 0,
@ -628,10 +615,10 @@
wproductList2: {
count: 0,
},
wproductList3: {
wproductList3: {
count: 0,
},
wproductList4: {
wproductList4: {
count: 0,
},
listQuery: {
@ -646,7 +633,7 @@
page: 1,
page_size: 20,
},
listQuery3: {
listQuery3: {
page: 1,
page_size: 20,
},
@ -654,38 +641,38 @@
page: 1,
page_size: 20,
},
formLabelWidth:'',
formLabelWidthL:'',
formLabelWidth: '',
formLabelWidthL: '',
actstate_: {
6: "待复检",
10: "操作进行中",
20: "待检验",
30: "已合格",
40: "库存中",
50: "不合格",
60: "待成品检验",
8: "操作准备中",
26: "待夹层检验",
70: "报废",
10: "操作进行中",
20: "待检验",
30: "已合格",
40: "库存中",
50: "不合格",
60: "待成品检验",
8: "操作准备中",
26: "待夹层检验",
70: "报废",
},
checkTypes:{
10:"子工序检验",
20:"工序检验",
30:"工序复检",
36:"夹层检验",
40:"成品检验",
checkTypes: {
10: "子工序检验",
20: "工序检验",
30: "工序复检",
36: "夹层检验",
40: "成品检验",
},
ng_sign_: {
10: "返工",
20: "返修",
30: "报废",
40: "让步接受",
50: "偏离许可",
60: "降级使用",
70: "退回供方",
80: "召回",
},
ng_sign_: {
10: "返工",
20: "返修",
30: "报废",
40: "让步接受",
50: "偏离许可",
60: "降级使用",
70: "退回供方",
80: "召回",
},
choice: [
{
value: true,
@ -696,12 +683,12 @@
label: "不合格",
},
],
scrapreason: [
{ lable: "气泡", value: 10 },
{ lable: "破点", value: 20 },
{ lable: "划伤", value: 30 },
{ lable: "其他", value: 40 },
],
scrapreason: [
{lable: "气泡", value: 10},
{lable: "破点", value: 20},
{lable: "划伤", value: 30},
{lable: "其他", value: 40},
],
recordList: [],
transitions: null,
options: [],
@ -720,10 +707,10 @@
listQueryrecordform: {
page: 0,
},
recordVisible:false,
dialogFormVisiblebcp:false,
innerIndex:null,
origintest:null,
recordVisible: false,
dialogFormVisiblebcp: false,
innerIndex: null,
origintest: null,
mutipID: [],
wproduct: null,
isPost: false,
@ -742,10 +729,10 @@
retrialResponse: {},//复检对象
//复检表单
retrialForm: {
title:'',
transition:null,
workflow:'',
ticket_data:{},
title: '',
transition: null,
workflow: '',
ticket_data: {},
},
WarehouseData: "",
formName: '项目检查表',
@ -757,8 +744,8 @@
this.getList();
this.getList2();
this.getList1();
this.getList3();
this.getList4();
this.getList3();
this.getList4();
// this.getLists();
},
methods: {
@ -775,22 +762,22 @@
});
},
//待检半成品报废
handleScrapbcp(scope){
this.dialogFormVisiblebcp=true;
this.bcpbf=scope.row.id;
handleScrapbcp(scope) {
this.dialogFormVisiblebcp = true;
this.bcpbf = scope.row.id;
},
//确定报废半成品
scrapesubmit(){
scrapesubmit() {
console.log(this.formbcp);
scrap(this.bcpbf,this.formbcp).then((response) => {
scrap(this.bcpbf, this.formbcp).then((response) => {
if (response.data) {
this.$message.success("该半成品已报废!");
this.dialogFormVisiblebcp=false;
this.getList();
this.$message.success("该半成品已报废!");
this.dialogFormVisiblebcp = false;
this.getList();
}
});
},
//复检半成品列表
@ -813,39 +800,39 @@
});
},
//不合格半成品
getList4(){
this.listQuery4.act_state = 50;
//不合格半成品
getList4() {
this.listQuery4.act_state = 50;
this.listQuery4.material__type = 2;
getwproductList(this.listQuery4).then((response) => {
if (response.data) {
this.wproductList4= response.data;
this.wproductList4 = response.data;
}
});
},
//不合格半成品报废
handleScrap(scope){
this.$confirm("确认该半成品报废?", "警告", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "error",
})
.then(async () => {
await scrap(scope.row.id);
this.getList4();
this.$message.success("该半成品已报废!");
},
//不合格半成品报废
handleScrap(scope) {
this.$confirm("确认该半成品报废?", "警告", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "error",
})
.catch((err) => {
console.error(err);
});
},
.then(async () => {
await scrap(scope.row.id);
this.getList4();
this.$message.success("该半成品已报废!");
})
.catch((err) => {
console.error(err);
});
},
//不合格产品重审展示
handleRetrial(scope){
let that =this;
handleRetrial(scope) {
let that = this;
this.retrialItem = Object.assign({}, scope.row);
console.log(this.retrialItem);
getRetrial(scope.row.id).then(res=>{
getRetrial(scope.row.id).then(res => {
that.retrialResponse = res.data;
getWorkflowInit(res.data.workflow).then((response) => {
if (response.data) {
@ -853,26 +840,26 @@
console.log(response.data);
that.retrialForm.transition = response.data.transitions[0].id;
that.customfieldList = response.data.field_list;
for (let i=0;i<that.customfieldList.length;i++) {
if(that.customfieldList[i].field_key==="wproduct"){
for (let i = 0; i < that.customfieldList.length; i++) {
if (that.customfieldList[i].field_key === "wproduct") {
that.customfieldList[i].default_value = that.retrialResponse.exist_data.wproduct;
}
if(that.customfieldList[i].field_key==="wproduct_name"){
if (that.customfieldList[i].field_key === "wproduct_name") {
that.customfieldList[i].default_value = that.retrialResponse.exist_data.wproduct_name;
}
if(that.customfieldList[i].field_key==="wproduct_type"){
if (that.customfieldList[i].field_key === "wproduct_type") {
that.customfieldList[i].default_value = that.retrialResponse.exist_data.wproduct_specification;
}
if(that.customfieldList[i].field_key==="finder"){
if (that.customfieldList[i].field_key === "finder") {
that.customfieldList[i].default_value = that.retrialResponse.exist_data.finder;
}
if(that.customfieldList[i].field_key==="find_process"){
if (that.customfieldList[i].field_key === "find_process") {
that.customfieldList[i].default_value = that.retrialResponse.exist_data.find_process;
}
if(that.customfieldList[i].label==="sys_user"){
if (that.customfieldList[i].label === "sys_user") {
that.customfieldList[i].field_choice = that.userList;
}
if(that.customfieldList[i].label==="deptSelect"){
if (that.customfieldList[i].label === "deptSelect") {
that.customfieldList[i].field_choice = that.orgList;
}
@ -883,16 +870,16 @@
})
},
//不合格产品重审提交
retrialSubmit(){
retrialSubmit() {
let that = this;
let fields = this.customfieldList;
let obj = new Object();
for(let i=0;i<fields.length;i++){
for (let i = 0; i < fields.length; i++) {
obj[fields[i].field_key] = fields[i].default_value
}
this.retrialForm.ticket_data = obj;
this.retrialForm.workflow = that.retrialResponse.workflow;
this.retrialForm.title = that.retrialResponse.exist_data.wproduct_name+'的重审';
this.retrialForm.title = that.retrialResponse.exist_data.wproduct_name + '的重审';
createTicket(this.retrialForm).then((res) => {
if (res.code >= 200) {
this.getList4();
@ -901,7 +888,7 @@
}
});
},
//夹层半成品列表
//夹层半成品列表
getList3() {
this.listQuery3.act_state = 26;
getwproductList(this.listQuery3).then((response) => {
@ -911,7 +898,7 @@
});
},
//半成品批量入库
handleCreate() {
this.dialogFormVisibles = true;
@ -923,7 +910,7 @@
_this.mutipID = []
this.$refs.multipleTable.selection.forEach((item) => {
_this.mutipID.push(item.id);
});
console.log(_this.mutipID);
createputins({
@ -947,7 +934,7 @@
});
},
//点击检验:如果有一个直接进入如果有多个表再进行选择
handleInspection(scope,index) {
handleInspection(scope, index) {
//调该物料对应的检查表
let that = this;
this.innerIndex = index;
@ -960,11 +947,11 @@
getrecordformList(this.listQueryrecordform).then((response) => {
if (response.data) {
this.recordformList = response.data;
if(response.data.length===1){
if (response.data.length === 1) {
that.recordform = response.data[0].id;
that.formName = response.data[0].name;
that.formName = response.data[0].name;
that.submitrecordform(index);
}else{
} else {
//弹出列表选择框
this.outerVisible = true;
}
@ -982,22 +969,22 @@
// that.submitrecordform(that.innerIndex);
},
//检验记录
checkRecord(scope,index){
checkRecord(scope, index) {
let that = this;
that.innerIndex = index;
that.wproduct = scope.row.id;//半成品ID
that.limitedCheckRecord = true;
getTestRecord({wproduct:scope.row.id}).then(res=>{
if(res.code==200){
getTestRecord({wproduct: scope.row.id}).then(res => {
if (res.code == 200) {
that.recordList = res.data.results;
}else{
} else {
this.$message.error(res.msg);
}
})
},
//点击记录里的检验
handleInspectionRecord(scope){
let that =this;
handleInspectionRecord(scope) {
let that = this;
that.fieldList = [];
that.recordVisible = false;
that.recordId = scope.row.id;
@ -1018,11 +1005,11 @@
getTestRecordItem(scope.row.id).then((res) => {
let arr = [];
let fieldList = res.data.record_data;
for(let i=0;i<that.fieldList.length;i++){
for (let i = 0; i < that.fieldList.length; i++) {
let obj = that.fieldList[i];
obj.is_testok = null;
for(let j=0;j<fieldList.length;j++){
if(that.fieldList[i].field_key===fieldList[j].field_key){
for (let j = 0; j < fieldList.length; j++) {
if (that.fieldList[i].field_key === fieldList[j].field_key) {
obj.id = fieldList[j].id;
obj.is_testok = fieldList[j].is_testok;
obj.field_value = fieldList[j].field_value;
@ -1031,14 +1018,14 @@
arr.push(obj)
}
that.fieldList = arr;
that.$nextTick(()=>{
that.$nextTick(() => {
that.isDisabled = false;
that.recordVisible = true;
});
})
}
});
}else if(that.innerIndex==='2'){//复检
} else if (that.innerIndex === '2') {//复检
getTestRecordItem(scope.row.id).then((res) => {
if (res.data) {
that.hasPicture = false;
@ -1061,19 +1048,19 @@
that.fieldList.push(obj)
}
// that.fieldList = [...fieldList];
let arr = fieldList.filter(item => {
return item.field_type === 'draw'
});
if (arr.length > 0) {
that.hasPicture = true;
}
this.limitedReview = true;
let arr = fieldList.filter(item => {
return item.field_type === 'draw'
});
if (arr.length > 0) {
that.hasPicture = true;
}
this.limitedReview = true;
}
})
}
},
//点击记录里的查看
handleRecordDetail(scope){
handleRecordDetail(scope) {
let that = this;
that.fieldList = [];
that.recordVisible = false;
@ -1094,11 +1081,11 @@
getTestRecordItem(scope.row.id).then((res) => {
let arr = [];
let fieldList = res.data.record_data;
for(let i=0;i<that.fieldList.length;i++){
for (let i = 0; i < that.fieldList.length; i++) {
let obj = that.fieldList[i];
obj.is_testok = null;
for(let j=0;j<fieldList.length;j++){
if(that.fieldList[i].field_key===fieldList[j].field_key){
for (let j = 0; j < fieldList.length; j++) {
if (that.fieldList[i].field_key === fieldList[j].field_key) {
obj.id = fieldList[j].id;
obj.is_testok = fieldList[j].is_testok;
obj.field_value = fieldList[j].field_value;
@ -1107,7 +1094,7 @@
arr.push(obj)
}
that.fieldList = arr;
that.$nextTick(()=>{
that.$nextTick(() => {
that.isDisabled = true;
that.recordVisible = true;
});
@ -1119,7 +1106,7 @@
handleReview() {
let that = this;
that.fieldList = [];
testInit({ wproduct: this.wproduct,form: that.recordform}).then((response) => {
testInit({wproduct: this.wproduct, form: that.recordform}).then((response) => {
if (response.data) {
that.hasPicture = false;
that.recordId = response.data.id;
@ -1158,8 +1145,8 @@
this.outerVisible = false;
that.fieldList = [];
if (that.recordform != "") {
if(index==='1'){//非复检
testInit({ wproduct: that.wproduct,form: that.recordform}).then((response) => {
if (index === '1') {//非复检
testInit({wproduct: that.wproduct, form: that.recordform}).then((response) => {
if (response.data) {
that.hasPicture = false;
that.recordId = response.data.id;
@ -1173,14 +1160,14 @@
if (arr.length > 0) {
that.hasPicture = true;
}
that.$nextTick(()=>{
that.$nextTick(() => {
that.isDisabled = false;
that.recordVisible = true;
});
})
}
});
}else if(index==='2'){//复检
} else if (index === '2') {//复检
that.handleReview();
}
} else this.$message.error("请选择检查表!");
@ -1201,7 +1188,7 @@
}
});
},
delTestRecord(scope){
delTestRecord(scope) {
let that = this;
this.$confirm("确认删除?", "警告", {
confirmButtonText: "确认",
@ -1209,15 +1196,15 @@
type: "error",
})
.then(async () => {
await delTestRecordItem(scope.row.id).then(res=>{
if(res.code>=200){
await delTestRecordItem(scope.row.id).then(res => {
if (res.code >= 200) {
that.$message.success("成功");
that.refreshRecord();
that.getList();
that.getList2();
that.getList1();
that.getList3();
}else{
} else {
this.$message.error(res.msg);
}
});
@ -1227,12 +1214,12 @@
});
},
//更新检验记录列表
refreshRecord(){
refreshRecord() {
let that = this;
getTestRecord({wproduct:that.wproduct}).then(res=>{
if(res.code==200){
getTestRecord({wproduct: that.wproduct}).then(res => {
if (res.code == 200) {
that.recordList = res.data.results;
}else{
} else {
this.$message.error(res.msg);
}
})
@ -1244,7 +1231,7 @@
let params = {};
params.record_data = value.record_data;
params.is_testok = value.is_testok;
putTestRecordItem(id,params).then((res) => {
putTestRecordItem(id, params).then((res) => {
if (res.code >= 200) {
that.recordVisible = false;
that.limitedReview = false;
@ -1253,10 +1240,10 @@
that.getList1();
that.getList3();
that.refreshRecord();
}else{
} else {
this.$message.error(res.msg)
}
}) .catch((err) => {
}).catch((err) => {
console.error(err);
});
},
@ -1267,9 +1254,9 @@
let params = {};
params.record_data = value.record_data;
params.is_testok = value.is_testok;
putTestRecordItem(id,params).then((res) => {
putTestRecordItem(id, params).then((res) => {
if (res.code >= 200) {
subTestRecordItem(id,params).then((res) => {
subTestRecordItem(id, params).then((res) => {
if (res.code >= 200) {
that.recordVisible = false;
that.limitedReview = false;
@ -1281,10 +1268,10 @@
that.refreshRecord();
}
});
}else{
} else {
this.$message.error(res.msg)
}
}) .catch((err) => {
}).catch((err) => {
console.error(err);
});
},
@ -1297,12 +1284,12 @@
this.getList1();
this.getList3();
},
pageRefresh(){
pageRefresh() {
this.reload()
},
},
mounted() {
getUserList({page:0}).then(response => {
getUserList({page: 0}).then(response => {
if (response.data) {
this.userList = response.data
}

View File

@ -2,9 +2,10 @@ from django.db.models import base
from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.develop.views import CleanDataView
from apps.develop.views import CleanDataView, UpdateCuttingView
urlpatterns = [
path('cleandata/', CleanDataView.as_view()),
path('update_cutting/', UpdateCuttingView.as_view())
]

View File

@ -1,4 +1,6 @@
from django.db import transaction
from django.shortcuts import render
from rest_framework.decorators import permission_classes
from rest_framework.views import APIView
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
@ -7,7 +9,8 @@ from apps.mtm.models import Material
from apps.pm.models import ProductionPlan
from apps.sam.models import Order
from apps.wf.models import Ticket
from apps.wpm.models import Operation
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow
from apps.wpm.services import WpmServies
# Create your views here.
class CleanDataView(APIView):
@ -25,4 +28,22 @@ class CleanDataView(APIView):
Inventory.objects.filter(material__type__in=[Material.MA_TYPE_GOOD, Material.MA_TYPE_HALFGOOD]).delete()
Ticket.objects.all().delete(soft=False)
Operation.objects.all().delete()
return Response()
return Response()
class UpdateCuttingView(APIView):
permission_classes = [IsAdminUser]
@transaction.atomic
def post(self, request, format=None):
"""
更新下料清单
"""
for i in WProduct.objects.all():
sp = WproductFlow.objects.filter(wproduct=i).order_by('id').first().subproduction_plan
op_q = OperationMaterial.objects.filter(subproduction_plan=sp, operation__step__id=1, operation__is_submited=True)
op = op_q.first().operation
i.coperation = op
i.save()
WproductFlow.objects.filter(wproduct=i).update(coperation=op)
WpmServies.update_cutting_list_with_operation(op)
return Response()

View File

@ -2,7 +2,7 @@ from django_filters import rest_framework as filters
from apps.mtm.models import Material, Step
from apps.wpm.services import WpmServies
from .models import Operation, WMaterial, WProduct
from .models import Operation, OperationMaterial, WMaterial, WProduct
class WMaterialFilterSet(filters.FilterSet):
@ -33,4 +33,10 @@ class WProductFilterSet(filters.FilterSet):
def filter_tag(self, queryset, name, value):
if value == 'no_scrap':
queryset = queryset.exclude(act_state=WProduct.WPR_ACT_STATE_SCRAP)
return queryset
return queryset
class CuttingFilterSet(filters.FilterSet):
production_plan = filters.NumberFilter(field_name='subproduction_plan__production_plan')
class Meta:
model = OperationMaterial
fields = ['operation', 'subproduction_plan', 'material']

View File

@ -0,0 +1,59 @@
# Generated by Django 3.2.9 on 2022-01-04 08:41
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0042_alter_recordformfield_field_type'),
('wpm', '0043_auto_20211231_1130'),
]
operations = [
migrations.RemoveField(
model_name='operation',
name='use_scrap',
),
migrations.AddField(
model_name='operationmaterial',
name='from_batch',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='源批次'),
),
migrations.AddField(
model_name='operationmaterial',
name='from_material',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='om_fmaterial', to='mtm.material', verbose_name='源物料'),
),
migrations.AddField(
model_name='operationmaterial',
name='use_scrap',
field=models.BooleanField(default=False, verbose_name='是否使用的边角料'),
),
migrations.AddField(
model_name='operationwproduct',
name='ng_sign',
field=models.PositiveSmallIntegerField(blank=True, choices=[(10, '返工'), (20, '返修'), (30, '报废'), (40, '让步接收'), (50, '偏离许可'), (60, '降级使用'), (70, '退回供方'), (80, '召回')], null=True, verbose_name='当时的不合格标记'),
),
migrations.AddField(
model_name='wproduct',
name='coperation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wp_coperation', to='wpm.operation', verbose_name='创建所关联操作'),
),
migrations.AddField(
model_name='wproductflow',
name='coperation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wpf_coperation', to='wpm.operation', verbose_name='创建所关联操作'),
),
migrations.AlterField(
model_name='operationmaterial',
name='material',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='om_material', to='mtm.material', verbose_name='可能产出的产品'),
),
migrations.AlterField(
model_name='wproductflow',
name='operation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wpf_operation', to='wpm.operation', verbose_name='当前操作'),
),
]

View File

@ -96,6 +96,8 @@ class WProduct(CommonAModel):
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_operation')
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_coperation')
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test')
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
@ -144,7 +146,9 @@ class WproductFlow(CommonAModel):
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
on_delete=models.SET_NULL, null=True, blank=True)
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_operation')
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_coperation')
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
on_delete=models.SET_NULL, null=True, blank=True)
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
@ -183,7 +187,6 @@ class Operation(CommonADModel):
生产操作
"""
step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True)
use_scrap = models.BooleanField('是否使用的边角料', default=False)
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
is_submited = models.BooleanField('是否提交', default=False)
@ -196,7 +199,7 @@ class OperationWproduct(BaseModel):
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='ow_subplan')
ng_sign = models.PositiveSmallIntegerField('当时的不合格标记', choices= WProduct.ng_choices, null=True, blank=True)
class Meta:
unique_together = (
('operation','wproduct')
@ -209,7 +212,8 @@ class OperationMaterial(BaseModel):
type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices)
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, null=True, blank=True)
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE,
null=True, blank=True, related_name='om_material')
count = models.PositiveSmallIntegerField('消耗或产出数量', null=True, blank=True)
wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
@ -217,8 +221,12 @@ class OperationMaterial(BaseModel):
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True)
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
use_scrap = models.BooleanField('是否使用的边角料', default=False)
#以下为冷加工下料清单所用字段
from_material = models.ForeignKey(Material, verbose_name='源物料', on_delete=models.CASCADE,
null=True, blank=True, related_name='om_fmaterial')
from_batch = models.CharField('源批次', max_length=100, null=True, blank=True)
count_cut = models.PositiveIntegerField('切裁片数', default=0)
count_real = models.PositiveIntegerField('生产片数', default=0)
count_ok = models.PositiveIntegerField('成品数量', default=0)
@ -226,6 +234,7 @@ class OperationMaterial(BaseModel):
count_podian = models.PositiveIntegerField('破点甩片', default=0)
count_hua = models.PositiveIntegerField('划伤甩片', default=0)
count_other = models.PositiveIntegerField('其他甩片', default=0)
class Meta:
unique_together = (
('operation','material', 'batch')

View File

@ -207,7 +207,7 @@ class OperationCreateSerializer(serializers.Serializer):
class OperationUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Operation
fields =['use_scrap', 'remark']
fields =['remark']
class OperationInitSerializer(serializers.Serializer):
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
@ -350,7 +350,7 @@ class OperationMaterialCreate1Serailizer(serializers.ModelSerializer):
wmaterial = serializers.PrimaryKeyRelatedField(required=True, queryset=WMaterial.objects.all())
class Meta:
model = OperationMaterial
fields = ['operation', 'wmaterial', 'count']
fields = ['operation', 'wmaterial', 'count', 'use_scrap']
def validate(self, attrs):
if attrs['count'] <=0:
@ -376,7 +376,7 @@ class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
subproduction_progress = serializers.PrimaryKeyRelatedField(required=True, queryset=SubProductionProgress.objects.all())
class Meta:
model = OperationMaterial
fields = ['operation', 'subproduction_progress', 'count']
fields = ['operation', 'subproduction_progress', 'count', 'use_scrap']
def create(self, validated_data):
subproduction_progress = validated_data['subproduction_progress']
@ -448,8 +448,8 @@ class WproductTicketListSerializer(serializers.ModelSerializer):
class CuttingListSerializer(serializers.ModelSerializer):
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
material_ = MaterialSimpleSerializer(source='material', read_only=True)
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
from_material_ = MaterialSimpleSerializer(source='from_material', read_only=True)
create_by_ = UserSimpleSerializer(source='operation.create_by', read_only=True)
class Meta:
model = OperationMaterial
fields = '__all__'

View File

@ -154,28 +154,28 @@ class WpmServies(object):
"""
inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN)
outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
for i in inputs:
sp = i.subproduction_plan
i.count_cut = outputs.filter(subproduction_plan=sp).first().count
i.count_real = sp.count_real
i.count_ok = sp.count_ok
wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count()
i.is_cutting = True
i.save()
@classmethod
def update_cutting_list_with_sp(cls, sp:SubProductionPlan):
"""
根据子计划更新下料清单
"""
wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
for i in OperationMaterial.objects.filter(subproduction_plan=sp, is_cutting=True):
i.count_real = sp.count_real
i.count_ok = sp.count_ok
for i in outputs:
if i.use_scrap: # 如果使用了边角料
i.count_cut = 0
i.from_material = SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
subproduction__subplan_subprod=i.subproduction_plan).first().material
else:
input_q = inputs.filter(subproduction_plan=i.subproduction_plan) # 同计划的消耗
i.from_material = input_q.first().material
count_cut = 0
from_batch = ''
for m in input_q:
count_cut = count_cut + m.count
if from_batch and m.batch:
from_batch = from_batch + ';' + m.batch
else:
from_batch = m.batch
i.count_cut = count_cut
i.from_batch = from_batch
wpfs = WproductFlow.objects.filter(subproduction_plan=i.subproduction_plan,
is_lastlog=True, coperation=op)# 筛选本次操作下子计划的产品日志
i.count_real = wpfs.count()
i.count_ok = wpfs.filter(scrap_reason=None).count()
i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()

View File

@ -19,7 +19,7 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from apps.wf.models import Workflow
from apps.wf.serializers import WorkflowSimpleSerializer
from apps.wpm.filters import WMaterialFilterSet, WProductFilterSet
from apps.wpm.filters import CuttingFilterSet, WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
@ -386,7 +386,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
obj.save()
WpmServies.add_wproduct_flow_log(obj, 'scrap')
if obj.step.process.id == 1: #如果是冷加工
WpmServies.update_cutting_list_with_sp(obj.subproduction_plan)
WpmServies.update_cutting_list_with_operation(obj.coperation)
return Response()
# @action(methods=['get'], detail=False, perms_map={'get':'*'})
@ -510,12 +510,13 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
owp['number'] = wpd.number
owp['material'] = wpd.material
owp['subproduction_plan'] = wpd.subproduction_plan
owp['ng_sign'] = wpd.ng_sign
owps.append(OperationWproduct(**owp))
OperationWproduct.objects.bulk_create(owps)
else:
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
# 查询需要填写的自定义表格
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO)
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO, enabled=True)
for i in forms:
opr = OperationRecord()
opr.operation = op
@ -555,11 +556,22 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
step = op.step
if op.is_submited:
raise exceptions.APIException('该操作已提交')
# 校验消耗产出是否正确填写
omis = OperationMaterial.objects.filter(operation=op,
type=SubprodctionMaterial.SUB_MA_TYPE_IN)
sps_omi_l = omis.values_list('subproduction_plan', flat=True)
omos = OperationMaterial.objects.filter(operation=op,
type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
sps_omo_l = omos.filter(use_scrap=False).values_list('subproduction_plan', flat=True)
if set(list(sps_omi_l)) == set(list(sps_omo_l)):
pass
else:
raise exceptions.APIException('消耗与产出不一致')
# 检查自定义表单填写
if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
raise exceptions.APIException('存在自定义表单未填写')
# 更新物料消耗进度
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN):
for i in omis:
# 更新车间物料
i_wmat = i.wmaterial
i_wmat.count = i_wmat.count- i.count
@ -570,7 +582,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
spp.count_real = spp.count_real + i.count
spp.save()
# 更新产出
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
for i in omos:
if not i.subproduction_progress.is_main:
# 更新车间物料产出情况
ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan, material=i.material)
@ -607,24 +619,23 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
elif step.type == Step.STEP_TYPE_DIV:
# 更新物料产出情况
outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
if not outputs.exists():
if not omos.exists():
raise exceptions.APIException('请选择物料产出')
for i in outputs:
for i in omos:
if i.subproduction_progress.is_main:
newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
wpr = dict(material=i.material, step=newstep,
act_state=WProduct.WPR_ACT_STATE_DOWAIT, remark='',
subproduction_plan=i.subproduction_plan, create_by=request.user)
subproduction_plan=i.subproduction_plan,
create_by=request.user, coperation=op)
for x in range(i.count):
ins = WProduct.objects.create(**wpr)
# 添加日志
WpmServies.add_wproduct_flow_log(ins, 'operation_submit')
WpmServies.add_wproduct_flow_log(ins, 'wproduct_create')
# 更新进度
WpmServies.update_subproduction_progress_main(sp=i.subproduction_plan)
elif step.type == Step.STEP_TYPE_COMB:
oms_w = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT,
subproduction_progress__is_main=True)
oms_w = omos.filter(subproduction_progress__is_main=True)
if len(oms_w) == 1:
oms_w = oms_w[0]
# 校验单片数量是否正确, 暂时未写
@ -640,8 +651,9 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
# 更新子计划进度
WpmServies.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, 'operation_submit')
WpmServies.add_wproduct_flow_log(wproduct, 'wproduct_create')
# 隐藏原半成品
wps = WProduct.objects.filter(ow_wproduct__operation = op)
wps.update(is_hidden=True, child=wproduct, update_by=request.user, update_time=timezone.now())
@ -793,9 +805,9 @@ class CuttingListViewSet(ListModelMixin, GenericViewSet):
"""
perms_map={'*':'*'}
queryset = OperationMaterial.objects.select_related('operation',
'subproduction_plan', 'material', 'create_by').filter(operation__step__process__id=1)
'subproduction_plan', 'material', 'operation__create_by').filter(operation__step__id=1, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
serializer_class = CuttingListSerializer
filterset_fields = ['operation', 'subproduction_plan', 'material']
filterset_class = CuttingFilterSet
ordering_fields = ['id']
ordering = ['-id']