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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//个人离岗说明
|
||||
|
||||
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>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<el-card >
|
||||
<el-descriptions title="物料基本信息" direction="vertical" :column="8" border>
|
||||
<el-descriptions-item label="物料编号"> {{materialdetail.number}}</el-descriptions-item>
|
||||
<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-card>
|
||||
<el-descriptions
|
||||
title="物料基本信息"
|
||||
direction="vertical"
|
||||
:column="8"
|
||||
border
|
||||
>
|
||||
<el-descriptions-item label="物料编号">
|
||||
{{ materialdetail.number }}</el-descriptions-item
|
||||
>
|
||||
<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-tab-pane label="供应商" name="5" v-if="this.type==3||this.type==4">
|
||||
<el-tabs v-model="activeName" type="card">
|
||||
<el-tab-pane
|
||||
label="供应商"
|
||||
name="5"
|
||||
v-if="this.type == 3 || this.type == 4"
|
||||
>
|
||||
</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
|
||||
|
||||
: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-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-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>
|
||||
|
||||
<el-tab-pane label="关联的订单" name="1">
|
||||
<el-table
|
||||
|
||||
:data="orderlist"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
highlight-current-row
|
||||
height="460"
|
||||
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
|
||||
<el-table-column label="订单编号" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||
<el-tab-pane label="关联的订单" name="1">
|
||||
<el-table
|
||||
:data="orderlist"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
highlight-current-row
|
||||
height="460"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
|
||||
<el-table-column label="订单编号" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="客户" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{
|
||||
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 label="客户" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{ 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>
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
:title="dialogType === 'edit' ? '编辑装箱单' : '新增装箱单'"
|
||||
>
|
||||
<el-form
|
||||
ref="Form"
|
||||
:model="packitem"
|
||||
label-width="100px"
|
||||
label-position="right"
|
||||
:rules="rule1"
|
||||
>
|
||||
<el-form-item label="物料"
|
||||
prop="material"
|
||||
>
|
||||
|
||||
<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>
|
||||
warehouse_
|
||||
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-select v-model="packitem.material" @change="selectmaterial" >
|
||||
<el-option
|
||||
v-for="item in materialoptions"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="packitem.name" placeholder="名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input v-model="packitem.unit" placeholder="单位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="型号" prop="specification">
|
||||
<el-input v-model="packitem.specification" placeholder="型号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="count">
|
||||
<el-input-number
|
||||
style="width: 100%"
|
||||
v-model="packitem.count"
|
||||
:step="1"
|
||||
:min="0"
|
||||
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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import checkPermission from "@/utils/permission";
|
||||
import vueJsonEditor from "vue-json-editor";
|
||||
import {upUrl, upHeaders} from "@/api/file";
|
||||
import {getProductionplanList } from "@/api/pm";
|
||||
import {getmaterialbatchList} from "@/api/inm";
|
||||
import {getOrderList } from "@/api/sam";
|
||||
import {getMaterial } from "@/api/mtm";
|
||||
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'
|
||||
import checkPermission from "@/utils/permission";
|
||||
import vueJsonEditor from "vue-json-editor";
|
||||
import { upUrl, upHeaders } from "@/api/file";
|
||||
import { getProductionplanList } from "@/api/pm";
|
||||
import { getmaterialbatchList } from "@/api/inm";
|
||||
import { getOrderList } from "@/api/sam";
|
||||
import { getMaterial,getpackitemList,createpackitem,updatepackitem,deletepackitem,getMaterialList } from "@/api/mtm";
|
||||
import { getwproductList } from "@/api/wpm";
|
||||
|
||||
export default {
|
||||
components: {Pagination, vueJsonEditor, Treeselect},
|
||||
data() {
|
||||
return {
|
||||
materialdetail:"",
|
||||
orderlist:[],
|
||||
wproductList:[],
|
||||
productionplanList:[],
|
||||
InventoryList:[],
|
||||
activeName:'3',
|
||||
actstate_: {
|
||||
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";
|
||||
const defaultpackitem = {
|
||||
name:"",
|
||||
unit:"",
|
||||
specification:"",
|
||||
};
|
||||
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: "待复检",
|
||||
10: "操作进行中",
|
||||
20: "待检验",
|
||||
|
|
@ -229,67 +377,162 @@
|
|||
26: "待夹层检验",
|
||||
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: {},
|
||||
created() {
|
||||
this.material = this.$route.params.id;
|
||||
this.type=this.$route.params.type;
|
||||
this.getMaterial();
|
||||
|
||||
this.getOrderList();
|
||||
this.getplanList();
|
||||
this.getmaterialbatchList();
|
||||
this.getwproductList();
|
||||
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
getMaterial(){
|
||||
|
||||
selectmaterial(selval){
|
||||
getMaterial(selval).then((response) => {
|
||||
if (response.data) {
|
||||
this.packitem.name = response.data.name;
|
||||
this.packitem.unit = response.data.unit;
|
||||
this.packitem.specification = response.data.specification;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
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) => {
|
||||
if (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;//物料关联计划
|
||||
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; //物料关联计划
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getmaterialbatchList() {
|
||||
|
||||
|
||||
getmaterialbatchList({material:this.material,page:0}).then((response) => {
|
||||
if (response.data) {
|
||||
this.InventoryList = response.data;
|
||||
getmaterialbatchList() {
|
||||
getmaterialbatchList({ material: this.material, page: 0 }).then(
|
||||
(response) => {
|
||||
if (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>
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
</el-form-item>
|
||||
|
||||
<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
|
||||
v-for="item in typeoption"
|
||||
:key="item.value"
|
||||
|
|
@ -411,6 +411,7 @@
|
|||
const defaultstep = {
|
||||
name: "",
|
||||
number: "",
|
||||
type:null,
|
||||
};
|
||||
|
||||
const defaultrecordform = {
|
||||
|
|
@ -486,15 +487,15 @@
|
|||
'selects': '多选',
|
||||
},
|
||||
typeoption: [{
|
||||
value: '1',
|
||||
value: 1,
|
||||
label: '常规'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
value: 2,
|
||||
label: '分割'
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
value: 3,
|
||||
label: '结合'
|
||||
}],
|
||||
fieldtypeoptions: [{
|
||||
|
|
@ -684,7 +685,7 @@
|
|||
recordformLists()
|
||||
{
|
||||
this.listQueryrecordform.step=this.stepid;
|
||||
this.listQueryrecordform.type=1;
|
||||
this.listQueryrecordform.type=10;
|
||||
getrecordformList(this.listQueryrecordform).then((response) => {
|
||||
if (response.data) {
|
||||
this.recordformList = response.data;
|
||||
|
|
|
|||
|
|
@ -2,154 +2,149 @@
|
|||
<div class="app-container">
|
||||
<el-card>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="今日到岗">
|
||||
<el-table
|
||||
|
||||
:data="userList.results"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="100"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<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="center" label="到岗情况">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" v-if="scope.row.is_atwork">在岗</el-tag>
|
||||
<el-tab-pane label="今日到岗">
|
||||
<el-table
|
||||
:data="userList.results"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="100"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<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="center" label="到岗情况">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" v-if="scope.row.is_atwork">在岗</el-tag>
|
||||
|
||||
<el-tag type="danger" v-else>离岗</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-tag type="danger" v-else>离岗</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="离岗备注">
|
||||
<template slot-scope="scope">{{ scope.row.not_work_remark }}</template>
|
||||
</el-table-column>
|
||||
<template slot-scope="scope">{{
|
||||
scope.row.not_work_remark
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="header-center" label="部门">
|
||||
<template v-if="scope.row.dept_" slot-scope="scope">{{
|
||||
scope.row.dept_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
fixed="right"
|
||||
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="scope.row.is_atwork==false"
|
||||
@click="handlestopwork(scope)"
|
||||
>离岗说明
|
||||
</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">
|
||||
<el-table-column align="header-center" label="部门">
|
||||
<template v-if="scope.row.dept_" slot-scope="scope">{{
|
||||
scope.row.dept_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="scope.row.is_atwork == false"
|
||||
@click="handlestopwork(scope)"
|
||||
>离岗说明
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<span class="demonstration">年、月</span>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="month"
|
||||
placeholder="选择年月">
|
||||
</el-date-picker>
|
||||
<el-button type="primary" @click="submit">查询</el-button>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-table
|
||||
|
||||
:data="atworkList"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="680"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<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 >
|
||||
|
||||
<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>
|
||||
|
||||
<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="到岗统计">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div class="container">
|
||||
<span class="demonstration">年、月</span>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="month"
|
||||
placeholder="选择年月"
|
||||
>
|
||||
</el-date-picker>
|
||||
<el-button type="primary" @click="submit">查询</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="atworkList"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="680"
|
||||
stripe
|
||||
border
|
||||
@current-change="handleCurrentChange"
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -181,9 +176,9 @@
|
|||
<script>
|
||||
import { getEmployeeList } from "@/api/employee";
|
||||
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 Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
|
|
@ -195,89 +190,114 @@ export default {
|
|||
return {
|
||||
userList: { count: 0 },
|
||||
atworkList: [],
|
||||
stopwork:{not_work_remark:""},
|
||||
value3:null,
|
||||
value2:null,
|
||||
stopwork: { not_work_remark: "" },
|
||||
value3: null,
|
||||
value2: null,
|
||||
listLoading: true,
|
||||
dialogVisible:false,
|
||||
stopworkID:null,
|
||||
dialogVisible: false,
|
||||
stopworkID: null,
|
||||
notworkList: "",
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
},
|
||||
resDate: [
|
||||
{"date":"2022-02-20","content":"放假"},
|
||||
{"date":"2022-02-26","content":"去交电费"},
|
||||
{"date":"2022-02-25","content":"去学习vue"}
|
||||
],
|
||||
atworkDate:{year:null,month:null},
|
||||
resDate: [
|
||||
{ date: "2022-02-20", content: "放假" },
|
||||
{ date: "2022-02-26", content: "去交电费" },
|
||||
{ date: "2022-02-25", content: "去学习vue" },
|
||||
],
|
||||
atworkDate: { year: null, month: null },
|
||||
value: new Date(),
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
created() {
|
||||
this.getList();
|
||||
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
//今日到岗
|
||||
//今日到岗
|
||||
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) => {
|
||||
if (response.data) {
|
||||
this.userList = response.data;
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
handlestopwork(scope)
|
||||
{
|
||||
this.dialogVisible=true;
|
||||
this.stopworkID=scope.row.id;
|
||||
handlestopwork(scope) {
|
||||
this.dialogVisible = true;
|
||||
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()
|
||||
{
|
||||
console.log(this.stopwork);
|
||||
notWork(this.stopworkID, this.stopwork).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.$message.success("离职备注提交成功!");
|
||||
this.dialogVisible=false;
|
||||
this.getList();
|
||||
}
|
||||
})
|
||||
|
||||
smtconfirm() {
|
||||
|
||||
notWork(this.stopworkID, this.stopwork).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
this.$message.success("离职备注提交成功!");
|
||||
this.dialogVisible = false;
|
||||
this.getList();
|
||||
}
|
||||
});
|
||||
},
|
||||
//到岗统计
|
||||
|
||||
submit()
|
||||
{
|
||||
|
||||
this.atworkDate.year=this.value2.getFullYear();
|
||||
this.atworkDate.month=this.value2.getMonth()+1;
|
||||
|
||||
|
||||
submit() {
|
||||
this.atworkDate.year = this.value2.getFullYear();
|
||||
this.atworkDate.month = this.value2.getMonth() + 1;
|
||||
this.value = this.value2;
|
||||
(this.resDate = []),
|
||||
getatwork(this.atworkDate).then((response) => {
|
||||
if (response.data) {
|
||||
this.atworkList = response.data;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (response.data) {
|
||||
this.atworkList = response.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//考勤日历
|
||||
dealMyDate(v) {
|
||||
console.log(v)
|
||||
let len = this.resDate.length
|
||||
let res = ""
|
||||
for(let i=0; i<len; i++){
|
||||
if(this.resDate[i].date == v) {
|
||||
res = this.resDate[i].content
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
|
||||
let len = this.resDate.length;
|
||||
let res = "";
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (this.resDate[i].data == v) {
|
||||
res = this.resDate[i].content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -192,33 +192,29 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="设备状态">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.equip_.type === 2">
|
||||
<el-tag
|
||||
v-if="scope.row.equip_.state === 40"
|
||||
type="danger"
|
||||
>
|
||||
禁用
|
||||
</el-tag>
|
||||
<el-tag v-else type="success"> 合格 </el-tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-tag v-if="scope.row.state === 10" type="success">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.state === 20">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.state === 30" type="warning">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="danger">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
{{ state_[scope.row.state] }}</template
|
||||
>
|
||||
<div v-if="scope.row.type===2">
|
||||
<el-tag v-if="scope.row.state===40" type="danger">
|
||||
禁用
|
||||
</el-tag>
|
||||
<el-tag v-else type="success">
|
||||
合格
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-tag v-if="scope.row.state===10" type="success">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.state===20">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.state===30" type="warning">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="danger">
|
||||
{{ state_[scope.row.state] }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="设备编号">
|
||||
<template slot-scope="scope">
|
||||
|
|
|
|||
|
|
@ -1,16 +1,38 @@
|
|||
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
|
||||
|
||||
class ClockRecordFilterSet(filters.FilterSet):
|
||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||
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:
|
||||
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 Meta:
|
||||
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)
|
||||
month = models.PositiveSmallIntegerField('月', default=2)
|
||||
day = models.PositiveSmallIntegerField('日', default=1)
|
||||
not_work_date = models.DateField('未打卡日期')
|
||||
user = models.ForeignKey(User, verbose_name='用户', on_delete=models.CASCADE)
|
||||
remark = models.CharField('未打卡说明', null=True, blank=True, max_length=200)
|
||||
|
||||
|
|
@ -58,4 +56,6 @@ class ClockRecord(CommonADModel):
|
|||
type_choice = (
|
||||
(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 utils.mixins import DynamicFieldsSerializerMixin
|
||||
from .models import ClockRecord, Employee
|
||||
from .models import ClockRecord, Employee, NotWorkRemark
|
||||
from apps.system.serializers import OrganizationSimpleSerializer, UserListSerializer, UserSimpleSerializer
|
||||
from django.db.models.query import Prefetch
|
||||
|
||||
|
|
@ -30,3 +30,8 @@ class ClockRecordListSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = ClockRecord
|
||||
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
|
||||
def update_all_user_facedata_cache():
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
from django.db.models import base
|
||||
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 rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('employee', EmployeeViewSet, basename='employee')
|
||||
router.register('clock_record', ClockRecordViewSet, basename='clock_record')
|
||||
router.register('not_work_remark', NotWorkRemarkViewSet, basename='not_work_reamrk')
|
||||
urlpatterns = [
|
||||
path('facelogin/', FaceLogin.as_view()),
|
||||
path('', include(router.urls)),
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ from django.utils import timezone
|
|||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
||||
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.tasks import update_all_user_facedata_cache
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
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', '')
|
||||
obj.not_work_remark = remark
|
||||
obj.save()
|
||||
now_local = timezone.localtime()
|
||||
now = timezone.now()
|
||||
instance, created = NotWorkRemark.objects.get_or_create(
|
||||
year = now_local.year,
|
||||
month = now_local.month,
|
||||
day = now_local.day,
|
||||
not_work_date = now.date(),
|
||||
user = obj.user,
|
||||
defaults={
|
||||
"year":now_local.year,
|
||||
"month":now_local.month,
|
||||
"day":now_local.day,
|
||||
"not_work_date":now.date(),
|
||||
"user":obj.user,
|
||||
"remark":remark,
|
||||
"create_by":request.user,
|
||||
|
|
@ -134,7 +130,15 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -28,6 +28,5 @@ class IProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
|||
update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte')
|
||||
class Meta:
|
||||
model = IProduct
|
||||
fields = ['material', 'warehouse', 'batch', 'order', 'material__type',
|
||||
'is_saled', 'update_time_start', 'update_time_end',
|
||||
fields = ['material', 'warehouse', 'batch', 'order', 'material__type', 'update_time_start', 'update_time_end',
|
||||
'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
|
||||
from django.db.models.query import QuerySet
|
||||
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 utils.model import SoftModel, BaseModel
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
|
@ -86,6 +87,8 @@ class FIFO(CommonADModel):
|
|||
on_delete=models.CASCADE, null=True, blank=True)
|
||||
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
|
||||
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):
|
||||
|
|
@ -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)
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
|
|
@ -121,7 +132,7 @@ class IProduct(BaseModel):
|
|||
batch = models.CharField('所属批次号', max_length=100, default='')
|
||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False,
|
||||
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):
|
||||
|
|
@ -139,4 +150,4 @@ class FIFOItemProduct(BaseModel):
|
|||
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
iproduct = models.ForeignKey(
|
||||
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_HALFGOOD, '半成品'),
|
||||
(MA_TYPE_MAINSO, '主要原料'),
|
||||
(MA_TYPE_HELPSO, '辅助材料') ,
|
||||
(MA_TYPE_HELPSO, '辅助材料'),
|
||||
(MA_TYPE_TOOL, '加工工具'),
|
||||
(MA_TYPE_HELPTOOL, '辅助工装')
|
||||
)
|
||||
|
|
@ -54,8 +54,10 @@ class PackItem(CommonAModel):
|
|||
"""
|
||||
装箱项目
|
||||
"""
|
||||
material = models.ForeignKey(Material, verbose_name='关联成品',
|
||||
on_delete=models.CASCADE)
|
||||
product = models.ForeignKey(Material, verbose_name='装箱产品',
|
||||
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)
|
||||
specification = models.CharField('型号', max_length=100, null=True, blank=True)
|
||||
unit = models.CharField('单位', max_length=10)
|
||||
|
|
@ -105,7 +107,6 @@ class Step(CommonAModel):
|
|||
name = models.CharField('工序步骤名称', max_length=100)
|
||||
number = models.CharField('步骤编号', max_length=100, null=True, blank=True)
|
||||
instruction_content = models.TextField('相应操作指导', null=True, blank=True)
|
||||
need_test = models.BooleanField('是否需要检验', default=False)
|
||||
sort = models.IntegerField('排序号', default=1)
|
||||
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')
|
||||
return ProcessSimpleSerializer(instance=objs, many=True).data
|
||||
|
||||
|
||||
|
||||
class PackItemSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = PackItem
|
||||
|
|
@ -32,7 +34,7 @@ class PackItemSerializer(serializers.ModelSerializer):
|
|||
class PackItemCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = PackItem
|
||||
fields = ['material', 'name', 'specification', 'unit', 'count', 'sort']
|
||||
fields = ['product', 'material', 'name', 'specification', 'unit', 'count', 'sort']
|
||||
|
||||
class PackItemUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
|
@ -44,6 +46,12 @@ class MaterialSimpleSerializer(serializers.ModelSerializer):
|
|||
model = Material
|
||||
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):
|
||||
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
||||
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class PackItemViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
queryset = PackItem.objects.all()
|
||||
serializer_class = PackItemSerializer
|
||||
search_fields = ['name', 'number']
|
||||
filterset_fields = ['material']
|
||||
filterset_fields = ['material', 'product']
|
||||
ordering = ['sort']
|
||||
|
||||
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 django.db import models
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
|
|
@ -69,6 +70,7 @@ class SubProductionPlan(CommonAModel):
|
|||
(SUBPLAN_STATE_WORKING, '生产中'),
|
||||
(SUBPLAN_STATE_DONE, '已完成'),
|
||||
)
|
||||
|
||||
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
|
||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE, related_name='subplan_plan')
|
||||
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)
|
||||
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
||||
is_picked = models.BooleanField('是否已领料', default=False)
|
||||
|
||||
# wproducts = models.JSONField('半成品表', default=list, blank=True)
|
||||
is_testok = models.BooleanField('首件是否合格', null=True, blank=True)
|
||||
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')
|
||||
|
||||
first_test = models.ForeignKey('qm.testrecord', on_delete=models.SET_NULL,
|
||||
null=True, blank=True, verbose_name='首件检验')
|
||||
leader_1 = models.ForeignKey(User, on_delete=models.CASCADE,
|
||||
verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1')
|
||||
leader_2 = models.ForeignKey(User, on_delete=models.CASCADE,
|
||||
|
|
@ -108,16 +107,10 @@ class SubProductionPlan(CommonAModel):
|
|||
class Meta:
|
||||
verbose_name = '子生产计划'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
class FirstItem(BaseModel):
|
||||
"""
|
||||
首件确认表记录条目
|
||||
"""
|
||||
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')
|
||||
|
||||
# @property
|
||||
# def first_test(self):
|
||||
# return self.test_subplan.filter(type=TestRecord.TEST_FIRST, is_deleted=False).first()
|
||||
|
||||
class SubProductionProgress(BaseModel):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
from apps.mtm.models import RecordForm
|
||||
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
||||
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.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, SubProductionSimpleSerializer
|
||||
from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer
|
||||
|
|
@ -33,12 +35,17 @@ class ResourceConvertListSerializer(serializers.ListSerializer):
|
|||
class ResourceCalListSerializer(serializers.ListSerializer):
|
||||
child = ResourceCalSerializer()
|
||||
|
||||
class SubProductionPlanListSerializer(serializers.ModelSerializer):
|
||||
class SubProductionPlanListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||
workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True)
|
||||
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
||||
subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True)
|
||||
product_ = MaterialSimpleSerializer(source='product', read_only=True)
|
||||
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:
|
||||
model=SubProductionPlan
|
||||
fields = '__all__'
|
||||
|
|
@ -46,7 +53,10 @@ class SubProductionPlanListSerializer(serializers.ModelSerializer):
|
|||
def get_plan_product_(self, obj):
|
||||
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):
|
||||
|
|
@ -81,20 +91,6 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
|
|||
class FirstTestInitSerializer(serializers.Serializer):
|
||||
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:
|
||||
model = SubProductionPlan
|
||||
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
|
||||
class FirstTestAuditSerializer(serializers.Serializer):
|
||||
leader = serializers.CharField()
|
||||
|
|
@ -5,23 +5,29 @@ from rest_framework import serializers
|
|||
from rest_framework.views import APIView
|
||||
from apps.em.models import Equipment
|
||||
from apps.em.serializers import EquipmentSimpleSerializer
|
||||
from apps.hrm.services import HRMService
|
||||
from apps.inm.models import MaterialBatch
|
||||
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.qm.models import TestRecord, TestRecordItem
|
||||
from apps.qm.serializers import TestRecordDetailBaseSerializer
|
||||
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 apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from django.shortcuts import render
|
||||
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.decorators import action
|
||||
from django.db.models import F
|
||||
from apps.system.serializers import UserSimpleSerializer
|
||||
from utils.tools import ranstr
|
||||
from django.db import transaction
|
||||
from rest_framework import status
|
||||
from django.utils import timezone
|
||||
# Create your views here.
|
||||
|
||||
def updateOrderPlanedCount(order):
|
||||
|
|
@ -145,7 +151,9 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
子生产计划-列表/修改
|
||||
"""
|
||||
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 = []
|
||||
serializer_class = SubProductionPlanListSerializer
|
||||
filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop']
|
||||
|
|
@ -229,20 +237,68 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
have = MaterialBatchSerializer(instance=objs, many=True).data
|
||||
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
|
||||
def first_test_init(self, request, pk=None):
|
||||
"""
|
||||
获取首件检查表
|
||||
首件检查表初始化
|
||||
"""
|
||||
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
|
||||
serializer = self.get_serializer(data=rdata)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
form = serializer.validated_data.get('form')
|
||||
|
||||
raise APIException('已经过首件确认')
|
||||
savedict = dict(
|
||||
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_RE = 30
|
||||
TEST_COMB = 36
|
||||
|
|
@ -55,16 +56,17 @@ class TestRecord(CommonADModel):
|
|||
(TEST_PROCESS, '工序检验'),
|
||||
(TEST_PROCESS_RE, '工序复检'),
|
||||
(TEST_COMB, '夹层检验'),
|
||||
(TEST_FINAL, '成品检验')
|
||||
(TEST_FINAL, '成品检验'),
|
||||
(TEST_FIRST, '首件检验')
|
||||
)
|
||||
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
origin_test = models.ForeignKey('self', verbose_name='原检验记录', on_delete=models.CASCADE, null=True, blank=True)
|
||||
is_submited = models.BooleanField('是否提交', default=False)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,11 @@ class TestRecordItemSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = TestRecordItem
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TestRecordShortSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TestRecord
|
||||
fields = ['id', 'form', 'is_testok', 'is_submited']
|
||||
class TestRecordCreateSerializer(serializers.ModelSerializer):
|
||||
record_data = TestRecordItemCreateSerializer(many=True)
|
||||
class Meta:
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De
|
|||
with transaction.atomic():
|
||||
obj.is_submited=True
|
||||
obj.save()
|
||||
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
||||
if obj.wproduct:
|
||||
WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算
|
||||
return Response()
|
||||
|
||||
# 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 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)
|
||||
order = models.ForeignKey(Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
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)
|
||||
|
||||
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):
|
||||
"""
|
||||
|
|
@ -84,11 +102,22 @@ class SaleProduct(BaseModel):
|
|||
number = models.CharField('物品编号', max_length=50)
|
||||
iproduct = models.ForeignKey('inm.iproduct', verbose_name='关联库存产品', on_delete=models.CASCADE, related_name='sale_iproduct')
|
||||
remark = models.TextField('备注', null=True, blank=True)
|
||||
|
||||
packnum = models.CharField('装箱单号', max_length=100, null=True, blank=True)
|
||||
class Meta:
|
||||
unique_together = (
|
||||
('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 apps.inm.models import IProduct
|
||||
from apps.inm.serializers import IProductListSerializer
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
from apps.sam.models import Sale, SaleProduct
|
||||
from apps.mtm.models import Material, PackItem
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer, PackItemDetailSerializer
|
||||
from apps.sam.models import Sale, SalePack, SaleProduct
|
||||
from apps.sam.serializers import CustomerSimpleSerializer, OrderSimpleSerializer
|
||||
from django.db import transaction
|
||||
from rest_framework.exceptions import ValidationError
|
||||
class SaleCreateSerializer(serializers.ModelSerializer):
|
||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=
|
||||
IProduct.objects.all(), many=True)
|
||||
class Meta:
|
||||
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):
|
||||
order = attrs.get('order', None)
|
||||
|
|
@ -18,9 +23,11 @@ class SaleCreateSerializer(serializers.ModelSerializer):
|
|||
if order.customer:
|
||||
attrs['customer'] = order.customer
|
||||
attrs['product'] = order.product
|
||||
for i in attrs['iproducts']:
|
||||
if i.material != attrs['product']:
|
||||
raise exceptions.APIException('产品选取错误')
|
||||
ips = IProduct.objects.filter(id__in=[i.id for i in attrs['iproducts']])
|
||||
if ips.exclude(state=IProduct.SALE_OK).exists():
|
||||
raise exceptions.APIException('选取了非可用的产品')
|
||||
if ips.count() != ips.filter(material=attrs['product']).count():
|
||||
raise exceptions.APIException('产品选取错误')
|
||||
return super().validate(attrs)
|
||||
|
||||
|
||||
|
|
@ -44,8 +51,43 @@ class SaleProductCreateSerializer(serializers.ModelSerializer):
|
|||
fields = ['sale', 'iproduct']
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['number'] = validated_data['iproduct'].number
|
||||
instance = SaleProduct.objects.create(**validated_data)
|
||||
instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count()
|
||||
instance.sale.save()
|
||||
return instance
|
||||
with transaction.atomic():
|
||||
validated_data['number'] = validated_data['iproduct'].number
|
||||
instance = SaleProduct.objects.create(**validated_data)
|
||||
sale = instance.sale
|
||||
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.viewsets import GenericViewSet
|
||||
from rest_framework.response import Response
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
||||
from apps.inm.services import InmService
|
||||
from apps.mtm.models import Material
|
||||
from apps.sam.models import Sale, SaleProduct
|
||||
from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer
|
||||
from apps.mtm.models import Material, PackItem
|
||||
from apps.sam.models import Sale, SalePack, SaleProduct
|
||||
from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer, SaleProductPackDetailSerializer, SaleProductPackSerializer
|
||||
from rest_framework import exceptions
|
||||
from django.db import transaction
|
||||
from rest_framework.decorators import action
|
||||
|
|
@ -35,6 +36,13 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
elif self.action == 'retrieve':
|
||||
return SaleListSerializer
|
||||
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):
|
||||
data = request.data
|
||||
|
|
@ -49,6 +57,8 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
sale = Sale.objects.create(**vdata)
|
||||
i_l = []
|
||||
for i in iproducts:
|
||||
i.state = IProduct.SALE_LOCK
|
||||
i.save()
|
||||
i_d ={}
|
||||
i_d['sale'] = sale
|
||||
i_d['number'] = i.number
|
||||
|
|
@ -66,56 +76,59 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
obj = self.get_object()
|
||||
if obj.is_audited:
|
||||
raise exceptions.APIException('已审核通过')
|
||||
if obj.order:
|
||||
if obj.count + obj.order.delivered_count > obj.order.count:
|
||||
raise exceptions.APIException('超过订单所需数量')
|
||||
# 创建出库记录
|
||||
fifo = FIFO()
|
||||
fifo.sale = obj
|
||||
fifo.type = FIFO.FIFO_TYPE_SALE_OUT
|
||||
fifo.is_audited = True
|
||||
fifo.is_audited = False
|
||||
fifo.auditor = request.user
|
||||
fifo.inout_date = timezone.now()
|
||||
fifo.create_by = request.user
|
||||
fifo.number = 'CK' + ranstr(7)
|
||||
fifo.save()
|
||||
# 创建出库条目
|
||||
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
||||
for i in items:
|
||||
warehouse = WareHouse.objects.get(id=i['warehouse'])
|
||||
material = Material.objects.get(id=i['material'])
|
||||
fifoitem = FIFOItem()
|
||||
fifoitem.need_test = False
|
||||
fifoitem.warehouse = warehouse
|
||||
fifoitem.material = material
|
||||
fifoitem.count = i['total']
|
||||
fifoitem.batch = i['batch']
|
||||
fifoitem.fifo = fifo
|
||||
fifoitem.save()
|
||||
items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
|
||||
ipxs = []
|
||||
for i in items_p:
|
||||
# 创建出库明细半成品
|
||||
ip = {}
|
||||
ip['fifoitem'] = fifoitem
|
||||
ip['number'] = i.number
|
||||
ip['material'] = i.material
|
||||
ip['iproduct'] = i
|
||||
ipxs.append(FIFOItemProduct(**ip))
|
||||
FIFOItemProduct.objects.bulk_create(ipxs)
|
||||
# 更新成品库情况
|
||||
ips.update(is_saled=True)
|
||||
# ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||
# items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
||||
# for i in items:
|
||||
# warehouse = WareHouse.objects.get(id=i['warehouse'])
|
||||
# material = Material.objects.get(id=i['material'])
|
||||
# fifoitem = FIFOItem()
|
||||
# fifoitem.need_test = False
|
||||
# fifoitem.warehouse = warehouse
|
||||
# fifoitem.material = material
|
||||
# fifoitem.count = i['total']
|
||||
# fifoitem.batch = i['batch']
|
||||
# fifoitem.fifo = fifo
|
||||
# fifoitem.save()
|
||||
# items_p = ips.filter(warehouse=warehouse, batch=i['batch'])
|
||||
# ipxs = []
|
||||
# for i in items_p:
|
||||
# # 创建出库明细半成品
|
||||
# ip = {}
|
||||
# ip['fifoitem'] = fifoitem
|
||||
# ip['number'] = i.number
|
||||
# ip['material'] = i.material
|
||||
# ip['iproduct'] = i
|
||||
# ipxs.append(FIFOItemProduct(**ip))
|
||||
# FIFOItemProduct.objects.bulk_create(ipxs)
|
||||
|
||||
# 更新动态产品表情况
|
||||
from apps.wpm.models import WProduct
|
||||
WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update(
|
||||
act_state=WProduct.WPR_ACT_STATE_SELLED)
|
||||
# from apps.wpm.models import WProduct
|
||||
# WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update(
|
||||
# act_state=WProduct.WPR_ACT_STATE_SELLED)
|
||||
# 更新库存
|
||||
InmService.update_inm(fifo)
|
||||
# 变更审核状态
|
||||
# InmService.update_inm(fifo)
|
||||
# 变更销售提货审核状态
|
||||
obj.is_audited = True
|
||||
obj.save()
|
||||
# 变更订单状态
|
||||
if obj.order:
|
||||
order = obj.order
|
||||
order.delivered_count = order.delivered_count + obj.count
|
||||
order.save()
|
||||
# if obj.order:
|
||||
# order = obj.order
|
||||
# order.delivered_count = order.delivered_count + obj.count
|
||||
# order.save()
|
||||
return Response()
|
||||
|
||||
|
||||
|
|
@ -136,13 +149,41 @@ class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, Ge
|
|||
if self.action == 'create':
|
||||
return SaleProductCreateSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
sale = obj.sale
|
||||
if sale.is_audited:
|
||||
raise exceptions.APIException('该销售记录已审核,不可删除产品')
|
||||
obj.delete()
|
||||
sale.count = SaleProduct.objects.filter(sale=obj.sale).count()
|
||||
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):
|
||||
perms_map = {'get':'*', 'post':'workflow_update',
|
||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
||||
'put':'workflow_update', 'delete':'workflow_update'}
|
||||
queryset = State.objects.all()
|
||||
serializer_class = StateSerializer
|
||||
search_fields = ['name']
|
||||
|
|
@ -99,7 +99,7 @@ class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, Destr
|
|||
|
||||
class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
perms_map = {'get':'*', 'post':'workflow_update',
|
||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
||||
'put':'workflow_update', 'delete':'workflow_update'}
|
||||
queryset = Transition.objects.all()
|
||||
serializer_class = TransitionSerializer
|
||||
search_fields = ['name']
|
||||
|
|
@ -108,7 +108,7 @@ class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin,
|
|||
|
||||
class CustomFieldViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
perms_map = {'get':'*', 'post':'workflow_update',
|
||||
'put':'workflow_update', 'delete':'workflow_delete'}
|
||||
'put':'workflow_update', 'delete':'workflow_update'}
|
||||
queryset = CustomField.objects.all()
|
||||
serializer_class = CustomFieldSerializer
|
||||
search_fields = ['field_name']
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ class FitJSONRenderer(JSONRenderer):
|
|||
if isinstance(data, list):
|
||||
data = data[0]
|
||||
|
||||
response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert
|
||||
response_body.msg = prefix + str(data) # 取一部分放入msg,方便前端alert
|
||||
else:
|
||||
response_body.data = data
|
||||
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