Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
d6915a9f19
|
@ -15,3 +15,12 @@ export function getProcessYield(data) {
|
|||
data
|
||||
})
|
||||
}
|
||||
//到岗统计
|
||||
export function getatwork(data) {
|
||||
return request({
|
||||
url: '/srm/at_work/',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -418,12 +418,12 @@ export const asyncRoutes = [
|
|||
meta: { title: '人员列表', icon: 'example', perms: ['user_manage'] }
|
||||
},
|
||||
{
|
||||
path: 'personnel',
|
||||
name: 'personnel',
|
||||
component: () => import('@/views/personnel/user'),
|
||||
meta: { title: '考勤列表', icon: 'example', perms: ['user_manage'] }
|
||||
path: 'attendance',
|
||||
name: 'attendance',
|
||||
component: () => import('@/views/personnel/attendance'),
|
||||
meta: { title: '考勤列表', icon: 'example', perms: ['attendance_manage'] }
|
||||
} ,{
|
||||
path: 'userupdate',
|
||||
path: 'userupdate/:id',
|
||||
name: 'userupdate',
|
||||
component: () => import('@/views/personnel/userupdate'),
|
||||
meta: { title: '人员信息详情', icon: 'employee', perms: ['employee_detail'] },
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="今日到岗">
|
||||
<el-table
|
||||
|
||||
:data="userList.results"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="100"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<el-table-column type="index" width="50" label="序号" />
|
||||
<el-table-column align="center" label="工号">
|
||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="姓名">
|
||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="到岗情况">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" v-if="scope.row.is_atwork">在岗</el-tag>
|
||||
|
||||
<el-tag type="danger" v-else>离岗</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="header-center" label="部门">
|
||||
<template v-if="scope.row.dept_" slot-scope="scope">{{
|
||||
scope.row.dept_.name
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="userList.count > 0"
|
||||
:total="userList.count"
|
||||
:page.sync="listQuery.page"
|
||||
:limit.sync="listQuery.page_size"
|
||||
@pagination="getList"
|
||||
/></el-tab-pane>
|
||||
<el-tab-pane label="到岗统计">
|
||||
<div class="container">
|
||||
|
||||
|
||||
<span class="demonstration">年、月</span>
|
||||
<el-date-picker
|
||||
v-model="value2"
|
||||
type="month"
|
||||
placeholder="选择年月">
|
||||
</el-date-picker>
|
||||
<el-button type="primary" @click="submit">主要按钮</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
|
||||
:data="atworkList"
|
||||
style="width: 100%; margin-top: 6px"
|
||||
highlight-current-row
|
||||
row-key="id"
|
||||
height="680"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{ bottomOffset: 41 }"
|
||||
>
|
||||
<el-table-column type="index" width="50" label="序号" />
|
||||
<el-table-column align="center" label="工号">
|
||||
<template slot-scope="scope">{{ scope.row.number }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="姓名">
|
||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="header-center" label="部门">
|
||||
<template slot-scope="scope">{{ scope.row.dept_name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="出勤天数">
|
||||
<template slot-scope="scope">{{ scope.row.count }}</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { getEmployeeList } from "@/api/employee";
|
||||
import checkPermission from "@/utils/permission";
|
||||
|
||||
import {getatwork } from "@/api/srm";
|
||||
import { upUrl, upHeaders } from "@/api/file";
|
||||
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
|
||||
export default {
|
||||
components: { Pagination, Treeselect },
|
||||
data() {
|
||||
return {
|
||||
userList: { count: 0 },
|
||||
atworkList: "",
|
||||
value3:null,
|
||||
value2:null,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
},
|
||||
|
||||
atworkDate:{year:null,month:null},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
created() {
|
||||
this.getList();
|
||||
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
//今日到岗
|
||||
getList() {
|
||||
this.listQuery.fields='number,name,is_atwork,dept_';
|
||||
getEmployeeList(this.listQuery).then((response) => {
|
||||
if (response.data) {
|
||||
this.userList = response.data;
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
//到岗统计
|
||||
|
||||
submit()
|
||||
{
|
||||
|
||||
this.atworkDate.year=this.value2.getFullYear();
|
||||
this.atworkDate.month=this.value2.getMonth()+1;
|
||||
|
||||
getatwork(this.atworkDate).then((response) => {
|
||||
if (response.data) {
|
||||
this.atworkList = response.data;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -2,9 +2,7 @@
|
|||
<div class="app-container">
|
||||
|
||||
<el-card>
|
||||
<div slot="header" class="clearfix">
|
||||
<span>用户</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<el-input
|
||||
|
@ -39,7 +37,7 @@
|
|||
height="100"
|
||||
stripe
|
||||
border
|
||||
v-el-height-adaptive-table="{bottomOffset: 50}"
|
||||
v-el-height-adaptive-table="{bottomOffset: 41}"
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column align="center" label="工号">
|
||||
|
@ -179,8 +177,7 @@ export default {
|
|||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getOrgAll();
|
||||
this.getRoleAll();
|
||||
|
||||
},
|
||||
methods: {
|
||||
checkPermission,
|
||||
|
@ -212,18 +209,7 @@ export default {
|
|||
this.listLoading = false;
|
||||
});
|
||||
},
|
||||
getOrgAll() {
|
||||
this.treeLoding = true;
|
||||
getOrgAll().then(response => {
|
||||
this.orgData = genTree(response.data);
|
||||
this.treeLoding = false;
|
||||
});
|
||||
},
|
||||
getRoleAll() {
|
||||
getRoleAll().then(response => {
|
||||
this.roles = genTree(response.data);
|
||||
});
|
||||
},
|
||||
|
||||
resetFilter() {
|
||||
this.listQuery = {
|
||||
page: 1,
|
||||
|
|
|
@ -1,24 +1,56 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-card>
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<el-row :gutter="2">
|
||||
<el-col :span="9" >
|
||||
<el-card style="height:655px" >
|
||||
|
||||
<div>基础信息</div>
|
||||
<el-form label-width="60px">
|
||||
<el-form-item label="姓名">{{userDate.name}}</el-form-item>
|
||||
<el-form-item label="账户">{{userDate.username}}</el-form-item>
|
||||
|
||||
<el-form-item label="角色">
|
||||
<el-tag
|
||||
v-for="(item, index) in userDate.roles_name"
|
||||
:key="index"
|
||||
style="margin:2px"
|
||||
>{{item}}</el-tag>
|
||||
<el-form ref="Form" :model="user" label-width="80px" label-position="right" :rules="rule1">
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="user.name" placeholder="姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="账户" prop="username">
|
||||
<el-input v-model="user.username" placeholder="账户" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="dept">
|
||||
<el-cascader ref="cascader" :options="orgData" v-model="user.dept" :show-all-levels="false"></el-cascader>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item label="角色" prop="roles">
|
||||
<el-select v-model="user.roles" multiple placeholder="请选择" style="width:100%">
|
||||
<el-option
|
||||
v-for="item in roles"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" prop="dept">
|
||||
<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="user.avatar" :src="user.avatar" class="avatar" />
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon" />
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item size="large">
|
||||
<el-button type="primary" @click="submitFormuser" >保存</el-button>
|
||||
<el-button @click="goBack">返回</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机">{{userDate.phone}}</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-col :span="15" >
|
||||
<el-card style="height:655px" >
|
||||
<div>详细信息</div>
|
||||
<el-form ref="elForm" :model="formData" :rules="rules" size="medium" label-width="100px">
|
||||
<el-row>
|
||||
|
@ -31,6 +63,8 @@
|
|||
:style="{width: '100%'}"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="学历" prop="qualification">
|
||||
<el-input
|
||||
v-model="formData.qualification"
|
||||
|
@ -39,7 +73,7 @@
|
|||
:style="{width: '100%'}"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-col>
|
||||
|
||||
|
||||
|
@ -61,7 +95,8 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="在职状态" prop="job_state">
|
||||
<el-select
|
||||
v-model="formData.job_state"
|
||||
|
@ -77,6 +112,12 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出生年月" prop="birthday">
|
||||
<el-date-picker
|
||||
v-model="formData.birthday"
|
||||
|
@ -87,12 +128,9 @@
|
|||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
|
||||
<el-form-item label="身份证号" prop="id_number">
|
||||
<el-input
|
||||
v-model="formData.id_number"
|
||||
|
@ -107,7 +145,7 @@
|
|||
|
||||
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件照" prop="photo">
|
||||
<el-upload
|
||||
:action="upUrl"
|
||||
|
@ -123,9 +161,8 @@
|
|||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="签名图片" prop="signature">
|
||||
<el-upload :action="upUrl" :headers="upHeaders" accept=".png, .jpeg, .jpg" :before-upload="beforeUpload" class="avatar-uploader"
|
||||
:show-file-list="false"
|
||||
|
@ -139,9 +176,10 @@
|
|||
<el-button @click="goBack">返回</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
|
@ -186,21 +224,27 @@
|
|||
|
||||
import { upUrl, upHeaders } from "@/api/file"
|
||||
import { genSignature } from "@/api/util"
|
||||
import { getUser } from "@/api/user";
|
||||
import { getUser,updateUser } from "@/api/user";
|
||||
import { genTree } from "@/utils"
|
||||
import { getOrgAll } from "@/api/org"
|
||||
import { getRoleAll } from "@/api/role"
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import { getEmployee, updateEmployee } from "@/api/employee";
|
||||
const defaultForm = {
|
||||
user:{},
|
||||
};
|
||||
export default {
|
||||
name: "Employeedetail",
|
||||
components: {},
|
||||
components: { Treeselect },
|
||||
props: ["id"],
|
||||
data() {
|
||||
return {
|
||||
upHeaders: upHeaders(),
|
||||
upUrl: upUrl(),
|
||||
formData: Object.assign({}, defaultForm),
|
||||
userDate:[],
|
||||
user:[],
|
||||
orgData: [],
|
||||
roles: [],
|
||||
genderOptions: [
|
||||
{ value: "男", label: "男" },
|
||||
{ value: "女", label: "女" }
|
||||
|
@ -209,6 +253,7 @@ export default {
|
|||
{ value: 1, label: "在职" },
|
||||
{ value: 2, label: "离职" }
|
||||
],
|
||||
deptvalue:null,
|
||||
rules: {
|
||||
|
||||
ID_number: [
|
||||
|
@ -226,7 +271,8 @@ export default {
|
|||
created() {
|
||||
this.formData.id = this.$route.params.id;
|
||||
this.getDetail();
|
||||
|
||||
this.getOrgAll();
|
||||
this.getRoleAll();
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
|
@ -235,13 +281,38 @@ export default {
|
|||
this.formData = res.data;
|
||||
getUser(res.data.user).then(Response => {
|
||||
|
||||
this.userDate=Response.data;
|
||||
this.user=Response.data;
|
||||
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
getOrgAll() {
|
||||
|
||||
getOrgAll().then(response => {
|
||||
this.orgData = genTree(response.data);
|
||||
|
||||
});
|
||||
},
|
||||
getRoleAll() {
|
||||
getRoleAll({page:0}).then(response => {
|
||||
this.roles =response.data;
|
||||
});
|
||||
},
|
||||
|
||||
handleAvatarSuccess(res, file) {
|
||||
this.user.avatar = res.data.path
|
||||
},
|
||||
beforeAvatarUpload(file) {
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
if (!isLt2M) {
|
||||
this.$message.error("上传头像图片大小不能超过 2MB!");
|
||||
}
|
||||
return isLt2M;
|
||||
},
|
||||
filterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.label.indexOf(value) !== -1;
|
||||
},
|
||||
beforeUpload(file) {
|
||||
const isLt1M = file.size / 1024 / 1024 < 1;
|
||||
if (!isLt1M) {
|
||||
|
@ -277,6 +348,26 @@ export default {
|
|||
},
|
||||
goBack() {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
submitFormuser() {
|
||||
this.$refs["Form"].validate(valid => {
|
||||
if (!valid) return;
|
||||
|
||||
|
||||
this.deptvalue= this.$refs['cascader'].getCheckedNodes();
|
||||
if( this.deptvalue!="")
|
||||
{
|
||||
this.user.dept=this.deptvalue[0].value;
|
||||
}
|
||||
|
||||
updateUser(this.user.id, this.user).then(res => {
|
||||
|
||||
this.$message({
|
||||
message: "编辑成功",
|
||||
type: "success",
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -88,9 +88,9 @@
|
|||
</el-table-column>
|
||||
<el-table-column align="header-center" label="部门">
|
||||
<template
|
||||
v-if="scope.row.dept_name != null"
|
||||
v-if="scope.row.dept"
|
||||
slot-scope="scope"
|
||||
>{{ scope.row.dept_name }}</template>
|
||||
>{{ scope.row.dept_.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建日期">
|
||||
<template slot-scope="scope">
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.db.models import base
|
|||
from rest_framework import urlpatterns
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg
|
||||
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateFIFONumber, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg
|
||||
|
||||
urlpatterns = [
|
||||
path('cleandata/', CleanDataView.as_view()),
|
||||
|
@ -12,6 +12,7 @@ urlpatterns = [
|
|||
path('update_fifoitem/', UpdateFIFOItem.as_view()),
|
||||
path('update_spg/', UpdateSpg.as_view()),
|
||||
path('update_equip_state/', UpdateEquipState.as_view()),
|
||||
path('update_need_to_order/', UpdateNeedToOrder.as_view())
|
||||
path('update_need_to_order/', UpdateNeedToOrder.as_view()),
|
||||
path('update_fifo_number/', UpdateFIFONumber.as_view())
|
||||
]
|
||||
|
||||
|
|
|
@ -105,4 +105,16 @@ class UpdateNeedToOrder(APIView):
|
|||
permission_classes = [IsAdminUser]
|
||||
def post(self, request):
|
||||
WProduct.objects.exclude(to_order=None).update(need_to_order=True)
|
||||
return Response()
|
||||
|
||||
class UpdateFIFONumber(APIView):
|
||||
permission_classes = [IsAdminUser]
|
||||
def post(self, request):
|
||||
from utils.tools import ranstr
|
||||
for i in FIFO.objects.all():
|
||||
if i.type in [FIFO.FIFO_TYPE_DO_IN, FIFO.FIFO_TYPE_PUR_IN]:
|
||||
i.number = 'RK'+ ranstr(7)
|
||||
else:
|
||||
i.number = 'CK' + ranstr(7)
|
||||
i.save()
|
||||
return Response()
|
|
@ -10,6 +10,8 @@ from django.db.models.query import Prefetch
|
|||
class EmployeeSerializer(DynamicFieldsSerializerMixin, ModelSerializer):
|
||||
name = serializers.CharField(source='user.name', read_only=True)
|
||||
dept_ = OrganizationSimpleSerializer(source='user.dept', read_only=True)
|
||||
is_atwork = serializers.BooleanField(source='user.is_atwork', read_only=True)
|
||||
last_check_time = serializers.DateTimeField(source='user.last_check_time', read_only=True)
|
||||
class Meta:
|
||||
model = Employee
|
||||
exclude = ['face_data']
|
||||
|
|
|
@ -2,7 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
class InmConfig(AppConfig):
|
||||
name = 'apps.inm'
|
||||
verbose_name = '库存管理'
|
||||
|
||||
def ready(self):
|
||||
import apps.inm.signals
|
||||
verbose_name = '库存管理'
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-27 07:47
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pum', '0004_puorder_puorderitem'),
|
||||
('inm', '0028_alter_fifoitem_files'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='pu_order',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pum.puorder', verbose_name='关联采购订单'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-28 01:43
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pum', '0004_puorder_puorderitem'),
|
||||
('inm', '0029_fifo_pu_order'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='number',
|
||||
field=models.CharField(default=1, max_length=100, verbose_name='记录编号'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='vendor',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pum.vendor', verbose_name='供应商'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='fifoitemproduct',
|
||||
name='fifoitem',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.fifoitem', verbose_name='关联出入库条目'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-28 06:32
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pum', '0004_puorder_puorderitem'),
|
||||
('inm', '0030_auto_20220128_0943'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifoitem',
|
||||
name='pu_order_item',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pum.puorderitem', verbose_name='关联采购订单条目'),
|
||||
),
|
||||
]
|
|
@ -2,6 +2,7 @@ from django.db import models
|
|||
from django.db.models.base import Model
|
||||
import django.utils.timezone as timezone
|
||||
from django.db.models.query import QuerySet
|
||||
from apps.pum.models import PuOrder, PuOrderItem, Vendor
|
||||
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||
from utils.model import SoftModel, BaseModel
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
@ -72,12 +73,17 @@ class FIFO(CommonADModel):
|
|||
(FIFO_TYPE_PUR_IN, '采购入库'),
|
||||
(FIFO_TYPE_DO_IN, '生产入库')
|
||||
)
|
||||
number = models.CharField('记录编号', max_length=100)
|
||||
type = models.IntegerField('出入库类型', default=1)
|
||||
is_audited = models.BooleanField('是否审核', default=False)
|
||||
auditor = models.ForeignKey(
|
||||
User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True)
|
||||
inout_date = models.DateField('出入库日期', null=True, blank=True)
|
||||
remark = models.CharField('备注', max_length=1000, default='')
|
||||
vendor = models.ForeignKey(Vendor, verbose_name='供应商',
|
||||
on_delete=models.CASCADE, null=True, blank=True)
|
||||
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
|
||||
null=True, blank=True, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class FIFOItem(BaseModel):
|
||||
|
@ -97,6 +103,8 @@ class FIFOItem(BaseModel):
|
|||
subproduction_plan = models.ForeignKey(
|
||||
SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, null=True, blank=True)
|
||||
files = models.ManyToManyField(File, verbose_name='上传材料', blank=True)
|
||||
pu_order_item = models.ForeignKey(PuOrderItem,
|
||||
verbose_name='关联采购订单条目', null=True, blank=True, on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class IProduct(BaseModel):
|
||||
|
@ -116,14 +124,17 @@ class IProduct(BaseModel):
|
|||
|
||||
class FIFOItemProduct(BaseModel):
|
||||
"""
|
||||
出入库产品
|
||||
出入库记录具体产品
|
||||
"""
|
||||
fifoitem = models.ForeignKey(
|
||||
FIFOItem, verbose_name='关联出入库具体产品', on_delete=models.CASCADE)
|
||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True,
|
||||
related_name='fifoitem_wproduct')
|
||||
FIFOItem, verbose_name='关联出入库条目', on_delete=models.CASCADE)
|
||||
wproduct = models.ForeignKey('wpm.wproduct',
|
||||
on_delete=models.CASCADE, verbose_name='关联的动态产品',
|
||||
db_constraint=False, null=True, blank=True,
|
||||
related_name='fifoitem_wproduct')
|
||||
number = models.CharField('物品编号', max_length=50)
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
iproduct = models.ForeignKey(
|
||||
IProduct, verbose_name='关联库存产品', null=True, blank=True, on_delete=models.SET_NULL)
|
||||
IProduct, verbose_name='关联库存产品',
|
||||
null=True, blank=True, on_delete=models.SET_NULL)
|
||||
|
|
|
@ -2,6 +2,7 @@ from rest_framework import exceptions
|
|||
from rest_framework import serializers
|
||||
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse, Inventory
|
||||
from apps.pum.models import PuOrder, Vendor
|
||||
from apps.qm.models import TestRecord, TestRecordItem
|
||||
from apps.sam.serializers import OrderSimpleSerializer
|
||||
|
||||
|
@ -10,6 +11,8 @@ from apps.system.serializers import FileSimpleSerializer, UserSimpleSerializer
|
|||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
from django.db import transaction
|
||||
from utils.mixins import DynamicFieldsSerializerMixin
|
||||
from utils.tools import ranstr
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
|
||||
|
||||
|
@ -73,6 +76,28 @@ class FIFOListSerializer(serializers.ModelSerializer):
|
|||
model = FIFO
|
||||
fields = '__all__'
|
||||
|
||||
class FIFOItemCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FIFOItem
|
||||
fields = ['warehouse',
|
||||
'material', 'batch', 'fifo', 'files', 'pu_order_item']
|
||||
|
||||
def create(self, validated_data):
|
||||
fifo = validated_data['fifo']
|
||||
pu_order_item = validated_data.get('pu_order_item', None)
|
||||
if pu_order_item:
|
||||
if fifo.pu_order != pu_order_item.pu_order:
|
||||
raise ValidationError('项目与采购订单不一致')
|
||||
validated_data['material']=pu_order_item.material
|
||||
else:
|
||||
if fifo.pu_order is not None:
|
||||
raise ValidationError('非采购订单')
|
||||
return super().create(validated_data)
|
||||
|
||||
class FIFOItemUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = FIFOItem
|
||||
fields = ['warehouse', 'batch', 'files']
|
||||
|
||||
class FIFOItemSerializer(serializers.ModelSerializer):
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
|
@ -83,14 +108,14 @@ class FIFOItemSerializer(serializers.ModelSerializer):
|
|||
fields = '__all__'
|
||||
|
||||
|
||||
class IProductInPurSerializer(serializers.ModelSerializer):
|
||||
class FIFOItemProductCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = IProduct
|
||||
fields = ['number']
|
||||
|
||||
|
||||
class FIFODetailInPurSerializer(serializers.ModelSerializer):
|
||||
details = IProductInPurSerializer(many=True, required=False)
|
||||
details = FIFOItemProductCreateSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = FIFOItem
|
||||
|
@ -101,41 +126,26 @@ class MaterialBatchQuerySerializer(serializers.Serializer):
|
|||
warehouse = serializers.IntegerField(label="仓库ID", required=False)
|
||||
materials = serializers.ListField(child=serializers.IntegerField(label="物料ID"), required=False)
|
||||
|
||||
|
||||
class FIFOInPurSerializer(serializers.ModelSerializer):
|
||||
class FIFOInOtherSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
采购入库序列化
|
||||
其他入库序列化
|
||||
"""
|
||||
details = FIFODetailInPurSerializer(many=True)
|
||||
|
||||
details = FIFODetailInPurSerializer(many=True, required=False)
|
||||
vendor = serializers.PrimaryKeyRelatedField(label='供应商ID',
|
||||
queryset=Vendor.objects.all())
|
||||
class Meta:
|
||||
model = FIFO
|
||||
fields = ['details']
|
||||
fields = ['details', 'vendor']
|
||||
|
||||
def create(self, validated_data):
|
||||
details = validated_data.pop('details')
|
||||
if len(details) > 0:
|
||||
pass
|
||||
else:
|
||||
raise serializers.ValidationError('没有入库内容')
|
||||
|
||||
# for i in details:
|
||||
# # 校验批次
|
||||
# try:
|
||||
# if i['batch']:
|
||||
# obj = MaterialBatch.objects.get(batch=i['batch'], material=i['material'])
|
||||
# if obj.warehouse != validated_data['warehouse']:
|
||||
# raise serializers.ValidationError('批次号{}在其他仓库已存在'.format(i['batch']))
|
||||
# except:
|
||||
# pass
|
||||
|
||||
# 创建采购入库
|
||||
with transaction.atomic():
|
||||
validated_data['type'] = FIFO.FIFO_TYPE_PUR_IN
|
||||
obj = FIFO(**validated_data)
|
||||
obj.save()
|
||||
for i in details:
|
||||
if 'details' in i:
|
||||
i['number'] = 'RK' + ranstr(7)
|
||||
p_details = i.pop('details')
|
||||
if len(p_details) != i['count']:
|
||||
raise serializers.ValidationError('数目对不上')
|
||||
|
@ -148,19 +158,30 @@ class FIFOInPurSerializer(serializers.ModelSerializer):
|
|||
x['fifoitem'] = fifoitem
|
||||
p_list0.append(FIFOItemProduct(**x))
|
||||
FIFOItemProduct.objects.bulk_create(p_list0)
|
||||
|
||||
p_list = []
|
||||
for x in p_details:
|
||||
x['material'] = i['material']
|
||||
x['warehouse'] = validated_data['warehouse']
|
||||
x['batch'] = i['batch']
|
||||
p_list.append(IProduct(**x))
|
||||
IProduct.objects.bulk_create(p_list)
|
||||
else:
|
||||
i['fifo'] = obj
|
||||
i['number'] = 'RK' + ranstr(7)
|
||||
FIFOItem.objects.create(**i)
|
||||
return obj
|
||||
|
||||
class FIFOInPurSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
采购入库序列化
|
||||
"""
|
||||
pu_order = serializers.PrimaryKeyRelatedField(label='采购订单ID',
|
||||
queryset = PuOrder.objects.filter(is_audited=True))
|
||||
|
||||
class Meta:
|
||||
model = FIFO
|
||||
fields = ['pu_order']
|
||||
|
||||
def create(self, validated_data):
|
||||
pu_order = validated_data['pu_order']
|
||||
validated_data['vendor'] = pu_order.vendor
|
||||
validated_data['number'] = 'RK' + ranstr(7)
|
||||
obj = FIFO.objects.create(**validated_data)
|
||||
return obj
|
||||
|
||||
|
||||
class InmTestRecordItemCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
from rest_framework.exceptions import ValidationError
|
||||
from apps.inm.models import FIFOItemProduct, IProduct, Inventory, MaterialBatch, FIFO, FIFOItem
|
||||
|
||||
class InmService:
|
||||
@classmethod
|
||||
def update_inm(cls, instance:FIFO, type:int=1):
|
||||
"""
|
||||
更新库存(正反)
|
||||
"""
|
||||
if instance.type in [FIFO.FIFO_TYPE_PUR_IN, FIFO.FIFO_TYPE_DO_IN]: # 采购入库, 生产入库
|
||||
# 更新相关表
|
||||
for i in FIFOItem.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
warehouse = i.warehouse
|
||||
o1, _ = Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0})
|
||||
o1.count = o1.count + i.count
|
||||
o1.save()
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
||||
o2.count = o2.count + i.count
|
||||
o2.save()
|
||||
material.count = material.count + i.count
|
||||
material.save()
|
||||
|
||||
# 创建IProduct
|
||||
ips2 = []
|
||||
for m in FIFOItemProduct.objects.filter(fifoitem=i):
|
||||
ip = {}
|
||||
ip['warehouse'] = warehouse
|
||||
ip['batch'] = i.batch
|
||||
wp = m.wproduct
|
||||
ip['wproduct'] = wp
|
||||
ip['number'] = m.number
|
||||
ip['material'] = m.material
|
||||
ips2.append(IProduct(**ip))
|
||||
IProduct.objects.bulk_create(ips2)
|
||||
|
||||
# 如果是采购入库更新采购订单表
|
||||
if instance.type == FIFO.FIFO_TYPE_PUR_IN:
|
||||
pur_order_item = i.pur_order_item
|
||||
delivered_count = pur_order_item.delivered_count + i.count
|
||||
if delivered_count > pur_order_item.count:
|
||||
raise ValidationError('超出采购订单所需量')
|
||||
pur_order_item.delivered_count = delivered_count
|
||||
pur_order_item.save()
|
||||
|
||||
elif instance.type in [FIFO.FIFO_TYPE_DO_OUT, FIFO.FIFO_TYPE_SALE_OUT]: # 生产领料 销售出库
|
||||
# 更新相关表
|
||||
for i in FIFOItem.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
warehouse = i.warehouse
|
||||
o1 = Inventory.objects.get(material=material, warehouse=warehouse)
|
||||
temp_count = o1.count - i.count
|
||||
if temp_count < 0:
|
||||
raise ValidationError('库存不足,操作失败')
|
||||
o1.count = temp_count
|
||||
o1.save()
|
||||
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=i.batch)
|
||||
temp_count = o2.count - i.count
|
||||
if temp_count < 0:
|
||||
raise ValidationError('库存不足,操作失败')
|
||||
o2.count = temp_count
|
||||
o2.save()
|
||||
temp_count = material.count - i.count
|
||||
if temp_count < 0:
|
||||
raise ValidationError('库存不足,操作失败')
|
||||
material.count = temp_count
|
||||
material.save()
|
||||
|
||||
# 删除IProduct
|
||||
if instance.type == FIFO.FIFO_TYPE_DO_OUT:
|
||||
# 生产领料的情况直接从IProduct中删除
|
||||
numbers = FIFOItemProduct.objects.filter(fifoitem=i).values_list('number', flat=True)
|
||||
IProduct.objects.filter(number__in=numbers).delete()
|
|
@ -1,58 +0,0 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from apps.inm.models import FIFOItemProduct, IProduct, Inventory, MaterialBatch, FIFO, FIFOItem
|
||||
|
||||
|
||||
def update_inm(instance:FIFO, type:int=1):
|
||||
"""
|
||||
更新库存(正反)
|
||||
"""
|
||||
if instance.type in [FIFO.FIFO_TYPE_PUR_IN, FIFO.FIFO_TYPE_DO_IN]: # 采购入库, 生产入库
|
||||
# 更新相关表
|
||||
for i in FIFOItem.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
warehouse = i.warehouse
|
||||
o1, _ = Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0})
|
||||
o1.count = o1.count + i.count
|
||||
o1.save()
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
||||
o2.count = o2.count + i.count
|
||||
o2.save()
|
||||
material.count = material.count + i.count
|
||||
material.save()
|
||||
|
||||
# 创建IProduct
|
||||
ips2 = []
|
||||
for m in FIFOItemProduct.objects.filter(fifoitem=i):
|
||||
ip = {}
|
||||
ip['warehouse'] = warehouse
|
||||
ip['batch'] = i.batch
|
||||
wp = m.wproduct
|
||||
ip['wproduct'] = wp
|
||||
ip['number'] = m.number
|
||||
ip['material'] = m.material
|
||||
ips2.append(IProduct(**ip))
|
||||
IProduct.objects.bulk_create(ips2)
|
||||
|
||||
elif instance.type in [FIFO.FIFO_TYPE_DO_OUT, FIFO.FIFO_TYPE_SALE_OUT]: # 生产领料 销售出库
|
||||
# 更新相关表
|
||||
for i in FIFOItem.objects.filter(fifo=instance):
|
||||
material = i.material
|
||||
warehouse = i.warehouse
|
||||
o1 = Inventory.objects.get(material=material, warehouse=warehouse)
|
||||
o1.count = o1.count - i.count
|
||||
o1.save()
|
||||
o2 = MaterialBatch.objects.get(material=material, warehouse=warehouse, batch=i.batch)
|
||||
o2.count = o2.count - i.count
|
||||
o2.save()
|
||||
material.count = material.count - i.count
|
||||
material.save()
|
||||
|
||||
# 删除IProduct
|
||||
if instance.type == FIFO.FIFO_TYPE_DO_OUT:
|
||||
numbers = FIFOItemProduct.objects.filter(fifoitem=i).values_list('number', flat=True)
|
||||
IProduct.objects.filter(number__in=numbers).delete()
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin
|
||||
from rest_framework.exceptions import APIException, ValidationError
|
||||
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin, CreateModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.inm.filters import IProductFilterSet, MbFilterSet
|
||||
|
||||
from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse, Inventory
|
||||
from apps.inm.serializers import FIFOItemSerializer, FIFOInPurSerializer, FIFOItemUpdateSerializer, FIFOListSerializer, IProductListSerializer, \
|
||||
from apps.inm.serializers import FIFOInOtherSerializer, FIFOItemCreateSerializer, FIFOItemSerializer, FIFOInPurSerializer, FIFOItemUpdateSerializer, FIFOListSerializer, IProductListSerializer, \
|
||||
InmTestRecordCreateSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, \
|
||||
WareHouseCreateUpdateSerializer, InventorySerializer
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.inm.services import InmService
|
||||
from apps.qm.models import TestRecordItem
|
||||
from apps.system.mixins import CreateUpdateModelAMixin
|
||||
from rest_framework.decorators import action
|
||||
|
@ -77,7 +77,7 @@ class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
|
|||
return Response(MaterialBatchSerializer(instance=queryset, many=True).data)
|
||||
|
||||
|
||||
class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
|
||||
class FIFOItemViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
|
||||
"""
|
||||
出入库记录详情表
|
||||
"""
|
||||
|
@ -93,12 +93,27 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, Gener
|
|||
def get_serializer_class(self):
|
||||
if self.action == 'update':
|
||||
return FIFOItemUpdateSerializer
|
||||
elif self.action == 'create':
|
||||
return FIFOItemCreateSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
if instance.fifo.is_audited:
|
||||
raise APIException('该出入库记录已通过审核, 无法删除')
|
||||
return super().perform_destroy(instance)
|
||||
def create(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.fifo.is_audited:
|
||||
raise ValidationError('该出入库记录已审核')
|
||||
return super().create(request, *args, **kwargs)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.fifo.is_audited:
|
||||
raise ValidationError('该出入库记录已审核')
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.fifo.is_audited:
|
||||
raise ValidationError('该出入库记录已审核')
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=InmTestRecordCreateSerializer)
|
||||
def test(self, request, pk=None):
|
||||
|
@ -160,6 +175,17 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save(create_by=request.user)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'},
|
||||
serializer_class=FIFOInOtherSerializer)
|
||||
def in_other(self, request, pk=None):
|
||||
"""
|
||||
其他入库
|
||||
"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save(create_by=request.user)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=serializers.Serializer)
|
||||
def audit(self, request, pk=None):
|
||||
|
@ -167,6 +193,8 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
审核通过
|
||||
"""
|
||||
obj = self.get_object()
|
||||
if not FIFOItem.objects.filter(fifo=obj).exists():
|
||||
raise ValidationError('出入库条目为空')
|
||||
for i in FIFOItem.objects.filter(fifo=obj, need_test=True):
|
||||
if not i.is_testok:
|
||||
raise APIException('未检验通过, 不可审核')
|
||||
|
@ -177,7 +205,7 @@ class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
|
|||
obj.auditor = request.user
|
||||
obj.inout_date = timezone.now() # 也是审核日期
|
||||
obj.save()
|
||||
update_inm(obj) # 更新库存
|
||||
InmService.update_inm(obj) # 更新库存
|
||||
return Response()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-27 07:47
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('mtm', '0044_subproduction_need_combtest'),
|
||||
('pum', '0003_remove_vendor_material'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PuOrder',
|
||||
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='删除标记')),
|
||||
('number', models.CharField(max_length=100, unique=True, verbose_name='订单编号')),
|
||||
('is_audited', models.BooleanField(default=False, verbose_name='是否审核')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='puorder_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='puorder_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
('vendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pum.vendor', verbose_name='供应商')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '采购订单',
|
||||
'verbose_name_plural': '采购订单',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PuOrderItem',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
|
||||
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
|
||||
('count', models.PositiveIntegerField(default=0, verbose_name='所需数量')),
|
||||
('delivered_count', models.PositiveIntegerField(default=0, verbose_name='已到货数量')),
|
||||
('delivery_date', models.DateField(verbose_name='截止到货日期')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='采购材料')),
|
||||
('pu_order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='item_pu_order', to='pum.puorder', verbose_name='关联采购订单')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -5,7 +5,7 @@ from django.db.models.query import QuerySet
|
|||
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
|
||||
from utils.model import SoftModel, BaseModel
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
from apps.mtm.models import Material
|
||||
|
||||
|
||||
class Vendor(CommonAModel):
|
||||
|
@ -23,4 +23,26 @@ class Vendor(CommonAModel):
|
|||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
||||
class PuOrder(CommonAModel):
|
||||
"""
|
||||
采购订单信息
|
||||
"""
|
||||
number = models.CharField('订单编号', max_length=100, unique=True)
|
||||
vendor = models.ForeignKey(Vendor, verbose_name='供应商', on_delete=models.CASCADE)
|
||||
is_audited = models.BooleanField('是否审核', default=False)
|
||||
class Meta:
|
||||
verbose_name = '采购订单'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
class PuOrderItem(BaseModel):
|
||||
"""
|
||||
采购具体项目
|
||||
"""
|
||||
material = models.ForeignKey(Material, verbose_name='采购材料', on_delete=models.CASCADE)
|
||||
count = models.PositiveIntegerField('所需数量', default=0)
|
||||
delivered_count = models.PositiveIntegerField('已到货数量', default=0)
|
||||
delivery_date = models.DateField('截止到货日期')
|
||||
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
|
||||
on_delete=models.CASCADE, null=True, blank=True, related_name='item_pu_order')
|
|
@ -1,9 +1,47 @@
|
|||
from rest_framework.serializers import ModelSerializer
|
||||
|
||||
from .models import Vendor
|
||||
|
||||
from rest_framework.serializers import ModelSerializer, ValidationError
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
from .models import PuOrder, PuOrderItem, Vendor
|
||||
|
||||
class VendorSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = Vendor
|
||||
fields = '__all__'
|
||||
|
||||
class VendorSimpleSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = Vendor
|
||||
fields = ['id', 'name']
|
||||
|
||||
class PuOrderItemSerializer(ModelSerializer):
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
class Meta:
|
||||
model = PuOrderItem
|
||||
fields = '__all__'
|
||||
|
||||
class PuOrderItemCreateSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = PuOrderItem
|
||||
fields = ['count', 'delivery_date', 'pu_order', 'material']
|
||||
|
||||
def validate(self, attrs):
|
||||
pu_order = attrs['pu_order']
|
||||
if pu_order.is_audited:
|
||||
raise ValidationError('采购订单已审核')
|
||||
return super().validate(attrs)
|
||||
|
||||
class PuOrderItemUpdateSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = PuOrderItem
|
||||
fields = ['count', 'delivery_date']
|
||||
|
||||
class PuOrderSerializer(ModelSerializer):
|
||||
vendor_ = VendorSimpleSerializer(source='vendor', read_only=True)
|
||||
items = PuOrderItemSerializer(source='item_pu_order', many=True, read_only=True)
|
||||
class Meta:
|
||||
model = PuOrder
|
||||
fields = '__all__'
|
||||
|
||||
class PuOrderCreateUpdateSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = PuOrder
|
||||
fields = ['number', 'vendor']
|
|
@ -1,11 +1,13 @@
|
|||
from django.db.models import base
|
||||
from rest_framework import urlpatterns
|
||||
from apps.pum.views import VendorViewSet
|
||||
from apps.pum.views import PuOrderItemViewSet, PuOrderViewSet, VendorViewSet
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('vendor', VendorViewSet, basename='vendor')
|
||||
router.register('pu_order', PuOrderViewSet, basename='pu_order')
|
||||
router.register('pu_order_item', PuOrderItemViewSet, basename='pu_order_item')
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
|
||||
from django.shortcuts import render
|
||||
from numpy import delete
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from apps.pum.models import Vendor
|
||||
from apps.pum.serializers import VendorSerializer
|
||||
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
from apps.pum.models import PuOrder, PuOrderItem, Vendor
|
||||
from apps.pum.serializers import PuOrderCreateUpdateSerializer, PuOrderItemCreateSerializer, PuOrderItemSerializer, PuOrderItemUpdateSerializer, PuOrderSerializer, VendorSerializer
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
|
||||
|
||||
from rest_framework.exceptions import APIException, ValidationError
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework import serializers
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
# Create your views here.
|
||||
class VendorViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||
"""
|
||||
|
@ -19,3 +25,69 @@ class VendorViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
filterset_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
|
||||
class PuOrderViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||
"""
|
||||
采购订单-增删改查
|
||||
"""
|
||||
perms_map = {'get': '*', 'post': '*',
|
||||
'put': '*', 'delete': '*'}
|
||||
queryset = PuOrder.objects.select_related('vendor').\
|
||||
prefetch_related('item_pu_order').all()
|
||||
serializer_class = PuOrderSerializer
|
||||
search_fields = ['number', 'vendor__name']
|
||||
filterset_fields = ['vendor']
|
||||
ordering = ['-create_time']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action in ['create', 'update']:
|
||||
return PuOrderCreateUpdateSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.is_audited:
|
||||
raise ValidationError('该采购订单已审核')
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.is_audited:
|
||||
raise ValidationError('该采购订单已审核')
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'},
|
||||
serializer_class=serializers.Serializer)
|
||||
def audit(self, request, pk=None):
|
||||
obj = self.get_object()
|
||||
if obj.item_pu_order.exists() and not obj.is_audited:
|
||||
obj.is_audited = True
|
||||
obj.update_by = request.user
|
||||
obj.save()
|
||||
return Response()
|
||||
return Response('订单状态有误', status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class PuOrderItemViewSet(CreateModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
采购订单条目
|
||||
"""
|
||||
perms_map = {'get': '*', 'post': '*',
|
||||
'put': '*', 'delete': '*'}
|
||||
queryset = PuOrderItem.objects.select_related('material').all()
|
||||
serializer_class = PuOrderItemSerializer
|
||||
filterset_fields = ['pu_order', 'material']
|
||||
ordering = ['-create_time']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'create':
|
||||
return PuOrderItemCreateSerializer
|
||||
elif self.action == 'update':
|
||||
return PuOrderItemUpdateSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
obj = self.get_object()
|
||||
if obj.pu_order.is_audited:
|
||||
raise ValidationError('所属采购已审核')
|
||||
return super().destroy(request, *args, **kwargs)
|
|
@ -73,7 +73,7 @@ class TestRecord(CommonADModel):
|
|||
remark = models.TextField('备注', default='')
|
||||
|
||||
|
||||
class TestRecordItem(BaseModel):
|
||||
class TestRecordItem(CommonADModel):
|
||||
"""
|
||||
记录表格字段值
|
||||
"""
|
||||
|
|
|
@ -124,13 +124,17 @@ class TestRecordUpdateSerializer(serializers.ModelSerializer):
|
|||
fields = ['is_testok', 'record_data']
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
# 获取更新人
|
||||
update_by = self.context['request'].user
|
||||
record_data = validated_data.pop('record_data')
|
||||
for attr, value in validated_data.items():
|
||||
setattr(instance, attr, value)
|
||||
instance.save()
|
||||
instance.save(update_by=update_by)
|
||||
for i in record_data:
|
||||
tri = i['id']
|
||||
tri.field_value = i['field_value']
|
||||
if i['field_value'] != tri.field_value:
|
||||
tri.field_value = i['field_value']
|
||||
tri.update_by = update_by
|
||||
tri.is_testok = i['is_testok']
|
||||
tri.is_hidden = i['is_hidden']
|
||||
tri.save()
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-27 07:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sam', '0011_order_need_mtest'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='delivery_date',
|
||||
field=models.DateField(verbose_name='截止交货日期'),
|
||||
),
|
||||
]
|
|
@ -58,7 +58,7 @@ class Order(CommonAModel):
|
|||
count = models.PositiveIntegerField('所需数量', default=0)
|
||||
planed_count = models.PositiveIntegerField('已排数量', default=0)
|
||||
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
|
||||
delivery_date = models.DateField('交货日期')
|
||||
delivery_date = models.DateField('截止交货日期')
|
||||
need_mtest = models.BooleanField('是否需要军检', default=False)
|
||||
class Meta:
|
||||
verbose_name = '订单信息'
|
||||
|
|
|
@ -2,6 +2,7 @@ from rest_framework.mixins import ListModelMixin, DestroyModelMixin, CreateModel
|
|||
from rest_framework.viewsets import GenericViewSet
|
||||
from rest_framework.response import Response
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse
|
||||
from apps.inm.services import InmService
|
||||
from apps.mtm.models import Material
|
||||
from apps.sam.models import Sale, SaleProduct
|
||||
from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer
|
||||
|
@ -11,10 +12,11 @@ from rest_framework.decorators import action
|
|||
from django.utils import timezone
|
||||
|
||||
from apps.system.mixins import CreateUpdateModelAMixin
|
||||
from apps.inm.signals import update_inm
|
||||
from rest_framework import serializers
|
||||
from django.db.models import Count
|
||||
|
||||
from utils.tools import ranstr
|
||||
|
||||
class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
销售记录
|
||||
|
@ -71,6 +73,7 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
fifo.auditor = request.user
|
||||
fifo.inout_date = timezone.now()
|
||||
fifo.create_by = request.user
|
||||
fifo.number = 'CK' + ranstr(7)
|
||||
fifo.save()
|
||||
# 创建出库条目
|
||||
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||
|
@ -104,7 +107,7 @@ class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update(
|
||||
act_state=WProduct.WPR_ACT_STATE_SELLED)
|
||||
# 更新库存
|
||||
update_inm(fifo)
|
||||
InmService.update_inm(fifo)
|
||||
# 变更审核状态
|
||||
obj.is_audited = True
|
||||
obj.save()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
from django.shortcuts import render
|
||||
from numpy import number
|
||||
from rest_framework import serializers
|
||||
from rest_framework.generics import ListAPIView, CreateAPIView
|
||||
from rest_framework.views import APIView
|
||||
|
@ -78,10 +79,11 @@ class AtWorkCountView(CreateAPIView):
|
|||
serializer.is_valid(raise_exception=True)
|
||||
vdata = serializer.validated_data
|
||||
ret = ClockRecord.objects.filter(
|
||||
create_time__year = vdata['year'],
|
||||
create_time__month = vdata['month']
|
||||
update_time__year = vdata['year'],
|
||||
update_time__month = vdata['month']
|
||||
).values(
|
||||
user_id = F('create_by'),
|
||||
number = F('create_by__employee_user__number'),
|
||||
username = F('create_by__username'),
|
||||
name = F('create_by__name'),
|
||||
dept_name = F('create_by__dept__name')).annotate(
|
||||
|
|
|
@ -4,8 +4,8 @@ from rest_framework.serializers import ModelSerializer
|
|||
from apps.em.models import Equipment
|
||||
from apps.em.serializers import EquipmentSimpleSerializer
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.inm.serializers import WareHouseSimpleSerializer
|
||||
from apps.inm.services import InmService
|
||||
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, StepSimpleSerializer
|
||||
|
||||
|
@ -21,6 +21,7 @@ from apps.wpm.models import Operation, OperationEquip, OperationMaterial, Operat
|
|||
from django.db import transaction
|
||||
from apps.sam.models import Order
|
||||
from utils.mixins import DynamicFieldsSerializerMixin
|
||||
from utils.tools import ranstr
|
||||
|
||||
class PickHalfSerializer(serializers.Serializer):
|
||||
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||
|
@ -29,12 +30,14 @@ class PickHalfSerializer(serializers.Serializer):
|
|||
|
||||
class PickHalfsSerializer(serializers.ListSerializer):
|
||||
child = PickHalfSerializer()
|
||||
|
||||
class PickDetailSerializer(serializers.Serializer):
|
||||
material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID")
|
||||
batch = serializers.CharField(label='物料批次', allow_blank=True)
|
||||
warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID")
|
||||
pick_count = serializers.IntegerField(label="领料数量", required=False)
|
||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), label='库存半成品ID',required=False, many=True)
|
||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), label='库存半成品ID',
|
||||
required=False, many=True)
|
||||
|
||||
class PickSerializer(serializers.Serializer):
|
||||
subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID")
|
||||
|
@ -58,7 +61,9 @@ class PickSerializer(serializers.Serializer):
|
|||
# 创建出库记录
|
||||
|
||||
with transaction.atomic():
|
||||
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user)
|
||||
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT,
|
||||
inout_date=timezone.now(), create_by=self.context['request'].user,
|
||||
number = 'CK' + ranstr(7))
|
||||
for i in picks:
|
||||
isLowLevel = False
|
||||
# 更新出库详情
|
||||
|
@ -123,7 +128,7 @@ class PickSerializer(serializers.Serializer):
|
|||
# 更新库存
|
||||
fifo.is_audited = True
|
||||
fifo.save()
|
||||
update_inm(fifo)
|
||||
InmService.update_inm(fifo)
|
||||
return fifo
|
||||
|
||||
class WMaterialListSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, \
|
|||
ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct
|
||||
from apps.inm.signals import update_inm
|
||||
from apps.inm.services import InmService
|
||||
from apps.mtm.models import Material, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc
|
||||
from apps.mtm.serializers import RecordFormDetailSerializer, SubprodctionMaterialListSerializer, TechDocListSerializer
|
||||
from apps.pm.models import SubProductionPlan, SubProductionProgress
|
||||
|
@ -37,6 +37,8 @@ from django.utils import timezone
|
|||
from rest_framework import status
|
||||
from django.db.models import Count
|
||||
|
||||
from utils.tools import ranstr
|
||||
|
||||
|
||||
# Create your views here.
|
||||
|
||||
|
@ -188,7 +190,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
raise exceptions.APIException('该产品当前状态不可检验')
|
||||
|
||||
savedict = dict(
|
||||
create_by=self.request.user,
|
||||
create_by=request.user,
|
||||
wproduct=wproduct,
|
||||
material=wproduct.material,
|
||||
number=wproduct.number,
|
||||
|
@ -219,6 +221,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
tri.test_record = tr
|
||||
tri.form_field = i
|
||||
tri.is_hidden = i.is_hidden
|
||||
tri.create_by = request.user
|
||||
tri.save()
|
||||
return Response(TestRecordDetailSerializer(instance=tr).data)
|
||||
|
||||
|
@ -242,9 +245,10 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
'subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id'))
|
||||
# 创建入库记录
|
||||
remark = vdata.get('remark', '')
|
||||
fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN,
|
||||
is_audited=True, auditor=request.user, inout_date=timezone.now(),
|
||||
create_by=request.user, remark=remark)
|
||||
fifo = FIFO.objects.create(
|
||||
type=FIFO.FIFO_TYPE_DO_IN,
|
||||
is_audited=True, auditor=request.user, inout_date=timezone.now(),
|
||||
create_by=request.user, remark=remark, number='RK'+ranstr(7))
|
||||
# 创建入库明细
|
||||
for i in wproducts_a:
|
||||
spi = SubProductionPlan.objects.get(pk=i['subproduction_plan'])
|
||||
|
@ -270,7 +274,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
ips.append(FIFOItemProduct(**ip))
|
||||
FIFOItemProduct.objects.bulk_create(ips)
|
||||
# 更新库存并修改半成品进行状态
|
||||
update_inm(fifo)
|
||||
InmService.update_inm(fifo)
|
||||
for i in wproducts:
|
||||
i.act_state = WProduct.WPR_ACT_STATE_INM
|
||||
i.warehouse = warehouse
|
||||
|
@ -320,7 +324,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
ips.append(FIFOItemProduct(**ip))
|
||||
FIFOItemProduct.objects.bulk_create(ips)
|
||||
# 更新库存并修改半成品进行状态
|
||||
update_inm(fifo)
|
||||
InmService.update_inm(fifo)
|
||||
wproduct.act_state = WProduct.WPR_ACT_STATE_INM
|
||||
wproduct.warehouse = warehouse
|
||||
wproduct.save()
|
||||
|
|
|
@ -11,3 +11,4 @@ psutil==5.8.0
|
|||
pillow==8.3.1
|
||||
opencv-python==4.5.3.56
|
||||
django-celery-results==2.2.0
|
||||
numpy==1.21.2
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.parsers import MultiPartParser
|
||||
|
@ -6,10 +7,9 @@ from PIL import Image
|
|||
from django.conf import settings
|
||||
from rest_framework import status
|
||||
from datetime import datetime
|
||||
import os
|
||||
import uuid
|
||||
import cv2
|
||||
from server.settings import BASE_DIR
|
||||
import numpy as np
|
||||
|
||||
# class UploadFileView(APIView):
|
||||
# permission_classes = [IsAuthenticated]
|
||||
|
@ -39,16 +39,33 @@ class GenSignature(APIView):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
path = (BASE_DIR + request.data['path']).replace('\\', '/')
|
||||
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
||||
size = image.shape
|
||||
for i in range(size[0]):
|
||||
for j in range(size[1]):
|
||||
if image[i][j][0]>100 and image[i][j][1]>100 and image[i][j][2]>100:
|
||||
image[i][j][3] = 0
|
||||
else:
|
||||
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
|
||||
cv2.imwrite(path,image)
|
||||
return Response(request.data, status=status.HTTP_200_OK)
|
||||
try:
|
||||
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
|
||||
size = image.shape
|
||||
width = size[0] # 宽度
|
||||
height = size[1] # 高度
|
||||
if size[2] != 4: # 判断
|
||||
background = np.zeros((size[0], size[1], 4))
|
||||
for yh in range(height):
|
||||
for xw in range(width):
|
||||
background[xw, yh, :3] = image[xw, yh]
|
||||
background[xw, yh, 3] = 255
|
||||
image = background
|
||||
size = image.shape
|
||||
for i in range(size[0]):
|
||||
for j in range(size[1]):
|
||||
if image[i][j][0]>100 and image[i][j][1]>100 and image[i][j][2]>100:
|
||||
image[i][j][3] = 0
|
||||
else:
|
||||
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
|
||||
ext = os.path.splitext(path)
|
||||
new_path = ext[0] + '.png'
|
||||
cv2.imwrite(new_path, image)
|
||||
return Response({'path':new_path.replace(BASE_DIR, '')}, status=status.HTTP_200_OK)
|
||||
except:
|
||||
return Response('签名照处理失败,请重新上传',
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
import time
|
||||
class UpdateDevelop(APIView):
|
||||
|
|
Loading…
Reference in New Issue