Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
a4c37d5255
|
|
@ -16,3 +16,10 @@ export function getFileList(query) {
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function upFile(data) {
|
||||||
|
return request({
|
||||||
|
url: '/file/',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -2,27 +2,34 @@
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card>
|
<el-card>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
|
<!--表格-->
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header" class="clearfix">
|
<div
|
||||||
<span style="font-size: 16px; font-weight: 700"
|
slot="header"
|
||||||
>物料检验记录表</span
|
class="clearfix"
|
||||||
>
|
>
|
||||||
|
<span style="font-size: 16px; font-weight: 700">物料检验记录表</span>
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" icon="el-icon-plus" @click="handleCreate"
|
<el-button
|
||||||
>新增</el-button
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="handleCreate"
|
||||||
>
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<!--表格列表-->
|
||||||
<el-table
|
<el-table
|
||||||
|
v-el-height-adaptive-table="{ bottomOffset: 50 }"
|
||||||
:data="recordformList.results"
|
:data="recordformList.results"
|
||||||
border
|
border
|
||||||
fit
|
fit
|
||||||
stripe
|
stripe
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
height="100"
|
height="100"
|
||||||
v-el-height-adaptive-table="{ bottomOffset: 50 }"
|
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column type="index" width="50"/>
|
||||||
<el-table-column label="表名称">
|
<el-table-column label="表名称">
|
||||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -31,22 +38,26 @@
|
||||||
<el-link
|
<el-link
|
||||||
v-if="checkPermission(['material_update'])"
|
v-if="checkPermission(['material_update'])"
|
||||||
@click="handleLook(scope)"
|
@click="handleLook(scope)"
|
||||||
>查看</el-link
|
>查看
|
||||||
|
</el-link
|
||||||
>
|
>
|
||||||
<el-link
|
<el-link
|
||||||
v-if="checkPermission(['material_update'])"
|
v-if="checkPermission(['material_update'])"
|
||||||
@click="handleEdit(scope)"
|
@click="handleEdit(scope)"
|
||||||
>编辑</el-link
|
>编辑
|
||||||
|
</el-link
|
||||||
>
|
>
|
||||||
<el-link
|
<el-link
|
||||||
v-if="checkPermission(['material_delete'])"
|
v-if="checkPermission(['material_delete'])"
|
||||||
type="danger"
|
type="danger"
|
||||||
@click="handleDelete(scope)"
|
@click="handleDelete(scope)"
|
||||||
>删除</el-link
|
>删除
|
||||||
|
</el-link
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<!--新增、编辑记录表格-->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
:title="dialogType === 'edit' ? '编辑记录表格' : '新增记录表格'"
|
:title="dialogType === 'edit' ? '编辑记录表格' : '新增记录表格'"
|
||||||
|
|
@ -58,42 +69,46 @@
|
||||||
label-position="right"
|
label-position="right"
|
||||||
>
|
>
|
||||||
<el-form-item label="表格名称" prop="name">
|
<el-form-item label="表格名称" prop="name">
|
||||||
<el-input v-model="recordform.name" placeholder="表格名称" />
|
<el-input v-model="recordform.name" placeholder="表格名称"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="text-align: right">
|
<div style="text-align: right">
|
||||||
<el-button type="danger" @click="dialogVisible = false"
|
<el-button type="danger" @click="dialogVisible = false"
|
||||||
>取消</el-button
|
>取消
|
||||||
>
|
</el-button>
|
||||||
<el-button type="primary" @click="recordformconfirm('Forms')"
|
<el-button type="primary" @click="recordformconfirm('Forms')"
|
||||||
>确认</el-button
|
>确认
|
||||||
>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<!--表格展示-->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:model="tableForm"
|
|
||||||
:visible.sync="dialogVisibleForm"
|
:visible.sync="dialogVisibleForm"
|
||||||
:title="tableForm.name"
|
:title="tableForm.name"
|
||||||
>
|
>
|
||||||
<el-form label-width="80px" label-position="right">
|
<el-form ref="Forms" label-width="80px" :model="checkForm">
|
||||||
<el-row
|
<el-row
|
||||||
v-for="(item, $index) in fieldList.results"
|
v-for="(item, $index) in fieldList.results"
|
||||||
|
v-show="filterBlock(item.parent,item.rule_expression,item.need_judge)"
|
||||||
:key="$index"
|
:key="$index"
|
||||||
>
|
>
|
||||||
<el-form-item
|
<!--<div v-if="item.field_type === 'img'">-->
|
||||||
v-if="item.field_type === 'string'"
|
<el-form-item v-if="item.field_type === 'string'" :label="item.field_name">
|
||||||
:label="item.field_name"
|
<el-input
|
||||||
>
|
v-model="checkForm[item.field_key]"
|
||||||
<el-input placeholder="请输入" v-model="item.sort" />
|
placeholder="请输入"
|
||||||
|
@input="keyChange(item.field_key)"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-else-if="item.field_type === 'int'"
|
v-else-if="item.field_type === 'int'"
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-input
|
<el-input
|
||||||
|
v-model="checkForm[item.field_key]"
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
v-model="item.sort"
|
@input="keyChange(item.field_key)"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
|
|
@ -101,9 +116,10 @@
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-input
|
<el-input
|
||||||
|
v-model="checkForm[item.field_key]"
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
v-model="item.sort"
|
@input="keyChange(item.field_key)"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
|
|
@ -111,11 +127,12 @@
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="item.create_time"
|
v-model="checkForm[item.field_key]"
|
||||||
type="date"
|
type="date"
|
||||||
placeholder="选择日期"
|
placeholder="选择日期"
|
||||||
value-format="yyyy-MM-dd"
|
value-format="yyyy-MM-dd"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@change="keyChange(item.field_key)"
|
||||||
>
|
>
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -124,11 +141,12 @@
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="item.create_time"
|
v-model="checkForm[item.field_key]"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
placeholder="选择日期"
|
placeholder="选择日期"
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@change="keyChange(item.field_key)"
|
||||||
>
|
>
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -137,9 +155,10 @@
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-select
|
<el-select
|
||||||
|
v-model="checkForm[item.field_key]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model="item.sort"
|
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
@change="keyChange(item.field_key)"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item1 in item.field_choice"
|
v-for="item1 in item.field_choice"
|
||||||
|
|
@ -155,8 +174,8 @@
|
||||||
:label="item.field_name"
|
:label="item.field_name"
|
||||||
>
|
>
|
||||||
<el-select
|
<el-select
|
||||||
|
v-model="checkForm[item.field_key]"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model="optio"
|
|
||||||
multiple
|
multiple
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
>
|
>
|
||||||
|
|
@ -169,26 +188,46 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="图表" v-else-if="item.field_type === 'draw'">
|
||||||
|
<div>
|
||||||
|
<img id="canvasImg" src="./../../assets/glass.png" style="width:300px;height: 200px;display: none">
|
||||||
|
<div style="position: relative;display: flex">
|
||||||
|
<canvas id="canvas" width="300" height="200">
|
||||||
|
您的浏览器不支持绘图,请升级或更换浏览器!
|
||||||
|
</canvas>
|
||||||
|
<input type="text" value="" class="hide" id="txt" placeholder="请输入文字">
|
||||||
|
<textarea class="hide" id="word" cols="15" rows="5" placeholder="请输入文字" autofocus></textarea>
|
||||||
|
<input id="inputV" type="hidden" value="1">
|
||||||
|
<div class="canvasBtnWrap">
|
||||||
|
<div class="canvasBtn" @click="error1">标记</div>
|
||||||
|
<div class="canvasBtn" @click="word1()">文字</div>
|
||||||
|
<!--<button @click="restuya()">清除批注</button>-->
|
||||||
|
<div class="canvasBtn" @click="back()">回退</div>
|
||||||
|
<div class="canvasBtn" @click="saveTu()">保存</div>
|
||||||
|
</div>
|
||||||
|
<div id="res"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<!--<div style="text-align: right">-->
|
|
||||||
<!--<el-button type="danger">取消</el-button>-->
|
|
||||||
<!--<el-button type="primary">确认</el-button>-->
|
|
||||||
<!--</div>-->
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<!--表格字段-->
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span style="font-size: 16px; font-weight: 700">记录字段</span>
|
<span style="font-size: 16px; font-weight: 300">记录字段</span>
|
||||||
</div>
|
</div>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
@click="handlefieldCreate"
|
@click="handlefieldCreate"
|
||||||
>新增</el-button
|
>新增
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
|
<!--表格字段列表-->
|
||||||
<el-table
|
<el-table
|
||||||
:data="fieldList.results"
|
:data="fieldList.results"
|
||||||
border
|
border
|
||||||
|
|
@ -198,23 +237,26 @@
|
||||||
height="100"
|
height="100"
|
||||||
v-el-height-adaptive-table="{ bottomOffset: 50 }"
|
v-el-height-adaptive-table="{ bottomOffset: 50 }"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column type="index" width="50"/>
|
||||||
<el-table-column label="字段名称">
|
<el-table-column label="字段名称">
|
||||||
<template slot-scope="scope">{{
|
<template slot-scope="scope">{{
|
||||||
scope.row.field_name
|
scope.row.field_name
|
||||||
}}</template>
|
}}
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="字段类型">
|
<el-table-column label="字段类型">
|
||||||
<template slot-scope="scope">{{
|
<template slot-scope="scope">{{
|
||||||
options_[scope.row.field_type]
|
options_[scope.row.field_type]
|
||||||
}}</template>
|
}}
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="字段标识">
|
<el-table-column label="字段标识">
|
||||||
<template slot-scope="scope">{{
|
<template slot-scope="scope">{{
|
||||||
scope.row.field_key
|
scope.row.field_key
|
||||||
}}</template>
|
}}
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!--
|
<!--
|
||||||
<el-table-column label="上限值">
|
<el-table-column label="上限值">
|
||||||
|
|
@ -250,13 +292,15 @@
|
||||||
<el-link
|
<el-link
|
||||||
v-if="checkPermission(['material_update'])"
|
v-if="checkPermission(['material_update'])"
|
||||||
@click="handlefieldEdit(scope)"
|
@click="handlefieldEdit(scope)"
|
||||||
>编辑</el-link
|
>编辑
|
||||||
|
</el-link
|
||||||
>
|
>
|
||||||
<el-link
|
<el-link
|
||||||
v-if="checkPermission(['material_delete'])"
|
v-if="checkPermission(['material_delete'])"
|
||||||
type="danger"
|
type="danger"
|
||||||
@click="handlefieldDelete(scope)"
|
@click="handlefieldDelete(scope)"
|
||||||
>删除</el-link
|
>删除
|
||||||
|
</el-link
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -268,6 +312,7 @@
|
||||||
:limit.sync="listQueryfield.page_size"
|
:limit.sync="listQueryfield.page_size"
|
||||||
@pagination="fieldLists"
|
@pagination="fieldLists"
|
||||||
/>
|
/>
|
||||||
|
<!--表格字段新增编辑-->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:visible.sync="dialogVisible1"
|
:visible.sync="dialogVisible1"
|
||||||
:title="dialogType1 === 'edit' ? '编辑表格字段' : '新增表格字段'"
|
:title="dialogType1 === 'edit' ? '编辑表格字段' : '新增表格字段'"
|
||||||
|
|
@ -294,14 +339,10 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="字段标识" prop="field_key">
|
<el-form-item label="字段标识" prop="field_key">
|
||||||
<el-input
|
<el-input v-model="field.field_key" placeholder="字段标识" @input="checkValue"/>
|
||||||
v-model="field.field_key"
|
|
||||||
placeholder="字段标识"
|
|
||||||
onkeyup="value=value.replace(/[^A-Za-z_\/]/ig,'')"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="字段名称" prop="field_name">
|
<el-form-item label="字段名称" prop="field_name">
|
||||||
<el-input v-model="field.field_name" placeholder="字段名称" />
|
<el-input v-model="field.field_name" placeholder="字段名称"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="选项"
|
label="选项"
|
||||||
|
|
@ -340,7 +381,9 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="字段父级">
|
||||||
|
<treeselect v-model="field.parent" :multiple="false" :options="treeDate" placeholder="字段父级"/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="是否需要判定" prop="need_judge">
|
<el-form-item label="是否需要判定" prop="need_judge">
|
||||||
<el-switch v-model="field.need_judge"></el-switch>
|
<el-switch v-model="field.need_judge"></el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -406,14 +449,24 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
!-->
|
!-->
|
||||||
|
<el-form-item label="表达式" v-if="field.need_judge === true">
|
||||||
|
|
||||||
|
|
||||||
<el-form-item label="表达式" v-if="field.need_judge == true">
|
|
||||||
<el-input v-model="field.rule_expression" type="textarea"/>
|
<el-input v-model="field.rule_expression" type="textarea"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="模板图片" v-if="field.field_type === 'img'">
|
||||||
|
<el-upload
|
||||||
|
class="avatar-uploader"
|
||||||
|
:action="upUrl"
|
||||||
|
accept="image/jpeg, image/gif, image/png, image/bmp"
|
||||||
|
:show-file-list="false"
|
||||||
|
:on-success="handleAvatarSuccess"
|
||||||
|
:before-upload="beforeAvatarUpload"
|
||||||
|
:headers="upHeaders"
|
||||||
|
>
|
||||||
|
<img v-if="field.draw_template" :src="field.draw_template" class="avatar" />
|
||||||
|
<i v-else class="el-icon-plus avatar-uploader-icon" />
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="排序" prop="sort">
|
<el-form-item label="排序" prop="sort">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="field.sort"
|
v-model="field.sort"
|
||||||
|
|
@ -424,10 +477,12 @@
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="text-align: right">
|
<div style="text-align: right">
|
||||||
<el-button type="danger" @click="dialogVisible1 = false"
|
<el-button type="danger" @click="dialogVisible1 = false"
|
||||||
>取消</el-button
|
>取消
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
<el-button type="primary" @click="fieldconfirm('Form')"
|
<el-button type="primary" @click="fieldconfirm('Form')"
|
||||||
>确认</el-button
|
>确认
|
||||||
|
</el-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
@ -439,11 +494,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import checkPermission from "@/utils/permission";
|
import checkPermission from "@/utils/permission";
|
||||||
import { getEquipmentAll } from "@/api/equipment";
|
import {getEquipmentAll} from "@/api/equipment";
|
||||||
import vueJsonEditor from "vue-json-editor";
|
import vueJsonEditor from "vue-json-editor";
|
||||||
import { upUrl, upHeaders } from "@/api/file";
|
import {upUrl, upHeaders} from "@/api/file";
|
||||||
import {
|
import {
|
||||||
getrecordformList,
|
getrecordformList,
|
||||||
createrecordform,
|
createrecordform,
|
||||||
updaterecordform,
|
updaterecordform,
|
||||||
|
|
@ -452,18 +507,23 @@ import {
|
||||||
createrffield,
|
createrffield,
|
||||||
updaterffield,
|
updaterffield,
|
||||||
deleterffield,
|
deleterffield,
|
||||||
} from "@/api/mtm";
|
} from "@/api/mtm";
|
||||||
import { genTree } from "@/utils";
|
import { upFile } from "@/api/file";
|
||||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
import {genTree} from "@/utils";
|
||||||
const defaultstep = {
|
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 defaultstep = {
|
||||||
name: "",
|
name: "",
|
||||||
number: "",
|
number: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultrecordform = {};
|
const defaultrecordform = {};
|
||||||
const defaultfield = {};
|
const defaultfield = {};
|
||||||
export default {
|
let preDrawAry = [];
|
||||||
components: { Pagination, vueJsonEditor },
|
export default {
|
||||||
|
components: {Pagination, vueJsonEditor, Treeselect},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
step: defaultstep,
|
step: defaultstep,
|
||||||
|
|
@ -481,22 +541,25 @@ export default {
|
||||||
field_key: "",
|
field_key: "",
|
||||||
field_name: "",
|
field_name: "",
|
||||||
sort: "",
|
sort: "",
|
||||||
|
parent: "",
|
||||||
|
draw_template: "",//图片模板
|
||||||
field_choice: [""],
|
field_choice: [""],
|
||||||
},
|
},
|
||||||
field_choice: [""],
|
field_choice: [""],
|
||||||
options: [],
|
options: [],
|
||||||
optio: [],
|
optio: [],
|
||||||
rule1: {
|
rule1: {
|
||||||
name: [{ required: true, message: "请输入", trigger: "blur" }],
|
name: [{required: true, message: "请输入", trigger: "blur"}],
|
||||||
number: [{ required: true, message: "请输入", trigger: "blur" }],
|
number: [{required: true, message: "请输入", trigger: "blur"}],
|
||||||
},
|
},
|
||||||
recordform: defaultrecordform,
|
recordform: defaultrecordform,
|
||||||
dialogType: "new",
|
dialogType: "new",
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
dialogType1: "new",
|
dialogType1: "new",
|
||||||
dialogVisible1: false,
|
dialogVisible1: false,
|
||||||
tableForm: {
|
tableForm: defaultrecordform,
|
||||||
name: "",
|
checkForm:{
|
||||||
|
hhh:'',
|
||||||
},
|
},
|
||||||
listQueryrecordform: {
|
listQueryrecordform: {
|
||||||
page: 1,
|
page: 1,
|
||||||
|
|
@ -508,17 +571,18 @@ export default {
|
||||||
fieldList: {
|
fieldList: {
|
||||||
count: 0,
|
count: 0,
|
||||||
},
|
},
|
||||||
|
treeDate: [],
|
||||||
listQueryfield: {
|
listQueryfield: {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20,
|
page_size: 20,
|
||||||
},
|
},
|
||||||
highoptions: [
|
highoptions: [
|
||||||
{ value: 1, label: "<" },
|
{value: 1, label: "<"},
|
||||||
{ value: 2, label: "<=" },
|
{value: 2, label: "<="},
|
||||||
],
|
],
|
||||||
lowoptions: [
|
lowoptions: [
|
||||||
{ value: 1, label: ">" },
|
{value: 1, label: ">"},
|
||||||
{ value: 2, label: ">=" },
|
{value: 2, label: ">="},
|
||||||
],
|
],
|
||||||
highoptionss_: {
|
highoptionss_: {
|
||||||
1: "<",
|
1: "<",
|
||||||
|
|
@ -536,6 +600,7 @@ export default {
|
||||||
datetime: "日期时间",
|
datetime: "日期时间",
|
||||||
select: "单选",
|
select: "单选",
|
||||||
selects: "多选",
|
selects: "多选",
|
||||||
|
draw: "绘图模板",
|
||||||
},
|
},
|
||||||
fieldtypeoptions: [
|
fieldtypeoptions: [
|
||||||
{
|
{
|
||||||
|
|
@ -570,6 +635,10 @@ export default {
|
||||||
value: "selects",
|
value: "selects",
|
||||||
label: "多选",
|
label: "多选",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: "draw",
|
||||||
|
label: "绘图模板",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
typeoptions: [
|
typeoptions: [
|
||||||
{
|
{
|
||||||
|
|
@ -577,6 +646,17 @@ export default {
|
||||||
label: "生产记录",
|
label: "生产记录",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
canvas:null,
|
||||||
|
ctx:null,
|
||||||
|
myCanvas_rect:null,
|
||||||
|
Txt:null,
|
||||||
|
word:null,
|
||||||
|
widths:0,
|
||||||
|
heights:0,
|
||||||
|
lineW:3,
|
||||||
|
colorF:"#e42343",
|
||||||
|
imgData:'',
|
||||||
|
canvasImg:'',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
|
|
@ -586,6 +666,95 @@ export default {
|
||||||
this.recordformLists();
|
this.recordformLists();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleAvatarSuccess(res, file) {
|
||||||
|
this.field.draw_template = res.data.path;
|
||||||
|
},
|
||||||
|
beforeAvatarUpload(file) {
|
||||||
|
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||||
|
if (!isLt2M) {
|
||||||
|
this.$message.error("上传头像图片大小不能超过 2MB!");
|
||||||
|
}
|
||||||
|
return isLt2M;
|
||||||
|
},
|
||||||
|
keyChange(key){
|
||||||
|
let y = this.checkForm[key];
|
||||||
|
this.$set(this.checkForm,key,y);
|
||||||
|
this.fieldList.results=[...this.fieldList.results];
|
||||||
|
this.filterBlock();
|
||||||
|
},
|
||||||
|
filterBlock(parent,rule,judge){
|
||||||
|
let that = this;
|
||||||
|
if(parent!==''&&parent!==null&&parent!==undefined){
|
||||||
|
if(judge){
|
||||||
|
if(rule!==''&&rule!==null&&rule!==undefined){
|
||||||
|
let reg = /\{(.+?)\}/g;
|
||||||
|
//let str = rule.replace(temp,'').replace('$','');//=='有'
|
||||||
|
//let y = that.checkForm[key];
|
||||||
|
if(rule.indexOf('||')>-1||rule.indexOf('&&')>-1){
|
||||||
|
let tam = '', arr = [];
|
||||||
|
if(rule.indexOf('||')>-1){
|
||||||
|
arr = rule.split('||');
|
||||||
|
}else{
|
||||||
|
arr = rule.split('&&');
|
||||||
|
}
|
||||||
|
for (let i = 0;i<arr.length;i++){
|
||||||
|
//获取判断依据
|
||||||
|
let a = '';
|
||||||
|
a = arr[i].replace(/`/g,'');
|
||||||
|
a = '`'+ a+'`';
|
||||||
|
let tem =a.match(reg)[0];
|
||||||
|
let ky = tem.replace(/\{|\}/g, '');//qipao
|
||||||
|
if(that.checkForm[ky]){
|
||||||
|
//替换变量
|
||||||
|
a = a.replace(ky, 'yyy');
|
||||||
|
let yyy = "'"+that.checkForm[ky]+"'";
|
||||||
|
if(eval(eval( a))){
|
||||||
|
tam += 'true';
|
||||||
|
}else{
|
||||||
|
tam += 'false';
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
tam += 'false';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let rea = true;
|
||||||
|
if(rule.indexOf('||')>-1){
|
||||||
|
if( tam.indexOf('true')>-1){
|
||||||
|
rea = true;
|
||||||
|
}else{
|
||||||
|
rea = false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( tam.indexOf('false')>-1){
|
||||||
|
rea = false;
|
||||||
|
}else{
|
||||||
|
rea = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rea;
|
||||||
|
}else{
|
||||||
|
let temp =rule.match(reg)[0];
|
||||||
|
let key = temp.replace(/\{|\}/g, '');//qipao
|
||||||
|
let a = rule.replace(key, 'yy');
|
||||||
|
a = a.replace(key, 'yy');
|
||||||
|
let yy = "'"+that.checkForm[key]+"'";
|
||||||
|
return eval(eval(a));
|
||||||
|
// return eval("'"+y+"'"+str);
|
||||||
|
}
|
||||||
|
debugger;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkValue() {
|
||||||
|
this.field.field_key = this.field.field_key.replace(/[^a-zA-Z]/g, '');
|
||||||
|
},
|
||||||
//添加字段选项
|
//添加字段选项
|
||||||
addDomain() {
|
addDomain() {
|
||||||
this.field_choice.push("");
|
this.field_choice.push("");
|
||||||
|
|
@ -595,18 +764,48 @@ export default {
|
||||||
this.field_choice.splice(index, 1);
|
this.field_choice.splice(index, 1);
|
||||||
},
|
},
|
||||||
handleLook(scope) {
|
handleLook(scope) {
|
||||||
|
let that = this;
|
||||||
|
that.tableForm = Object.assign({}, scope.row); // copy obj
|
||||||
|
that.formID = that.tableForm.id;
|
||||||
|
that.listQueryfield.form = that.formID;
|
||||||
|
getrffieldList(that.listQueryfield).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
debugger;
|
debugger;
|
||||||
console.log(scope);
|
that.fieldList = response.data;
|
||||||
this.dialogVisibleForm = true;
|
let list = response.data.results;
|
||||||
this.tableForm = Object.assign({}, scope.row); // copy obj
|
for(let i=0;i<list.length;i++){
|
||||||
this.formID = this.tableForm.id;
|
let key = list[i].field_key;
|
||||||
this.fieldLists();
|
that.checkForm[key]='';
|
||||||
|
that.$set(that.checkForm,key,'')
|
||||||
|
}
|
||||||
|
that.dialogVisibleForm = true;
|
||||||
|
setTimeout(function(){
|
||||||
|
that.canvasInit();
|
||||||
|
},500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
that.fieldLists();
|
||||||
|
},
|
||||||
|
canvasInit(){
|
||||||
|
let that = this;
|
||||||
|
preDrawAry = [];
|
||||||
|
that.canvas = document.getElementById('canvas');
|
||||||
|
that.ctx = that.canvas.getContext('2d');
|
||||||
|
that.myCanvas_rect = that.canvas.getBoundingClientRect();
|
||||||
|
that.Txt = document.getElementById('txt');
|
||||||
|
that.word = document.getElementById('word');
|
||||||
|
that.widths = that.myCanvas_rect.width;
|
||||||
|
that.heights = that.myCanvas_rect.height;
|
||||||
|
setTimeout(function(){
|
||||||
|
that.draw();
|
||||||
|
},500);
|
||||||
},
|
},
|
||||||
checkPermission,
|
checkPermission,
|
||||||
|
|
||||||
handleCurrentChange(row) {
|
handleCurrentChange(row) {
|
||||||
this.formID = row.id;
|
this.formID = row.id;
|
||||||
this.fieldLists();
|
this.fieldLists();
|
||||||
|
this.fieldLists1();
|
||||||
},
|
},
|
||||||
recordformLists() {
|
recordformLists() {
|
||||||
this.listQueryrecordform.material = this.material;
|
this.listQueryrecordform.material = this.material;
|
||||||
|
|
@ -618,13 +817,218 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fieldLists() {
|
fieldLists() {
|
||||||
this.listQueryfield.form = this.formID;
|
let that = this;
|
||||||
getrffieldList(this.listQueryfield).then((response) => {
|
that.listQueryfield.form = that.formID;
|
||||||
|
getrffieldList(that.listQueryfield).then((response) => {
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
this.fieldList = response.data;
|
that.fieldList = response.data;
|
||||||
|
that.fieldList.results=[...that.fieldList.results]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
fieldLists1() {
|
||||||
|
let params = new Object();
|
||||||
|
let that = this;
|
||||||
|
params.page = 0;
|
||||||
|
params.form = this.formID;
|
||||||
|
getrffieldList(params).then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
let data = response.data;
|
||||||
|
data.forEach(item => {
|
||||||
|
item.name = item.field_name;
|
||||||
|
});
|
||||||
|
that.treeDate = genTree(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
draw(){
|
||||||
|
let canvasImg = document.getElementById("canvasImg");
|
||||||
|
canvasImg.style.width = '300px';
|
||||||
|
canvasImg.style.height = '200px';
|
||||||
|
this.ctx.drawImage(canvasImg,0,0,300,200);
|
||||||
|
},
|
||||||
|
// 叉号
|
||||||
|
error1(){
|
||||||
|
let canvas1 = document.getElementById('canvas');
|
||||||
|
let ctx1 = canvas1.getContext('2d');
|
||||||
|
this.Txt.style.display="none";
|
||||||
|
document.getElementById('word').style.display="none";
|
||||||
|
ctx1.closePath();
|
||||||
|
canvas1.onmousedown=function () {
|
||||||
|
this.imgData= ctx1.getImageData(0,0,canvas1.width,canvas1.height);
|
||||||
|
preDrawAry.push(this.imgData);
|
||||||
|
ctx1.beginPath();
|
||||||
|
ctx1.strokeStyle = "#e42343";
|
||||||
|
ctx1.lineWidth = "3";
|
||||||
|
ctx1.lineJoin="round";
|
||||||
|
};
|
||||||
|
//鼠标按下的位置
|
||||||
|
canvas1.onmouseup=function (ev) {
|
||||||
|
let oldX = ev.offsetX;
|
||||||
|
let oldY = ev.offsetY;
|
||||||
|
ctx1.moveTo(oldX,oldY);
|
||||||
|
ctx1.lineTo(ev.offsetX+10,ev.offsetY+10);
|
||||||
|
ctx1.moveTo(ev.offsetX+10,ev.offsetY);
|
||||||
|
ctx1.lineTo(ev.offsetX,ev.offsetY+10);
|
||||||
|
ctx1.stroke();
|
||||||
|
};
|
||||||
|
this.ctx.closePath();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 文字先写字
|
||||||
|
text(){
|
||||||
|
let canvas2 = document.getElementById('canvas');
|
||||||
|
let ctx2 = canvas2.getContext('2d');
|
||||||
|
let Txt2 = document.getElementById('txt');
|
||||||
|
Txt2.style.display="block";
|
||||||
|
document.getElementById('word').style.display="none";
|
||||||
|
ctx2.font="16px Microsoft Yahei";
|
||||||
|
canvas2.onmousedown=function (ev) {
|
||||||
|
this.imgData=ctx2.getImageData(0,0,canvas2.width,canvas2.height);
|
||||||
|
preDrawAry.push(this.imgData);
|
||||||
|
var v = Txt2.value;
|
||||||
|
// console.log(v);
|
||||||
|
if (v != '') {
|
||||||
|
var oldX = ev.offsetX;
|
||||||
|
var oldY = ev.offsetY;
|
||||||
|
// console.log(oldX,oldY);
|
||||||
|
ctx2.moveTo(oldX,oldY);
|
||||||
|
canvas2.onmouseup=function () {
|
||||||
|
ctx2.fillStyle=this.colorF;
|
||||||
|
ctx2.fillText(v,oldX,oldY);
|
||||||
|
canvas2.TextAutoLine(v,canvas2,oldX,oldY,20);
|
||||||
|
// Txt.value = "";
|
||||||
|
Txt2.style.display="none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 文字
|
||||||
|
word1(){
|
||||||
|
let canvas3 = document.getElementById('canvas');
|
||||||
|
let ctx3 = canvas3.getContext('2d');
|
||||||
|
let Txt3 = document.getElementById('txt');
|
||||||
|
let word3 = document.getElementById('word');
|
||||||
|
Txt3.style.display="none";
|
||||||
|
ctx3.font="16px Microsoft Yahei";
|
||||||
|
canvas3.onmousedown=function () {
|
||||||
|
ctx3.closePath();
|
||||||
|
}
|
||||||
|
canvas3.onmouseup=function (ev) {
|
||||||
|
var inputV= document.getElementById('inputV').value;
|
||||||
|
if(inputV == 1){
|
||||||
|
document.getElementById('word').focus();
|
||||||
|
// console.log(ev.offsetX,ev.offsetY);
|
||||||
|
var oldX = ev.offsetX;
|
||||||
|
var oldY = ev.offsetY;
|
||||||
|
word3.style.display="block";
|
||||||
|
word3.style.left=oldX+'px';
|
||||||
|
word3.style.top =oldY+'px';
|
||||||
|
|
||||||
|
word3.onblur=function () {
|
||||||
|
let v = word3.value;
|
||||||
|
if(v != '' && v != ' '){
|
||||||
|
this.imgData=ctx3.getImageData(0,0,canvas3.width,canvas3.height);
|
||||||
|
let img = ctx3.getImageData(0,0,canvas3.width,canvas3.height);
|
||||||
|
debugger;
|
||||||
|
preDrawAry.push(img);
|
||||||
|
ctx3.moveTo(oldX,oldY);
|
||||||
|
ctx3.fillStyle="#e42343";
|
||||||
|
let lineWidth = 0;
|
||||||
|
let canvasWidth = canvas3.width;
|
||||||
|
let lastSubStrIndex= 0;
|
||||||
|
for(let i=0;i<v.length;i++){
|
||||||
|
lineWidth+=ctx3.measureText(v[i]).width;
|
||||||
|
if(lineWidth>canvasWidth-oldX){
|
||||||
|
ctx3.fillText(v.substring(lastSubStrIndex,i),oldX,(oldY+10));
|
||||||
|
oldY+=20;
|
||||||
|
lineWidth=0;
|
||||||
|
lastSubStrIndex=i;
|
||||||
|
}
|
||||||
|
if(i==v.length-1){
|
||||||
|
ctx3.fillText(v.substring(lastSubStrIndex,i+1),oldX,(oldY+10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputV ="2";
|
||||||
|
word3.value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 文字过长超出换行toDataURL()
|
||||||
|
canvasTextAutoLine(str,canvas,initX,initY,lineHeight){
|
||||||
|
let ctx = canvas.getContext("2d");
|
||||||
|
let lineWidth = 0;
|
||||||
|
let canvasWidth = canvas.width;
|
||||||
|
let lastSubStrIndex= 0;
|
||||||
|
for(let i=0;i<str.length;i++){
|
||||||
|
lineWidth+=ctx.measureText(str[i]).width;
|
||||||
|
if(lineWidth>canvasWidth-initX){
|
||||||
|
ctx.fillText(str.substring(lastSubStrIndex,i),initX,initY);
|
||||||
|
initY+=lineHeight;
|
||||||
|
lineWidth=0;
|
||||||
|
lastSubStrIndex=i;
|
||||||
|
}
|
||||||
|
if(i==str.length-1){
|
||||||
|
ctx.fillText(str.substring(lastSubStrIndex,i+1),initX,initY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* // 删除批注
|
||||||
|
restuya(){
|
||||||
|
this.word.style.display="none";
|
||||||
|
this.Txt.style.display="none";
|
||||||
|
this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
|
||||||
|
window.location.reload();
|
||||||
|
},*/
|
||||||
|
|
||||||
|
// 撤销
|
||||||
|
back(){
|
||||||
|
this.word.style.display="none";
|
||||||
|
this.Txt.style.display="none";
|
||||||
|
if(preDrawAry.length>0) {
|
||||||
|
var popData = preDrawAry.pop();
|
||||||
|
this.ctx.putImageData(popData, 0, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 回退一次
|
||||||
|
put(){
|
||||||
|
this.ctx.putImageData(this.imgData,0,0);
|
||||||
|
},
|
||||||
|
|
||||||
|
//保存
|
||||||
|
saveTu(){
|
||||||
|
let canvas = document.getElementById('canvas');
|
||||||
|
let image = new Image();
|
||||||
|
image = canvas.toDataURL('image/png');
|
||||||
|
this.canvasImg = image;
|
||||||
|
let file = this.base64ToFile(image);
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
upFile(formData).then((res) => {
|
||||||
|
debugger;
|
||||||
|
console.log(res);
|
||||||
|
debugger;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
base64ToFile(baseUrl) {
|
||||||
|
let arr = baseUrl.split(',');
|
||||||
|
// let type = arr[0].match(/:(.*?);/)[1]; // 解锁图片类型
|
||||||
|
let bytes = atob(arr[1]); // 解码base64
|
||||||
|
let n = bytes .length;
|
||||||
|
let bufferArray = new Uint8Array(n);
|
||||||
|
while (n--) {
|
||||||
|
bufferArray[n] = bytes.charCodeAt(n);
|
||||||
|
}
|
||||||
|
// let fileOfBlob = new File([bufferArray], new Date()+'.jpg');
|
||||||
|
return new File([bufferArray ],'draw.jpg');
|
||||||
|
},
|
||||||
|
|
||||||
//新增记录表
|
//新增记录表
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.recordform = Object.assign({}, defaultrecordform);
|
this.recordform = Object.assign({}, defaultrecordform);
|
||||||
|
|
@ -637,7 +1041,7 @@ export default {
|
||||||
//新增字段
|
//新增字段
|
||||||
handlefieldCreate() {
|
handlefieldCreate() {
|
||||||
this.field_choice = [""];
|
this.field_choice = [""];
|
||||||
this.field = Object.assign({}, defaultfield);
|
// this.field = Object.assign({}, defaultfield);
|
||||||
this.dialogType1 = "new";
|
this.dialogType1 = "new";
|
||||||
this.dialogVisible1 = true;
|
this.dialogVisible1 = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
@ -685,6 +1089,7 @@ export default {
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await deleterffield(scope.row.id);
|
await deleterffield(scope.row.id);
|
||||||
this.fieldLists();
|
this.fieldLists();
|
||||||
|
this.fieldLists1();
|
||||||
this.$message.success("成功");
|
this.$message.success("成功");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|
@ -733,6 +1138,7 @@ export default {
|
||||||
updaterffield(this.field.id, this.field).then((res) => {
|
updaterffield(this.field.id, this.field).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code >= 200) {
|
||||||
this.fieldLists();
|
this.fieldLists();
|
||||||
|
this.fieldLists1();
|
||||||
this.dialogVisible1 = false;
|
this.dialogVisible1 = false;
|
||||||
this.$message.success("成功");
|
this.$message.success("成功");
|
||||||
}
|
}
|
||||||
|
|
@ -740,9 +1146,12 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.field.form = this.formID;
|
this.field.form = this.formID;
|
||||||
this.field.field_choice = this.field_choice;
|
this.field.field_choice = this.field_choice;
|
||||||
|
debugger;
|
||||||
|
console.log(this.field);
|
||||||
createrffield(this.field).then((res) => {
|
createrffield(this.field).then((res) => {
|
||||||
if (res.code >= 200) {
|
if (res.code >= 200) {
|
||||||
this.fieldLists();
|
this.fieldLists();
|
||||||
|
this.fieldLists1();
|
||||||
this.dialogVisible1 = false;
|
this.dialogVisible1 = false;
|
||||||
this.$message.success("成功");
|
this.$message.success("成功");
|
||||||
}
|
}
|
||||||
|
|
@ -754,14 +1163,65 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.my-label {
|
.my-label {
|
||||||
background: #e1f3d8;
|
background: #e1f3d8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-content {
|
.my-content {
|
||||||
background: #fde2e2;
|
background: #fde2e2;
|
||||||
}
|
}
|
||||||
|
canvas{
|
||||||
|
border:1px solid #000000;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.canvasBtnWrap{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 80px;
|
||||||
|
padding-left: 20px;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.canvasBtn{
|
||||||
|
width: 70px;
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
border: 1px solid #aaaaaa;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
.hide{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#txt{
|
||||||
|
position: absolute;
|
||||||
|
top: 1%;
|
||||||
|
left: 1%;
|
||||||
|
width: 150px;
|
||||||
|
height: 30px;
|
||||||
|
border:1px solid #e42343;
|
||||||
|
}
|
||||||
|
#word{
|
||||||
|
position: absolute;
|
||||||
|
width: 150px;
|
||||||
|
height: 70px;
|
||||||
|
padding: 0 2px;
|
||||||
|
background:none;
|
||||||
|
color:#e42343;
|
||||||
|
border: 1px dashed #b9b9b9;
|
||||||
|
}
|
||||||
|
#word::-webkit-input-placeholder{
|
||||||
|
color:#e42343;
|
||||||
|
}
|
||||||
|
#word::-moz-placeholder{
|
||||||
|
color:#e42343;
|
||||||
|
}
|
||||||
|
#word::placeholder{
|
||||||
|
color:#e42343;
|
||||||
|
}
|
||||||
|
#res{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-23 02:52
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0035_auto_20211117_1637'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='recordformfield',
|
||||||
|
name='draw_template',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='绘图模板'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='recordformfield',
|
||||||
|
name='field_type',
|
||||||
|
field=models.CharField(choices=[('string', '字符串'), ('int', '整型'), ('float', '浮点'), ('boolean', '布尔'), ('date', '日期'), ('time', '时间'), ('datetime', '日期时间'), ('radio', '单选'), ('checkbox', '多选'), ('select', '单选下拉'), ('selects', '多选下拉'), ('textarea', '文本域'), ('draw', '绘图')], max_length=50, verbose_name='类型'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -131,6 +131,7 @@ class RecordFormField(CommonAModel):
|
||||||
('select', '单选下拉'),
|
('select', '单选下拉'),
|
||||||
('selects', '多选下拉'),
|
('selects', '多选下拉'),
|
||||||
('textarea', '文本域'),
|
('textarea', '文本域'),
|
||||||
|
('draw', '绘图')
|
||||||
)
|
)
|
||||||
high_rule_choices = (
|
high_rule_choices = (
|
||||||
(1, '小于'),
|
(1, '小于'),
|
||||||
|
|
@ -161,6 +162,8 @@ class RecordFormField(CommonAModel):
|
||||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
is_hidden = models.BooleanField('是否隐藏', default=False)
|
||||||
parent = models.ForeignKey('self', verbose_name='父', on_delete=models.CASCADE, null=True, blank=True)
|
parent = models.ForeignKey('self', verbose_name='父', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
|
draw_template = models.CharField('绘图模板', max_length=200, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '记录表格字段'
|
verbose_name = '记录表格字段'
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class MaterialDetailSerializer(serializers.ModelSerializer):
|
||||||
class MaterialSimpleSerializer(serializers.ModelSerializer):
|
class MaterialSimpleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Material
|
model = Material
|
||||||
fields = ['id', 'name', 'number', 'unit','specification']
|
fields = ['id', 'name', 'number', 'unit','specification', 'type']
|
||||||
|
|
||||||
class ProcessSerializer(serializers.ModelSerializer):
|
class ProcessSerializer(serializers.ModelSerializer):
|
||||||
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
instruction_ = FileSimpleSerializer(source='instruction', read_only=True)
|
||||||
|
|
@ -209,6 +209,12 @@ class RecordFormDetailSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
def get_form_fields(self, obj):
|
def get_form_fields(self, obj):
|
||||||
serializer = RecordFormFieldSerializer(instance=RecordFormField.objects.filter(form=obj, is_deleted=False), many=True)
|
serializer = RecordFormFieldSerializer(instance=RecordFormField.objects.filter(form=obj, is_deleted=False), many=True)
|
||||||
|
vdata = serializer.data
|
||||||
|
if obj.type == RecordForm.RF_TYPE_TEST:
|
||||||
|
for i in vdata:
|
||||||
|
if i['need_judge']:
|
||||||
|
i['is_testok'] = False
|
||||||
|
i['is_teskok_robot'] = False
|
||||||
return serializer.data
|
return serializer.data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
from apps.mtm.models import Material, Step
|
||||||
|
from apps.pm.models import SubProductionProgress
|
||||||
|
from apps.wpm.models import Operation, WProduct
|
||||||
|
|
||||||
|
from apps.wpm.services import WpmServies
|
||||||
|
|
||||||
|
|
||||||
|
class SubproductionProgressFilterSet(filters.FilterSet):
|
||||||
|
|
||||||
|
operation = filters.NumberFilter(method='filter_operation')
|
||||||
|
class Meta:
|
||||||
|
model = SubProductionProgress
|
||||||
|
fields = ['material', 'subproduction_plan', 'operation', 'type']
|
||||||
|
|
||||||
|
def filter_operation(self, queryset, name, value):
|
||||||
|
operation = Operation.objects.get(pk=value)
|
||||||
|
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
|
||||||
|
step = operation.step
|
||||||
|
if wproducts.exists():
|
||||||
|
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
|
||||||
|
else:
|
||||||
|
subplans = WpmServies.get_subplans_queyset_from_step(step)
|
||||||
|
queryset = queryset.filter(subproduction_plan__in=subplans)
|
||||||
|
if step.type == Step.STEP_TYPE_NOM:
|
||||||
|
queryset = queryset.exclude(material__type=Material.MA_TYPE_HALFGOOD)
|
||||||
|
return queryset
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-19 02:34
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='number',
|
||||||
|
field=models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='子计划编号'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-22 07:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pm', '0014_subproductionplan_number'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionplan',
|
||||||
|
name='main_count_ok',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='合格数'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subproductionprogress',
|
||||||
|
name='count_ok',
|
||||||
|
field=models.IntegerField(default=0, verbose_name='合格数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -44,6 +44,7 @@ class SubProductionPlan(CommonAModel):
|
||||||
(SUBPLAN_STATE_WORKING, '生产中'),
|
(SUBPLAN_STATE_WORKING, '生产中'),
|
||||||
(SUBPLAN_STATE_DONE, '已完成')
|
(SUBPLAN_STATE_DONE, '已完成')
|
||||||
)
|
)
|
||||||
|
number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True)
|
||||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
|
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
|
||||||
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
|
subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod')
|
||||||
start_date = models.DateField('计划开工日期')
|
start_date = models.DateField('计划开工日期')
|
||||||
|
|
@ -55,6 +56,7 @@ class SubProductionPlan(CommonAModel):
|
||||||
main_product = models.ForeignKey(Material, verbose_name='主要产品', on_delete=models.CASCADE, null=True, blank=True)
|
main_product = models.ForeignKey(Material, verbose_name='主要产品', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
main_count = models.IntegerField('应产出数', default=0)
|
main_count = models.IntegerField('应产出数', default=0)
|
||||||
main_count_real = models.IntegerField('实际产出数', default=0)
|
main_count_real = models.IntegerField('实际产出数', default=0)
|
||||||
|
main_count_ok = models.IntegerField('合格数', default=0)
|
||||||
|
|
||||||
steps = models.JSONField('工艺步骤', default=list)
|
steps = models.JSONField('工艺步骤', default=list)
|
||||||
|
|
||||||
|
|
@ -79,3 +81,4 @@ class SubProductionProgress(BaseModel):
|
||||||
count = models.IntegerField('应出入数')
|
count = models.IntegerField('应出入数')
|
||||||
count_pick = models.IntegerField('实际领用数', default=0)
|
count_pick = models.IntegerField('实际领用数', default=0)
|
||||||
count_real = models.IntegerField('实际消耗/产出数', default=0)
|
count_real = models.IntegerField('实际消耗/产出数', default=0)
|
||||||
|
count_ok = models.IntegerField('合格数量', default=0)
|
||||||
|
|
|
||||||
|
|
@ -55,3 +55,8 @@ class PickNeedSerializer(serializers.Serializer):
|
||||||
|
|
||||||
class PlanDestorySerializer(serializers.Serializer):
|
class PlanDestorySerializer(serializers.Serializer):
|
||||||
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')
|
ids = serializers.ListField(child=serializers.IntegerField(), label='主计划ID列表')
|
||||||
|
|
||||||
|
class SubproductionPlanSimpleSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = SubProductionPlan
|
||||||
|
fields = ['id', 'number']
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from apps.pm.views import ProductionPlanViewSet, ResourceViewSet, SubProductionPlanViewSet
|
from apps.pm.views import ProductionPlanViewSet, ResourceViewSet, SubProductionPlanViewSet, SubProductionProgressViewSet
|
||||||
from django.db.models import base
|
from django.db.models import base
|
||||||
from rest_framework import urlpatterns
|
from rest_framework import urlpatterns
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
|
@ -7,6 +7,7 @@ from rest_framework.routers import DefaultRouter
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register('production_plan', ProductionPlanViewSet, basename='production_plan')
|
router.register('production_plan', ProductionPlanViewSet, basename='production_plan')
|
||||||
router.register('subproduction_plan', SubProductionPlanViewSet, basename='subproduction_plan')
|
router.register('subproduction_plan', SubProductionPlanViewSet, basename='subproduction_plan')
|
||||||
|
router.register('subproduction_progress', SubProductionProgressViewSet, basename='subproduction_progress')
|
||||||
router.register('resource', ResourceViewSet, basename='resource')
|
router.register('resource', ResourceViewSet, basename='resource')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
|
from typing import List
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
@ -7,6 +8,7 @@ from apps.em.serializers import EquipmentSerializer
|
||||||
from apps.inm.models import MaterialBatch
|
from apps.inm.models import MaterialBatch
|
||||||
from apps.inm.serializers import MaterialBatchSerializer
|
from apps.inm.serializers import MaterialBatchSerializer
|
||||||
from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep
|
from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep
|
||||||
|
from apps.pm.filters import SubproductionProgressFilterSet
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin
|
from apps.system.mixins import CreateUpdateModelAMixin
|
||||||
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||||
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
|
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
|
||||||
|
|
@ -62,12 +64,12 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise APIException('排产数量错误')
|
raise APIException('排产数量错误')
|
||||||
instance = serializer.save(create_by=request.user, product=order.product, number='JH-'+ranstr(7))
|
instance = serializer.save(create_by=request.user, product=order.product, number='JH'+ranstr(7))
|
||||||
updateOrderPlanedCount(instance.order)
|
updateOrderPlanedCount(instance.order)
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PlanDestorySerializer)
|
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=PlanDestorySerializer)
|
||||||
def destory(self, request, pk=None):
|
def deletes(self, request, pk=None):
|
||||||
"""
|
"""
|
||||||
批量物理删除
|
批量物理删除
|
||||||
"""
|
"""
|
||||||
|
|
@ -83,13 +85,13 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
||||||
if production_plan.is_planed:
|
if production_plan.is_planed:
|
||||||
raise APIException('已生成子计划')
|
raise APIException('已生成子计划')
|
||||||
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
|
subps = SubProduction.objects.filter(product=production_plan.product).order_by('process__number')
|
||||||
for i in subps:
|
for index, i in enumerate(subps):
|
||||||
steps = Step.objects.filter(usedstep__subproduction=i, usedstep__subproduction__is_deleted=False,
|
steps = Step.objects.filter(usedstep__subproduction=i, usedstep__subproduction__is_deleted=False,
|
||||||
usedstep__is_deleted=False, is_deleted=False).values('id', 'number', 'name', 'usedstep__remark')
|
usedstep__is_deleted=False, is_deleted=False).values('id', 'number', 'name', 'usedstep__remark')
|
||||||
instance = SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i,
|
instance = SubProductionPlan.objects.create(production_plan=production_plan, subproduction=i,
|
||||||
start_date=production_plan.start_date, end_date=production_plan.end_date,
|
start_date=production_plan.start_date, end_date=production_plan.end_date,
|
||||||
workshop=i.process.workshop, process=i.process, create_by=request.user,
|
workshop=i.process.workshop, process=i.process, create_by=request.user,
|
||||||
steps = list(steps))
|
steps = list(steps), number=production_plan.number + '-' + str(index+1))
|
||||||
# 生成子计划物料需求/进度
|
# 生成子计划物料需求/进度
|
||||||
for m in SubprodctionMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
|
for m in SubprodctionMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
|
||||||
spro = SubProductionProgress.objects.create(material=m.material, type=m.type,
|
spro = SubProductionProgress.objects.create(material=m.material, type=m.type,
|
||||||
|
|
@ -178,6 +180,17 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
||||||
have = MaterialBatchSerializer(instance=objs, many=True).data
|
have = MaterialBatchSerializer(instance=objs, many=True).data
|
||||||
return Response({'need':need, 'have':have})
|
return Response({'need':need, 'have':have})
|
||||||
|
|
||||||
|
class SubProductionProgressViewSet(ListModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
生产进度
|
||||||
|
"""
|
||||||
|
perms_map = {'*': '*'}
|
||||||
|
queryset = SubProductionProgress.objects.select_related('material', 'subproduction_plan')
|
||||||
|
search_fields = []
|
||||||
|
serializer_class = SubProductionProgressSerializer
|
||||||
|
filterset_class = SubproductionProgressFilterSet
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['id']
|
||||||
|
|
||||||
class ResourceViewSet(GenericViewSet):
|
class ResourceViewSet(GenericViewSet):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-19 00:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pm', '0013_alter_subproductionplan_subproduction'),
|
||||||
|
('qm', '0010_rename_m_state_testrecord_material'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='is_testok_robot',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='自动判定的是否合格'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='number',
|
||||||
|
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='产品编号'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='testrecord',
|
||||||
|
name='subproduction_plan',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联的生产子计划'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='testrecorditem',
|
||||||
|
name='is_testok_robot',
|
||||||
|
field=models.BooleanField(blank=True, null=True, verbose_name='自动判定的是否合格'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -49,8 +49,11 @@ class TestRecord(CommonAModel):
|
||||||
"""
|
"""
|
||||||
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE)
|
||||||
is_testok = models.BooleanField('是否合格', default=True)
|
is_testok = models.BooleanField('是否合格', default=True)
|
||||||
|
is_testok_robot = models.BooleanField('自动判定的是否合格', default=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)
|
wproduct = models.ForeignKey('wpm.wproduct', verbose_name='关联的动态产品', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
material = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True)
|
material = models.ForeignKey('mtm.material', 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)
|
||||||
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
fifo_item = models.ForeignKey('inm.fifoitem', verbose_name='关联的出入库批次', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
remark = models.TextField('备注', default='')
|
remark = models.TextField('备注', default='')
|
||||||
|
|
||||||
|
|
@ -67,4 +70,5 @@ class TestRecordItem(BaseModel):
|
||||||
need_judge = models.BooleanField('是否需要判定', default=False)
|
need_judge = models.BooleanField('是否需要判定', default=False)
|
||||||
sort = models.IntegerField('排序号', default=1)
|
sort = models.IntegerField('排序号', default=1)
|
||||||
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
is_testok = models.BooleanField('是否合格', null=True, blank=True)
|
||||||
|
is_testok_robot = models.BooleanField('自动判定的是否合格', null=True, blank=True)
|
||||||
test_record = models.ForeignKey(TestRecord, verbose_name='关联的检测记录', on_delete=models.CASCADE, related_name='item_test_record')
|
test_record = models.ForeignKey(TestRecord, verbose_name='关联的检测记录', on_delete=models.CASCADE, related_name='item_test_record')
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
from apps.mtm.models import Material, Step
|
||||||
|
|
||||||
|
from apps.wpm.services import WpmServies
|
||||||
|
from .models import Operation, WMaterial, WProduct
|
||||||
|
|
||||||
|
class WMaterialFilterSet(filters.FilterSet):
|
||||||
|
|
||||||
|
operation = filters.NumberFilter(method='filter_operation')
|
||||||
|
class Meta:
|
||||||
|
model = WMaterial
|
||||||
|
fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop', 'operation']
|
||||||
|
|
||||||
|
def filter_operation(self, queryset, name, value):
|
||||||
|
operation = Operation.objects.get(pk=value)
|
||||||
|
wproducts = WProduct.objects.filter(ow_wproduct__operation=value)
|
||||||
|
step = operation.step
|
||||||
|
if wproducts.exists():
|
||||||
|
subplans = WpmServies.get_subplans_queryset_from_wproducts(wproducts)
|
||||||
|
else:
|
||||||
|
subplans = WpmServies.get_subplans_queyset_from_step(step)
|
||||||
|
queryset = queryset.filter(subproduction_plan__in=subplans).exclude(material__type=Material.MA_TYPE_HALFGOOD)
|
||||||
|
return queryset
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-19 00:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0015_auto_20211117_2332'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='operation',
|
||||||
|
name='wproducts',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='operation',
|
||||||
|
name='is_submited',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='是否提交'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='operation',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-19 02:34
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('em', '0009_auto_20210916_1108'),
|
||||||
|
('wpm', '0016_auto_20211119_0848'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='operationrecord',
|
||||||
|
name='create_by',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='operationrecord',
|
||||||
|
name='update_by',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='operationrecord',
|
||||||
|
name='is_filled',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='是否填写'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operation',
|
||||||
|
name='is_submited',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否提交'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OperationEquip',
|
||||||
|
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='删除标记')),
|
||||||
|
('remark', models.TextField(blank=True, null=True, verbose_name='备注')),
|
||||||
|
('equip', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='生产设备')),
|
||||||
|
('operation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.operation', verbose_name='关联操作')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-19 05:40
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0017_auto_20211119_1034'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationequip',
|
||||||
|
name='operation',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='oe_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationrecord',
|
||||||
|
name='operation',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='or_operation', to='wpm.operation', verbose_name='关联的生产操作'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationwproduct',
|
||||||
|
name='operation',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ow_operation', to='wpm.operation', verbose_name='关联操作'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-22 03:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mtm', '0035_auto_20211117_1637'),
|
||||||
|
('pm', '0014_subproductionplan_number'),
|
||||||
|
('wpm', '0018_auto_20211119_1340'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='operationmaterial',
|
||||||
|
name='batch',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='operationmaterial',
|
||||||
|
name='subproduction_plan',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联的子计划'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='operationmaterial',
|
||||||
|
name='subproduction_progress',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionprogress', verbose_name='关联的生产进度'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationmaterial',
|
||||||
|
name='material',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='可能产出的产品'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationmaterial',
|
||||||
|
name='type',
|
||||||
|
field=models.IntegerField(choices=[(1, '输入物料'), (2, '输出物料'), (3, '工具工装')], default=0, verbose_name='类型'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='subproduction_plan',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wproduct_subplan', to='pm.subproductionplan', verbose_name='当前子生产计划'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-22 07:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0019_auto_20211122_1110'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationwproduct',
|
||||||
|
name='wproduct',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ow_wproduct', to='wpm.wproduct', verbose_name='关联半成品'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-23 01:45
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0020_alter_operationwproduct_wproduct'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='operationwproduct',
|
||||||
|
name='production_plan',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='production_plan',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.9 on 2021-11-23 06:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0021_auto_20211123_0945'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='parent',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='child',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -3,12 +3,13 @@ from django.db.models.base import Model
|
||||||
import django.utils.timezone as timezone
|
import django.utils.timezone as timezone
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from apps.inm.models import WareHouse
|
from apps.inm.models import WareHouse
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
|
||||||
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
|
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||||
from utils.model import SoftModel, BaseModel
|
from utils.model import SoftModel, BaseModel
|
||||||
from simple_history.models import HistoricalRecords
|
from simple_history.models import HistoricalRecords
|
||||||
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm
|
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm, SubprodctionMaterial
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
|
from apps.em.models import Equipment
|
||||||
class WMaterial(BaseModel):
|
class WMaterial(BaseModel):
|
||||||
"""
|
"""
|
||||||
车间生产物料
|
车间生产物料
|
||||||
|
|
@ -39,54 +40,56 @@ class WProduct(CommonAModel):
|
||||||
act_state = models.IntegerField('进行状态', default=0, choices=act_state_choices)
|
act_state = models.IntegerField('进行状态', default=0, choices=act_state_choices)
|
||||||
is_executed = models.BooleanField('子工序是否已执行', default=False)
|
is_executed = models.BooleanField('子工序是否已执行', default=False)
|
||||||
is_hidden = models.BooleanField('是否隐藏', default=False)
|
is_hidden = models.BooleanField('是否隐藏', default=False)
|
||||||
parent = models.JSONField('父', default=list, blank=True)
|
child = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE)
|
||||||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='wproduct_subplan')
|
||||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE)
|
|
||||||
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
|
warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
operation = models.ForeignKey('wpm.operation', verbose_name='关联操作',
|
||||||
|
on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation')
|
||||||
|
|
||||||
class Operation(CommonAModel):
|
class Operation(CommonADModel):
|
||||||
"""
|
"""
|
||||||
生产操作
|
生产操作
|
||||||
"""
|
"""
|
||||||
wproducts = models.ManyToManyField(WProduct, verbose_name='关联半成品', through='wpm.operationwproduct')
|
|
||||||
step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True)
|
step = models.ForeignKey(Step, verbose_name='操作步骤', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
use_scrap = models.BooleanField('是否使用的边角料', default=False)
|
use_scrap = models.BooleanField('是否使用的边角料', default=False)
|
||||||
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
|
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
|
||||||
|
is_submited = models.BooleanField('是否提交', default=False)
|
||||||
|
|
||||||
class OperationWproduct(BaseModel):
|
class OperationWproduct(BaseModel):
|
||||||
"""
|
"""
|
||||||
生产操作半成品关联表
|
生产操作半成品关联表
|
||||||
"""
|
"""
|
||||||
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE)
|
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='ow_operation')
|
||||||
wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE)
|
wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='ow_wproduct')
|
||||||
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
|
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
|
||||||
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
|
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
|
||||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
|
||||||
production_plan = models.ForeignKey(ProductionPlan, verbose_name='当前主生产计划', on_delete=models.CASCADE)
|
|
||||||
|
|
||||||
|
|
||||||
class OperationMaterial(BaseModel):
|
class OperationMaterial(BaseModel):
|
||||||
"""
|
"""
|
||||||
生产操作物料消耗产出表
|
生产操作物料消耗产出表
|
||||||
"""
|
"""
|
||||||
type_choices=(
|
type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices)
|
||||||
(1, '消耗'),
|
|
||||||
(2, '产出')
|
|
||||||
)
|
|
||||||
type = models.IntegerField('类型', default=0, choices=type_choices)
|
|
||||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
||||||
wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
|
|
||||||
material = models.ForeignKey(Material, verbose_name='可能产出的副产品', on_delete=models.CASCADE, null=True, blank=True)
|
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
count = models.IntegerField('消耗或产出数量', validators=[MinValueValidator(0)])
|
count = models.IntegerField('消耗或产出数量', validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
class OperationRecord(CommonAModel):
|
wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
subproduction_progress = models.ForeignKey(SubProductionProgress, verbose_name='关联的生产进度', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
|
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||||
|
|
||||||
|
class OperationRecord(BaseModel):
|
||||||
"""
|
"""
|
||||||
记录表格
|
记录表格
|
||||||
"""
|
"""
|
||||||
form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', on_delete=models.CASCADE)
|
form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格', on_delete=models.CASCADE)
|
||||||
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE)
|
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE, related_name='or_operation')
|
||||||
|
is_filled = models.BooleanField('是否填写', default=True)
|
||||||
|
|
||||||
class OperationRecordItem(BaseModel):
|
class OperationRecordItem(BaseModel):
|
||||||
"""
|
"""
|
||||||
|
|
@ -100,3 +103,7 @@ class OperationRecordItem(BaseModel):
|
||||||
sort = models.IntegerField('排序号', default=1)
|
sort = models.IntegerField('排序号', default=1)
|
||||||
operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE)
|
operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class OperationEquip(BaseModel):
|
||||||
|
operation = models.ForeignKey(Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation')
|
||||||
|
equip = models.ForeignKey(Equipment, verbose_name='生产设备', on_delete=models.CASCADE)
|
||||||
|
remark = models.TextField('备注', null=True, blank=True)
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
from rest_framework import serializers, exceptions
|
from rest_framework import serializers, exceptions
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
|
from apps.em.serializers import EquipmentSimpleSerializer
|
||||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse
|
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse
|
||||||
from apps.inm.signals import update_inm
|
from apps.inm.signals import update_inm
|
||||||
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial
|
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer, StepSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer, RecordFormSimpleSerializer, StepSimpleSerializer
|
||||||
|
|
||||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from apps.pm.serializers import SubproductionPlanSimpleSerializer
|
||||||
from apps.qm.models import TestRecord, TestRecordItem
|
from apps.qm.models import TestRecord, TestRecordItem
|
||||||
from apps.system.serializers import UserSimpleSerializer
|
from apps.system.serializers import UserSimpleSerializer
|
||||||
from apps.wpm.models import Operation, WMaterial, WProduct, OperationRecord, OperationRecordItem
|
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
class PickHalfSerializer(serializers.Serializer):
|
class PickHalfSerializer(serializers.Serializer):
|
||||||
|
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||||
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
|
wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'),
|
||||||
required=False) # 从半成品表里直接修改状态
|
required=False) # 从半成品表里直接修改状态
|
||||||
class PickDetailSerializer(serializers.Serializer):
|
class PickDetailSerializer(serializers.Serializer):
|
||||||
|
|
@ -129,25 +132,68 @@ class WProductListSerializer(serializers.ModelSerializer):
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
class OperationDetailSerializer(serializers.ModelSerializer):
|
class OperationDetailSerializer(serializers.ModelSerializer):
|
||||||
wproducts_ = serializers.SerializerMethodField()
|
|
||||||
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
||||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
|
||||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Operation
|
model = Operation
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
def get_wproducts_(self, obj):
|
|
||||||
return list(WProduct.objects.filter(id__in=obj.wproducts).values('id', 'number'))
|
|
||||||
|
|
||||||
class OperationListSerializer(serializers.ModelSerializer):
|
class OperationListSerializer(serializers.ModelSerializer):
|
||||||
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
|
||||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
|
||||||
step_ = StepSimpleSerializer(source='step', read_only=True)
|
step_ = StepSimpleSerializer(source='step', read_only=True)
|
||||||
|
wproduct_count = serializers.SerializerMethodField()
|
||||||
|
equip_count = serializers.SerializerMethodField()
|
||||||
|
record_count = serializers.SerializerMethodField()
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Operation
|
model = Operation
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
def get_wproduct_count(self, obj):
|
||||||
|
return obj.ow_operation.count()
|
||||||
|
|
||||||
|
def get_equip_count(self, obj):
|
||||||
|
return obj.oe_operation.count()
|
||||||
|
|
||||||
|
def get_record_count(self, obj):
|
||||||
|
return obj.or_operation.count()
|
||||||
|
|
||||||
|
class OperationCreateSerializer(serializers.Serializer):
|
||||||
|
"""
|
||||||
|
操作创建
|
||||||
|
"""
|
||||||
|
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
|
||||||
|
# subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False)
|
||||||
|
wproducts = serializers.ListField(child=
|
||||||
|
serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label="半成品ID列表", required=False)
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
# subproduction_plan = data['subproduction_plan']
|
||||||
|
step = data['step']
|
||||||
|
|
||||||
|
# stepIds=[i['id'] for i in subproduction_plan.steps]
|
||||||
|
# if step.id not in stepIds:
|
||||||
|
# raise exceptions.ValidationError('请选择正确的子工序操作')
|
||||||
|
|
||||||
|
if 'wproducts' in data and data['wproducts']:
|
||||||
|
if step.type == Step.STEP_TYPE_DIV:
|
||||||
|
raise exceptions.ValidationError(_('不可进行此操作'))
|
||||||
|
for i in data['wproducts']:
|
||||||
|
if i.is_executed:
|
||||||
|
raise exceptions.ValidationError('不可进行操作')
|
||||||
|
# if i.subproduction_plan != subproduction_plan:
|
||||||
|
# raise exceptions.ValidationError('半成品所属子计划不一致')
|
||||||
|
if i.step != step:
|
||||||
|
raise exceptions.ValidationError('半成品所属子工序不一致')
|
||||||
|
else:
|
||||||
|
if step.type != Step.STEP_TYPE_DIV:
|
||||||
|
raise exceptions.ValidationError(_('请选择半成品进行操作'))
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class OperationUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Operation
|
||||||
|
fields =['use_scrap', 'remark']
|
||||||
|
|
||||||
class OperationInitSerializer(serializers.Serializer):
|
class OperationInitSerializer(serializers.Serializer):
|
||||||
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
|
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")
|
||||||
|
|
@ -193,12 +239,24 @@ class OperationRecordItemSerializer(serializers.ModelSerializer):
|
||||||
model = OperationRecordItem
|
model = OperationRecordItem
|
||||||
fields = ['form_field', 'field_value']
|
fields = ['form_field', 'field_value']
|
||||||
|
|
||||||
|
class OperationRecordSubmitSerializer(serializers.ModelSerializer):
|
||||||
|
record_data = OperationRecordItemSerializer(many=True)
|
||||||
|
class Meta:
|
||||||
|
model = OperationRecord
|
||||||
|
fields = ['record_data']
|
||||||
|
|
||||||
class OperationRecordSerializer(serializers.ModelSerializer):
|
class OperationRecordSerializer(serializers.ModelSerializer):
|
||||||
record_data = OperationRecordItemSerializer(many=True)
|
record_data = OperationRecordItemSerializer(many=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OperationRecord
|
model = OperationRecord
|
||||||
fields = ['form', 'record_data']
|
fields = ['form', 'record_data']
|
||||||
|
|
||||||
|
class OperationWproductListSerializer(serializers.ModelSerializer):
|
||||||
|
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||||
|
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = OperationWproduct
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class OperationSubmitSerializer(serializers.Serializer):
|
class OperationSubmitSerializer(serializers.Serializer):
|
||||||
|
|
@ -238,5 +296,65 @@ class WproductPutInSerializer(serializers.Serializer):
|
||||||
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
|
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
|
||||||
remark = serializers.CharField(label="入库备注", required =False)
|
remark = serializers.CharField(label="入库备注", required =False)
|
||||||
|
|
||||||
|
class OperationEquipListSerializer(serializers.Serializer):
|
||||||
|
equip_ = EquipmentSimpleSerializer(source='equip', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = OperationEquip
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
class OperationEquipUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = OperationEquip
|
||||||
|
fields = ['remark']
|
||||||
|
|
||||||
|
class OperationRecordListSerializer(serializers.ModelSerializer):
|
||||||
|
form_ = RecordFormSimpleSerializer(source='form', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = OperationRecord
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
class OperationMaterialListSerializer(serializers.ModelSerializer):
|
||||||
|
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||||
|
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = OperationMaterial
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
class OperationMaterialCreate1Serailizer(serializers.ModelSerializer):
|
||||||
|
wmaterial = serializers.PrimaryKeyRelatedField(required=True, queryset=WMaterial.objects.all())
|
||||||
|
class Meta:
|
||||||
|
model = OperationMaterial
|
||||||
|
fields = ['operation', 'wmaterial', 'count']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
wmaterial = validated_data['wmaterial']
|
||||||
|
validated_data['material'] = wmaterial.material
|
||||||
|
validated_data['subproduction_plan'] = wmaterial.subproduction_plan
|
||||||
|
validated_data['batch'] = wmaterial.batch
|
||||||
|
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_IN
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
class OperationMaterialCreate2Serailizer(serializers.ModelSerializer):
|
||||||
|
subproduction_progress = serializers.PrimaryKeyRelatedField(required=True, queryset=SubProductionProgress.objects.all())
|
||||||
|
class Meta:
|
||||||
|
model = OperationMaterial
|
||||||
|
fields = ['operation', 'subproduction_progress', 'count']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
subproduction_progress = validated_data['subproduction_progress']
|
||||||
|
validated_data['material'] = subproduction_progress.material
|
||||||
|
validated_data['subproduction_plan'] = subproduction_progress.subproduction_plan
|
||||||
|
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_OUT
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
class OperationMaterialCreate3Serializer(serializers.ModelSerializer):
|
||||||
|
material = serializers.PrimaryKeyRelatedField(required=True, queryset=Material.objects.all())
|
||||||
|
class Meta:
|
||||||
|
model = OperationMaterial
|
||||||
|
fields = ['operation', 'material']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
validated_data['type'] = SubprodctionMaterial.SUB_MA_TYPE_TOOL
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
from typing import List
|
||||||
from apps.pm.models import SubProductionPlan
|
from apps.pm.models import SubProductionPlan
|
||||||
from apps.mtm.models import Step
|
from apps.mtm.models import Step, SubprodctionMaterial
|
||||||
|
from apps.wpm.models import WProduct
|
||||||
class WpmServies(object):
|
class WpmServies(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -13,3 +15,20 @@ class WpmServies(object):
|
||||||
return Step.objects.get(pk=stepIds[pindex+1]), True
|
return Step.objects.get(pk=stepIds[pindex+1]), True
|
||||||
else:
|
else:
|
||||||
return nowstep, False
|
return nowstep, False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_subplans_queryset_from_wproducts(cls, wproducts:List):
|
||||||
|
"""
|
||||||
|
通过半成品列表获取所属子计划
|
||||||
|
"""
|
||||||
|
splans = SubProductionPlan.objects.filter(is_deleted=False, wproduct_subplan__in=wproducts)
|
||||||
|
return splans
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_subplans_queyset_from_step(cls, step:Step):
|
||||||
|
"""
|
||||||
|
通过当前操作获取所有正在进行的子计划
|
||||||
|
"""
|
||||||
|
splans = SubProductionPlan.objects.filter(is_deleted=False,
|
||||||
|
subproduction__usedstep_subproduction__step=step, state=SubProductionPlan.SUBPLAN_STATE_WORKING)
|
||||||
|
return splans
|
||||||
|
|
@ -3,12 +3,18 @@ from rest_framework import urlpatterns
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
|
from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||||
router.register('wproduct', WProductViewSet, basename='wproduct')
|
router.register('wproduct', WProductViewSet, basename='wproduct')
|
||||||
router.register('operation', OperationViewSet, basename='operation')
|
router.register('operation', OperationViewSet, basename='operation')
|
||||||
|
router.register('operation_wproduct', OperationWproductViewSet, basename='operation_wproduct')
|
||||||
|
router.register('operation_equip', OperationEquipViewSet, basename='operation_equip')
|
||||||
|
router.register('operation_record', OperationRecordViewSet, basename='operation_record')
|
||||||
|
router.register('operation_input', OperationMaterialInputViewSet, basename='operation_input')
|
||||||
|
router.register('operation_output', OperationMaterialOutputViewSet, basename='operation_output')
|
||||||
|
router.register('operation_tool', OperationMaterialToolViewSet, basename='operation_tool')
|
||||||
router.register('subplan', WPlanViewSet, basename='wplan')
|
router.register('subplan', WPlanViewSet, basename='wplan')
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('do/init/', DoFormInit.as_view()),
|
path('do/init/', DoFormInit.as_view()),
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from rest_framework.generics import CreateAPIView, GenericAPIView
|
from rest_framework.generics import CreateAPIView, GenericAPIView
|
||||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||||
from rest_framework.utils import serializer_helpers
|
from rest_framework.utils import serializer_helpers
|
||||||
from rest_framework.utils.field_mapping import get_relation_kwargs
|
from rest_framework.utils.field_mapping import get_relation_kwargs
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
||||||
from apps.inm.signals import update_inm
|
from apps.inm.signals import update_inm
|
||||||
from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial, TechDoc
|
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc
|
||||||
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
|
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
|
||||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||||
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer
|
from apps.pm.serializers import SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||||
from apps.qm.models import TestRecordItem
|
from apps.qm.models import TestRecordItem
|
||||||
|
|
||||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from apps.wpm.models import OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
|
from apps.wpm.filters import WMaterialFilterSet
|
||||||
|
from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem
|
||||||
|
|
||||||
from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
|
from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from rest_framework import exceptions, serializers
|
from rest_framework import exceptions, serializers
|
||||||
|
|
@ -25,6 +26,7 @@ from rest_framework import exceptions, serializers
|
||||||
from apps.wpm.services import WpmServies
|
from apps.wpm.services import WpmServies
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from utils.tools import ranstr
|
from utils.tools import ranstr
|
||||||
|
from rest_framework import status
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
class WPlanViewSet(ListModelMixin, GenericViewSet):
|
class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
@ -49,19 +51,25 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
领半成品
|
领半成品
|
||||||
"""
|
"""
|
||||||
mIds = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
|
spps = SubProductionProgress.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
|
||||||
material__type=Material.MA_TYPE_HALFGOOD).values_list('material', flat=True)
|
material__type=Material.MA_TYPE_HALFGOOD, subproduction_plan=sp).select_related('material')
|
||||||
queyset = WProduct.objects.filter(is_hidden=False, material__in=mIds, act_state=WProduct.WPR_ACT_STATE_OK)
|
return Response(SubProductionProgressSerializer(instance=spps, many=True).data)
|
||||||
return Response(WProductListSerializer(instance=queyset, many=True).data)
|
|
||||||
elif request.method=='POST':
|
elif request.method=='POST':
|
||||||
serializer= PickHalfSerializer(data=request.data)
|
serializer= PickHalfSerializer(data=request.data, many=True)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.data
|
vdata = serializer.data
|
||||||
wps = WProduct.objects.filter(pk__in=[x for x in vdata['wproducts']])
|
first_step = Step.objects.get(pk=sp.steps[0]['id'])
|
||||||
first_step = Step.objects.get(pk=sp.steps[0].id)
|
for i in vdata:
|
||||||
|
if 'wproducts' in i and len(i['wproducts'])>0:
|
||||||
|
spp = SubProductionProgress.objects.get(pk=i['id'])
|
||||||
|
spp.count_pick = spp.count_pick + len(i['wproducts'])
|
||||||
|
if spp.count_pick > spp.count:
|
||||||
|
raise exceptions.APIException('超过计划数')
|
||||||
|
spp.save()
|
||||||
|
wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']])
|
||||||
wps.update(step=first_step, is_executed=False,
|
wps.update(step=first_step, is_executed=False,
|
||||||
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
|
act_state=WProduct.WPR_ACT_STATE_DOING, is_hidden=False, warehouse=None,
|
||||||
subproduction_plan=sp, production_plan=sp.production_plan)
|
subproduction_plan=sp, update_by=request.user, update_time=timezone.now())
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -76,7 +84,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||||
vdata = serializer.data
|
vdata = serializer.data
|
||||||
subplan = self.get_object()
|
subplan = self.get_object()
|
||||||
material = subplan.main_product
|
material = subplan.main_product
|
||||||
batch = subplan.production_plan.number
|
batch = subplan.number
|
||||||
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
|
warehouse = WareHouse.objects.get(id=vdata['warehouse'])
|
||||||
wproducts = WProduct.objects.filter(subproduction_plan=subplan,
|
wproducts = WProduct.objects.filter(subproduction_plan=subplan,
|
||||||
act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False)
|
act_state=WProduct.WPR_ACT_STATE_OK, material=material, is_deleted=False)
|
||||||
|
|
@ -119,7 +127,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet):
|
||||||
IProduct.objects.bulk_create(ips2)
|
IProduct.objects.bulk_create(ips2)
|
||||||
# 更新库存并修改半成品进行状态
|
# 更新库存并修改半成品进行状态
|
||||||
update_inm(fifo)
|
update_inm(fifo)
|
||||||
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse)
|
wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user, update_time=timezone.now())
|
||||||
|
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
|
@ -131,7 +139,7 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet):
|
||||||
perms_map={'*':'*'}
|
perms_map={'*':'*'}
|
||||||
queryset = WMaterial.objects.select_related('material').all()
|
queryset = WMaterial.objects.select_related('material').all()
|
||||||
serializer_class = WMaterialListSerializer
|
serializer_class = WMaterialListSerializer
|
||||||
filterset_fields = ['material', 'subproduction_plan', 'subproduction_plan__process', 'subproduction_plan__workshop']
|
filterset_class = WMaterialFilterSet
|
||||||
ordering_fields = ['material__number']
|
ordering_fields = ['material__number']
|
||||||
ordering = ['material__number']
|
ordering = ['material__number']
|
||||||
|
|
||||||
|
|
@ -150,9 +158,9 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
半成品
|
半成品
|
||||||
"""
|
"""
|
||||||
perms_map={'*':'*'}
|
perms_map={'*':'*'}
|
||||||
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False)
|
queryset = WProduct.objects.select_related('step', 'material').filter(is_hidden=False, operation=None)
|
||||||
serializer_class = WProductListSerializer
|
serializer_class = WProductListSerializer
|
||||||
filterset_fields = ['step', 'subproduction_plan', 'material', 'production_plan', 'step__process', 'act_state']
|
filterset_fields = ['step', 'subproduction_plan', 'material', 'step__process', 'act_state']
|
||||||
search_fields = ['number']
|
search_fields = ['number']
|
||||||
ordering_fields = ['id']
|
ordering_fields = ['id']
|
||||||
ordering = ['id']
|
ordering = ['id']
|
||||||
|
|
@ -193,13 +201,13 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
if obj.is_testok:
|
if obj.is_testok:
|
||||||
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
|
wproduct.act_state = WProduct.WPR_ACT_STATE_OK
|
||||||
if wproduct.number is None: # 产生半成品编号
|
if wproduct.number is None: # 产生半成品编号
|
||||||
wproduct.number = 'WP-'+ranstr(7)
|
wproduct.number = 'WP'+ranstr(7)
|
||||||
wproduct.save()
|
wproduct.save()
|
||||||
# 更新子计划状态
|
# 更新子计划状态
|
||||||
# 更新子计划主产品数
|
# 更新子计划主产品数
|
||||||
instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
|
instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan,
|
||||||
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||||
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题
|
instance.count_ok = instance.count_ok + 1 # 这个地方可能会有问题
|
||||||
instance.save()
|
instance.save()
|
||||||
else:# 如果不合格
|
else:# 如果不合格
|
||||||
pass
|
pass
|
||||||
|
|
@ -220,7 +228,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
|
if wproduct.act_state != WProduct.WPR_ACT_STATE_OK:
|
||||||
raise exceptions.APIException('半成品不可入库')
|
raise exceptions.APIException('半成品不可入库')
|
||||||
material = wproduct.material
|
material = wproduct.material
|
||||||
batch = wproduct.production_plan.number
|
batch = wproduct.subproduction_plan.number
|
||||||
# 创建入库记录
|
# 创建入库记录
|
||||||
remark = vdata.get('remark', '')
|
remark = vdata.get('remark', '')
|
||||||
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
|
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
|
||||||
|
|
@ -253,22 +261,353 @@ class WProductViewSet(ListModelMixin, GenericViewSet):
|
||||||
wproduct.save()
|
wproduct.save()
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
class OperationViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
"""
|
"""
|
||||||
生产操作记录
|
生产操作记录
|
||||||
"""
|
"""
|
||||||
perms_map={'*':'*'}
|
perms_map={'*':'*'}
|
||||||
queryset = Operation.objects.select_related('step', 'material').all()
|
queryset = Operation.objects.select_related('step').prefetch_related('ow_operation', 'oe_operation', 'or_operation').all()
|
||||||
serializer_class = OperationListSerializer
|
serializer_class = OperationListSerializer
|
||||||
filterset_fields = ['step', 'step__process']
|
filterset_fields = ['step', 'step__process', 'is_submited']
|
||||||
ordering_fields = ['id']
|
ordering_fields = ['id']
|
||||||
ordering = ['-id']
|
ordering = ['-id']
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return self.queryset.filter(create_by=self.request.user)
|
||||||
|
|
||||||
def get_serializer_class(self):
|
def get_serializer_class(self):
|
||||||
if self.action == 'retrieve':
|
if self.action == 'retrieve':
|
||||||
return OperationDetailSerializer
|
return OperationDetailSerializer
|
||||||
|
elif self.action == 'create':
|
||||||
|
return OperationCreateSerializer
|
||||||
|
elif self.action == 'update':
|
||||||
|
return OperationUpdateSerializer
|
||||||
return super().get_serializer_class()
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
return super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
self.perform_destroy(instance)
|
||||||
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
data = request.data
|
||||||
|
serializer = OperationCreateSerializer(data=data, context={'request':self.request})
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data #校验之后的数据
|
||||||
|
step = vdata['step']
|
||||||
|
op = Operation()
|
||||||
|
op.step = step
|
||||||
|
op.is_submited = False
|
||||||
|
op.create_by = request.user
|
||||||
|
op.save()
|
||||||
|
splans = []
|
||||||
|
# 创建操作所用半成品关联记录
|
||||||
|
if 'wproducts' in vdata:
|
||||||
|
owps = []
|
||||||
|
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
||||||
|
for wpd in vdata['wproducts']:
|
||||||
|
owp = {}
|
||||||
|
owp['operation'] = op
|
||||||
|
owp['wproduct'] = wpd
|
||||||
|
owp['number'] = wpd.number
|
||||||
|
owp['material'] = wpd.material
|
||||||
|
owp['subproduction_plan'] = wpd.subproduction_plan
|
||||||
|
owps.append(OperationWproduct(**owp))
|
||||||
|
OperationWproduct.objects.bulk_create(owps)
|
||||||
|
else:
|
||||||
|
splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts'])
|
||||||
|
# 查询需要填写的自定义表格
|
||||||
|
forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO)
|
||||||
|
for i in forms:
|
||||||
|
opr = OperationRecord()
|
||||||
|
opr.operation = op
|
||||||
|
opr.form = i
|
||||||
|
opr.is_filled = False
|
||||||
|
opr.save()
|
||||||
|
# 查询需要使用的生产设备
|
||||||
|
for i in step.equipments.all():
|
||||||
|
ope = OperationEquip()
|
||||||
|
ope.operation = op
|
||||||
|
ope.equip = i
|
||||||
|
ope.save()
|
||||||
|
# 查询所需的工具工装
|
||||||
|
for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL,
|
||||||
|
subproduction__subplan_subprod__in = splans, is_deleted=False).distinct():
|
||||||
|
opm = OperationMaterial()
|
||||||
|
opm.operation = op
|
||||||
|
opm.material = i.material
|
||||||
|
opm.type = SubprodctionMaterial.SUB_MA_TYPE_TOOL
|
||||||
|
opm.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def submit(self, request, pk=None):
|
||||||
|
"""
|
||||||
|
提交车间操作重要
|
||||||
|
"""
|
||||||
|
op = self.get_object()
|
||||||
|
step = op.step
|
||||||
|
# 检查自定义表单填写
|
||||||
|
if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
|
||||||
|
raise exceptions.APIException('存在自定义表单未填写')
|
||||||
|
# 更新物料消耗进度
|
||||||
|
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN):
|
||||||
|
# 更新车间物料
|
||||||
|
i_wmat = i.wmaterial
|
||||||
|
i_wmat.count = i_wmat.count- i.count
|
||||||
|
i_wmat.save()
|
||||||
|
# 更新子计划物料消耗情况
|
||||||
|
spp = SubProductionProgress.objects.get(subproduction_plan=i_wmat.subproduction_plan,
|
||||||
|
material=i_wmat.material)
|
||||||
|
spp.count_real = spp.count_real + i.count
|
||||||
|
spp.save()
|
||||||
|
# 更新产出
|
||||||
|
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
|
||||||
|
if not i.subproduction_progress.is_main:
|
||||||
|
# 更新车间物料产出情况
|
||||||
|
ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i.subproduction_plan, material=i.material)
|
||||||
|
ins.count = ins.count + i.count
|
||||||
|
ins.save()
|
||||||
|
# 更新子计划物料产出情况
|
||||||
|
spp = i.subproduction_progress
|
||||||
|
spp.count_real = spp.count_real + i.count
|
||||||
|
spp.save()
|
||||||
|
# 更新动态产品表
|
||||||
|
if step.type == Step.STEP_TYPE_NOM:
|
||||||
|
for i in OperationWproduct.objects.filter(operation=op):
|
||||||
|
wp = i.wproduct
|
||||||
|
wsp = i.subproduction_plan
|
||||||
|
# 获取下一步子工序
|
||||||
|
newstep, hasNext = WpmServies.get_next_step(wsp, step)
|
||||||
|
wp.step = newstep
|
||||||
|
wp.pre_step = step
|
||||||
|
if hasNext:
|
||||||
|
wp.is_executed= False
|
||||||
|
else:
|
||||||
|
wp.is_executed = True
|
||||||
|
wp.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||||
|
wp.material = wsp.main_product
|
||||||
|
# 更新子计划进度
|
||||||
|
instance = SubProductionProgress.objects.get(subproduction_plan=wsp,
|
||||||
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||||
|
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题,不够严谨
|
||||||
|
instance.save()
|
||||||
|
wp.operation = None
|
||||||
|
wp.save()
|
||||||
|
elif step.type == Step.STEP_TYPE_DIV:
|
||||||
|
# 更新物料产出情况
|
||||||
|
for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT):
|
||||||
|
if i.subproduction_progress.is_main:
|
||||||
|
newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step)
|
||||||
|
wpr = dict(material=i.material, step=newstep,
|
||||||
|
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
|
||||||
|
subproduction_plan=i.subproduction_plan)
|
||||||
|
for x in range(i.count):
|
||||||
|
WProduct.objects.create(**wpr)
|
||||||
|
elif step.type == Step.STEP_TYPE_COMB:
|
||||||
|
# 隐藏原半成品
|
||||||
|
ows = OperationWproduct.objects.filter(operation=op)
|
||||||
|
if i.subproduction_progress.is_main:
|
||||||
|
newstep, hasNext = WpmServies.get_next_step(i.subproduction_plan, step)
|
||||||
|
wproduct = WProduct()
|
||||||
|
wproduct.material = i.material
|
||||||
|
wproduct.step = newstep
|
||||||
|
wproduct.subproduction_plan = i.subproduction_plan
|
||||||
|
if hasNext:
|
||||||
|
wproduct.act_state = WProduct.WPR_ACT_STATE_DOING
|
||||||
|
wproduct.is_executed = False
|
||||||
|
else:
|
||||||
|
wproduct.act_state = WProduct.WPR_ACT_STATE_TOTEST
|
||||||
|
wproduct.is_executed = True
|
||||||
|
# 更新子计划进度
|
||||||
|
instance = SubProductionProgress.objects.get(subproduction_plan=i.subproduction_plan,
|
||||||
|
is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||||
|
instance.count_real = instance.count_real + 1 # 这个地方可能会有问题,不够严谨
|
||||||
|
instance.save()
|
||||||
|
wproduct.save()
|
||||||
|
ows.update(is_hidden=True, child=wproduct)
|
||||||
|
op.is_submited = True
|
||||||
|
op.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
操作使用的半成品
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationWproduct.objects.select_related('subproduction_plan', 'material').all()
|
||||||
|
serializer_class = OperationWproductListSerializer
|
||||||
|
filterset_fields = ['material', 'subproduction_plan', 'operation']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
wp = instance.wproduct
|
||||||
|
wp.operation = None
|
||||||
|
wp.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
class OperationEquipViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
操作使用的设备
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationEquip.objects.select_related('operation', 'equip').all()
|
||||||
|
serializer_class = OperationEquipListSerializer
|
||||||
|
filterset_fields = ['operation', 'equip']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action == 'update':
|
||||||
|
return OperationEquipUpdateSerializer
|
||||||
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
return super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
操作使用的自定义表格
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationRecord.objects.select_related('operation', 'form').all()
|
||||||
|
serializer_class = OperationRecordListSerializer
|
||||||
|
filterset_fields = ['operation', 'form']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=OperationRecordSubmitSerializer)
|
||||||
|
def submit(self, request, pk=None):
|
||||||
|
serializer = OperationRecordSubmitSerializer(data=request.data, context={'request':self.request})
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.data
|
||||||
|
opr = self.get_object()
|
||||||
|
wrds = []
|
||||||
|
for m in vdata['record_data']: # 保存记录详情
|
||||||
|
form_field = RecordFormField.objects.get(pk=m['form_field'])
|
||||||
|
m['form_field'] = form_field
|
||||||
|
m['field_name'] = form_field.field_name
|
||||||
|
m['field_key'] = form_field.field_key
|
||||||
|
m['field_type'] = form_field.field_type
|
||||||
|
m['field_value'] = m['field_value']
|
||||||
|
m['sort'] = form_field.sort
|
||||||
|
m['operation_record'] = opr
|
||||||
|
wrds.append(OperationRecordItem(**m))
|
||||||
|
OperationRecordItem.objects.bulk_create(wrds)
|
||||||
|
opr.is_filled = True
|
||||||
|
opr.save()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
消耗物料
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN)
|
||||||
|
serializer_class = OperationMaterialListSerializer
|
||||||
|
filterset_fields = ['operation', 'subproduction_plan']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action == 'create':
|
||||||
|
return OperationMaterialCreate1Serailizer
|
||||||
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
产出物料
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
|
||||||
|
serializer_class = OperationMaterialListSerializer
|
||||||
|
filterset_fields = ['operation', 'subproduction_plan']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action == 'create':
|
||||||
|
return OperationMaterialCreate2Serailizer
|
||||||
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
"""
|
||||||
|
工具工装
|
||||||
|
"""
|
||||||
|
perms_map={'*':'*'}
|
||||||
|
queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL)
|
||||||
|
serializer_class = OperationMaterialListSerializer
|
||||||
|
filterset_fields = ['operation', 'subproduction_plan']
|
||||||
|
ordering_fields = ['id']
|
||||||
|
ordering = ['-id']
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action == 'create':
|
||||||
|
return OperationMaterialCreate3Serializer
|
||||||
|
return super().get_serializer_class()
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
instance = self.get_object()
|
||||||
|
if instance.operation.is_submited:
|
||||||
|
raise exceptions.APIException('该操作已提交')
|
||||||
|
instance.delete()
|
||||||
|
return Response()
|
||||||
|
|
||||||
class DoFormInit(CreateAPIView, GenericAPIView):
|
class DoFormInit(CreateAPIView, GenericAPIView):
|
||||||
perms_map={'*':'*'}
|
perms_map={'*':'*'}
|
||||||
serializer_class=OperationInitSerializer
|
serializer_class=OperationInitSerializer
|
||||||
|
|
@ -368,7 +707,6 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
||||||
owp['number'] = wp.number
|
owp['number'] = wp.number
|
||||||
owp['material'] = wp.material
|
owp['material'] = wp.material
|
||||||
owp['subproduction_plan'] = wp.subproduction_plan
|
owp['subproduction_plan'] = wp.subproduction_plan
|
||||||
owp['production_plan'] = wp.production_plan
|
|
||||||
owps.append(OperationWproduct(**owp))
|
owps.append(OperationWproduct(**owp))
|
||||||
OperationWproduct.objects.bulk_create(owps)
|
OperationWproduct.objects.bulk_create(owps)
|
||||||
|
|
||||||
|
|
@ -398,8 +736,7 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
||||||
newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
|
newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step'])
|
||||||
wpr = dict(material=ma, step=newstep,
|
wpr = dict(material=ma, step=newstep,
|
||||||
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
|
act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='',
|
||||||
subproduction_plan=i['subproduction_plan'],
|
subproduction_plan=i['subproduction_plan'])
|
||||||
production_plan=i['subproduction_plan'].production_plan)
|
|
||||||
for x in range(i['count_output']):
|
for x in range(i['count_output']):
|
||||||
WProduct.objects.create(**wpr)
|
WProduct.objects.create(**wpr)
|
||||||
else:
|
else:
|
||||||
|
|
@ -428,7 +765,6 @@ class DoFormSubmit(CreateAPIView, GenericAPIView):
|
||||||
wproduct.material = vdata['subproduction_plan'].main_product
|
wproduct.material = vdata['subproduction_plan'].main_product
|
||||||
wproduct.step = newstep
|
wproduct.step = newstep
|
||||||
wproduct.subproduction_plan=vdata['subproduction_plan']
|
wproduct.subproduction_plan=vdata['subproduction_plan']
|
||||||
wproduct.production_plan=vdata['subproduction_plan'].production_plan
|
|
||||||
wproduct.parent = data['wproducts']
|
wproduct.parent = data['wproducts']
|
||||||
if hasNext:
|
if hasNext:
|
||||||
wproduct.act_state=WProduct.WPR_ACT_STATE_DOING
|
wproduct.act_state=WProduct.WPR_ACT_STATE_DOING
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
celery==5.1.2
|
celery==5.1.2
|
||||||
Django==3.2.6
|
Django==3.2.9
|
||||||
django-celery-beat==2.2.1
|
django-celery-beat==2.2.1
|
||||||
django-cors-headers==3.7.0
|
django-cors-headers==3.7.0
|
||||||
django-filter==2.4.0
|
django-filter==2.4.0
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ from rest_framework.documentation import include_docs_urls
|
||||||
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
from rest_framework_simplejwt.views import (TokenObtainPairView,
|
||||||
TokenRefreshView)
|
TokenRefreshView)
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from utils.view import GenSignature
|
from utils.view import GenSignature, UpdateDevelop
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register('', FileViewSet, basename="file")
|
router.register('', FileViewSet, basename="file")
|
||||||
|
|
@ -72,6 +72,7 @@ urlpatterns = [
|
||||||
|
|
||||||
# 工具
|
# 工具
|
||||||
path('api/utils/signature/', GenSignature.as_view()),
|
path('api/utils/signature/', GenSignature.as_view()),
|
||||||
|
path('api/utils/develop/', UpdateDevelop.as_view()),
|
||||||
|
|
||||||
# 前端页面入口
|
# 前端页面入口
|
||||||
path('',TemplateView.as_view(template_name="index.html"))
|
path('',TemplateView.as_view(template_name="index.html"))
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@ import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
def ranstr(num):
|
def ranstr(num):
|
||||||
salt = ''.join(random.sample(string.ascii_letters + string.digits, num))
|
salt = ''.join(random.sample(string.ascii_lowercase + string.digits, num))
|
||||||
return salt
|
return salt
|
||||||
ranstr(10)
|
ranstr(10)
|
||||||
|
|
@ -49,3 +49,22 @@ class GenSignature(APIView):
|
||||||
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
|
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
|
||||||
cv2.imwrite(path,image)
|
cv2.imwrite(path,image)
|
||||||
return Response(request.data, status=status.HTTP_200_OK)
|
return Response(request.data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDevelop(APIView):
|
||||||
|
"""
|
||||||
|
更新开发服务器
|
||||||
|
"""
|
||||||
|
authentication_classes = ()
|
||||||
|
permission_classes = ()
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
import os
|
||||||
|
# 更新后端
|
||||||
|
os.chdir('/home/hberp')
|
||||||
|
ret = os.popen('git pull https://caoqianming%40ctc.ac.cn:9093qqww@e.coding.net/ctcdevteam/hberp/hberp.git develop')
|
||||||
|
# 打包前端
|
||||||
|
# os.chdir('/home/hberp/hb_client')
|
||||||
|
# os.system('npm run build:prod')
|
||||||
|
# os.system('\cp -rf /home/hberp/hb_client/dist/* /home/hberp/hb_server/vuedist')
|
||||||
|
return Response(ret.read())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue