276 lines
12 KiB
Python
276 lines
12 KiB
Python
import datetime
|
|
|
|
from django.core.cache import cache
|
|
from django.db.models import Sum
|
|
from django.utils import timezone
|
|
from typing import Union
|
|
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
|
|
|
from rest_framework.exceptions import ParseError
|
|
|
|
from apps.system.models import User
|
|
from apps.inm.models import MIO, MIOItem, MIOItemA
|
|
from apps.pm.models import Mtask
|
|
from apps.mtm.models import Mgroup, Shift, Material, Route
|
|
|
|
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
|
|
|
|
|
|
def get_sflog(mgroup: Mgroup, happen_time: datetime):
|
|
sflog = SfLog.objects.filter(
|
|
start_time__lt=happen_time, end_time__gte=happen_time, mgroup=mgroup).first()
|
|
if sflog is None: # 需要创建值班记录
|
|
make_sflogs(mgroup=mgroup, start_date=(
|
|
happen_time-datetime.timedelta(days=1)).date(), end_date=happen_time.date())
|
|
sflog = SfLog.objects.filter(
|
|
start_time__lt=happen_time, end_time__gte=happen_time, mgroup=mgroup).first()
|
|
return sflog
|
|
|
|
|
|
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date, create_by=None):
|
|
shift_rule = mgroup.shift_rule
|
|
shifts = Shift.objects.filter(rule=shift_rule) # 根据排班规则制定排班记录
|
|
for shift in shifts:
|
|
start_time_o = shift.start_time_o
|
|
end_time_o = shift.end_time_o
|
|
current_date = start_date
|
|
while current_date <= end_date:
|
|
start_time = datetime.datetime.combine(current_date, start_time_o)
|
|
end_time = datetime.datetime.combine(current_date, end_time_o)
|
|
if start_time > end_time:
|
|
start_time -= datetime.timedelta(days=1)
|
|
duration = end_time - start_time
|
|
total_hour = duration.total_seconds() / 3600
|
|
SfLog.objects.get_or_create(mgroup=mgroup, shift=shift, start_time=start_time, defaults={
|
|
"mgroup": mgroup,
|
|
"shift": shift,
|
|
"work_date": current_date,
|
|
"start_time": start_time,
|
|
"end_time": end_time,
|
|
"total_hour_now": total_hour,
|
|
"total_hour": total_hour,
|
|
"create_by": create_by
|
|
})
|
|
current_date = current_date + datetime.timedelta(days=1)
|
|
|
|
|
|
def get_pcoal_heat(year_s: int, month_s: int, day_s: int):
|
|
"""
|
|
获取煤粉热值
|
|
只有回转窑需要录入煤粉热值
|
|
"""
|
|
key = f'pgoal_val_{year_s}_{month_s}_{day_s}'
|
|
pcoal_heat = cache.get(key, None)
|
|
if pcoal_heat is not None:
|
|
return pcoal_heat
|
|
else:
|
|
try:
|
|
qs = SfLog.objects.get(end_time__year=year_s, end_time__month=month_s, end_time__day=day_s,
|
|
mgroup__name='回转窑', shift__name='白班')
|
|
if qs.pcoal_heat is None:
|
|
qs.pcoal_heat = 0
|
|
qs.save()
|
|
cache.set(f'pgoal_val_{year_s}_{month_s}_{day_s}', qs.pcoal_heat)
|
|
return qs.pcoal_heat
|
|
except Exception:
|
|
return 0
|
|
|
|
|
|
def do_out(mio: MIO):
|
|
"""
|
|
生产领料到车间
|
|
"""
|
|
belong_dept = mio.belong_dept
|
|
do_user = mio.do_user
|
|
mioitems = MIOItem.objects.filter(mio=mio)
|
|
for item in mioitems:
|
|
wm, new_create = WMaterial.objects.get_or_create(batch=item.batch, material=item.material,
|
|
belong_dept=belong_dept, defaults={
|
|
"batch": item.batch,
|
|
"material": item.material,
|
|
"count": item.count,
|
|
"create_by": do_user,
|
|
"belong_dept": belong_dept
|
|
})
|
|
if not new_create:
|
|
wm.count = wm.count + item.count
|
|
wm.update_by = do_user
|
|
wm.save()
|
|
|
|
|
|
def do_in(mio: MIO):
|
|
"""
|
|
生产入库后更新车间物料
|
|
"""
|
|
belong_dept = mio.belong_dept
|
|
do_user = mio.do_user
|
|
mioitems = MIOItem.objects.filter(mio=mio)
|
|
for item in mioitems:
|
|
action_list = []
|
|
mias = MIOItemA.objects.filter(mioitem=item)
|
|
if mias.exists(): # 组合件入库
|
|
mias_list = list(mias.values_list('material', 'batch', 'rate'))
|
|
for i in range(len(mias_list)):
|
|
material, batch, rate = mias_list[i]
|
|
new_count = rate * item.count # 假设 item.count 存在
|
|
action_list.append([material, batch, new_count])
|
|
else:
|
|
action_list = [[item.material, item.batch, item.count]]
|
|
for al in action_list:
|
|
xmaterial, xbatch, xcount = al
|
|
try:
|
|
wm = WMaterial.objects.get(
|
|
batch=xbatch, material=xmaterial, belong_dept=belong_dept)
|
|
except ObjectDoesNotExist:
|
|
raise ParseError('车间物料不存在!')
|
|
except MultipleObjectsReturned:
|
|
raise ParseError('存在多行车间物料!')
|
|
new_count = wm.count - xcount
|
|
if new_count > 0:
|
|
wm.count = new_count
|
|
wm.update_by = do_user
|
|
wm.save()
|
|
elif new_count == 0:
|
|
pass
|
|
else:
|
|
raise ParseError('车间物料不足')
|
|
|
|
|
|
def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
|
"""
|
|
生产日志提交后需要执行的操作
|
|
"""
|
|
if mlog.submit_time is not None:
|
|
return
|
|
if now is None:
|
|
now = timezone.now()
|
|
if now.date() < mlog.handle_date:
|
|
raise ParseError('不可提交未来的日志')
|
|
belong_dept = mlog.mgroup.belong_dept
|
|
material_out = mlog.material_out
|
|
material_in = mlog.material_in
|
|
if material_in: # 需要进行车间库存管理
|
|
# 需要判断领用数是否合理
|
|
material_has_qs = WMaterial.objects.filter(
|
|
batch=mlog.batch, material=material_in, belong_dept=belong_dept)
|
|
count_x = material_has_qs.count()
|
|
if count_x == 1:
|
|
material_has = material_has_qs.first()
|
|
elif count_x == 0:
|
|
raise ParseError(
|
|
f'{str(material_in)}-{mlog.batch}-批次库存不存在!')
|
|
else:
|
|
raise ParseError(
|
|
f'{str(material_in)}-{mlog.batch}-存在多个相同批次!')
|
|
if mlog.count_use > material_has.count:
|
|
raise ParseError(
|
|
f'{str(material_in)}-{mlog.batch}-该批次车间库存不足!')
|
|
else:
|
|
material_has.count = material_has.count - mlog.count_use
|
|
material_has.save()
|
|
if material_out: # 需要入车间库存
|
|
# 有多个产物的情况
|
|
if material_out.brothers and Mlogb.objects.filter(mlog=mlog).exists():
|
|
for item in Mlogb.objects.filter(mlog=mlog):
|
|
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=item.material_out, belong_dept=belong_dept, defaults={
|
|
'batch': mlog.batch, 'material': item.material_out, 'belong_dept': belong_dept
|
|
})
|
|
wmaterial.count = wmaterial.count + item.count_ok
|
|
wmaterial.save()
|
|
else:
|
|
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_out, belong_dept=belong_dept, defaults={
|
|
'batch': mlog.batch, 'material': material_out, 'belong_dept': belong_dept
|
|
})
|
|
wmaterial.count = wmaterial.count + mlog.count_ok
|
|
wmaterial.save()
|
|
mlog.submit_time = now
|
|
mlog.submit_user = user
|
|
mlog.save()
|
|
|
|
|
|
def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
|
"""日志撤回
|
|
"""
|
|
if mlog.submit_time is None:
|
|
return
|
|
if now is None:
|
|
now = timezone.now()
|
|
belong_dept = mlog.mgroup.belong_dept
|
|
material_out = mlog.material_out
|
|
material_in = mlog.material_in
|
|
if material_in:
|
|
# 领用数退回
|
|
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_in, belong_dept=belong_dept, defaults={
|
|
'batch': mlog.batch, 'material': material_in, 'belong_dept': belong_dept})
|
|
wmaterial.count = wmaterial.count + mlog.count_use
|
|
wmaterial.save()
|
|
if material_out: # 产物退回
|
|
# 有多个产物的情况
|
|
if material_out.brothers and Mlogb.objects.filter(mlog=mlog).exists():
|
|
for item in Mlogb.objects.filter(mlog=mlog):
|
|
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=item.material_out, belong_dept=belong_dept, defaults={
|
|
'batch': mlog.batch, 'material': item.material_out, 'belong_dept': belong_dept
|
|
})
|
|
wmaterial.count = wmaterial.count - item.count_ok
|
|
if wmaterial.count < 0:
|
|
raise ParseError('车间库存不足, 产物无法回退')
|
|
wmaterial.save()
|
|
else:
|
|
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_out, belong_dept=belong_dept, defaults={
|
|
'batch': mlog.batch, 'material': material_out, 'belong_dept': belong_dept
|
|
})
|
|
wmaterial.count = wmaterial.count - mlog.count_ok
|
|
if wmaterial.count < 0:
|
|
raise ParseError('车间库存不足, 产物无法回退')
|
|
wmaterial.save()
|
|
mlog.submit_time = None
|
|
mlog.submit_user = None
|
|
mlog.save()
|
|
|
|
|
|
def update_mtask(mtask: Mtask):
|
|
from apps.pm.models import Utask
|
|
res = Mlog.objects.filter(mtask=mtask).exclude(submit_time=None).aggregate(sum_count_real=Sum(
|
|
'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok'))
|
|
mtask.count_real = res['sum_count_real'] if res['sum_count_real'] else 0
|
|
mtask.count_ok = res['sum_count_ok'] if res['sum_count_ok'] else 0
|
|
mtask.count_notok = res['sum_count_notok'] if res['sum_count_notok'] else 0
|
|
mtask.save()
|
|
utask = mtask.utask
|
|
if utask and mtask.is_count_utask:
|
|
res2 = Mtask.objects.filter(utask=utask, mgroup=mtask.mgroup).aggregate(sum_count_real=Sum(
|
|
'count_real'), sum_count_ok=Sum('count_ok'), sum_count_notok=Sum('count_notok'))
|
|
utask.count_real = res2['sum_count_real'] if res2['sum_count_real'] else 0
|
|
utask.count_ok = res2['sum_count_ok'] if res2['sum_count_ok'] else 0
|
|
utask.count_notok = res2['sum_count_notok'] if res2['sum_count_notok'] else 0
|
|
if utask.count_ok > 0 and utask.state == Utask.UTASK_ASSGINED:
|
|
utask.state = Utask.UTASK_WORKING
|
|
if Mtask.objects.filter(utask=utask).exclude(state=Mtask.MTASK_SUBMIT).count() == 0:
|
|
utask.state = Utask.UTASK_SUBMIT
|
|
utask.save()
|
|
|
|
|
|
def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime, None]):
|
|
"""
|
|
交接提交后需要执行的操作
|
|
"""
|
|
if handover.submit_time is not None:
|
|
return
|
|
now = timezone.now()
|
|
if handover.wm:
|
|
wm = handover.wm
|
|
count_x = wm.count - handover.count
|
|
if count_x < 0:
|
|
raise ParseError('车间库存不足!')
|
|
else:
|
|
wm.count = count_x
|
|
wm.save()
|
|
wm_to, _ = WMaterial.objects.get_or_create(batch=handover.batch, material=handover.material, belong_dept=handover.send_dept, defaults={
|
|
'batch': handover.batch, 'material': handover.material, 'belong_dept': handover.send_dept
|
|
})
|
|
wm_to.count = wm_to.count + handover.count
|
|
wm_to.save()
|
|
handover.submit_user = user
|
|
handover.submit_time = now
|
|
handover.save()
|