hberp/hb_server/apps/wpm/models.py

347 lines
16 KiB
Python

import re
from rest_framework import exceptions
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.inm.models import FIFO, WareHouse
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
from apps.qm.models import TestRecord
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
from apps.wf.models import Ticket
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm, SubprodctionMaterial
from apps.em.models import Equipment
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.PositiveIntegerField('当前数量', default=0)
class WProduct(CommonAModel):
"""
动态半成品/成品表
"""
WPR_ACT_STATE_TORETEST = 6
WPR_ACT_STATE_DOWAIT = 8
WPR_ACT_STATE_DOING = 10
WPR_ACT_STATE_TOTEST = 20
WPR_ACT_STATE_TOCOMBTEST = 26
WPR_ACT_STATE_OK = 30
WPR_ACT_STATE_INM = 40
WPR_ACT_STATE_NOTOK = 50
WPR_ACT_STATE_TOFINALTEST = 60
WPR_ACT_STATE_SCRAP = 70
WPR_ACT_STATE_SELLED = 80
WPR_ACT_STATE_USED = 90
act_state_choices = (
(WPR_ACT_STATE_TORETEST, '待复检'),
(WPR_ACT_STATE_DOWAIT, '操作准备中'),
(WPR_ACT_STATE_DOING, '操作进行中'),
(WPR_ACT_STATE_TOTEST, '待检验'),
(WPR_ACT_STATE_TOCOMBTEST, '待夹层检验'),
(WPR_ACT_STATE_OK, '已合格'),
(WPR_ACT_STATE_INM, '已入库'),
(WPR_ACT_STATE_NOTOK, '不合格'),
(WPR_ACT_STATE_TOFINALTEST, '待成品检验'),
(WPR_ACT_STATE_SCRAP, '已报废'),
(WPR_ACT_STATE_SELLED, '已售出'),
(WPR_ACT_STATE_USED, '已使用'),
)
SCRAP_REASON_QIPAO = 10
SCRAP_REASON_PODIAN = 20
SCRAP_REASON_HUA = 30
SCRAP_REASON_OTHER = 40
scrap_reason_choices = (
(10, '气泡'),
(20, '破点'),
(30, '划伤'),
(40, '其他')
)
NG_BACK_WORK = 10
NG_BACK_FIX = 20
NG_SCRAP = 30
NG_ACCEPT = 40
NG_PERMIT = 50
NG_DOWN = 60
NG_BACK_FROM = 70
NG_RECALL = 80
ng_choices = (
(NG_BACK_WORK, '返工'),
(NG_BACK_FIX, '返修'),
(NG_SCRAP, '报废'),
(NG_ACCEPT, '让步接收'),
(NG_PERMIT, '偏离许可'),
(NG_DOWN, '降级使用'),
(NG_BACK_FROM, '退回供方'),
(NG_RECALL, '召回')
)
number = models.CharField(
'物品编号', unique=True, null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='所属物料状态', on_delete=models.CASCADE,
related_name='wp_material')
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
on_delete=models.CASCADE, related_name='wp_pre_step')
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
related_name='wp_step')
act_state = models.IntegerField(
'进行状态', default=0, choices=act_state_choices)
is_hidden = models.BooleanField('是否隐藏', default=False)
child = models.ForeignKey('wpm.wproduct', blank=True, null=True,
on_delete=models.CASCADE, related_name='wp_child')
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE,
related_name='wproduct_subplan')
scrap_reason = models.IntegerField(
'报废原因', choices=scrap_reason_choices, null=True, blank=True)
ng_sign = models.PositiveSmallIntegerField(
'不合格标记', choices=ng_choices, null=True, blank=True)
warehouse = models.ForeignKey(
WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_operation')
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_coperation')
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test')
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket')
need_to_order = models.BooleanField('是否要指派订单', default=False)
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True)
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
@property
def last_process_test(self):
"""
最后提交的工序自检
"""
return self.test_wproduct.filter(type=TestRecord.TEST_PROCESS, is_submited=True).order_by('-id').first()
class WprouctTicket(CommonAModel):
"""
玻璃审批工单
"""
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
wproduct = models.ForeignKey(
WProduct, verbose_name='关联产品', on_delete=models.CASCADE)
material = models.ForeignKey(
Material, verbose_name='所在物料状态', on_delete=models.CASCADE)
step = models.ForeignKey(
Step, verbose_name='所在步骤/发现步骤', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(
SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE)
resp_process = models.ForeignKey(
Process, verbose_name='责任工序', on_delete=models.CASCADE, null=True, blank=True)
ticket = models.ForeignKey(
'wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket')
decision = models.PositiveSmallIntegerField(
'最终决定', choices=WProduct.ng_choices, null=True, blank=True)
class WproductFlow(CommonAModel):
"""
动态产品表日志
"""
wproduct = models.ForeignKey(
WProduct, on_delete=models.CASCADE, verbose_name='关联产品', null=True, blank=True)
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='所属物料状态', on_delete=models.CASCADE, related_name='wpf_material')
pre_step = models.ForeignKey(Step, verbose_name='已执行到', help_text='已执行完的步骤', null=True, blank=True,
on_delete=models.CASCADE, related_name='wpf_pre_step')
step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE, null=True, blank=True,
related_name='wpf_step')
act_state = models.IntegerField(
'进行状态', default=0, choices=WProduct.act_state_choices)
is_hidden = models.BooleanField('是否隐藏', default=False)
child = models.ForeignKey('wpm.wproduct', blank=True, null=True,
on_delete=models.CASCADE, related_name='wpf_child')
remark = models.CharField('备注', max_length=200, null=True, blank=True)
subproduction_plan = models.ForeignKey(
SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE)
scrap_reason = models.IntegerField(
'报废原因', choices=WProduct.scrap_reason_choices, null=True, blank=True)
ng_sign = models.PositiveSmallIntegerField(
'不合格标记', choices=WProduct.ng_choices, null=True, blank=True)
warehouse = models.ForeignKey(
WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True)
operation = models.ForeignKey('wpm.operation', verbose_name='当前操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_operation')
coperation = models.ForeignKey('wpm.operation', verbose_name='创建所关联操作',
on_delete=models.SET_NULL, null=True, blank=True, related_name='wpf_coperation')
test = models.ForeignKey('qm.testrecord', verbose_name='当前检验',
on_delete=models.SET_NULL, null=True, blank=True)
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
on_delete=models.SET_NULL, null=True, blank=True)
need_to_order = models.BooleanField('是否要指派订单', default=False)
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True)
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
is_lastlog = models.BooleanField('是否该子计划下的最后一条日志', default=True)
change_str = models.CharField('变动描述', default='', max_length=1000)
class Pick(CommonADModel):
"""
领料记录
"""
PICK_FROM_WAREHOUSE = 10
PICK_FROM_WPRODUCT = 20
type_choice = (
(PICK_FROM_WAREHOUSE, '仓库领取'),
(PICK_FROM_WPRODUCT, '半成品领取'),
)
subproduction_plan = models.ForeignKey(
SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE)
type = models.PositiveSmallIntegerField(
choices=type_choice, default=PICK_FROM_WAREHOUSE)
fifo = models.ForeignKey(
FIFO, verbose_name='关联的出入库记录', on_delete=models.CASCADE, null=True, blank=True)
class PickWproduct(BaseModel):
"""
领取半成品时详情
"""
pick = models.ForeignKey(Pick, verbose_name='关联领料',
on_delete=models.CASCADE)
wproduct = models.ForeignKey(
WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='pw_wproduct')
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='领取时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(
SubProductionPlan, verbose_name='领取时所属子生产计划', on_delete=models.CASCADE)
class Operation(CommonADModel):
"""
生产操作
"""
step = models.ForeignKey(Step, verbose_name='操作步骤',
on_delete=models.CASCADE, null=True, blank=True)
remark = models.CharField('操作备注', max_length=200, null=True, blank=True)
is_submited = models.BooleanField('是否提交', default=False)
class OperationWproduct(BaseModel):
"""
生产操作半成品关联表
"""
operation = models.ForeignKey(
Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='ow_operation')
wproduct = models.ForeignKey(
WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='ow_wproduct')
number = models.CharField('物品编号', null=True, blank=True, max_length=50)
material = models.ForeignKey(
Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE,
related_name='ow_subplan')
ng_sign = models.PositiveSmallIntegerField(
'当时的不合格标记', choices=WProduct.ng_choices, null=True, blank=True)
place = models.CharField('摆放位置', null=True, blank=True, max_length=200)
class Meta:
unique_together = (
('operation', 'wproduct')
)
class OperationMaterial(BaseModel):
"""
生产操作物料消耗产出表
"""
type = models.IntegerField(
'类型', default=0, choices=SubprodctionMaterial.type_choices)
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE,
related_name='om_operation')
material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE,
null=True, blank=True, related_name='om_material')
count = models.PositiveSmallIntegerField('消耗或产出数量', null=True, blank=True)
wmaterial = models.ForeignKey(
WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True)
subproduction_progress = models.ForeignKey(SubProductionProgress, verbose_name='关联的生产进度', on_delete=models.CASCADE,
null=True, blank=True)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE,
null=True, blank=True)
batch = models.CharField('批次号', max_length=100, null=True, blank=True)
use_scrap = models.BooleanField('是否使用的边角料', default=False)
# 以下为冷加工下料清单所用字段
from_material = models.ForeignKey(Material, verbose_name='源物料', on_delete=models.CASCADE,
null=True, blank=True, related_name='om_fmaterial')
from_batch = models.CharField('源批次', max_length=100, null=True, blank=True)
count_cut = models.PositiveIntegerField('切裁片数', default=0)
count_real = models.PositiveIntegerField('生产片数', default=0)
count_ok = models.PositiveIntegerField('成品数量', default=0)
count_qipao = models.PositiveIntegerField('气泡甩片', default=0)
count_podian = models.PositiveIntegerField('破点甩片', default=0)
count_hua = models.PositiveIntegerField('划伤甩片', default=0)
count_other = models.PositiveIntegerField('其他甩片', default=0)
class Meta:
unique_together = (
('operation', 'material', 'batch')
)
class OperationRecord(BaseModel):
"""
记录表格
"""
form = models.ForeignKey(RecordForm, verbose_name='所用的生产记录表格',
on_delete=models.CASCADE, related_name='or_form')
operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE,
related_name='or_operation')
is_filled = models.BooleanField('是否填写', default=True)
class OperationRecordItem(BaseModel):
"""
记录表格字段值
"""
form_field = models.ForeignKey(RecordFormField, verbose_name='关联字段', on_delete=models.CASCADE,
related_name='ori_form_field')
field_value = models.JSONField('录入值', null=True, blank=True)
operation_record = models.ForeignKey(OperationRecord, verbose_name='关联的生产记录', on_delete=models.CASCADE,
related_name='item_operation_record')
class OperationEquip(BaseModel):
operation = models.ForeignKey(
Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation')
equip = models.ForeignKey(Equipment, verbose_name='生产设备',
on_delete=models.CASCADE, related_name='oe_equip')
state = models.PositiveSmallIntegerField('当前设备状态', choices=Equipment.state_choices, default=Equipment.EQUIP_STATE_OK)
remark = models.TextField('备注', null=True, blank=True)