Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
e71d5e0e32
|
@ -19,7 +19,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted(){
|
||||
// this.$store.dispatch("user/getCount", {})
|
||||
this.$store.dispatch("user/getCount", {});
|
||||
this.timer = window.setInterval(() => {
|
||||
setTimeout(() => {
|
||||
this.$store.dispatch("user/getCount", {})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="right-menu">
|
||||
<template>
|
||||
<el-badge v-if="count.total_count>0" :value="count.total_count" class="item right-menu-item navbarBadge" @click.native="gotoTicketPage">
|
||||
<el-badge :value="count.total_count" class="item right-menu-item navbarBadge" @click.native="gotoTicketPage">
|
||||
<el-icon class="el-icon-s-management" style="font-size: 25px;color: #409EFF;padding-top: 12px;cursor: pointer;"></el-icon>
|
||||
</el-badge>
|
||||
<search id="header-search" class="right-menu-item" />
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
</router-link>
|
||||
</scroll-pane>
|
||||
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
|
||||
<li @click="refreshSelectedTag(selectedTag)">Refresh</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">Close</li>
|
||||
<li @click="closeOthersTags">Close Others</li>
|
||||
<li @click="closeAllTags(selectedTag)">Close All</li>
|
||||
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭</li>
|
||||
<li @click="closeOthersTags">关闭其他</li>
|
||||
<li @click="closeAllTags(selectedTag)">关闭多有</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScrollPane from './ScrollPane'
|
||||
import path from 'path'
|
||||
|
@ -62,7 +61,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initTags()
|
||||
this.initTags();
|
||||
this.addTags()
|
||||
},
|
||||
methods: {
|
||||
|
@ -73,10 +72,10 @@ export default {
|
|||
return tag.meta && tag.meta.affix
|
||||
},
|
||||
filterAffixTags(routes, basePath = '/') {
|
||||
let tags = []
|
||||
let tags = [];
|
||||
routes.forEach(route => {
|
||||
if (route.meta && route.meta.affix) {
|
||||
const tagPath = path.resolve(basePath, route.path)
|
||||
const tagPath = path.resolve(basePath, route.path);
|
||||
tags.push({
|
||||
fullPath: tagPath,
|
||||
path: tagPath,
|
||||
|
@ -85,16 +84,16 @@ export default {
|
|||
})
|
||||
}
|
||||
if (route.children) {
|
||||
const tempTags = this.filterAffixTags(route.children, route.path)
|
||||
const tempTags = this.filterAffixTags(route.children, route.path);
|
||||
if (tempTags.length >= 1) {
|
||||
tags = [...tags, ...tempTags]
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
return tags
|
||||
},
|
||||
initTags() {
|
||||
const affixTags = this.affixTags = this.filterAffixTags(this.routes)
|
||||
const affixTags = this.affixTags = this.filterAffixTags(this.routes);
|
||||
for (const tag of affixTags) {
|
||||
// Must have tag name
|
||||
if (tag.name) {
|
||||
|
@ -103,18 +102,18 @@ export default {
|
|||
}
|
||||
},
|
||||
addTags() {
|
||||
const { name } = this.$route
|
||||
const { name } = this.$route;
|
||||
if (name) {
|
||||
this.$store.dispatch('tagsView/addView', this.$route)
|
||||
}
|
||||
return false
|
||||
},
|
||||
moveToCurrentTag() {
|
||||
const tags = this.$refs.tag
|
||||
const tags = this.$refs.tag;
|
||||
this.$nextTick(() => {
|
||||
for (const tag of tags) {
|
||||
if (tag.to.path === this.$route.path) {
|
||||
this.$refs.scrollPane.moveToTarget(tag)
|
||||
this.$refs.scrollPane.moveToTarget(tag);
|
||||
// when query is different then update
|
||||
if (tag.to.fullPath !== this.$route.fullPath) {
|
||||
this.$store.dispatch('tagsView/updateVisitedView', this.$route)
|
||||
|
@ -126,7 +125,7 @@ export default {
|
|||
},
|
||||
refreshSelectedTag(view) {
|
||||
this.$store.dispatch('tagsView/delCachedView', view).then(() => {
|
||||
const { fullPath } = view
|
||||
const { fullPath } = view;
|
||||
this.$nextTick(() => {
|
||||
this.$router.replace({
|
||||
path: '/redirect' + fullPath
|
||||
|
@ -142,7 +141,7 @@ export default {
|
|||
})
|
||||
},
|
||||
closeOthersTags() {
|
||||
this.$router.push(this.selectedTag)
|
||||
this.$router.push(this.selectedTag);
|
||||
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
|
||||
this.moveToCurrentTag()
|
||||
})
|
||||
|
|
|
@ -80,7 +80,17 @@ export const constantRoutes = [
|
|||
* the routes that need to be dynamically loaded based on user perms
|
||||
*/
|
||||
export const asyncRoutes = [
|
||||
|
||||
{
|
||||
path: '/redirect',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
component: () => import('@/views/redirect/index')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/mtm',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="dashboard-container">
|
||||
<el-badge v-if="count.total_count>0" :value="count.total_count" class="item" @click.native="gotoTicketPage">
|
||||
<el-badge :value="count.total_count" class="item" @click.native="gotoTicketPage">
|
||||
<el-icon class="el-icon-s-management" style="font-size: 70px;color: #d29898"></el-icon>
|
||||
</el-badge>
|
||||
<div></div>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<script>
|
||||
export default {
|
||||
created() {
|
||||
const { params, query } = this.$route;
|
||||
const { path } = params;
|
||||
this.$router.replace({ path: '/' + path, query })
|
||||
},
|
||||
render: function(h) {
|
||||
return h() // avoid warning message
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -12,9 +12,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import {faceLogin} from "@/api/testModel";
|
||||
import { setToken, removeToken } from '@/utils/auth'
|
||||
import { login, getInfo } from '@/api/user'
|
||||
// import "tracking/build/data/face-min.js";
|
||||
// import "tracking/build/data/mouth-min.js";
|
||||
// import "tracking/build/data/tracking-min.js";
|
||||
|
@ -75,8 +74,6 @@
|
|||
let imgData = {base64:img};
|
||||
faceLogin(imgData).then((res) => {
|
||||
if (res.code >= 200) {
|
||||
debugger;
|
||||
console.log(res);
|
||||
let data = res.data;
|
||||
this.$confirm("是否切换登陆人?", "提示", {
|
||||
confirmButtonText: "确认",
|
||||
|
@ -85,7 +82,11 @@
|
|||
}).then(async () => {
|
||||
await this.$store.dispatch("user/resetToken",data);
|
||||
await this.$store.dispatch("user/getInfo",data.access);
|
||||
window.location.reload();
|
||||
// window.location.reload();
|
||||
this.$emit('func',false);
|
||||
debugger;
|
||||
console.log(getToken());
|
||||
debugger;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
|
@ -104,8 +105,6 @@
|
|||
});
|
||||
this.$refs['video'].srcObject = null
|
||||
},
|
||||
|
||||
|
||||
//切换本地摄像头
|
||||
changePhoto(){
|
||||
/**得到所有的设备*/
|
||||
|
@ -146,8 +145,6 @@
|
|||
navigator.getUserMedia(constraints, success, error);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 检查取景框是否有人脸
|
||||
* */
|
||||
|
@ -181,9 +178,6 @@
|
|||
setFace(data){
|
||||
this.isHasFace = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
|
|
|
@ -8,19 +8,27 @@
|
|||
<hr>
|
||||
<img id="canvasImg" src="./../../assets/404_images/404.png" style="display: none">
|
||||
<div style="position: relative;">
|
||||
<canvas id="canvas" width="700" height="500" >
|
||||
<canvas id="canvas" width="700" height="500">
|
||||
您的浏览器不支持绘图,请升级或更换浏览器!
|
||||
</canvas>
|
||||
<input type="text" value="" class="hide" id="txt" placeholder="请输入文字">
|
||||
<textarea class="hide" id="word" cols="30" rows="10" placeholder="请输入文字" autofocus></textarea>
|
||||
<input id="inputV" type="hidden" value="1">
|
||||
<textarea class="hide" id="word" cols="30" rows="10" placeholder="请输入文字" autofocus></textarea>
|
||||
<input id="inputV" type="hidden" value="1">
|
||||
<span>保存的图片</span>
|
||||
<div id="res"></div>
|
||||
</div>
|
||||
<button @click="takePhoto()">拍照</button>
|
||||
<el-form
|
||||
style="width: 700px;"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="test" placeholder="名称"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog :visible.sync="limitedPhoto" title="人脸登录">
|
||||
<div class="testTracking">
|
||||
<faceLogin name="faceLogin"></faceLogin>
|
||||
<faceLogin name="faceLogin" @func="getMsgFormSon"></faceLogin>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
@ -46,6 +54,7 @@
|
|||
colorF:"#e42343",
|
||||
imgData:'',
|
||||
limitedPhoto:false,
|
||||
test:''
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
|
@ -64,6 +73,9 @@
|
|||
},1000)
|
||||
},
|
||||
methods: {
|
||||
getMsgFormSon(data){
|
||||
this.limitedPhoto = data;
|
||||
},
|
||||
takePhoto(){
|
||||
this.limitedPhoto = true;
|
||||
},
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色" prop="participant" v-if="wfstate.participant_type==4">
|
||||
<el-select style="width: 100%" v-model="participants" placeholder="请选择角色">
|
||||
<el-select style="width: 100%" v-model="participants" multiple placeholder="请选择角色">
|
||||
<el-option v-for="item in roles" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
@ -158,6 +158,12 @@
|
|||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="抄送给" prop="participant">
|
||||
<el-select style="width: 100%" v-model="wfstate.participant_cc" multiple placeholder="请选择抄送给谁">
|
||||
<el-option v-for="item in staffs" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段状态">
|
||||
<el-button @click="addWordStatusChange">添加修改</el-button>
|
||||
<el-row v-for="(item,$index) in statusChange" :key="item+$index" style="margin-top: 10px">
|
||||
|
@ -210,6 +216,7 @@
|
|||
is_hidden: '',
|
||||
sort: '',
|
||||
type: '',
|
||||
participant_cc: [],
|
||||
enable_retreat: '',
|
||||
participant_type: '',
|
||||
filter_policy: '',
|
||||
|
@ -291,7 +298,6 @@
|
|||
},
|
||||
|
||||
created() {
|
||||
|
||||
this.getList();
|
||||
this.getUser();
|
||||
this.getDepartment();
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
@pagination="getList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="抄送我" name="relation">
|
||||
<el-tab-pane label="抄送我" name="cc">
|
||||
<el-table :data="tickets"
|
||||
border fit stripe
|
||||
style="width: 100%"
|
||||
|
|
|
@ -4,4 +4,5 @@ class InmConfig(AppConfig):
|
|||
name = 'apps.inm'
|
||||
verbose_name = '库存管理'
|
||||
|
||||
|
||||
def ready(self):
|
||||
import apps.inm.signals
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
from django_filters import rest_framework as filters
|
||||
|
||||
from apps.mtm.models import Material
|
||||
from .models import MaterialBatch
|
||||
class MbFilterSet(filters.FilterSet):
|
||||
material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all())
|
||||
class Meta:
|
||||
model = MaterialBatch
|
||||
fields = ['material', 'warehouse']
|
|
@ -0,0 +1,84 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-25 07:33
|
||||
|
||||
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', '0025_outputmaterial_is_main'),
|
||||
('pm', '0007_auto_20211025_1533'),
|
||||
('inm', '0004_auto_20210929_0842'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='inout_date',
|
||||
field=models.DateField(default=django.utils.timezone.now, verbose_name='出入库日期'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='operator',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='system.user', verbose_name='操作人'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='subproduction_plan',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='pm.subproductionplan', verbose_name='关联子生产计划'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='warehouse',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='inm.warehouse', verbose_name='仓库'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='materialbatch',
|
||||
name='batch',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, unique=True, verbose_name='批次号'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IProduct',
|
||||
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='删除标记')),
|
||||
('state', models.IntegerField(default=1, verbose_name='物品状态')),
|
||||
('number', models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='物品编号')),
|
||||
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='所属批次号')),
|
||||
('fifos', models.JSONField(blank=True, default=list, verbose_name='关联出入库记录')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='iproduct_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料类型')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='iproduct_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.warehouse', verbose_name='所在仓库')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FIFODetail',
|
||||
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.IntegerField(default=0, verbose_name='数量')),
|
||||
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fifodetail_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料类型')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fifodetail_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-27 01:41
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inm', '0005_auto_20211025_1533'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fifodetail',
|
||||
name='fifo',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='inm.fifo', verbose_name='关联出入库'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,34 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-28 05:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inm', '0006_auto_20211027_0941'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='fifodetail',
|
||||
name='create_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='fifodetail',
|
||||
name='update_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='iproduct',
|
||||
name='create_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='iproduct',
|
||||
name='update_by',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='fifo',
|
||||
name='remark',
|
||||
field=models.CharField(default='', max_length=1000, verbose_name='备注'),
|
||||
),
|
||||
]
|
|
@ -41,12 +41,14 @@ class MaterialBatch(BaseModel):
|
|||
material = models.ForeignKey(Material, on_delete=models.CASCADE, verbose_name='物料信息')
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
count = models.IntegerField('存量', default=0)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True, unique=True)
|
||||
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||
class Meta:
|
||||
verbose_name = '库存表'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
|
||||
class FIFO(CommonAModel):
|
||||
"""
|
||||
出入库记录
|
||||
|
@ -58,12 +60,38 @@ class FIFO(CommonAModel):
|
|||
(4, '生产入库')
|
||||
)
|
||||
type = models.IntegerField('出入库类型', default=1)
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||
operator = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True)
|
||||
inout_date = models.DateField('出入库日期')
|
||||
remark = models.CharField('备注', max_length=1000, default='')
|
||||
|
||||
# class FIFODetail(CommonAModel):
|
||||
# """
|
||||
# 领料详细记录
|
||||
# """
|
||||
|
||||
class FIFODetail(BaseModel):
|
||||
"""
|
||||
出入库详细记录
|
||||
"""
|
||||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
count = models.IntegerField('数量', default=0)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class IProduct(BaseModel):
|
||||
"""
|
||||
具体产品条目
|
||||
"""
|
||||
inm_product_state_choices = (
|
||||
(1, '可用'),
|
||||
(2, '锁定'),
|
||||
(3, '已消耗')
|
||||
)
|
||||
state = models.IntegerField('物品状态', default=1)
|
||||
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||
material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE)
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
batch = models.CharField('所属批次号', max_length=100, null=True, blank=True)
|
||||
wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True)
|
||||
fifos = models.JSONField('关联出入库记录', default=list, blank=True)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from apps.inm.models import WareHouse,Inventory
|
||||
from apps.inm.models import FIFO, FIFODetail, IProduct, MaterialBatch, WareHouse,Inventory
|
||||
|
||||
from apps.system.serializers import UserSimpleSerializer
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
|
@ -23,12 +23,84 @@ class WareHouseSimpleSerializer(serializers.ModelSerializer):
|
|||
|
||||
class InventorySerializer(serializers. ModelSerializer):
|
||||
material_= MaterialSimpleSerializer(source='material', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='material', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
class Meta:
|
||||
model = Inventory
|
||||
fields = '__all__'
|
||||
|
||||
class InventoryCreateUpdateSerializer(serializers.ModelSerializer):
|
||||
class MaterialBatchSerializer(serializers. ModelSerializer):
|
||||
material_= MaterialSimpleSerializer(source='material', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
class Meta:
|
||||
model = Inventory
|
||||
fields = ['material', 'count', 'warehouse']
|
||||
model = MaterialBatch
|
||||
fields = '__all__'
|
||||
|
||||
class FIFOListSerializer(serializers.ModelSerializer):
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
operator_ = UserSimpleSerializer(source='operator', read_only=True)
|
||||
class Meta:
|
||||
model=FIFO
|
||||
fields = '__all__'
|
||||
|
||||
class FIFODetailSerializer(serializers.ModelSerializer):
|
||||
material_= MaterialSimpleSerializer(source='material', read_only=True)
|
||||
class Meta:
|
||||
model=FIFODetail
|
||||
fields = '__all__'
|
||||
|
||||
class IProductInPurSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = IProduct
|
||||
fields = ['number']
|
||||
|
||||
class FIFODetailInPurSerializer(serializers.ModelSerializer):
|
||||
details = IProductInPurSerializer(many=True, required=False)
|
||||
class Meta:
|
||||
model = FIFODetail
|
||||
fields = ['material', 'count', 'batch', 'details']
|
||||
|
||||
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):
|
||||
"""
|
||||
采购入库序列化
|
||||
"""
|
||||
details = FIFODetailInPurSerializer(many=True)
|
||||
class Meta:
|
||||
model = FIFO
|
||||
fields = ['warehouse', 'operator', 'details', 'inout_date']
|
||||
|
||||
def create(self, validated_data):
|
||||
details = validated_data.pop('details')
|
||||
if len(details)>0:
|
||||
pass
|
||||
else:
|
||||
raise serializers.ValidationError('没有入库内容')
|
||||
validated_data['type'] = 3
|
||||
obj = FIFO(**validated_data)
|
||||
obj.save()
|
||||
for i in details:
|
||||
if 'details' in i:
|
||||
p_details = i.pop('details')
|
||||
if len(p_details) != i['count']:
|
||||
raise serializers.ValidationError('数目对不上')
|
||||
else:
|
||||
i['fifo'] = obj
|
||||
fifod = FIFODetail.objects.create(**i)
|
||||
p_list = []
|
||||
for x in p_details:
|
||||
x['state'] = 1
|
||||
x['material'] = i['material']
|
||||
x['warehouse'] = validated_data['warehouse']
|
||||
x['batch'] = i['batch']
|
||||
x['fifos'] = [fifod.id]
|
||||
p_list.append(IProduct(**x))
|
||||
IProduct.objects.bulk_create(p_list)
|
||||
else:
|
||||
i['fifo'] = obj
|
||||
FIFODetail.objects.create(**i)
|
||||
return obj
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from apps.inm.models import FIFODetail, Inventory, MaterialBatch
|
||||
|
||||
|
||||
@receiver(post_save, sender=FIFODetail)
|
||||
def update_by_fifodetail(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
fifo = instance.fifo
|
||||
material = instance.material
|
||||
warehouse = fifo.warehouse
|
||||
if fifo.type in [3]: # 采购入库
|
||||
# 更新相关表
|
||||
o1, _ = Inventory.objects.get_or_create(material=material, warehouse=warehouse, \
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0})
|
||||
o1.count = o1.count + instance.count
|
||||
o1.save()
|
||||
o2, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=instance.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':instance.batch})
|
||||
o2.count = o2.count + instance.count
|
||||
o2.save()
|
||||
material.count = material.count + 1
|
||||
material.save()
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
from django.db.models import base
|
||||
from rest_framework import urlpatterns
|
||||
from apps.inm.views import WarehouseViewSet,InventoryViewSet
|
||||
from apps.inm.views import FIFODetailViewSet, FIFOViewSet, MaterialBatchViewSet, WarehouseViewSet,InventoryViewSet
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('warehouse', WarehouseViewSet, basename='warehouse')
|
||||
router.register('inventory', InventoryViewSet, basename='inventory')
|
||||
router.register('materialbatch', MaterialBatchViewSet, basename='materialbatch')
|
||||
router.register('fifo', FIFOViewSet, basename='fifo'),
|
||||
router.register('fifodetail', FIFODetailViewSet, basename='fifodetail')
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.mixins import ListModelMixin
|
||||
from rest_framework import serializers
|
||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from apps.inm.filters import MbFilterSet
|
||||
|
||||
from apps.inm.models import WareHouse,Inventory
|
||||
from apps.inm.serializers import WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer,InventoryCreateUpdateSerializer
|
||||
from apps.inm.models import FIFO, FIFODetail, MaterialBatch, WareHouse,Inventory
|
||||
from apps.inm.serializers import FIFODetailSerializer, FIFOInPurSerializer, FIFOListSerializer, MaterialBatchQuerySerializer, MaterialBatchSerializer, WareHouseSerializer, WareHouseCreateUpdateSerializer,InventorySerializer
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
# Create your views here.
|
||||
class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||
|
@ -27,11 +30,69 @@ class WarehouseViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
|
||||
class InventoryViewSet(ListModelMixin, GenericViewSet):
|
||||
"""
|
||||
物料基本信息-增删改查
|
||||
仓库物料表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = Inventory.objects.select_related('create_by').all()
|
||||
queryset = Inventory.objects.select_related('material', 'warehouse').all()
|
||||
serializer_class = InventorySerializer
|
||||
filterset_fields = []
|
||||
filterset_fields = ['material', 'warehouse']
|
||||
search_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
class MaterialBatchViewSet(ListModelMixin, GenericViewSet):
|
||||
perms_map = {'*': '*'}
|
||||
queryset = MaterialBatch.objects.select_related('material', 'warehouse').all()
|
||||
serializer_class = MaterialBatchSerializer
|
||||
# filterset_fields = ['material', 'warehouse']
|
||||
filterset_class = MbFilterSet
|
||||
search_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
# @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=MaterialBatchQuerySerializer)
|
||||
# def query(self, request, pk=None):
|
||||
# """
|
||||
# 复杂查询
|
||||
# """
|
||||
# serializer = MaterialBatchQuerySerializer(data=request.data)
|
||||
# serializer.is_valid(raise_exception=True)
|
||||
# queryset = self.queryset.filter()
|
||||
# return Response()
|
||||
|
||||
class FIFODetailViewSet(ListModelMixin, GenericViewSet):
|
||||
"""
|
||||
出入库记录详情表
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = FIFODetail.objects.select_related('material', 'fifo').all()
|
||||
serializer_class = FIFODetailSerializer
|
||||
filterset_fields = ['material', 'fifo']
|
||||
search_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
class FIFOViewSet(ListModelMixin, GenericViewSet):
|
||||
"""
|
||||
出入库记录
|
||||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = FIFO.objects.select_related('warehouse', 'operator')
|
||||
serializer_class = FIFOListSerializer
|
||||
filterset_fields = ['warehouse', 'type']
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'list':
|
||||
return FIFOListSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=FIFOInPurSerializer)
|
||||
def in_pur(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()
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-25 07:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0006_alter_subproductionprogress_count_real'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subproductionplan',
|
||||
name='end_date_real',
|
||||
field=models.DateField(blank=True, null=True, verbose_name='实际完工日期'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subproductionplan',
|
||||
name='start_date_real',
|
||||
field=models.DateField(blank=True, null=True, verbose_name='实际开工日期'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-28 06:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0007_auto_20211025_1533'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='subproductionprogress',
|
||||
name='count_current',
|
||||
field=models.IntegerField(default=0, verbose_name='当前数量'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-29 02:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pm', '0008_subproductionprogress_count_current'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='subproductionprogress',
|
||||
name='count_current',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subproductionplan',
|
||||
name='is_picked',
|
||||
field=models.BooleanField(default=False, verbose_name='是否已领料'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subproductionprogress',
|
||||
name='count',
|
||||
field=models.FloatField(verbose_name='应出入数'),
|
||||
),
|
||||
]
|
|
@ -1,3 +1,4 @@
|
|||
from io import open_code
|
||||
from apps.system.models import CommonAModel, Organization
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
|
@ -46,13 +47,16 @@ class SubProductionPlan(CommonAModel):
|
|||
process = models.ForeignKey(Process, verbose_name='关联大工序', on_delete=models.CASCADE)
|
||||
steps = models.JSONField('工艺步骤', default=list)
|
||||
state = models.IntegerField('状态', default=0)
|
||||
start_date_real = models.DateField('实际开工日期', null=True, blank=True)
|
||||
end_date_real = models.DateField('实际完工日期', null=True, blank=True)
|
||||
is_picked = models.BooleanField('是否已领料', default=False)
|
||||
class Meta:
|
||||
verbose_name = '子生产计划'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
class SubProductionProgress(BaseModel):
|
||||
"""
|
||||
子计划生产进度统计表
|
||||
子计划生产进度统计表/物料消耗
|
||||
"""
|
||||
type_choices=(
|
||||
(1, '输入物料'),
|
||||
|
@ -61,5 +65,5 @@ class SubProductionProgress(BaseModel):
|
|||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE, related_name='progress_subplan')
|
||||
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
|
||||
type = models.IntegerField('物料应用类型', default=1)
|
||||
count = models.IntegerField('应出入数')
|
||||
count = models.FloatField('应出入数')
|
||||
count_real = models.IntegerField('实际出入数', default=0)
|
||||
|
|
|
@ -43,4 +43,7 @@ class SubProductionProgressSerializer(serializers.ModelSerializer):
|
|||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
class Meta:
|
||||
model = SubProductionProgress
|
||||
fields = '__all__'
|
||||
fields = '__all__'
|
||||
|
||||
class PickNeedSerializer(serializers.Serializer):
|
||||
warehouse = serializers.IntegerField(label="仓库ID")
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
from datetime import timezone
|
||||
from rest_framework import serializers
|
||||
from rest_framework.views import APIView
|
||||
from apps.em.models import Equipment
|
||||
from apps.em.serializers import EquipmentSerializer
|
||||
from apps.inm.models import MaterialBatch
|
||||
from apps.inm.serializers import MaterialBatchSerializer
|
||||
from apps.mtm.models import InputMaterial, OutputMaterial, Step, SubProduction, UsedStep
|
||||
from apps.system.mixins import CreateUpdateModelAMixin
|
||||
from apps.pm.serializers import GenSubPlanSerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||
from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer
|
||||
from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin
|
||||
from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
|
@ -77,9 +80,9 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel
|
|||
workshop=i.process.workshop, process=i.process, create_by=request.user,
|
||||
steps = list(steps))
|
||||
for m in InputMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
|
||||
SubProductionProgress.objects.create(material=m.material, type=1, count=m.count, subproduction_plan=instance)
|
||||
SubProductionProgress.objects.create(material=m.material, type=1, count=m.count*production_plan.count, subproduction_plan=instance)
|
||||
for m in OutputMaterial.objects.filter(subproduction=i, is_deleted=False).order_by('sort'):
|
||||
SubProductionProgress.objects.create(material=m.material, type=2, count=m.count, subproduction_plan=instance)
|
||||
SubProductionProgress.objects.create(material=m.material, type=2, count=m.count*production_plan.count, subproduction_plan=instance)
|
||||
production_plan.is_planed=True
|
||||
production_plan.save()
|
||||
return Response()
|
||||
|
@ -91,6 +94,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
perms_map = {'*': '*'}
|
||||
queryset = SubProductionPlan.objects.select_related('process', 'workshop')
|
||||
search_fields = []
|
||||
serializer_class = SubProductionPlanListSerializer
|
||||
filterset_fields = ['production_plan']
|
||||
ordering_fields = ['process__number']
|
||||
ordering = ['process__number']
|
||||
|
@ -100,7 +104,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
return SubProductionPlanListSerializer
|
||||
elif self.action == 'update':
|
||||
return SubProductionPlanUpdateSerializer
|
||||
return SubProductionPlanListSerializer
|
||||
return super().get_serializer_class()
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get':'*'}, serializer_class=SubProductionProgressSerializer)
|
||||
def progress(self, request, pk=None):
|
||||
|
@ -122,6 +126,36 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo
|
|||
obj.save()
|
||||
return Response()
|
||||
raise APIException('计划状态有误')
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer)
|
||||
def start(self, request, pk=None):
|
||||
"""
|
||||
开始生产
|
||||
"""
|
||||
obj = self.get_object()
|
||||
if obj.state in [1,2]:
|
||||
obj.state = 3
|
||||
obj.start_date_real = timezone.now()
|
||||
obj.save()
|
||||
return Response()
|
||||
raise APIException('计划状态有误')
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickNeedSerializer)
|
||||
def pick_need(self, request, pk=None):
|
||||
"""
|
||||
领料需求清单/库存数
|
||||
"""
|
||||
obj = self.get_object()
|
||||
instance = SubProductionProgress.objects.filter(subproduction_plan=obj, type=1)
|
||||
serializer = SubProductionProgressSerializer(instance=instance, many=True)
|
||||
need = serializer.data
|
||||
materials = []
|
||||
for i in need:
|
||||
materials.append(i['material'])
|
||||
objs = MaterialBatch.objects.filter(warehouse=request.data['warehouse'], material__id__in=materials)
|
||||
have = MaterialBatchSerializer(instance=objs, many=True).data
|
||||
return Response({'need':need, 'have':have})
|
||||
|
||||
|
||||
class ResourceViewSet(GenericViewSet):
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ class GetParticipants:
|
|||
# # return list(filter(lambda x: x.startswith('get_') and callable(getattr(self, x)), dir(self)))
|
||||
# return [(func, getattr(self, func).__doc__) for func in dir(self) if callable(getattr(self, func)) and func.startswith('get_')]
|
||||
|
||||
def get_create_by(self, state:dict={}, ticket:dict={}, ticket_data:dict={}, request={}):
|
||||
@classmethod
|
||||
def get_create_by(cls, state:dict={}, ticket:dict={}, ticket_data:dict={}, request={}):
|
||||
"""工单创建人"""
|
||||
participant = ticket.create_by.id
|
||||
return participant
|
|
@ -159,13 +159,13 @@ class WfService(object):
|
|||
elif destination_participant_type == State.PARTICIPANT_TYPE_ROLE:#角色
|
||||
user_queryset = User.objects.filter(roles__in=destination_participant)
|
||||
# 如果选择了角色, 需要走过滤策略
|
||||
if ticket.filter_policy == 1:
|
||||
if state.filter_policy == 1:
|
||||
depts = get_parent_queryset(ticket.belong_dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
elif ticket.filter_policy == 2:
|
||||
elif state.filter_policy == 2:
|
||||
depts = get_parent_queryset(ticket.create_by.dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
elif ticket.filter_policy == 3:
|
||||
elif state.filter_policy == 3:
|
||||
depts = get_parent_queryset(request.user.dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
destination_participant = list(user_queryset.values_list('id', flat=True))
|
||||
|
|
|
@ -183,7 +183,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin
|
|||
participant=None, participant_cc=start_state.participant_cc)
|
||||
# 目标状态需要抄送
|
||||
if next_state.participant_cc:
|
||||
TicketFlow.objects.create(ticket=ticket, state=ticket.next_state,
|
||||
TicketFlow.objects.create(ticket=ticket, state=next_state,
|
||||
participant_type=0, intervene_type=Transition.TRANSITION_INTERVENE_TYPE_CC,
|
||||
participant=None, participant_cc=next_state.participant_cc)
|
||||
return Response(TicketSerializer(instance=ticket).data)
|
||||
|
@ -276,7 +276,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin
|
|||
participant=request.user, transition=transition)
|
||||
# 目标状态需要抄送
|
||||
if destination_state.participant_cc:
|
||||
TicketFlow.objects.create(ticket=ticket, state=ticket.destination_state,
|
||||
TicketFlow.objects.create(ticket=ticket, state=destination_state,
|
||||
participant_type=0, intervene_type=Transition.TRANSITION_INTERVENE_TYPE_CC,
|
||||
participant=None, participant_cc=destination_state.participant_cc)
|
||||
return Response(TicketSerializer(instance=ticket).data)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# Generated by Django 3.2.6 on 2021-10-29 02:19
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('pm', '0009_auto_20211029_1017'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('mtm', '0025_outputmaterial_is_main'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='WProduct',
|
||||
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(blank=True, max_length=50, null=True, unique=True, verbose_name='物品编号')),
|
||||
('act_state', models.IntegerField(default=0, verbose_name='进行状态')),
|
||||
('remark', models.CharField(blank=True, max_length=200, null=True, verbose_name='备注')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproduct_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('m_state', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='所属物料状态')),
|
||||
('p_state', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.step', verbose_name='所在步骤')),
|
||||
('parent', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='上一级')),
|
||||
('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子生产计划')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproduct_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WProductForm',
|
||||
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='删除标记')),
|
||||
('data', models.JSONField(blank=True, default=dict, verbose_name='记录的数据')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproductform_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('record_form', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.recordform', verbose_name='所用表格')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wproductform_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WProductFlow',
|
||||
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='删除标记')),
|
||||
('wproduct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='产品')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WMaterial',
|
||||
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='删除标记')),
|
||||
('batch', models.CharField(blank=True, max_length=100, null=True, verbose_name='批次号')),
|
||||
('count', models.IntegerField(default=0, verbose_name='当前数量')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='关联物料')),
|
||||
('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子计划')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -2,27 +2,39 @@ 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.pm.models import SubProductionPlan
|
||||
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, Step, RecordForm
|
||||
|
||||
class Product(CommonAModel):
|
||||
class WMaterial(BaseModel):
|
||||
"""
|
||||
产品(所有生产过程中出现过的)
|
||||
车间生产物料
|
||||
"""
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子计划', on_delete=models.CASCADE)
|
||||
material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE)
|
||||
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
|
||||
count = models.IntegerField('当前数量', default=0)
|
||||
|
||||
class WProduct(CommonAModel):
|
||||
"""
|
||||
半成品/成品
|
||||
"""
|
||||
act_state_choices=(
|
||||
(0, '待执行'),
|
||||
(1, '进行中'),
|
||||
(2, '已完成')
|
||||
)
|
||||
number = models.CharField('物品编号', primary_key=True, null=True, blank=True, max_length=50)
|
||||
number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50)
|
||||
m_state = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE)
|
||||
p_state = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True)
|
||||
act_state = models.IntegerField('进行状态', default=0)
|
||||
parent = models.ForeignKey('self', verbose_name='上一级', on_delete=models.CASCADE, db_constraint=False)
|
||||
remark = models.CharField('备注', max_length=200, null=True, blank=True)
|
||||
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE)
|
||||
|
||||
class ProductForm(CommonAModel):
|
||||
class WProductForm(CommonAModel):
|
||||
"""
|
||||
记录表格
|
||||
"""
|
||||
|
@ -30,8 +42,8 @@ class ProductForm(CommonAModel):
|
|||
data = models.JSONField('记录的数据', default=dict, blank=True)
|
||||
|
||||
|
||||
class ProductFlow(BaseModel):
|
||||
class WProductFlow(BaseModel):
|
||||
"""
|
||||
产品流转日志
|
||||
"""
|
||||
product = models.ForeignKey(Product, verbose_name='产品', on_delete=models.CASCADE)
|
||||
wproduct = models.ForeignKey(WProduct, verbose_name='产品', on_delete=models.CASCADE)
|
|
@ -1,9 +1,10 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
|
||||
from .models import Vendor
|
||||
class PickDetailSerializer(serializers.Serializer):
|
||||
material = serializers.IntegerField(label='物料ID')
|
||||
batch = serializers.CharField(label='物料批次')
|
||||
pick_count = serializers.IntegerField(label="领料数量")
|
||||
|
||||
|
||||
class VendorSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = Vendor
|
||||
fields = '__all__'
|
||||
class PickSerializer(serializers.Serializer):
|
||||
warehouse = serializers.IntegerField(label="仓库ID")
|
|
@ -1,11 +1,10 @@
|
|||
from django.db.models import base
|
||||
from rest_framework import urlpatterns
|
||||
from apps.pum.views import VendorViewSet
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('vendor', VendorViewSet, basename='vendor')
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.generics import CreateAPIView, GenericAPIView
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
|
||||
from apps.pum.models import Vendor
|
||||
from apps.pum.serializers import VendorSerializer
|
||||
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
|
||||
|
||||
# Create your views here.
|
||||
class VendorViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
||||
class WpmPickView(CreateUpdateModelAMixin, CreateAPIView):
|
||||
"""
|
||||
供应商-增删改查
|
||||
领料
|
||||
"""
|
||||
perms_map = {'get': '*', 'post': 'vendor_create',
|
||||
'put': 'vendor_update', 'delete': 'vendor_delete'}
|
||||
queryset = Vendor.objects.all()
|
||||
serializer_class = VendorSerializer
|
||||
search_fields = ['name', 'contact']
|
||||
filterset_fields = []
|
||||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
pass
|
|
@ -57,7 +57,7 @@ INSTALLED_APPS = [
|
|||
'apps.sam',
|
||||
'apps.qm',
|
||||
'apps.pm',
|
||||
# 'apps.wpm'
|
||||
'apps.wpm'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
|
Loading…
Reference in New Issue