Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
52b0f469d9
|
|
@ -29,3 +29,22 @@ export function getEmployee(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//个人离岗说明
|
||||||
|
|
||||||
|
export function getNotWorkList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/hrm/not_work_remark/',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getClockrecordList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/hrm/clock_record/',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -377,3 +377,34 @@ export function deletetechdoc(id, data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//装箱
|
||||||
|
//记录表格字段表
|
||||||
|
|
||||||
|
export function getpackitemList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/mtm/packitem/',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function createpackitem(data) {
|
||||||
|
return request({
|
||||||
|
url: '/mtm/packitem/',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function updatepackitem(id, data) {
|
||||||
|
return request({
|
||||||
|
url: `/mtm/packitem/${id}/`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function deletepackitem(id, data) {
|
||||||
|
return request({
|
||||||
|
url: `/mtm/packitem/${id}/`,
|
||||||
|
method: 'delete',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,223 +1,371 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card>
|
<el-card>
|
||||||
<el-card >
|
<el-card>
|
||||||
<el-descriptions title="物料基本信息" direction="vertical" :column="8" border>
|
<el-descriptions
|
||||||
<el-descriptions-item label="物料编号"> {{materialdetail.number}}</el-descriptions-item>
|
title="物料基本信息"
|
||||||
<el-descriptions-item label="物料名称"> {{materialdetail.name}}</el-descriptions-item>
|
direction="vertical"
|
||||||
<el-descriptions-item label="规格型号" :span="2"> {{materialdetail.specification}}</el-descriptions-item>
|
:column="8"
|
||||||
<el-descriptions-item label="计量单位"> {{materialdetail.unit}} </el-descriptions-item>
|
border
|
||||||
<el-descriptions-item label="数量"> {{materialdetail.count}}</el-descriptions-item>
|
>
|
||||||
</el-descriptions>
|
<el-descriptions-item label="物料编号">
|
||||||
|
{{ materialdetail.number }}</el-descriptions-item
|
||||||
|
>
|
||||||
</el-card>
|
<el-descriptions-item label="物料名称">
|
||||||
|
{{ materialdetail.name }}</el-descriptions-item
|
||||||
|
>
|
||||||
|
<el-descriptions-item label="规格型号" :span="2">
|
||||||
|
{{ materialdetail.specification }}</el-descriptions-item
|
||||||
|
>
|
||||||
|
<el-descriptions-item label="计量单位">
|
||||||
|
{{ materialdetail.unit }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="数量">
|
||||||
|
{{ materialdetail.count }}</el-descriptions-item
|
||||||
|
>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<el-tabs v-model="activeName" type="card">
|
<el-tabs v-model="activeName" type="card">
|
||||||
<el-tab-pane label="供应商" name="5" v-if="this.type==3||this.type==4">
|
<el-tab-pane
|
||||||
|
label="供应商"
|
||||||
|
name="5"
|
||||||
|
v-if="this.type == 3 || this.type == 4"
|
||||||
|
>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="批次" name="3">
|
<el-tab-pane label="批次" name="3">
|
||||||
|
<el-table
|
||||||
|
:data="InventoryList"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
stripe
|
||||||
|
height="460"
|
||||||
|
highlight-current-row
|
||||||
|
>
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column label="物料批次">
|
||||||
|
<template slot-scope="scope">{{ scope.row.batch }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<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
|
<el-table-column label="物料编号">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
:data="InventoryList"
|
scope.row.material_.number
|
||||||
border
|
}}</template>
|
||||||
fit
|
</el-table-column>
|
||||||
stripe
|
<el-table-column label="仓库名称">
|
||||||
height="460"
|
<template slot-scope="scope">{{
|
||||||
highlight-current-row
|
scope.row.warehouse_.name
|
||||||
|
}}</template>
|
||||||
>
|
</el-table-column>
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column label="仓库编号">
|
||||||
<el-table-column label="物料批次">
|
<template slot-scope="scope">{{
|
||||||
<template slot-scope="scope">{{ scope.row.batch }}</template>
|
scope.row.warehouse_.number
|
||||||
</el-table-column>
|
}}</template>
|
||||||
<el-table-column label="物料名称">
|
</el-table-column>
|
||||||
<template slot-scope="scope">{{ scope.row.material_.name }}</template>
|
<el-table-column label="物料总存量">
|
||||||
</el-table-column>
|
<template slot-scope="scope">{{ scope.row.count }}</template>
|
||||||
<el-table-column label="规格型号">
|
</el-table-column>
|
||||||
<template slot-scope="scope">{{ scope.row.material_.specification }}</template>
|
</el-table>
|
||||||
</el-table-column>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-table-column label="物料编号">
|
|
||||||
<template slot-scope="scope">{{
|
|
||||||
scope.row.material_.number
|
|
||||||
}}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="仓库名称">
|
|
||||||
<template slot-scope="scope">{{
|
|
||||||
scope.row.warehouse_.name
|
|
||||||
}}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="仓库编号">
|
|
||||||
<template slot-scope="scope">{{
|
|
||||||
scope.row.warehouse_.number
|
|
||||||
}}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="物料总存量">
|
|
||||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
</el-tab-pane>
|
<el-tab-pane label="关联的订单" name="1">
|
||||||
|
<el-table
|
||||||
<el-tab-pane label="关联的订单" name="1">
|
:data="orderlist"
|
||||||
<el-table
|
border
|
||||||
|
fit
|
||||||
:data="orderlist"
|
stripe
|
||||||
border
|
highlight-current-row
|
||||||
fit
|
height="460"
|
||||||
stripe
|
>
|
||||||
highlight-current-row
|
<el-table-column type="index" width="50" />
|
||||||
height="460"
|
|
||||||
|
<el-table-column label="订单编号" show-overflow-tooltip>
|
||||||
>
|
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||||
<el-table-column type="index" width="50" />
|
</el-table-column>
|
||||||
|
<el-table-column label="客户" show-overflow-tooltip>
|
||||||
<el-table-column label="订单编号" show-overflow-tooltip>
|
<template slot-scope="scope">{{
|
||||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
scope.row.customer_.name
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="所属合同" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.contract_.name
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="产品名称" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.product_.name
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="产品型号" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.product_.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.delivery_date
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.create_time
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="关联的计划" name="2">
|
||||||
|
<el-table
|
||||||
|
:data="productionplanList"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
stripe
|
||||||
|
style="width: 100%"
|
||||||
|
height="460"
|
||||||
|
>
|
||||||
|
<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">{{
|
||||||
|
scope.row.order_.number
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="合同编号">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.order_.contract_.number
|
||||||
|
}}</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.start_date }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="计划完工时间">
|
||||||
|
<template slot-scope="scope">{{ scope.row.end_date }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="交付截止时间">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.order_.delivery_date
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="是否生成子计划">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.is_planed == false">否</el-tag>
|
||||||
|
<el-tag v-if="scope.row.is_planed == true">是</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.create_time
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane
|
||||||
|
label="物料"
|
||||||
|
name="4"
|
||||||
|
v-if="this.type == 1 || this.type == 2"
|
||||||
|
>
|
||||||
|
<el-table
|
||||||
|
:data="wproductList"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
stripe
|
||||||
|
style="width: 100%"
|
||||||
|
height="460"
|
||||||
|
>
|
||||||
|
<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">{{ scope.row.step_.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
actstate_[scope.row.act_state]
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="仓库">
|
||||||
|
<template slot-scope="scope" v-if="scope.row.warehouse_">{{
|
||||||
|
scope.row.warehouse_.name
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="装箱单" name="5" v-if="this.type == 1">
|
||||||
|
<el-button type="primary" icon="el-icon-plus" @click="handleCreate">
|
||||||
|
新增装箱单
|
||||||
|
</el-button>
|
||||||
|
<el-table
|
||||||
|
:data="pickList"
|
||||||
|
border
|
||||||
|
fit
|
||||||
|
stripe
|
||||||
|
style="width: 100%"
|
||||||
|
height="460"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
|
||||||
|
<el-table-column label="名称">
|
||||||
|
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="单位">
|
||||||
|
<template slot-scope="scope">{{ scope.row.unit }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="数量">
|
||||||
|
<template slot-scope="scope" >{{
|
||||||
|
scope.row.count
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
align="center"
|
||||||
|
label="操作"
|
||||||
|
width="220px"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
|
||||||
|
<el-link
|
||||||
|
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit(scope)"
|
||||||
|
>编辑
|
||||||
|
</el-link>
|
||||||
|
|
||||||
|
<el-link
|
||||||
|
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(scope)"
|
||||||
|
>删除
|
||||||
|
</el-link>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="客户" show-overflow-tooltip>
|
</el-table>
|
||||||
<template slot-scope="scope">{{ scope.row.customer_.name }}</template>
|
<el-dialog
|
||||||
</el-table-column>
|
:visible.sync="dialogVisible"
|
||||||
<el-table-column label="所属合同" show-overflow-tooltip>
|
:close-on-click-modal="false"
|
||||||
<template slot-scope="scope">{{ scope.row.contract_.name }}</template>
|
:title="dialogType === 'edit' ? '编辑装箱单' : '新增装箱单'"
|
||||||
</el-table-column>
|
>
|
||||||
<el-table-column label="产品名称" show-overflow-tooltip>
|
<el-form
|
||||||
<template slot-scope="scope">{{ scope.row.product_.name }}</template>
|
ref="Form"
|
||||||
</el-table-column>
|
:model="packitem"
|
||||||
<el-table-column label="产品型号" show-overflow-tooltip>
|
label-width="100px"
|
||||||
<template slot-scope="scope">{{ scope.row.product_.specification }}</template>
|
label-position="right"
|
||||||
</el-table-column>
|
:rules="rule1"
|
||||||
<el-table-column label="产品数量" >
|
>
|
||||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
<el-form-item label="物料"
|
||||||
</el-table-column>
|
prop="material"
|
||||||
<el-table-column label="交货日期" >
|
|
||||||
<template slot-scope="scope">{{ scope.row.delivery_date }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="创建时间" >
|
|
||||||
<template slot-scope="scope">{{ scope.row.create_time }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="关联的计划" name="2">
|
|
||||||
<el-table
|
|
||||||
:data="productionplanList"
|
|
||||||
border
|
|
||||||
fit
|
|
||||||
stripe
|
|
||||||
style="width: 100%"
|
|
||||||
height="460"
|
|
||||||
|
|
||||||
>
|
|
||||||
<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">{{ scope.row.order_.number }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="合同编号" >
|
|
||||||
<template slot-scope="scope">{{ scope.row.order_.contract_.number }}</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.start_date }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="计划完工时间" >
|
|
||||||
<template slot-scope="scope">{{ scope.row.end_date }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="交付截止时间" >
|
|
||||||
<template slot-scope="scope">{{ scope.row.order_.delivery_date }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column label="是否生成子计划" >
|
|
||||||
<template slot-scope="scope" >
|
|
||||||
<el-tag v-if="scope.row.is_planed==false">否</el-tag>
|
|
||||||
<el-tag v-if="scope.row.is_planed==true">是</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="创建时间">
|
|
||||||
<template slot-scope="scope">{{ scope.row.create_time }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="物料" name="4" v-if="this.type==1||this.type==2">
|
|
||||||
<el-table
|
|
||||||
:data="wproductList"
|
|
||||||
border
|
|
||||||
fit
|
|
||||||
stripe
|
|
||||||
style="width: 100%"
|
|
||||||
height="460"
|
|
||||||
|
|
||||||
>
|
>
|
||||||
|
<el-select v-model="packitem.material" @change="selectmaterial" >
|
||||||
<el-table-column type="index" width="50" />
|
<el-option
|
||||||
|
v-for="item in materialoptions"
|
||||||
|
:key="item.id"
|
||||||
<el-table-column label="玻璃编号" >
|
:value="item.id"
|
||||||
<template slot-scope="scope" >{{ scope.row.number }}</template>
|
:label="item.name"
|
||||||
</el-table-column>
|
>
|
||||||
|
</el-option>
|
||||||
<el-table-column label="所在子工序">
|
</el-select>
|
||||||
<template slot-scope="scope" >{{
|
</el-form-item>
|
||||||
scope.row.step_.name
|
<el-form-item label="名称" prop="name">
|
||||||
}}</template>
|
<el-input v-model="packitem.name" placeholder="名称" />
|
||||||
</el-table-column>
|
</el-form-item>
|
||||||
<el-table-column label="状态" >
|
<el-form-item label="单位" prop="unit">
|
||||||
<template slot-scope="scope">{{
|
<el-input v-model="packitem.unit" placeholder="单位" />
|
||||||
actstate_[scope.row.act_state]
|
</el-form-item>
|
||||||
}}</template>
|
<el-form-item label="型号" prop="specification">
|
||||||
</el-table-column>
|
<el-input v-model="packitem.specification" placeholder="型号" />
|
||||||
<el-table-column label="仓库" >
|
</el-form-item>
|
||||||
<template slot-scope="scope" v-if=" scope.row.warehouse_">{{ scope.row.warehouse_.name }}</template>
|
<el-form-item label="数量" prop="count">
|
||||||
</el-table-column>
|
<el-input-number
|
||||||
warehouse_
|
style="width: 100%"
|
||||||
|
v-model="packitem.count"
|
||||||
</el-table>
|
:step="1"
|
||||||
</el-tab-pane>
|
:min="0"
|
||||||
</el-tabs>
|
step-strictly
|
||||||
|
placeholder="数量"
|
||||||
|
></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="sort">
|
||||||
|
<el-input-number
|
||||||
|
v-model="packitem.sort"
|
||||||
|
:min="1"
|
||||||
|
placeholder="排序"
|
||||||
|
></el-input-number>
|
||||||
|
</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>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import checkPermission from "@/utils/permission";
|
import checkPermission from "@/utils/permission";
|
||||||
import vueJsonEditor from "vue-json-editor";
|
import vueJsonEditor from "vue-json-editor";
|
||||||
import {upUrl, upHeaders} from "@/api/file";
|
import { upUrl, upHeaders } from "@/api/file";
|
||||||
import {getProductionplanList } from "@/api/pm";
|
import { getProductionplanList } from "@/api/pm";
|
||||||
import {getmaterialbatchList} from "@/api/inm";
|
import { getmaterialbatchList } from "@/api/inm";
|
||||||
import {getOrderList } from "@/api/sam";
|
import { getOrderList } from "@/api/sam";
|
||||||
import {getMaterial } from "@/api/mtm";
|
import { getMaterial,getpackitemList,createpackitem,updatepackitem,deletepackitem,getMaterialList } from "@/api/mtm";
|
||||||
import {getwproductList } from "@/api/wpm";
|
import { getwproductList } from "@/api/wpm";
|
||||||
|
|
||||||
import { upFile } from "@/api/file";
|
|
||||||
import {genTree} from "@/utils";
|
|
||||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
|
||||||
import Treeselect from '@riophae/vue-treeselect'
|
|
||||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
|
||||||
|
|
||||||
export default {
|
import { upFile } from "@/api/file";
|
||||||
components: {Pagination, vueJsonEditor, Treeselect},
|
import { genTree } from "@/utils";
|
||||||
data() {
|
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||||
return {
|
import Treeselect from "@riophae/vue-treeselect";
|
||||||
materialdetail:"",
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||||
orderlist:[],
|
const defaultpackitem = {
|
||||||
wproductList:[],
|
name:"",
|
||||||
productionplanList:[],
|
unit:"",
|
||||||
InventoryList:[],
|
specification:"",
|
||||||
activeName:'3',
|
};
|
||||||
actstate_: {
|
export default {
|
||||||
|
components: { Pagination, vueJsonEditor, Treeselect },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
materialdetail: "",
|
||||||
|
orderlist: [],
|
||||||
|
wproductList: [],
|
||||||
|
productionplanList: [],
|
||||||
|
InventoryList: [],
|
||||||
|
activeName: "3",
|
||||||
|
packitem:defaultpackitem,
|
||||||
|
dialogVisible: false,
|
||||||
|
dialogType: "new",
|
||||||
|
pickList:[],
|
||||||
|
materialoptions:[],
|
||||||
|
actstate_: {
|
||||||
6: "待复检",
|
6: "待复检",
|
||||||
10: "操作进行中",
|
10: "操作进行中",
|
||||||
20: "待检验",
|
20: "待检验",
|
||||||
|
|
@ -229,67 +377,162 @@
|
||||||
26: "待夹层检验",
|
26: "待夹层检验",
|
||||||
70: "报废",
|
70: "报废",
|
||||||
},
|
},
|
||||||
};
|
rule1: {
|
||||||
|
name: [{required: true, message: "请输入名称", trigger: "blur"}],
|
||||||
|
unit: [{required: true, message: "请输入单位", trigger: "blur"}],
|
||||||
|
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {},
|
||||||
|
created() {
|
||||||
|
this.material = this.$route.params.id;
|
||||||
|
this.type = this.$route.params.type;
|
||||||
|
this.getMaterialist()
|
||||||
|
this.getMaterial();
|
||||||
|
this.getpickList();
|
||||||
|
this.getOrderList();
|
||||||
|
this.getplanList();
|
||||||
|
this.getmaterialbatchList();
|
||||||
|
this.getwproductList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//新增装箱单
|
||||||
|
getMaterialist()
|
||||||
|
{
|
||||||
|
getMaterialList({ pageoff: true,type:3 }).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.materialoptions = response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
},
|
},
|
||||||
computed: {},
|
|
||||||
watch: {},
|
selectmaterial(selval){
|
||||||
created() {
|
getMaterial(selval).then((response) => {
|
||||||
this.material = this.$route.params.id;
|
if (response.data) {
|
||||||
this.type=this.$route.params.type;
|
this.packitem.name = response.data.name;
|
||||||
this.getMaterial();
|
this.packitem.unit = response.data.unit;
|
||||||
|
this.packitem.specification = response.data.specification;
|
||||||
this.getOrderList();
|
|
||||||
this.getplanList();
|
|
||||||
this.getmaterialbatchList();
|
|
||||||
this.getwproductList();
|
}
|
||||||
|
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
|
|
||||||
getMaterial(){
|
handleCreate() {
|
||||||
|
this.packitem = Object.assign({}, defaultpackitem);
|
||||||
|
this.dialogType = "new";
|
||||||
|
this.dialogVisible = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs["Form"].clearValidate();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleEdit(scope) {
|
||||||
|
this.packitem = 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 deletepackitem(scope.row.id);
|
||||||
|
this.getpickList();
|
||||||
|
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) {
|
||||||
|
updatepackitem(this.packitem.id, this.packitem).then((res) => {
|
||||||
|
if (res.code >= 200) {
|
||||||
|
this.getpickList();
|
||||||
|
this.dialogVisible = false;
|
||||||
|
this.$message.success("成功");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.packitem.product=this.material;
|
||||||
|
createpackitem(this.packitem).then((res) => {
|
||||||
|
if (res.code >= 200) {
|
||||||
|
this.getpickList();
|
||||||
|
this.dialogVisible = false;
|
||||||
|
this.$message.success("成功");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getpickList()
|
||||||
|
{
|
||||||
|
getpackitemList({ product: this.material, page: 0 }).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.pickList = response.data; //zhuangxiang信息
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getMaterial() {
|
||||||
getMaterial(this.material).then((response) => {
|
getMaterial(this.material).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
this.materialdetail = response.data;//物料基本信息
|
this.materialdetail = response.data; //物料基本信息
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getOrderList(){
|
|
||||||
getOrderList({material:this.material,page:0}).then((response) => {
|
|
||||||
if (response.data) {
|
|
||||||
this.orderlist = response.data;//物料关联的订单
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getplanList() {
|
|
||||||
getProductionplanList({material:this.material,page:0}).then((response) => {
|
|
||||||
if (response.data) {
|
|
||||||
this.productionplanList = response.data;//物料关联计划
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getOrderList() {
|
||||||
|
getOrderList({ material: this.material, page: 0 }).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.orderlist = response.data; //物料关联的订单
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getplanList() {
|
||||||
|
getProductionplanList({ material: this.material, page: 0 }).then(
|
||||||
|
(response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.productionplanList = response.data; //物料关联计划
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
getmaterialbatchList() {
|
getmaterialbatchList() {
|
||||||
|
getmaterialbatchList({ material: this.material, page: 0 }).then(
|
||||||
|
(response) => {
|
||||||
getmaterialbatchList({material:this.material,page:0}).then((response) => {
|
if (response.data) {
|
||||||
if (response.data) {
|
this.InventoryList = response.data;
|
||||||
this.InventoryList = response.data;
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getwproductList() {
|
||||||
|
getwproductList({ material: this.material, page: 0 }).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.wproductList = response.data; //半成品
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getwproductList(){
|
},
|
||||||
getwproductList({material:this.material,page:0}).then((response) => {
|
};
|
||||||
if (response.data) {
|
|
||||||
this.wproductList = response.data;//半成品
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="子工序类型" prop="type">
|
<el-form-item label="子工序类型" prop="type">
|
||||||
<el-select style="width: 100%" v-model="step.type" placeholder="请选择">
|
<el-select style="width: 100%" v-model="step.type" placeholder="请选择">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in typeoption"
|
v-for="item in typeoption"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
|
|
@ -411,6 +411,7 @@
|
||||||
const defaultstep = {
|
const defaultstep = {
|
||||||
name: "",
|
name: "",
|
||||||
number: "",
|
number: "",
|
||||||
|
type:null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultrecordform = {
|
const defaultrecordform = {
|
||||||
|
|
@ -486,15 +487,15 @@
|
||||||
'selects': '多选',
|
'selects': '多选',
|
||||||
},
|
},
|
||||||
typeoption: [{
|
typeoption: [{
|
||||||
value: '1',
|
value: 1,
|
||||||
label: '常规'
|
label: '常规'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '2',
|
value: 2,
|
||||||
label: '分割'
|
label: '分割'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '3',
|
value: 3,
|
||||||
label: '结合'
|
label: '结合'
|
||||||
}],
|
}],
|
||||||
fieldtypeoptions: [{
|
fieldtypeoptions: [{
|
||||||
|
|
@ -684,7 +685,7 @@
|
||||||
recordformLists()
|
recordformLists()
|
||||||
{
|
{
|
||||||
this.listQueryrecordform.step=this.stepid;
|
this.listQueryrecordform.step=this.stepid;
|
||||||
this.listQueryrecordform.type=1;
|
this.listQueryrecordform.type=10;
|
||||||
getrecordformList(this.listQueryrecordform).then((response) => {
|
getrecordformList(this.listQueryrecordform).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
this.recordformList = response.data;
|
this.recordformList = response.data;
|
||||||
|
|
|
||||||
|
|
@ -2,154 +2,149 @@
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card>
|
<el-card>
|
||||||
<el-tabs type="border-card">
|
<el-tabs type="border-card">
|
||||||
<el-tab-pane label="今日到岗">
|
<el-tab-pane label="今日到岗">
|
||||||
<el-table
|
<el-table
|
||||||
|
:data="userList.results"
|
||||||
:data="userList.results"
|
style="width: 100%; margin-top: 6px"
|
||||||
style="width: 100%; margin-top: 6px"
|
highlight-current-row
|
||||||
highlight-current-row
|
row-key="id"
|
||||||
row-key="id"
|
height="100"
|
||||||
height="100"
|
stripe
|
||||||
stripe
|
border
|
||||||
border
|
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
>
|
||||||
>
|
<el-table-column type="index" width="50" label="序号" />
|
||||||
<el-table-column type="index" width="50" label="序号" />
|
<el-table-column align="center" label="工号">
|
||||||
<el-table-column align="center" label="工号">
|
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
</el-table-column>
|
||||||
</el-table-column>
|
<el-table-column align="center" label="姓名">
|
||||||
<el-table-column align="center" label="姓名">
|
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
</el-table-column>
|
||||||
</el-table-column>
|
<el-table-column align="center" label="到岗情况">
|
||||||
<el-table-column align="center" label="到岗情况">
|
<template slot-scope="scope">
|
||||||
<template slot-scope="scope">
|
<el-tag type="success" v-if="scope.row.is_atwork">在岗</el-tag>
|
||||||
<el-tag type="success" v-if="scope.row.is_atwork">在岗</el-tag>
|
|
||||||
|
|
||||||
<el-tag type="danger" v-else>离岗</el-tag>
|
<el-tag type="danger" v-else>离岗</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="离岗备注">
|
<el-table-column align="center" label="离岗备注">
|
||||||
<template slot-scope="scope">{{ scope.row.not_work_remark }}</template>
|
<template slot-scope="scope">{{
|
||||||
</el-table-column>
|
scope.row.not_work_remark
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column align="header-center" label="部门">
|
<el-table-column align="header-center" label="部门">
|
||||||
<template v-if="scope.row.dept_" slot-scope="scope">{{
|
<template v-if="scope.row.dept_" slot-scope="scope">{{
|
||||||
scope.row.dept_.name
|
scope.row.dept_.name
|
||||||
}}</template>
|
}}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column align="center" label="操作" fixed="right">
|
||||||
align="center"
|
<template slot-scope="scope">
|
||||||
label="操作"
|
<el-link
|
||||||
fixed="right"
|
type="primary"
|
||||||
|
v-if="scope.row.is_atwork == false"
|
||||||
>
|
@click="handlestopwork(scope)"
|
||||||
<template slot-scope="scope">
|
>离岗说明
|
||||||
<el-link
|
</el-link>
|
||||||
type="primary"
|
</template>
|
||||||
v-if="scope.row.is_atwork==false"
|
</el-table-column>
|
||||||
@click="handlestopwork(scope)"
|
</el-table>
|
||||||
>离岗说明
|
|
||||||
</el-link>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination
|
|
||||||
v-show="userList.count > 0"
|
|
||||||
:total="userList.count"
|
|
||||||
:page.sync="listQuery.page"
|
|
||||||
:limit.sync="listQuery.page_size"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
title="离岗备注"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="Form"
|
|
||||||
:model="stopwork"
|
|
||||||
label-width="100px"
|
|
||||||
label-position="right"
|
|
||||||
|
|
||||||
>
|
|
||||||
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input type="textarea" v-model="stopwork.not_work_remark" placeholder="备注" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
<div style="text-align: right">
|
|
||||||
<el-button type="danger" @click="dialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="smtconfirm()">确认</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="到岗统计">
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
|
<pagination
|
||||||
<span class="demonstration">年、月</span>
|
v-show="userList.count > 0"
|
||||||
<el-date-picker
|
:total="userList.count"
|
||||||
v-model="value2"
|
:page.sync="listQuery.page"
|
||||||
type="month"
|
:limit.sync="listQuery.page_size"
|
||||||
placeholder="选择年月">
|
@pagination="getList"
|
||||||
</el-date-picker>
|
/>
|
||||||
<el-button type="primary" @click="submit">查询</el-button>
|
|
||||||
</div>
|
<el-dialog
|
||||||
<el-row>
|
:visible.sync="dialogVisible"
|
||||||
<el-col :span="12">
|
:close-on-click-modal="false"
|
||||||
<el-table
|
title="离岗备注"
|
||||||
|
>
|
||||||
:data="atworkList"
|
<el-form
|
||||||
style="width: 100%; margin-top: 6px"
|
ref="Form"
|
||||||
highlight-current-row
|
:model="stopwork"
|
||||||
row-key="id"
|
label-width="100px"
|
||||||
height="680"
|
label-position="right"
|
||||||
stripe
|
>
|
||||||
border
|
<el-form-item label="备注" prop="remark">
|
||||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
<el-input
|
||||||
>
|
type="textarea"
|
||||||
<el-table-column type="index" width="50" label="序号" />
|
v-model="stopwork.not_work_remark"
|
||||||
<el-table-column align="center" label="工号">
|
placeholder="备注"
|
||||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
/>
|
||||||
</el-table-column>
|
</el-form-item>
|
||||||
<el-table-column align="center" label="姓名">
|
</el-form>
|
||||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
<div style="text-align: right">
|
||||||
</el-table-column>
|
<el-button type="danger" @click="dialogVisible = false"
|
||||||
|
>取消</el-button
|
||||||
<el-table-column align="header-center" label="部门">
|
>
|
||||||
<template slot-scope="scope">{{ scope.row.dept_name }}</template>
|
<el-button type="primary" @click="smtconfirm()">确认</el-button>
|
||||||
</el-table-column>
|
</div>
|
||||||
<el-table-column align="center" label="出勤天数">
|
</el-dialog>
|
||||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
</el-tab-pane>
|
||||||
</el-table-column>
|
<el-tab-pane label="到岗统计">
|
||||||
<el-table-column align="center" label="应到天数">
|
<el-row>
|
||||||
<template slot-scope="scope">{{ scope.row.count_workday }}</template>
|
<el-col :span="12">
|
||||||
</el-table-column>
|
<div class="container">
|
||||||
|
<span class="demonstration">年、月</span>
|
||||||
|
<el-date-picker
|
||||||
</el-table>
|
v-model="value2"
|
||||||
</el-col>
|
type="month"
|
||||||
<el-col :span="12">
|
placeholder="选择年月"
|
||||||
<el-calendar >
|
>
|
||||||
|
</el-date-picker>
|
||||||
<template
|
<el-button type="primary" @click="submit">查询</el-button>
|
||||||
slot="dateCell"
|
</div>
|
||||||
slot-scope="{date, data}">
|
<el-table
|
||||||
<p>
|
:data="atworkList"
|
||||||
{{ data.day.split('-').slice(1).join('-') }}<br /> {{dealMyDate(data.day)}}
|
style="width: 100%; margin-top: 6px"
|
||||||
</p>
|
highlight-current-row
|
||||||
</template>
|
row-key="id"
|
||||||
</el-calendar>
|
height="680"
|
||||||
</el-col>
|
stripe
|
||||||
</el-row>
|
border
|
||||||
</el-tab-pane>
|
@current-change="handleCurrentChange"
|
||||||
|
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||||
</el-tabs>
|
>
|
||||||
|
<el-table-column type="index" width="50" label="序号" />
|
||||||
|
<el-table-column align="center" label="工号">
|
||||||
|
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="姓名">
|
||||||
|
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column align="header-center" label="部门">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.dept_name
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="出勤天数">
|
||||||
|
<template slot-scope="scope">{{ scope.row.count }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="应到天数">
|
||||||
|
<template slot-scope="scope">{{
|
||||||
|
scope.row.count_workday
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-calendar v-model="value">
|
||||||
|
<template slot="dateCell" slot-scope="{ date, data }">
|
||||||
|
<p>
|
||||||
|
{{ data.day.split("-").slice(1).join("-") }}<br />
|
||||||
|
{{ dealMyDate(data.day) }}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</el-calendar>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -181,9 +176,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { getEmployeeList } from "@/api/employee";
|
import { getEmployeeList } from "@/api/employee";
|
||||||
import checkPermission from "@/utils/permission";
|
import checkPermission from "@/utils/permission";
|
||||||
import { notWork } from "@/api/hrm";
|
import { notWork, getNotWorkList ,getClockrecordList} from "@/api/hrm";
|
||||||
|
|
||||||
import {getatwork } from "@/api/srm";
|
import { getatwork } from "@/api/srm";
|
||||||
import { upUrl, upHeaders } from "@/api/file";
|
import { upUrl, upHeaders } from "@/api/file";
|
||||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||||
import Treeselect from "@riophae/vue-treeselect";
|
import Treeselect from "@riophae/vue-treeselect";
|
||||||
|
|
@ -195,89 +190,114 @@ export default {
|
||||||
return {
|
return {
|
||||||
userList: { count: 0 },
|
userList: { count: 0 },
|
||||||
atworkList: [],
|
atworkList: [],
|
||||||
stopwork:{not_work_remark:""},
|
stopwork: { not_work_remark: "" },
|
||||||
value3:null,
|
value3: null,
|
||||||
value2:null,
|
value2: null,
|
||||||
listLoading: true,
|
listLoading: true,
|
||||||
dialogVisible:false,
|
dialogVisible: false,
|
||||||
stopworkID:null,
|
stopworkID: null,
|
||||||
|
notworkList: "",
|
||||||
listQuery: {
|
listQuery: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20,
|
page_size: 20,
|
||||||
},
|
},
|
||||||
resDate: [
|
resDate: [
|
||||||
{"date":"2022-02-20","content":"放假"},
|
{ date: "2022-02-20", content: "放假" },
|
||||||
{"date":"2022-02-26","content":"去交电费"},
|
{ date: "2022-02-26", content: "去交电费" },
|
||||||
{"date":"2022-02-25","content":"去学习vue"}
|
{ date: "2022-02-25", content: "去学习vue" },
|
||||||
],
|
],
|
||||||
atworkDate:{year:null,month:null},
|
atworkDate: { year: null, month: null },
|
||||||
|
value: new Date(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
watch: {},
|
watch: {},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkPermission,
|
checkPermission,
|
||||||
//今日到岗
|
//今日到岗
|
||||||
getList() {
|
getList() {
|
||||||
this.listQuery.fields='number,name,is_atwork,dept_,id,not_work_remark';
|
this.listQuery.fields = "number,name,is_atwork,dept_,id,not_work_remark";
|
||||||
getEmployeeList(this.listQuery).then((response) => {
|
getEmployeeList(this.listQuery).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
this.userList = response.data;
|
this.userList = response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handlestopwork(scope)
|
handlestopwork(scope) {
|
||||||
{
|
this.dialogVisible = true;
|
||||||
this.dialogVisible=true;
|
this.stopworkID = scope.row.id;
|
||||||
this.stopworkID=scope.row.id;
|
},
|
||||||
|
handleCurrentChange(row) {
|
||||||
|
this.resDate=[],
|
||||||
|
getNotWorkList({page:0,user:row.user_id}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
response.data.forEach((item) => {
|
||||||
|
this.resDate.push({
|
||||||
|
data: item.not_work_date,
|
||||||
|
content: item.remark,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getClockrecordList({page:0,create_by:row.user_id}).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
|
||||||
|
response.data.forEach((item) => {
|
||||||
|
|
||||||
|
|
||||||
|
var curTime=(item.update_time).substring(0,10)
|
||||||
|
console.log(curTime);
|
||||||
|
this.resDate.push({
|
||||||
|
data: curTime,
|
||||||
|
content: "在岗",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
//离职备注提交
|
//离职备注提交
|
||||||
smtconfirm()
|
smtconfirm() {
|
||||||
{
|
|
||||||
console.log(this.stopwork);
|
notWork(this.stopworkID, this.stopwork).then((res) => {
|
||||||
notWork(this.stopworkID, this.stopwork).then((res) => {
|
if (res.code >= 200) {
|
||||||
if (res.code >= 200) {
|
this.$message.success("离职备注提交成功!");
|
||||||
this.$message.success("离职备注提交成功!");
|
this.dialogVisible = false;
|
||||||
this.dialogVisible=false;
|
this.getList();
|
||||||
this.getList();
|
}
|
||||||
}
|
});
|
||||||
})
|
|
||||||
|
|
||||||
},
|
},
|
||||||
//到岗统计
|
//到岗统计
|
||||||
|
|
||||||
submit()
|
submit() {
|
||||||
{
|
this.atworkDate.year = this.value2.getFullYear();
|
||||||
|
this.atworkDate.month = this.value2.getMonth() + 1;
|
||||||
this.atworkDate.year=this.value2.getFullYear();
|
this.value = this.value2;
|
||||||
this.atworkDate.month=this.value2.getMonth()+1;
|
(this.resDate = []),
|
||||||
|
|
||||||
getatwork(this.atworkDate).then((response) => {
|
getatwork(this.atworkDate).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
this.atworkList = response.data;
|
this.atworkList = response.data;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//考勤日历
|
//考勤日历
|
||||||
dealMyDate(v) {
|
dealMyDate(v) {
|
||||||
console.log(v)
|
|
||||||
let len = this.resDate.length
|
let len = this.resDate.length;
|
||||||
let res = ""
|
let res = "";
|
||||||
for(let i=0; i<len; i++){
|
for (let i = 0; i < len; i++) {
|
||||||
if(this.resDate[i].date == v) {
|
if (this.resDate[i].data == v) {
|
||||||
res = this.resDate[i].content
|
res = this.resDate[i].content;
|
||||||
break
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -192,33 +192,29 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="设备状态">
|
<el-table-column label="设备状态">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div v-if="scope.row.equip_.type === 2">
|
<div v-if="scope.row.type===2">
|
||||||
<el-tag
|
<el-tag v-if="scope.row.state===40" type="danger">
|
||||||
v-if="scope.row.equip_.state === 40"
|
禁用
|
||||||
type="danger"
|
</el-tag>
|
||||||
>
|
<el-tag v-else type="success">
|
||||||
禁用
|
合格
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tag v-else type="success"> 合格 </el-tag>
|
</div>
|
||||||
</div>
|
<div v-else>
|
||||||
<div v-else>
|
<el-tag v-if="scope.row.state===10" type="success">
|
||||||
<el-tag v-if="scope.row.state === 10" type="success">
|
{{ state_[scope.row.state] }}
|
||||||
{{ state_[scope.row.state] }}
|
</el-tag>
|
||||||
</el-tag>
|
<el-tag v-else-if="scope.row.state===20">
|
||||||
<el-tag v-else-if="scope.row.state === 20">
|
{{ state_[scope.row.state] }}
|
||||||
{{ state_[scope.row.state] }}
|
</el-tag>
|
||||||
</el-tag>
|
<el-tag v-else-if="scope.row.state===30" type="warning">
|
||||||
<el-tag v-else-if="scope.row.state === 30" type="warning">
|
{{ state_[scope.row.state] }}
|
||||||
{{ state_[scope.row.state] }}
|
</el-tag>
|
||||||
</el-tag>
|
<el-tag v-else type="danger">
|
||||||
<el-tag v-else type="danger">
|
{{ state_[scope.row.state] }}
|
||||||
{{ state_[scope.row.state] }}
|
</el-tag>
|
||||||
</el-tag>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ state_[scope.row.state] }}</template
|
|
||||||
>
|
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="设备编号">
|
<el-table-column label="设备编号">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,38 @@
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
from apps.hrm.models import ClockRecord, Employee
|
from apps.hrm.models import ClockRecord, Employee, NotWorkRemark
|
||||||
from utils.mixins import DynamicFieldsFilterMixin
|
from utils.mixins import DynamicFieldsFilterMixin
|
||||||
|
|
||||||
class ClockRecordFilterSet(filters.FilterSet):
|
class ClockRecordFilterSet(filters.FilterSet):
|
||||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||||
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
|
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
|
||||||
|
year = filters.NumberFilter(method='filter_year')
|
||||||
|
month = filters.NumberFilter(method='filter_month')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ClockRecord
|
model = ClockRecord
|
||||||
fields = ['create_by', 'create_time_start', 'create_time_end']
|
fields = ['create_by', 'create_time_start', 'create_time_end', 'year', 'month']
|
||||||
|
|
||||||
|
def filter_year(self, queryset, name, value):
|
||||||
|
return queryset.filter(create_time_date__year=value)
|
||||||
|
|
||||||
|
def filter_month(self, queryset, name, value):
|
||||||
|
return queryset.filter(create_time_date__month=value)
|
||||||
|
|
||||||
class EmployeeFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
class EmployeeFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Employee
|
model = Employee
|
||||||
fields = ['job_state']
|
fields = ['job_state']
|
||||||
|
|
||||||
|
|
||||||
|
class NotWorkRemarkFilterSet(filters.FilterSet):
|
||||||
|
year = filters.NumberFilter(method='filter_year')
|
||||||
|
month = filters.NumberFilter(method='filter_month')
|
||||||
|
class Meta:
|
||||||
|
model = NotWorkRemark
|
||||||
|
fields = ['year', 'month', 'user']
|
||||||
|
|
||||||
|
def filter_year(self, queryset, name, value):
|
||||||
|
return queryset.filter(not_work_date__year=value)
|
||||||
|
|
||||||
|
def filter_month(self, queryset, name, value):
|
||||||
|
return queryset.filter(not_work_date__month=value)
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 03:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hrm', '0007_auto_20220218_0843'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='notworkremark',
|
||||||
|
name='day',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='notworkremark',
|
||||||
|
name='month',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='notworkremark',
|
||||||
|
name='year',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='notworkremark',
|
||||||
|
name='not_work_date',
|
||||||
|
field=models.DateField(default=django.utils.timezone.now, verbose_name='未打卡日期'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -44,9 +44,7 @@ class NotWorkRemark(CommonAModel):
|
||||||
"""
|
"""
|
||||||
离岗说明
|
离岗说明
|
||||||
"""
|
"""
|
||||||
year = models.PositiveSmallIntegerField('年', default=2022)
|
not_work_date = models.DateField('未打卡日期')
|
||||||
month = models.PositiveSmallIntegerField('月', default=2)
|
|
||||||
day = models.PositiveSmallIntegerField('日', default=1)
|
|
||||||
user = models.ForeignKey(User, verbose_name='用户', on_delete=models.CASCADE)
|
user = models.ForeignKey(User, verbose_name='用户', on_delete=models.CASCADE)
|
||||||
remark = models.CharField('未打卡说明', null=True, blank=True, max_length=200)
|
remark = models.CharField('未打卡说明', null=True, blank=True, max_length=200)
|
||||||
|
|
||||||
|
|
@ -58,4 +56,6 @@ class ClockRecord(CommonADModel):
|
||||||
type_choice = (
|
type_choice = (
|
||||||
(ClOCK_WORK1, '上班打卡'),
|
(ClOCK_WORK1, '上班打卡'),
|
||||||
)
|
)
|
||||||
type = models.PositiveSmallIntegerField('打卡类型', choices=type_choice, default=ClOCK_WORK1)
|
type = models.PositiveSmallIntegerField('打卡类型', choices=type_choice, default=ClOCK_WORK1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from utils.mixins import DynamicFieldsSerializerMixin
|
from utils.mixins import DynamicFieldsSerializerMixin
|
||||||
from .models import ClockRecord, Employee
|
from .models import ClockRecord, Employee, NotWorkRemark
|
||||||
from apps.system.serializers import OrganizationSimpleSerializer, UserListSerializer, UserSimpleSerializer
|
from apps.system.serializers import OrganizationSimpleSerializer, UserListSerializer, UserSimpleSerializer
|
||||||
from django.db.models.query import Prefetch
|
from django.db.models.query import Prefetch
|
||||||
|
|
||||||
|
|
@ -30,3 +30,8 @@ class ClockRecordListSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ClockRecord
|
model = ClockRecord
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
class NotWorkRemarkListSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = NotWorkRemark
|
||||||
|
fields = '__all__'
|
||||||
|
|
@ -10,7 +10,7 @@ def update_all_employee_not_atwork():
|
||||||
"""
|
"""
|
||||||
将所有员工设为非在岗状态
|
将所有员工设为非在岗状态
|
||||||
"""
|
"""
|
||||||
Employee.objects.all().update(is_atwork=False, last_check_time = None)
|
Employee.objects.all().update(is_atwork=False, last_check_time = None, not_work_remark=None)
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def update_all_user_facedata_cache():
|
def update_all_user_facedata_cache():
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
from django.db.models import base
|
from django.db.models import base
|
||||||
from rest_framework import urlpatterns
|
from rest_framework import urlpatterns
|
||||||
from apps.hrm.views import ClockRecordViewSet, EmployeeViewSet, FaceLogin
|
from apps.hrm.views import ClockRecordViewSet, EmployeeViewSet, FaceLogin, NotWorkRemarkViewSet
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register('employee', EmployeeViewSet, basename='employee')
|
router.register('employee', EmployeeViewSet, basename='employee')
|
||||||
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
|
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
|
||||||
|
router.register('not_work_remark', NotWorkRemarkViewSet, basename='not_work_reamrk')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('facelogin/', FaceLogin.as_view()),
|
path('facelogin/', FaceLogin.as_view()),
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ from django.utils import timezone
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
||||||
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
|
from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin
|
||||||
from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet
|
from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet, NotWorkRemarkFilterSet
|
||||||
from apps.hrm.services import HRMService
|
from apps.hrm.services import HRMService
|
||||||
from apps.hrm.tasks import update_all_user_facedata_cache
|
from apps.hrm.tasks import update_all_user_facedata_cache
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||||
from apps.hrm.models import ClockRecord, Employee, NotWorkRemark
|
from apps.hrm.models import ClockRecord, Employee, NotWorkRemark
|
||||||
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer
|
from apps.hrm.serializers import ClockRecordListSerializer, EmployeeNotWorkRemarkSerializer, EmployeeSerializer, FaceClockCreateSerializer, FaceLoginSerializer, NotWorkRemarkListSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -67,16 +67,12 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix
|
||||||
remark = request.data.get('not_work_remark', '')
|
remark = request.data.get('not_work_remark', '')
|
||||||
obj.not_work_remark = remark
|
obj.not_work_remark = remark
|
||||||
obj.save()
|
obj.save()
|
||||||
now_local = timezone.localtime()
|
now = timezone.now()
|
||||||
instance, created = NotWorkRemark.objects.get_or_create(
|
instance, created = NotWorkRemark.objects.get_or_create(
|
||||||
year = now_local.year,
|
not_work_date = now.date(),
|
||||||
month = now_local.month,
|
|
||||||
day = now_local.day,
|
|
||||||
user = obj.user,
|
user = obj.user,
|
||||||
defaults={
|
defaults={
|
||||||
"year":now_local.year,
|
"not_work_date":now.date(),
|
||||||
"month":now_local.month,
|
|
||||||
"day":now_local.day,
|
|
||||||
"user":obj.user,
|
"user":obj.user,
|
||||||
"remark":remark,
|
"remark":remark,
|
||||||
"create_by":request.user,
|
"create_by":request.user,
|
||||||
|
|
@ -134,7 +130,15 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
|
||||||
return Response('非打卡时间范围', status=status.HTTP_400_BAD_REQUEST)
|
return Response('非打卡时间范围', status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class NotWorkRemarkViewSet(ListModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
离岗说明
|
||||||
|
"""
|
||||||
|
perms_map = {'get':'*'}
|
||||||
|
queryset = NotWorkRemark.objects.select_related('user').all()
|
||||||
|
serializer_class = NotWorkRemarkListSerializer
|
||||||
|
filterset_class = NotWorkRemarkFilterSet
|
||||||
|
ordering = ['-pk']
|
||||||
|
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,5 @@ class IProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||||
update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte')
|
update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IProduct
|
model = IProduct
|
||||||
fields = ['material', 'warehouse', 'batch', 'order', 'material__type',
|
fields = ['material', 'warehouse', 'batch', 'order', 'material__type', 'update_time_start', 'update_time_end',
|
||||||
'is_saled', 'update_time_start', 'update_time_end',
|
|
||||||
'to_order', 'need_to_order']
|
'to_order', 'need_to_order']
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 01:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sam', '0013_auto_20220222_0941'),
|
||||||
|
('inm', '0031_fifoitem_pu_order_item'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='iproduct',
|
||||||
|
name='is_saled',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='sale',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.sale', verbose_name='关联销售记录'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='iproduct',
|
||||||
|
name='state',
|
||||||
|
field=models.IntegerField(choices=[(10, '可销售'), (20, '已锁定'), (30, '已售出')], default=10, verbose_name='状态'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -3,6 +3,7 @@ from django.db.models.base import Model
|
||||||
import django.utils.timezone as timezone
|
import django.utils.timezone as timezone
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from apps.pum.models import PuOrder, PuOrderItem, Vendor
|
from apps.pum.models import PuOrder, PuOrderItem, Vendor
|
||||||
|
from apps.sam.models import Sale
|
||||||
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
|
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||||
from utils.model import SoftModel, BaseModel
|
from utils.model import SoftModel, BaseModel
|
||||||
from simple_history.models import HistoricalRecords
|
from simple_history.models import HistoricalRecords
|
||||||
|
|
@ -86,6 +87,8 @@ class FIFO(CommonADModel):
|
||||||
on_delete=models.CASCADE, null=True, blank=True)
|
on_delete=models.CASCADE, null=True, blank=True)
|
||||||
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
|
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
|
||||||
null=True, blank=True, on_delete=models.CASCADE)
|
null=True, blank=True, on_delete=models.CASCADE)
|
||||||
|
sale = models.ForeignKey(Sale, verbose_name='关联销售记录',
|
||||||
|
null=True, blank=True, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
class FIFOItem(BaseModel):
|
class FIFOItem(BaseModel):
|
||||||
|
|
@ -113,6 +116,14 @@ class IProduct(BaseModel):
|
||||||
"""
|
"""
|
||||||
具体产品条目
|
具体产品条目
|
||||||
"""
|
"""
|
||||||
|
SALE_OK = 10
|
||||||
|
SALE_LOCK = 20
|
||||||
|
SALED = 30
|
||||||
|
state_choices = (
|
||||||
|
(SALE_OK, '可销售'),
|
||||||
|
(SALE_LOCK, '已锁定'),
|
||||||
|
(SALED, '已售出')
|
||||||
|
)
|
||||||
number = models.CharField('物品编号', unique=True, max_length=50)
|
number = models.CharField('物品编号', unique=True, max_length=50)
|
||||||
material = models.ForeignKey(
|
material = models.ForeignKey(
|
||||||
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||||
|
|
@ -121,7 +132,7 @@ class IProduct(BaseModel):
|
||||||
batch = models.CharField('所属批次号', max_length=100, default='')
|
batch = models.CharField('所属批次号', max_length=100, default='')
|
||||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False,
|
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False,
|
||||||
null=True, blank=True, related_name='iproduct_wproduct')
|
null=True, blank=True, related_name='iproduct_wproduct')
|
||||||
is_saled = models.BooleanField('是否售出', default=False)
|
state = models.IntegerField('状态', default=SALE_OK, choices=state_choices)
|
||||||
|
|
||||||
|
|
||||||
class FIFOItemProduct(BaseModel):
|
class FIFOItemProduct(BaseModel):
|
||||||
|
|
@ -139,4 +150,4 @@ class FIFOItemProduct(BaseModel):
|
||||||
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||||
iproduct = models.ForeignKey(
|
iproduct = models.ForeignKey(
|
||||||
IProduct, verbose_name='关联库存产品',
|
IProduct, verbose_name='关联库存产品',
|
||||||
null=True, blank=True, on_delete=models.SET_NULL)
|
null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-21 06:00
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0047_packitem'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='step',
|
||||||
|
name='need_test',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 01:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0048_remove_step_need_test'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='packitem',
|
||||||
|
name='product',
|
||||||
|
field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.CASCADE, related_name='pack_product', to='mtm.material', verbose_name='装箱产品'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='packitem',
|
||||||
|
name='material',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pack_material', to='mtm.material', verbose_name='装箱配件'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -23,7 +23,7 @@ class Material(CommonAModel):
|
||||||
(MA_TYPE_GOOD, '成品'),
|
(MA_TYPE_GOOD, '成品'),
|
||||||
(MA_TYPE_HALFGOOD, '半成品'),
|
(MA_TYPE_HALFGOOD, '半成品'),
|
||||||
(MA_TYPE_MAINSO, '主要原料'),
|
(MA_TYPE_MAINSO, '主要原料'),
|
||||||
(MA_TYPE_HELPSO, '辅助材料') ,
|
(MA_TYPE_HELPSO, '辅助材料'),
|
||||||
(MA_TYPE_TOOL, '加工工具'),
|
(MA_TYPE_TOOL, '加工工具'),
|
||||||
(MA_TYPE_HELPTOOL, '辅助工装')
|
(MA_TYPE_HELPTOOL, '辅助工装')
|
||||||
)
|
)
|
||||||
|
|
@ -54,8 +54,10 @@ class PackItem(CommonAModel):
|
||||||
"""
|
"""
|
||||||
装箱项目
|
装箱项目
|
||||||
"""
|
"""
|
||||||
material = models.ForeignKey(Material, verbose_name='关联成品',
|
product = models.ForeignKey(Material, verbose_name='装箱产品',
|
||||||
on_delete=models.CASCADE)
|
on_delete=models.CASCADE, related_name='pack_product')
|
||||||
|
material = models.ForeignKey(Material, verbose_name='装箱配件',
|
||||||
|
on_delete=models.CASCADE, null=True, blank=True, related_name='pack_material')
|
||||||
name = models.CharField('名称', max_length=100)
|
name = models.CharField('名称', max_length=100)
|
||||||
specification = models.CharField('型号', max_length=100, null=True, blank=True)
|
specification = models.CharField('型号', max_length=100, null=True, blank=True)
|
||||||
unit = models.CharField('单位', max_length=10)
|
unit = models.CharField('单位', max_length=10)
|
||||||
|
|
@ -105,7 +107,6 @@ class Step(CommonAModel):
|
||||||
name = models.CharField('工序步骤名称', max_length=100)
|
name = models.CharField('工序步骤名称', max_length=100)
|
||||||
number = models.CharField('步骤编号', max_length=100, null=True, blank=True)
|
number = models.CharField('步骤编号', max_length=100, null=True, blank=True)
|
||||||
instruction_content = models.TextField('相应操作指导', null=True, blank=True)
|
instruction_content = models.TextField('相应操作指导', null=True, blank=True)
|
||||||
need_test = models.BooleanField('是否需要检验', default=False)
|
|
||||||
sort = models.IntegerField('排序号', default=1)
|
sort = models.IntegerField('排序号', default=1)
|
||||||
equipments = models.ManyToManyField(Equipment, verbose_name='使用设备', related_name='step_equips')
|
equipments = models.ManyToManyField(Equipment, verbose_name='使用设备', related_name='step_equips')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ class MaterialDetailSerializer(serializers.ModelSerializer):
|
||||||
objs = Process.objects.filter(subproduction_process__product=obj, subproduction_process__is_deleted=False, is_deleted=False).distinct().order_by('number')
|
objs = Process.objects.filter(subproduction_process__product=obj, subproduction_process__is_deleted=False, is_deleted=False).distinct().order_by('number')
|
||||||
return ProcessSimpleSerializer(instance=objs, many=True).data
|
return ProcessSimpleSerializer(instance=objs, many=True).data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PackItemSerializer(serializers.ModelSerializer):
|
class PackItemSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PackItem
|
model = PackItem
|
||||||
|
|
@ -32,7 +34,7 @@ class PackItemSerializer(serializers.ModelSerializer):
|
||||||
class PackItemCreateSerializer(serializers.ModelSerializer):
|
class PackItemCreateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PackItem
|
model = PackItem
|
||||||
fields = ['material', 'name', 'specification', 'unit', 'count', 'sort']
|
fields = ['product', 'material', 'name', 'specification', 'unit', 'count', 'sort']
|
||||||
|
|
||||||
class PackItemUpdateSerializer(serializers.ModelSerializer):
|
class PackItemUpdateSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -44,6 +46,12 @@ class MaterialSimpleSerializer(serializers.ModelSerializer):
|
||||||
model = Material
|
model = Material
|
||||||
fields = ['id', 'name', 'number', 'unit','specification', 'type']
|
fields = ['id', 'name', 'number', 'unit','specification', 'type']
|
||||||
|
|
||||||
|
class PackItemDetailSerializer(serializers.ModelSerializer):
|
||||||
|
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = PackItem
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
class ProcessSerializer(serializers.ModelSerializer):
|
class ProcessSerializer(serializers.ModelSerializer):
|
||||||
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
||||||
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class PackItemViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||||
queryset = PackItem.objects.all()
|
queryset = PackItem.objects.all()
|
||||||
serializer_class = PackItemSerializer
|
serializer_class = PackItemSerializer
|
||||||
search_fields = ['name', 'number']
|
search_fields = ['name', 'number']
|
||||||
filterset_fields = ['material']
|
filterset_fields = ['material', 'product']
|
||||||
ordering = ['sort']
|
ordering = ['sort']
|
||||||
|
|
||||||
def get_serializer_class(self):
|
def get_serializer_class(self):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-21 02:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0025_alter_testrecord_type'),
|
||||||
|
('pm', '0026_auto_20220218_1636'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='form',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='is_testok',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='tester',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='first_test',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='qm.testrecord'),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='FirstItem',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 01:58
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0026_alter_testrecord_is_testok'),
|
||||||
|
('pm', '0027_auto_20220221_1027'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='first_test',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='qm.testrecord'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 02:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0026_alter_testrecord_is_testok'),
|
||||||
|
('pm', '0028_alter_subproductionplan_first_test'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='first_test',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='qm.testrecord', verbose_name='首件检验'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
from apps.qm.models import TestRecord
|
||||||
from apps.system.models import CommonAModel, Organization, User
|
from apps.system.models import CommonAModel, Organization, User
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
|
@ -69,6 +70,7 @@ class SubProductionPlan(CommonAModel):
|
||||||
(SUBPLAN_STATE_WORKING, '生产中'),
|
(SUBPLAN_STATE_WORKING, '生产中'),
|
||||||
(SUBPLAN_STATE_DONE, '已完成'),
|
(SUBPLAN_STATE_DONE, '已完成'),
|
||||||
)
|
)
|
||||||
|
|
||||||
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
|
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
|
||||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE, related_name='subplan_plan')
|
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE, related_name='subplan_plan')
|
||||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
|
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
|
||||||
|
|
@ -90,12 +92,9 @@ class SubProductionPlan(CommonAModel):
|
||||||
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
|
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
|
||||||
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
||||||
is_picked = models.BooleanField('是否已领料', default=False)
|
is_picked = models.BooleanField('是否已领料', default=False)
|
||||||
|
|
||||||
# wproducts = models.JSONField('半成品表', default=list, blank=True)
|
first_test = models.ForeignKey('qm.testrecord', on_delete=models.SET_NULL,
|
||||||
is_testok = models.BooleanField('首件是否合格', null=True, blank=True)
|
null=True, blank=True, verbose_name='首件检验')
|
||||||
form = models.ForeignKey(RecordForm, verbose_name='首件检查表', on_delete=models.CASCADE, null=True, blank=True)
|
|
||||||
tester = models.ForeignKey(User, on_delete=models.CASCADE,
|
|
||||||
verbose_name="首件检查员", null=True, blank=True, related_name='first_tester')
|
|
||||||
leader_1 = models.ForeignKey(User, on_delete=models.CASCADE,
|
leader_1 = models.ForeignKey(User, on_delete=models.CASCADE,
|
||||||
verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1')
|
verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1')
|
||||||
leader_2 = models.ForeignKey(User, on_delete=models.CASCADE,
|
leader_2 = models.ForeignKey(User, on_delete=models.CASCADE,
|
||||||
|
|
@ -108,16 +107,10 @@ class SubProductionPlan(CommonAModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '子生产计划'
|
verbose_name = '子生产计划'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
class FirstItem(BaseModel):
|
# @property
|
||||||
"""
|
# def first_test(self):
|
||||||
首件确认表记录条目
|
# return self.test_subplan.filter(type=TestRecord.TEST_FIRST, is_deleted=False).first()
|
||||||
"""
|
|
||||||
form_field = models.ForeignKey(RecordFormField, verbose_name='关联自定义表格字段', on_delete=models.CASCADE)
|
|
||||||
field_value = models.JSONField('录入值', null=True, blank=True)
|
|
||||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
|
||||||
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, related_name='item_test_record')
|
|
||||||
|
|
||||||
class SubProductionProgress(BaseModel):
|
class SubProductionProgress(BaseModel):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from apps.mtm.models import RecordForm
|
from apps.mtm.models import RecordForm
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from apps.qm.models import TestRecord
|
||||||
|
from apps.qm.serializers import TestRecordShortSerializer
|
||||||
from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer
|
from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, SubProductionSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, SubProductionSimpleSerializer
|
||||||
from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer
|
from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer
|
||||||
|
|
@ -33,12 +35,17 @@ class ResourceConvertListSerializer(serializers.ListSerializer):
|
||||||
class ResourceCalListSerializer(serializers.ListSerializer):
|
class ResourceCalListSerializer(serializers.ListSerializer):
|
||||||
child = ResourceCalSerializer()
|
child = ResourceCalSerializer()
|
||||||
|
|
||||||
class SubProductionPlanListSerializer(serializers.ModelSerializer):
|
class SubProductionPlanListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||||
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
||||||
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
||||||
subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True)
|
subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True)
|
||||||
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
||||||
plan_product_ = serializers.SerializerMethodField()
|
plan_product_ = serializers.SerializerMethodField()
|
||||||
|
leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True)
|
||||||
|
leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True)
|
||||||
|
leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True)
|
||||||
|
first_test_ = TestRecordShortSerializer(source='first_test', read_only=True)
|
||||||
|
# first_test_ = serializers.SerializerMethodField()
|
||||||
class Meta:
|
class Meta:
|
||||||
model=SubProductionPlan
|
model=SubProductionPlan
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
@ -46,7 +53,10 @@ class SubProductionPlanListSerializer(serializers.ModelSerializer):
|
||||||
def get_plan_product_(self, obj):
|
def get_plan_product_(self, obj):
|
||||||
return MaterialSimpleSerializer(instance=obj.production_plan.product).data
|
return MaterialSimpleSerializer(instance=obj.production_plan.product).data
|
||||||
|
|
||||||
|
# def get_first_test_(self, obj):
|
||||||
|
# if obj.first_test:
|
||||||
|
# return TestRecordShortSerializer(instance=obj.first_test).data
|
||||||
|
# return None
|
||||||
|
|
||||||
|
|
||||||
class SubProductionPlanUpdateSerializer(serializers.ModelSerializer):
|
class SubProductionPlanUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -81,20 +91,6 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
|
||||||
class FirstTestInitSerializer(serializers.Serializer):
|
class FirstTestInitSerializer(serializers.Serializer):
|
||||||
form = serializers.PrimaryKeyRelatedField(queryset=RecordForm.objects.all(), required=True)
|
form = serializers.PrimaryKeyRelatedField(queryset=RecordForm.objects.all(), required=True)
|
||||||
|
|
||||||
class FirstTestDetailSerializer(serializers.ModelSerializer):
|
|
||||||
tester_ = UserSimpleSerializer(source='tester', read_only=True)
|
|
||||||
leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True)
|
|
||||||
leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True)
|
|
||||||
leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True)
|
|
||||||
form_ = RecordFormSimpleSerializer(source='form', read_only=True)
|
|
||||||
# record_data = TestRecordItemSerializer(source='item_test_record', read_only=True, many=True)
|
|
||||||
record_data = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class FirstTestAuditSerializer(serializers.Serializer):
|
||||||
model = SubProductionPlan
|
leader = serializers.CharField()
|
||||||
fields = ['id', 'form', 'form_', 'is_testok', 'remark', 'first_sign_time'
|
|
||||||
'tester', 'tester_', 'leader_1', 'leader_1_', 'leader_2',
|
|
||||||
'leader_2_', 'leader_3', 'leader_3_']
|
|
||||||
|
|
||||||
def get_record_data(self, obj):
|
|
||||||
return None
|
|
||||||
|
|
@ -5,23 +5,29 @@ from rest_framework import serializers
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from apps.em.models import Equipment
|
from apps.em.models import Equipment
|
||||||
from apps.em.serializers import EquipmentSimpleSerializer
|
from apps.em.serializers import EquipmentSimpleSerializer
|
||||||
|
from apps.hrm.services import HRMService
|
||||||
from apps.inm.models import MaterialBatch
|
from apps.inm.models import MaterialBatch
|
||||||
from apps.inm.serializers import MaterialBatchSerializer
|
from apps.inm.serializers import MaterialBatchSerializer
|
||||||
from apps.mtm.models import Material, Step, SubProduction, SubprodctionMaterial
|
from apps.mtm.models import Material, RecordFormField, Step, SubProduction, SubprodctionMaterial
|
||||||
from apps.pm.filters import PlanFilterSet, SubproductionProgressFilterSet
|
from apps.pm.filters import PlanFilterSet, SubproductionProgressFilterSet
|
||||||
|
from apps.qm.models import TestRecord, TestRecordItem
|
||||||
|
from apps.qm.serializers import TestRecordDetailBaseSerializer
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin
|
from apps.system.mixins import CreateUpdateModelAMixin
|
||||||
from apps.pm.serializers import FirstTestInitSerializer, GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
from apps.pm.serializers import FirstTestAuditSerializer, FirstTestInitSerializer, GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||||
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||||
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from apps.sam.models import Order
|
from apps.sam.models import Order
|
||||||
from rest_framework.exceptions import APIException, ParseError
|
from rest_framework.exceptions import APIException, ParseError, ValidationError
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
|
from apps.system.serializers import UserSimpleSerializer
|
||||||
from utils.tools import ranstr
|
from utils.tools import ranstr
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from rest_framework import status
|
||||||
|
from django.utils import timezone
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
def updateOrderPlanedCount(order):
|
def updateOrderPlanedCount(order):
|
||||||
|
|
@ -145,7 +151,9 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
子生产计划-列表/修改
|
子生产计划-列表/修改
|
||||||
"""
|
"""
|
||||||
perms_map = {'get': '*', 'put':'subplan_update'}
|
perms_map = {'get': '*', 'put':'subplan_update'}
|
||||||
queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'product', 'production_plan__product')
|
queryset = SubProductionPlan.objects.select_related('process',
|
||||||
|
'workshop', 'subproduction', 'product',
|
||||||
|
'production_plan__product', 'leader_1', 'leader_2', 'leader_3', 'first_test')
|
||||||
search_fields = []
|
search_fields = []
|
||||||
serializer_class = SubProductionPlanListSerializer
|
serializer_class = SubProductionPlanListSerializer
|
||||||
filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop']
|
filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop']
|
||||||
|
|
@ -229,20 +237,68 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
have = MaterialBatchSerializer(instance=objs, many=True).data
|
have = MaterialBatchSerializer(instance=objs, many=True).data
|
||||||
return Response({'need':need, 'have':have})
|
return Response({'need':need, 'have':have})
|
||||||
|
|
||||||
@action(methods=['put'], detail=True, perms_map={'post':'first_test'}, serializer_class=FirstTestInitSerializer)
|
@action(methods=['post'], detail=True, perms_map={'post':'first_test'}, serializer_class=FirstTestInitSerializer)
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def first_test_init(self, request, pk=None):
|
def first_test_init(self, request, pk=None):
|
||||||
"""
|
"""
|
||||||
获取首件检查表
|
首件检查表初始化
|
||||||
"""
|
"""
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
if obj.is_testok is None:
|
first_test = obj.first_test
|
||||||
|
if first_test:
|
||||||
|
return Response(TestRecordDetailBaseSerializer(instance=first_test).data)
|
||||||
|
else:
|
||||||
rdata = request.data
|
rdata = request.data
|
||||||
serializer = self.get_serializer(data=rdata)
|
serializer = self.get_serializer(data=rdata)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
form = serializer.validated_data.get('form')
|
form = serializer.validated_data.get('form')
|
||||||
|
savedict = dict(
|
||||||
raise APIException('已经过首件确认')
|
create_by=request.user,
|
||||||
|
subproduction_plan=obj,
|
||||||
|
type = TestRecord.TEST_FIRST,
|
||||||
|
form=form)
|
||||||
|
tr = TestRecord.objects.create(**savedict)
|
||||||
|
for i in RecordFormField.objects.filter(form=form, is_deleted=False):
|
||||||
|
tri = TestRecordItem()
|
||||||
|
tri.test_record = tr
|
||||||
|
tri.form_field = i
|
||||||
|
tri.is_hidden = i.is_hidden
|
||||||
|
tri.create_by = request.user
|
||||||
|
tri.save()
|
||||||
|
obj.first_test = tr
|
||||||
|
obj.save()
|
||||||
|
return Response(TestRecordDetailBaseSerializer(instance=tr).data)
|
||||||
|
|
||||||
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=FirstTestAuditSerializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def first_audit(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
首件审核
|
||||||
|
"""
|
||||||
|
obj = self.get_object()
|
||||||
|
if obj.leader_1 and obj.leader_2 and obj.leader_3:
|
||||||
|
raise ValidationError('首件确认已完成')
|
||||||
|
if obj.first_test is None:
|
||||||
|
raise ValidationError('未进行首件检查')
|
||||||
|
if not obj.first_test.is_submited:
|
||||||
|
raise ValidationError('首件检查未提交')
|
||||||
|
if not obj.first_test.is_testok:
|
||||||
|
raise ValidationError('首件检查不合格')
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
le = vdata.get('leader')
|
||||||
|
if le not in ['leader_1', 'leader_2', 'leader_3']:
|
||||||
|
return Response('审核人有误', status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
if vdata.get('leader') == 'leader_1':
|
||||||
|
obj.leader_1 = request.user
|
||||||
|
elif vdata.get('leader') == 'leader_2':
|
||||||
|
obj.leader_2 = request.user
|
||||||
|
else:
|
||||||
|
obj.leader_3 = request.user
|
||||||
|
obj.first_sign_time = timezone.now()
|
||||||
|
obj.save()
|
||||||
|
return Response(UserSimpleSerializer(instance=request.user).data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-21 02:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0024_rename_is_midtesing_testrecord_is_midtesting'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='type',
|
||||||
|
field=models.PositiveSmallIntegerField(choices=[(20, '工序检验'), (30, '工序复检'), (36, '夹层检验'), (40, '成品检验'), (10, '首件检验')], default=20),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-21 07:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qm', '0025_alter_testrecord_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='is_testok',
|
||||||
|
field=models.BooleanField(blank=True, null=True, verbose_name='是否合格'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 02:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pm', '0029_alter_subproductionplan_first_test'),
|
||||||
|
('qm', '0026_alter_testrecord_is_testok'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='subproduction_plan',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='test_subplan', to='pm.subproductionplan', verbose_name='关联的生产子计划'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -47,6 +47,7 @@ class TestRecord(CommonADModel):
|
||||||
"""
|
"""
|
||||||
检验记录
|
检验记录
|
||||||
"""
|
"""
|
||||||
|
TEST_FIRST = 10
|
||||||
TEST_PROCESS = 20
|
TEST_PROCESS = 20
|
||||||
TEST_PROCESS_RE = 30
|
TEST_PROCESS_RE = 30
|
||||||
TEST_COMB = 36
|
TEST_COMB = 36
|
||||||
|
|
@ -55,16 +56,17 @@ class TestRecord(CommonADModel):
|
||||||
(TEST_PROCESS, '工序检验'),
|
(TEST_PROCESS, '工序检验'),
|
||||||
(TEST_PROCESS_RE, '工序复检'),
|
(TEST_PROCESS_RE, '工序复检'),
|
||||||
(TEST_COMB, '夹层检验'),
|
(TEST_COMB, '夹层检验'),
|
||||||
(TEST_FINAL, '成品检验')
|
(TEST_FINAL, '成品检验'),
|
||||||
|
(TEST_FIRST, '首件检验')
|
||||||
)
|
)
|
||||||
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
||||||
type = models.PositiveSmallIntegerField(choices=type_choice, default=TEST_PROCESS)
|
type = models.PositiveSmallIntegerField(choices=type_choice, default=TEST_PROCESS)
|
||||||
is_testok = models.BooleanField('是否合格', default=True)
|
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
||||||
number = models.CharField('产品编号', null=True, blank=True, max_length=50)
|
number = models.CharField('产品编号', null=True, blank=True, max_length=50)
|
||||||
wproduct = models.ForeignKey('wpm.wproduct', verbose_name='关联的动态产品', on_delete=models.CASCADE, null=True, blank=True, related_name='test_wproduct')
|
wproduct = models.ForeignKey('wpm.wproduct', verbose_name='关联的动态产品', on_delete=models.CASCADE, null=True, blank=True, related_name='test_wproduct')
|
||||||
material = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
material = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
step = models.ForeignKey('mtm.step', verbose_name='关联的工序步骤', on_delete=models.CASCADE, null=True, blank=True)
|
step = models.ForeignKey('mtm.step', verbose_name='关联的工序步骤', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
subproduction_plan = models.ForeignKey('pm.subproductionplan', verbose_name='关联的生产子计划', on_delete=models.CASCADE, null=True, blank=True)
|
subproduction_plan = models.ForeignKey('pm.subproductionplan', verbose_name='关联的生产子计划', on_delete=models.CASCADE, null=True, blank=True, related_name='test_subplan')
|
||||||
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
origin_test = models.ForeignKey('self', 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_submited = models.BooleanField('是否提交', default=False)
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,11 @@ class TestRecordItemSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TestRecordItem
|
model = TestRecordItem
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
class TestRecordShortSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = TestRecord
|
||||||
|
fields = ['id', 'form', 'is_testok', 'is_submited']
|
||||||
class TestRecordCreateSerializer(serializers.ModelSerializer):
|
class TestRecordCreateSerializer(serializers.ModelSerializer):
|
||||||
record_data = TestRecordItemCreateSerializer(many=True)
|
record_data = TestRecordItemCreateSerializer(many=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,8 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
obj.is_submited=True
|
obj.is_submited=True
|
||||||
obj.save()
|
obj.save()
|
||||||
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
if obj.wproduct:
|
||||||
|
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
# def create(self, request, *args, **kwargs):
|
# def create(self, request, *args, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 01:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sam', '0012_alter_order_delivery_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='count_real',
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='实际发货数量'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='edelivery_date',
|
||||||
|
field=models.DateField(blank=True, null=True, verbose_name='预计发货日期'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='receiver',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='收货人'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='receiver_address',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='收获地址'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='receiver_phone',
|
||||||
|
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='收货人联系电话'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='remark',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='备注'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sale',
|
||||||
|
name='trans_mode',
|
||||||
|
field=models.IntegerField(blank=True, choices=[(10, '铁路快运'), (20, '铁路慢件'), (30, '铁路整车'), (40, '汽车运输'), (50, '空运')], null=True, verbose_name='运输方式'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='sale',
|
||||||
|
name='count',
|
||||||
|
field=models.PositiveIntegerField(default=0, verbose_name='预计发货数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-02-22 07:30
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0049_auto_20220222_0944'),
|
||||||
|
('sam', '0013_auto_20220222_0941'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='saleproduct',
|
||||||
|
name='packnum',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='装箱单号'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SalePack',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||||
|
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||||
|
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||||
|
('count', models.PositiveSmallIntegerField(verbose_name='打包数量')),
|
||||||
|
('packitem', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.packitem', verbose_name='打包项目')),
|
||||||
|
('sale_product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sam.saleproduct', verbose_name='关联销售产品')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -7,7 +7,7 @@ from django.db.models.query import QuerySet
|
||||||
|
|
||||||
|
|
||||||
from utils.model import SoftModel, BaseModel
|
from utils.model import SoftModel, BaseModel
|
||||||
from apps.mtm.models import Material
|
from apps.mtm.models import Material, PackItem
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -69,12 +69,30 @@ class Sale(CommonADModel):
|
||||||
"""
|
"""
|
||||||
销售记录
|
销售记录
|
||||||
"""
|
"""
|
||||||
|
TRANS_RAIL_FAST = 10
|
||||||
|
TRANS_RAIL_SLOW = 20
|
||||||
|
TRANS_RAIL_WHOLE = 30
|
||||||
|
TRANS_LORRY = 40
|
||||||
|
TRANS_AIR = 50
|
||||||
|
trans_choices=(
|
||||||
|
(TRANS_RAIL_FAST, '铁路快运'),
|
||||||
|
(TRANS_RAIL_SLOW, '铁路慢件'),
|
||||||
|
(TRANS_RAIL_WHOLE, '铁路整车'),
|
||||||
|
(TRANS_LORRY, '汽车运输'),
|
||||||
|
(TRANS_AIR, '空运'),
|
||||||
|
)
|
||||||
customer = models.ForeignKey(Customer, verbose_name='客户', on_delete=models.CASCADE)
|
customer = models.ForeignKey(Customer, verbose_name='客户', on_delete=models.CASCADE)
|
||||||
order = models.ForeignKey(Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
order = models.ForeignKey(Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
product = models.ForeignKey(Material, verbose_name='所需产品', on_delete=models.CASCADE)
|
product = models.ForeignKey(Material, verbose_name='所需产品', on_delete=models.CASCADE)
|
||||||
count = models.PositiveIntegerField('交货数量', default=0)
|
count = models.PositiveIntegerField('预计发货数量', default=0)
|
||||||
|
count_real = models.PositiveIntegerField('实际发货数量', null=True, blank=True)
|
||||||
is_audited = models.BooleanField('是否审核', default=False)
|
is_audited = models.BooleanField('是否审核', default=False)
|
||||||
|
edelivery_date = models.DateField('预计发货日期', null=True, blank=True)
|
||||||
|
trans_mode = models.IntegerField('运输方式', null=True, blank=True, choices=trans_choices)
|
||||||
|
receiver = models.CharField('收货人', null=True, blank=True, max_length=200)
|
||||||
|
receiver_phone = models.CharField('收货人联系电话', null=True, blank=True, max_length=20)
|
||||||
|
receiver_address = models.CharField('收获地址', null=True, blank=True, max_length=200)
|
||||||
|
remark = models.CharField('备注', null=True, blank=True, max_length=200)
|
||||||
|
|
||||||
class SaleProduct(BaseModel):
|
class SaleProduct(BaseModel):
|
||||||
"""
|
"""
|
||||||
|
|
@ -84,11 +102,22 @@ class SaleProduct(BaseModel):
|
||||||
number = models.CharField('物品编号', max_length=50)
|
number = models.CharField('物品编号', max_length=50)
|
||||||
iproduct = models.ForeignKey('inm.iproduct', verbose_name='关联库存产品', on_delete=models.CASCADE, related_name='sale_iproduct')
|
iproduct = models.ForeignKey('inm.iproduct', verbose_name='关联库存产品', on_delete=models.CASCADE, related_name='sale_iproduct')
|
||||||
remark = models.TextField('备注', null=True, blank=True)
|
remark = models.TextField('备注', null=True, blank=True)
|
||||||
|
packnum = models.CharField('装箱单号', max_length=100, null=True, blank=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (
|
unique_together = (
|
||||||
('sale','iproduct'), # 联合唯一
|
('sale','iproduct'), # 联合唯一
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class SalePack(BaseModel):
|
||||||
|
"""
|
||||||
|
销售打包
|
||||||
|
"""
|
||||||
|
sale_product = models.ForeignKey(SaleProduct, verbose_name='关联销售产品',
|
||||||
|
on_delete=models.CASCADE)
|
||||||
|
packitem = models.ForeignKey(PackItem, verbose_name='打包项目',
|
||||||
|
on_delete=models.CASCADE)
|
||||||
|
count = models.PositiveSmallIntegerField('打包数量')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,20 @@ from rest_framework import serializers
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
from apps.inm.models import IProduct
|
from apps.inm.models import IProduct
|
||||||
from apps.inm.serializers import IProductListSerializer
|
from apps.inm.serializers import IProductListSerializer
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
from apps.mtm.models import Material, PackItem
|
||||||
from apps.sam.models import Sale, SaleProduct
|
from apps.mtm.serializers import MaterialSimpleSerializer, PackItemDetailSerializer
|
||||||
|
from apps.sam.models import Sale, SalePack, SaleProduct
|
||||||
from apps.sam.serializers import CustomerSimpleSerializer, OrderSimpleSerializer
|
from apps.sam.serializers import CustomerSimpleSerializer, OrderSimpleSerializer
|
||||||
|
from django.db import transaction
|
||||||
|
from rest_framework.exceptions import ValidationError
|
||||||
class SaleCreateSerializer(serializers.ModelSerializer):
|
class SaleCreateSerializer(serializers.ModelSerializer):
|
||||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=
|
iproducts = serializers.PrimaryKeyRelatedField(queryset=
|
||||||
IProduct.objects.all(), many=True)
|
IProduct.objects.all(), many=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Sale
|
model = Sale
|
||||||
fields = ['customer', 'order', 'product', 'iproducts']
|
fields = ['customer', 'order', 'product', 'iproducts',
|
||||||
|
'edelivery_date', 'trans_mode', 'receiver', 'receiver_phone'
|
||||||
|
, 'receiver_address', 'remark']
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
order = attrs.get('order', None)
|
order = attrs.get('order', None)
|
||||||
|
|
@ -18,9 +23,11 @@ class SaleCreateSerializer(serializers.ModelSerializer):
|
||||||
if order.customer:
|
if order.customer:
|
||||||
attrs['customer'] = order.customer
|
attrs['customer'] = order.customer
|
||||||
attrs['product'] = order.product
|
attrs['product'] = order.product
|
||||||
for i in attrs['iproducts']:
|
ips = IProduct.objects.filter(id__in=[i.id for i in attrs['iproducts']])
|
||||||
if i.material != attrs['product']:
|
if ips.exclude(state=IProduct.SALE_OK).exists():
|
||||||
raise exceptions.APIException('产品选取错误')
|
raise exceptions.APIException('选取了非可用的产品')
|
||||||
|
if ips.count() != ips.filter(material=attrs['product']).count():
|
||||||
|
raise exceptions.APIException('产品选取错误')
|
||||||
return super().validate(attrs)
|
return super().validate(attrs)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -44,8 +51,43 @@ class SaleProductCreateSerializer(serializers.ModelSerializer):
|
||||||
fields = ['sale', 'iproduct']
|
fields = ['sale', 'iproduct']
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
validated_data['number'] = validated_data['iproduct'].number
|
with transaction.atomic():
|
||||||
instance = SaleProduct.objects.create(**validated_data)
|
validated_data['number'] = validated_data['iproduct'].number
|
||||||
instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count()
|
instance = SaleProduct.objects.create(**validated_data)
|
||||||
instance.sale.save()
|
sale = instance.sale
|
||||||
return instance
|
sale.count = SaleProduct.objects.filter(sale=instance.sale).count()
|
||||||
|
sale.save()
|
||||||
|
order = sale.order
|
||||||
|
if order:
|
||||||
|
if sale.count+order.delivered_count>order.count:
|
||||||
|
raise exceptions.APIException('超过订单所需数量')
|
||||||
|
return instance
|
||||||
|
|
||||||
|
class SPackItemSerializer(serializers.ModelSerializer):
|
||||||
|
name = serializers.CharField(source='packitem.name', read_only=True)
|
||||||
|
specification = serializers.CharField(source='packitem.specification', read_only=True)
|
||||||
|
unit = serializers.CharField(source='packitem.unit', read_only=True)
|
||||||
|
material_ = MaterialSimpleSerializer(source='packitem.material', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = SalePack
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
class SaleProductPackDetailSerializer(serializers.ModelSerializer):
|
||||||
|
detail = serializers.SerializerMethodField()
|
||||||
|
class Meta:
|
||||||
|
model = ['packnum', 'detail']
|
||||||
|
|
||||||
|
def get_detail(self, obj):
|
||||||
|
return SPackItemSerializer(instance=SalePack.objects.filter(sale_product=obj)
|
||||||
|
, many=True).data
|
||||||
|
|
||||||
|
class SPackItemCreateSerializer(serializers.Serializer):
|
||||||
|
id = serializers.PrimaryKeyRelatedField(queryset=PackItem.objects.all())
|
||||||
|
count = serializers.IntegerField()
|
||||||
|
|
||||||
|
class SaleProductPackSerializer(serializers.ModelSerializer):
|
||||||
|
detail = SPackItemCreateSerializer(many=True)
|
||||||
|
class Meta:
|
||||||
|
model = SaleProduct
|
||||||
|
fields = ['packnum', 'detail']
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
|
|
||||||
from rest_framework.mixins import ListModelMixin, DestroyModelMixin, CreateModelMixin, RetrieveModelMixin
|
from rest_framework.mixins import ListModelMixin, DestroyModelMixin, CreateModelMixin, RetrieveModelMixin
|
||||||
from rest_framework.viewsets import GenericViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
||||||
from apps.inm.services import InmService
|
from apps.inm.services import InmService
|
||||||
from apps.mtm.models import Material
|
from apps.mtm.models import Material, PackItem
|
||||||
from apps.sam.models import Sale, SaleProduct
|
from apps.sam.models import Sale, SalePack, SaleProduct
|
||||||
from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer
|
from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer, SaleProductPackDetailSerializer, SaleProductPackSerializer
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
|
@ -35,6 +36,13 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
||||||
elif self.action == 'retrieve':
|
elif self.action == 'retrieve':
|
||||||
return SaleListSerializer
|
return SaleListSerializer
|
||||||
return super().get_serializer_class()
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
obj = self.get_object()
|
||||||
|
if obj.is_audited:
|
||||||
|
raise exceptions.APIException('该销售记录已审核,不可删除')
|
||||||
|
obj.delete()
|
||||||
|
IProduct.objects.filter(sale_iproduct__sale=obj).update()
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
data = request.data
|
data = request.data
|
||||||
|
|
@ -49,6 +57,8 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
||||||
sale = Sale.objects.create(**vdata)
|
sale = Sale.objects.create(**vdata)
|
||||||
i_l = []
|
i_l = []
|
||||||
for i in iproducts:
|
for i in iproducts:
|
||||||
|
i.state = IProduct.SALE_LOCK
|
||||||
|
i.save()
|
||||||
i_d ={}
|
i_d ={}
|
||||||
i_d['sale'] = sale
|
i_d['sale'] = sale
|
||||||
i_d['number'] = i.number
|
i_d['number'] = i.number
|
||||||
|
|
@ -66,56 +76,59 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
if obj.is_audited:
|
if obj.is_audited:
|
||||||
raise exceptions.APIException('已审核通过')
|
raise exceptions.APIException('已审核通过')
|
||||||
|
if obj.order:
|
||||||
|
if obj.count + obj.order.delivered_count > obj.order.count:
|
||||||
|
raise exceptions.APIException('超过订单所需数量')
|
||||||
# 创建出库记录
|
# 创建出库记录
|
||||||
fifo = FIFO()
|
fifo = FIFO()
|
||||||
|
fifo.sale = obj
|
||||||
fifo.type = FIFO.FIFO_TYPE_SALE_OUT
|
fifo.type = FIFO.FIFO_TYPE_SALE_OUT
|
||||||
fifo.is_audited = True
|
fifo.is_audited = False
|
||||||
fifo.auditor = request.user
|
fifo.auditor = request.user
|
||||||
fifo.inout_date = timezone.now()
|
fifo.inout_date = timezone.now()
|
||||||
fifo.create_by = request.user
|
fifo.create_by = request.user
|
||||||
fifo.number = 'CK' + ranstr(7)
|
fifo.number = 'CK' + ranstr(7)
|
||||||
fifo.save()
|
fifo.save()
|
||||||
# 创建出库条目
|
# 创建出库条目
|
||||||
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
# ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||||
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
# items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
||||||
for i in items:
|
# for i in items:
|
||||||
warehouse = WareHouse.objects.get(id=i['warehouse'])
|
# warehouse = WareHouse.objects.get(id=i['warehouse'])
|
||||||
material = Material.objects.get(id=i['material'])
|
# material = Material.objects.get(id=i['material'])
|
||||||
fifoitem = FIFOItem()
|
# fifoitem = FIFOItem()
|
||||||
fifoitem.need_test = False
|
# fifoitem.need_test = False
|
||||||
fifoitem.warehouse = warehouse
|
# fifoitem.warehouse = warehouse
|
||||||
fifoitem.material = material
|
# fifoitem.material = material
|
||||||
fifoitem.count = i['total']
|
# fifoitem.count = i['total']
|
||||||
fifoitem.batch = i['batch']
|
# fifoitem.batch = i['batch']
|
||||||
fifoitem.fifo = fifo
|
# fifoitem.fifo = fifo
|
||||||
fifoitem.save()
|
# fifoitem.save()
|
||||||
items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
|
# items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
|
||||||
ipxs = []
|
# ipxs = []
|
||||||
for i in items_p:
|
# for i in items_p:
|
||||||
# 创建出库明细半成品
|
# # 创建出库明细半成品
|
||||||
ip = {}
|
# ip = {}
|
||||||
ip['fifoitem'] = fifoitem
|
# ip['fifoitem'] = fifoitem
|
||||||
ip['number'] = i.number
|
# ip['number'] = i.number
|
||||||
ip['material'] = i.material
|
# ip['material'] = i.material
|
||||||
ip['iproduct'] = i
|
# ip['iproduct'] = i
|
||||||
ipxs.append(FIFOItemProduct(**ip))
|
# ipxs.append(FIFOItemProduct(**ip))
|
||||||
FIFOItemProduct.objects.bulk_create(ipxs)
|
# FIFOItemProduct.objects.bulk_create(ipxs)
|
||||||
# 更新成品库情况
|
|
||||||
ips.update(is_saled=True)
|
|
||||||
# 更新动态产品表情况
|
# 更新动态产品表情况
|
||||||
from apps.wpm.models import WProduct
|
# from apps.wpm.models import WProduct
|
||||||
WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update(
|
# WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update(
|
||||||
act_state=WProduct.WPR_ACT_STATE_SELLED)
|
# act_state=WProduct.WPR_ACT_STATE_SELLED)
|
||||||
# 更新库存
|
# 更新库存
|
||||||
InmService.update_inm(fifo)
|
# InmService.update_inm(fifo)
|
||||||
# 变更审核状态
|
# 变更销售提货审核状态
|
||||||
obj.is_audited = True
|
obj.is_audited = True
|
||||||
obj.save()
|
obj.save()
|
||||||
# 变更订单状态
|
# 变更订单状态
|
||||||
if obj.order:
|
# if obj.order:
|
||||||
order = obj.order
|
# order = obj.order
|
||||||
order.delivered_count = order.delivered_count + obj.count
|
# order.delivered_count = order.delivered_count + obj.count
|
||||||
order.save()
|
# order.save()
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -136,13 +149,41 @@ class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, Ge
|
||||||
if self.action == 'create':
|
if self.action == 'create':
|
||||||
return SaleProductCreateSerializer
|
return SaleProductCreateSerializer
|
||||||
return super().get_serializer_class()
|
return super().get_serializer_class()
|
||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
sale = obj.sale
|
sale = obj.sale
|
||||||
if sale.is_audited:
|
if sale.is_audited:
|
||||||
raise exceptions.APIException('该销售记录已审核,不可删除产品')
|
raise exceptions.APIException('该销售记录已审核,不可删除产品')
|
||||||
|
obj.delete()
|
||||||
sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
|
sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
|
||||||
sale.save()
|
sale.save()
|
||||||
obj.delete()
|
return Response()
|
||||||
return Response()
|
|
||||||
|
|
||||||
|
@action(methods=['get', 'post'], detail=True, perms_map={'post':'sale_pack'}, serializer_class=serializers.Serializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def pack(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
打包装箱
|
||||||
|
"""
|
||||||
|
obj = self.get_object()
|
||||||
|
if request.method == 'GET':
|
||||||
|
for i in PackItem.objects.filter(product=obj.product.material, is_deleted=False):
|
||||||
|
SalePack.objects.get_or_create(sale_product=obj, packitem=i,
|
||||||
|
defaults={
|
||||||
|
"sale_product":obj,
|
||||||
|
"packitem":i,
|
||||||
|
"count":i.count
|
||||||
|
})
|
||||||
|
return Response(SaleProductPackDetailSerializer(instance=obj).data)
|
||||||
|
elif request.method == 'POST':
|
||||||
|
serializer = SaleProductPackSerializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
obj.packnum = vdata['packnum']
|
||||||
|
for i in vdata['detail']:
|
||||||
|
pi = i['id']
|
||||||
|
pi.count = i['count']
|
||||||
|
pi.save()
|
||||||
|
return Response()
|
||||||
|
|
@ -90,7 +90,7 @@ class WorkflowViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||||
|
|
||||||
class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
perms_map = {'get':'*', 'post':'workflow_update',
|
perms_map = {'get':'*', 'post':'workflow_update',
|
||||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
'put':'workflow_update', 'delete':'workflow_update'}
|
||||||
queryset = State.objects.all()
|
queryset = State.objects.all()
|
||||||
serializer_class = StateSerializer
|
serializer_class = StateSerializer
|
||||||
search_fields = ['name']
|
search_fields = ['name']
|
||||||
|
|
@ -99,7 +99,7 @@ class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, Destr
|
||||||
|
|
||||||
class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
perms_map = {'get':'*', 'post':'workflow_update',
|
perms_map = {'get':'*', 'post':'workflow_update',
|
||||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
'put':'workflow_update', 'delete':'workflow_update'}
|
||||||
queryset = Transition.objects.all()
|
queryset = Transition.objects.all()
|
||||||
serializer_class = TransitionSerializer
|
serializer_class = TransitionSerializer
|
||||||
search_fields = ['name']
|
search_fields = ['name']
|
||||||
|
|
@ -108,7 +108,7 @@ class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin,
|
||||||
|
|
||||||
class CustomFieldViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
class CustomFieldViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
perms_map = {'get':'*', 'post':'workflow_update',
|
perms_map = {'get':'*', 'post':'workflow_update',
|
||||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
'put':'workflow_update', 'delete':'workflow_update'}
|
||||||
queryset = CustomField.objects.all()
|
queryset = CustomField.objects.all()
|
||||||
serializer_class = CustomFieldSerializer
|
serializer_class = CustomFieldSerializer
|
||||||
search_fields = ['field_name']
|
search_fields = ['field_name']
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ class FitJSONRenderer(JSONRenderer):
|
||||||
if isinstance(data, list):
|
if isinstance(data, list):
|
||||||
data = data[0]
|
data = data[0]
|
||||||
|
|
||||||
response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert
|
response_body.msg = prefix + str(data) # 取一部分放入msg,方便前端alert
|
||||||
else:
|
else:
|
||||||
response_body.data = data
|
response_body.data = data
|
||||||
renderer_context.get("response").status_code = 200 # 统一成200响应, 可用body里code区分业务异常
|
renderer_context.get("response").status_code = 200 # 统一成200响应, 可用body里code区分业务异常
|
||||||
return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context)
|
return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context)
|
||||||
Loading…
Reference in New Issue