factory/apps/wpm/models.py

315 lines
17 KiB
Python

from django.db import models
from apps.utils.models import CommonADModel, CommonBDModel, BaseModel
from apps.mtm.models import Mgroup, Team, Shift, Material, Route
from apps.pm.models import Mtask
from apps.system.models import User
from django.utils.timezone import localtime
from apps.em.models import Equipment
from apps.system.models import Dept
from datetime import timedelta
from apps.pum.models import Supplier
# Create your models here.
class SfLog(CommonADModel):
"""值班记录
"""
mgroup = models.ForeignKey(
Mgroup, verbose_name='关联工段', on_delete=models.CASCADE)
team = models.ForeignKey(Team, verbose_name='班组',
on_delete=models.CASCADE, null=True, blank=True)
shift = models.ForeignKey(
Shift, verbose_name='当班班次', on_delete=models.CASCADE)
leader = models.ForeignKey(
'system.user', verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True)
work_date = models.DateField('值班日期', null=True, blank=True)
start_time = models.DateTimeField('值班开始')
end_time = models.DateTimeField('值班结束')
note = models.TextField('其他备注', null=True, blank=True)
stlogs = models.ManyToManyField(
'wpm.stlog', verbose_name='关联异常记录', through='wpm.sflogexp', related_name='sflog_stlogs')
last_test_time = models.DateTimeField('最后质检时间', null=True, blank=True)
total_sec_now = models.PositiveIntegerField('总时长动', default=0)
total_sec = models.PositiveIntegerField('总时长', default=43200)
shut_sec = models.PositiveIntegerField('停机时长', default=0)
pcoal_heat = models.FloatField('煤粉热值', null=True, blank=True)
@property
def get_ymd(self):
"""
返回值班记录所属年月日
"""
end_time_local = localtime(self.end_time)
if end_time_local.hour == 0 and end_time_local.minute == 0 and end_time_local.second == 0: # 如果结束时间为00:00:00
end_time_local = localtime(self.start_time)
return end_time_local.year, end_time_local.month, end_time_local.day
class StLog(CommonADModel):
"""
异常记录
"""
title = models.CharField('异常名称', max_length=20, default='')
is_shutdown = models.BooleanField('是否是停机', default=False)
mgroup = models.ForeignKey(
Mgroup, verbose_name='关联工段', on_delete=models.CASCADE)
sflog = models.ForeignKey(
SfLog, on_delete=models.SET_NULL, verbose_name='发生时所在值班', null=True, blank=True)
sflogs = models.ManyToManyField(
'wpm.sflog', verbose_name='关联所有当班', through='wpm.sflogexp', related_name='stlog_sflogs')
start_time = models.DateTimeField('发生时间')
end_time = models.DateTimeField('结束时间', null=True, blank=True)
duration_sec = models.PositiveIntegerField('持续时长(s)', null=True, blank=True)
cate = models.CharField('原因类别', max_length=10, null=True, blank=True)
reason = models.TextField('事件原因', default='', max_length=100)
measure = models.TextField('处置措施', default='', max_length=100)
handler = models.CharField('处理人', default='', max_length=100)
class Meta:
unique_together = ('mgroup', 'start_time')
class SfLogExp(CommonADModel):
"""
异常处理
"""
sflog = models.ForeignKey(
SfLog, on_delete=models.CASCADE, verbose_name='关联值班记录')
stlog = models.ForeignKey(
StLog, verbose_name='关联异常记录', on_delete=models.CASCADE)
duration_sec = models.PositiveIntegerField('持续时长(s)', null=True, blank=True)
note = models.TextField('处理备注', default='', blank=True)
class Meta:
unique_together = ('sflog', 'stlog')
class WMaterial(CommonBDModel):
"""
belong_dept是所在车间
"""
material = models.ForeignKey(
Material, verbose_name='物料', on_delete=models.CASCADE, related_name='wm_m')
mgroup = models.ForeignKey(Mgroup, verbose_name='所在工段', on_delete=models.CASCADE, null=True, blank=True)
batch = models.CharField('批次号', max_length=50)
count = models.PositiveIntegerField('当前数量', default=0)
count_eweight = models.FloatField('单数重量', default=0)
notok_sign = models.CharField('不合格标记', max_length=10, null=True, blank=True)
material_origin = models.ForeignKey(Material, verbose_name='原始物料', on_delete=models.SET_NULL, null=True, blank=True, related_name='wm_mo')
count_xtest = models.PositiveIntegerField('已检数量', null=True, blank=True)
class Mlog(CommonADModel):
"""
生产日志
"""
# 变成父级的字段
MLOG_ONETIME = 10
MLOG_STEP = 20
MTYPE_SELF = 10
MTYPE_OUT = 20
fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:一次填写;20:分步填写')
mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产')))
supplier = models.ForeignKey(Supplier, verbose_name='外协供应商', on_delete=models.SET_NULL, null=True, blank=True)
work_start_time = models.DateTimeField('生产开始时间', null=True, blank=True)
work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True)
hour_work = models.FloatField('预计工时', null=True, blank=True)
reminder_interval_list = models.JSONField('提醒间隔', default=list, blank=True)
stored_mgroup = models.BooleanField('入库到工段', default=False)
stored_notok = models.BooleanField('不合格品是否已入库', default=False)
route = models.ForeignKey(Route, verbose_name='生产路线', on_delete=models.SET_NULL, null=True, blank=True)
mtask = models.ForeignKey(
Mtask, verbose_name='关联任务', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_mtask')
mgroup = models.ForeignKey(
Mgroup, verbose_name='工段', on_delete=models.CASCADE, null=True, blank=True)
wm_in = models.ForeignKey(WMaterial, verbose_name='投入物料所在库存', on_delete=models.SET_NULL, null=True, blank=True, related_name='mlog_wm_in')
material_in = models.ForeignKey(
Material, verbose_name='消耗物', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_material_in')
material_out = models.ForeignKey(
Material, verbose_name='产物', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_material_out')
equipment = models.ForeignKey(
Equipment, verbose_name='生产设备', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_equipment')
equipment_2 = models.ForeignKey(
Equipment, verbose_name='生产设备2', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_equipment_2')
equipments = models.ManyToManyField(
Equipment, verbose_name='多选生产设备', blank=True)
index = models.PositiveSmallIntegerField('第几锅', default=0)
shift = models.ForeignKey(
Shift, verbose_name='关联班次', on_delete=models.SET_NULL, null=True, blank=True)
batch = models.CharField('批次号', max_length=50, null=True, blank=True)
count_use = models.PositiveIntegerField('领用数', default=0)
count_real = models.PositiveIntegerField('实际生产数', default=0)
count_real_eweight = models.FloatField('单数重量', default=0)
count_break = models.PositiveIntegerField('加工碎料数', default=0)
count_ok = models.PositiveIntegerField('合格数', default=0)
count_notok = models.PositiveIntegerField('不合格数', default=0)
count_break_t = models.PositiveIntegerField('检验碎料数', default=0)
count_n_zw = models.PositiveIntegerField('炸纹', default=0)
count_n_tw = models.PositiveIntegerField('条纹', default=0)
count_n_qp = models.PositiveIntegerField('气泡', default=0)
count_n_wq = models.PositiveIntegerField('弯曲', default=0)
count_n_dl = models.PositiveIntegerField('断裂', default=0)
count_n_pb = models.PositiveIntegerField('偏壁', default=0)
count_n_dxt = models.PositiveIntegerField('大小头', default=0)
count_n_js = models.PositiveIntegerField('结石', default=0)
count_n_qx = models.PositiveIntegerField('气线', default=0)
count_n_hs = models.PositiveIntegerField('划伤', default=0)
count_n_cs = models.PositiveIntegerField('挫伤', default=0)
count_n_bl = models.PositiveIntegerField('不亮', default=0)
count_n_zz = models.PositiveIntegerField('杂质', default=0)
count_n_d = models.PositiveIntegerField('', default=0)
count_n_zdd = models.PositiveIntegerField('锥度大', default=0)
count_n_hw = models.PositiveIntegerField('横纹', default=0)
count_n_yp = models.PositiveIntegerField('有皮', default=0)
count_n_bp = models.PositiveIntegerField('爆皮', default=0)
count_n_sc = models.PositiveIntegerField('色差', default=0)
count_n_tydd = models.PositiveIntegerField('椭圆度大', default=0)
count_n_sw = models.PositiveIntegerField('水雾', default=0)
count_n_zjx = models.PositiveIntegerField('直径小', default=0)
count_n_zjd = models.PositiveIntegerField('直径大', default=0)
count_n_bhpcd = models.PositiveIntegerField('壁厚偏差大', default=0)
count_n_xzp = models.PositiveIntegerField('箱中破', default=0)
count_n_thhs = models.PositiveIntegerField('退火后碎', default=0)
count_n_swen = models.PositiveIntegerField('水纹', default=0)
count_n_bb = models.PositiveIntegerField('崩边', default=0)
count_n_wm = models.PositiveIntegerField('雾面', default=0)
count_n_md = models.PositiveIntegerField('麻点', default=0)
count_n_xh = models.PositiveIntegerField('线痕', default=0)
count_n_qt = models.PositiveIntegerField('其他', default=0)
handle_date = models.DateField('操作日期', null=True, blank=True)
handle_user = models.ForeignKey(
User, verbose_name='操作人', on_delete=models.CASCADE, related_name='mlog_handle_user', null=True, blank=True) # 成型人
handle_user_2 = models.ForeignKey(
User, verbose_name='操作人2', on_delete=models.CASCADE, related_name='mlog_handle_user_2', null=True, blank=True) # 切料人
handle_users = models.ManyToManyField(
User, verbose_name='操作人(多选)', blank=True)
handle_leader = models.ForeignKey(
User, verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_handle_leader')
note = models.TextField('备注', default='', blank=True)
material_outs = models.ManyToManyField(
Material, verbose_name='多个产出', blank=True, through='wpm.mlogb', related_name='mlog_material_outs', through_fields=('mlog', 'material_out'))
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
submit_user = models.ForeignKey(
User, verbose_name='提交人', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_submit_user')
@property
def mlogb(self):
return Mlogb.objects.filter(mlog=self).exclude(material_out=None)
@property
def mlogb_full(self):
return Mlogb.objects.filter(mlog=self)
@property
def audit_ignore_fields(self):
return ['create_by', 'update_by',
'create_time', 'update_time', 'id']
class Mlogb(BaseModel):
mlog = models.ForeignKey(Mlog, verbose_name='关联日志',
on_delete=models.CASCADE, related_name='b_mlog')
batch = models.CharField('批次号', max_length=50, null=True, blank=True)
mtask = models.ForeignKey(Mtask, verbose_name='关联任务',
on_delete=models.CASCADE, related_name='mlogb_mtask', null=True, blank=True)
wm_in = models.ForeignKey(WMaterial, verbose_name='投入物料所在库存', on_delete=models.SET_NULL, null=True, blank=True)
material_in = models.ForeignKey(
Material, verbose_name='投入物料', on_delete=models.CASCADE, related_name='mlogb_material_in', null=True, blank=True)
material_out = models.ForeignKey(
Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out', null=True, blank=True)
count_use = models.PositiveIntegerField('领用数量', default=0)
count_break = models.PositiveIntegerField('加工破碎数', default=0)
count_break_t = models.PositiveIntegerField('检验碎料数', default=0)
count_real = models.PositiveIntegerField('实际生产数', default=0)
count_ok = models.PositiveIntegerField('合格数量', default=0)
count_notok = models.PositiveIntegerField('不合格数', default=0)
# 添加不合格字段后需要更改cal_mlog_count_from_mlogb
count_n_hs = models.PositiveIntegerField('划伤', default=0)
count_n_qp = models.PositiveIntegerField('气泡', default=0)
count_n_swen = models.PositiveIntegerField('水纹', default=0)
count_n_bb = models.PositiveIntegerField('崩边', default=0)
count_n_wm = models.PositiveIntegerField('雾面', default=0)
count_n_md = models.PositiveIntegerField('麻点', default=0)
count_n_xh = models.PositiveIntegerField('线痕', default=0)
class Handover(CommonADModel):
"""
交接记录
"""
H_NORMAL = 10
H_REPAIR = 20
H_TEST = 30
type = models.PositiveSmallIntegerField('交接类型', choices=[(H_NORMAL, '正常交接'), (H_REPAIR, '返修交接'), (H_TEST, '检验交接')], default=H_NORMAL)
send_date = models.DateField('送料日期')
send_user = models.ForeignKey(
User, verbose_name='交送人', on_delete=models.CASCADE, related_name='handover_send_user')
send_mgroup = models.ForeignKey(
Mgroup, verbose_name='送料工段', on_delete=models.CASCADE, null=True, blank=True)
send_dept = models.ForeignKey(
Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept')
batch = models.CharField('批次号', max_length=50)
material = models.ForeignKey(
Material, verbose_name='物料', on_delete=models.CASCADE, related_name='h_ma')
material_changed = models.ForeignKey(Material, verbose_name='变更后物料', on_delete=models.CASCADE, null=True, blank=True, related_name='h_ma_c')
count = models.PositiveIntegerField('送料数', default=0)
count_eweight = models.FloatField('单数重量', default=0)
recive_dept = models.ForeignKey(
Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept')
recive_mgroup = models.ForeignKey(Mgroup, verbose_name='接收工段', on_delete=models.CASCADE, related_name='handover_recive_mgroup', null=True, blank=True)
recive_user = models.ForeignKey(
User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user')
wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL,
null=True, blank=True, related_name='handover_wm')
mlog = models.ForeignKey(Mlog, verbose_name='关联日志记录',
on_delete=models.SET_NULL, null=True, blank=True, related_name='handover_mlog')
doin_date = models.DateField('加料日期', null=True, blank=True)
doout_date = models.DateField('出料日期', null=True, blank=True)
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
submit_user = models.ForeignKey(
User, verbose_name='提交人', on_delete=models.CASCADE, null=True, blank=True, related_name='handover_submit_user')
class AttLog(CommonADModel):
"""
到岗记录
"""
ATT_STATE_CHOICES = [
('pending', '待定'),
('normal', '正常'),
('late', '迟到'),
('early_leave', '早退'),
('absent', '未到岗'),
('leave', '请假'),
# 可以根据需要添加更多状态
]
sflog = models.ForeignKey(
SfLog, verbose_name='关联值班记录', on_delete=models.CASCADE)
user = models.ForeignKey(
'system.user', verbose_name='到岗人', on_delete=models.CASCADE)
post = models.ForeignKey(
'system.post', verbose_name='岗位', on_delete=models.CASCADE)
state = models.CharField('状态', max_length=20,
choices=ATT_STATE_CHOICES, default='pending', help_text=str(ATT_STATE_CHOICES))
note = models.TextField('备注信息', default='', blank=True)
class OtherLog(CommonADModel):
"""
其他生产日志
"""
product = models.CharField('产品', max_length=10)
handle_date = models.DateField('操作日期')
count_real = models.PositiveIntegerField('实际生产数', default=0)
count_ok = models.PositiveIntegerField('合格数', default=0)
count_delivered = models.PositiveIntegerField('交付数', default=0)