factory/apps/mtm/services.py

171 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from apps.mtm.models import Goal, Mgroup, RoutePack, Route
from django.core.cache import cache
from django.db.models import Q
from apps.mtm.models import Material, Process
from rest_framework.exceptions import ParseError
from apps.utils.tools import ranstr
from datetime import datetime
from apps.wf.models import Ticket
from django.db.models import Sum
from typing import List
def cal_material_count(materialId_list: List[str]=None):
"""
计算物料总数量
"""
from apps.inm.models import MaterialBatch
from apps.wpm.models import WMaterial
if materialId_list is None:
materialId_list = []
if materialId_list:
objs = Material.objects.filter(id__in=set(materialId_list))
else:
objs = Material.objects.all()
for material in objs:
mb_count = MaterialBatch.objects.filter(material=material).aggregate(total=Sum("count"))["total"] or 0
wm_count = WMaterial.objects.filter(material=material).aggregate(total=Sum("count"))["total"] or 0
if mb_count is None:
mb_count = 0
if wm_count is None:
wm_count = 0
Material.objects.filter(id=material.id).update(
count_wm=wm_count,
count_mb=mb_count,
count=mb_count + wm_count)
def get_mgroup_goals(mgroupId, year, reload=False):
"""
获取工段某年的全部目标值, 以字典形式返回, 带缓存
"""
goals = Goal.objects.filter(
Q(mgroup__id=mgroupId) | Q(mgroup__name=mgroupId), year=year)
key = f'mgroup_{mgroupId}_goals'
if reload is False:
mgroup_goals = cache.get(key, None)
if mgroup_goals is not None:
return mgroup_goals
mgroup_goals = {}
for goal in goals:
mgroup_goals[f'{goal.goal_cate.code}_year'] = goal.goal_val
for i in range(12):
mgroup_goals[f'{goal.goal_cate.code}_{i+1}'] = getattr(
goal, f'goal_val_{i+1}')
cache.set(key, mgroup_goals, 10)
return mgroup_goals
def daoru_material(path: str):
"""
导入物料信息
"""
type_dict = {'主要原料': 30, '半成品': 20, '成品': 10,
'辅助材料': 40, '加工工具': 50, '辅助工装': 60, '办公用品': 70}
from apps.utils.snowflake import idWorker
from openpyxl import load_workbook
wb = load_workbook(path)
sheet = wb['物料']
process_l = Process.objects.all()
process_d = {p.name: p for p in process_l}
i = 3
if sheet['a2'].value != '物料编号':
raise ParseError('列错误导入失败')
while sheet[f'b{i}'].value is not None:
type_str = sheet[f'b{i}'].value.replace(' ', '')
try:
type = type_dict[type_str]
number = sheet[f'a{i}'].value.replace(' ', '')
name = sheet[f'c{i}'].value.replace(' ', '')
specification = sheet[f'd{i}'].value.replace(
'×', '*').replace(' ', '')
model = sheet[f'e{i}'].value.replace(' ', '')
unit = sheet[f'f{i}'].value.replace(' ', '')
count_safe = sheet[f'h{i}'].value
unit_price = sheet[f'i{i}'].value
except Exception as e:
raise ParseError(f'{i}行物料信息错误: {str(e)}')
if type in [20, 30]:
try:
process = process_d[sheet[f'g{i}'].value.replace(' ', '')]
except Exception as e:
raise ParseError(f'{i}行物料信息错误: {str(e)}')
try:
filters = {'type': type, 'name': name, 'specification': specification,
'model': model, 'unit__iexact': unit}
if type in [20, 30]:
filters['process'] = process
default = {'type': type, 'name': name, 'specification': specification,
'model': model, 'unit': unit, 'number': number if number else f'm{type}_{ranstr(6)}', 'id': idWorker.get_id(),
'count_safe': count_safe, 'unit_price': unit_price}
material, is_created = Material.objects.get_or_create(
**filters, defaults=default)
if not is_created:
material.count_safe = count_safe
material.save()
except Exception as e:
raise ParseError(f'{i}行物料有误, 导入失败--{e}')
i = i + 1
print(number, type, name, specification, model, unit, '导入成功')
def mgroup_run_change(mgroup: Mgroup, new_run: bool, last_timex: datetime):
"""
调用工段运行变动
"""
from apps.wpm.services import get_sflog
from apps.wpm.tasks import cal_exp_duration_sec
from apps.wpm.models import StLog
mgroup.is_running = new_run
mgroup.save(update_fields=["is_running"])
last_stlog = StLog.objects.filter(mgroup=mgroup, is_shutdown=True).order_by("-start_time").first() # 找到最后一次停机记录
if last_stlog:
if last_timex >= last_stlog.start_time: # 认为是有效信号
if last_stlog.end_time is None and new_run: # 从停到开
last_stlog.end_time = last_timex
last_stlog.duration_sec = (last_stlog.end_time - last_stlog.start_time).total_seconds()
last_stlog.save()
cal_exp_duration_sec(last_stlog.id) # 触发时间分配
elif last_stlog.end_time and new_run is False and last_timex > last_stlog.end_time: # 从开到停
has_same_stlog =StLog.objects.filter(mgroup=mgroup, is_shutdown=True, start_time=last_timex).exists()
if not has_same_stlog:
StLog.objects.create(title="停机", is_shutdown=True, mgroup=mgroup, end_time=None, start_time=last_timex, sflog=get_sflog(mgroup, last_timex))
elif new_run is False:
StLog.objects.create(title="停机", is_shutdown=True, mgroup=mgroup, end_time=None, start_time=last_timex, sflog=get_sflog(mgroup, last_timex))
mgroup.is_running = False
mgroup.save()
def bind_routepack(ticket: Ticket, transition, new_ticket_data: dict):
routepack = RoutePack.objects.get(id=new_ticket_data['t_id'])
if routepack.ticket and routepack.ticket.id!=ticket.id:
raise ParseError('重复创建工单')
if not Route.objects.filter(routepack=routepack).exists():
raise ParseError('缺少步骤')
first_route = Route.objects.filter(routepack=routepack).order_by('sort', 'process__sort', 'create_time').first()
if first_route.batch_bind:
first_route.batch_bind = False
first_route.save(update_fields=['batch_bind'])
ticket_data = ticket.ticket_data
ticket_data.update({
't_model': 'routepack',
't_id': routepack.id,
})
ticket.ticket_data = ticket_data
ticket.create_by = routepack.create_by
ticket.save()
if routepack.ticket is None:
routepack.ticket = ticket
routepack.state = RoutePack.RP_S_AUDIT
routepack.save()
def routepack_audit_end(ticket: Ticket):
routepack = RoutePack.objects.get(id=ticket.ticket_data['t_id'])
routepack.state = RoutePack.RP_S_CONFIRM
routepack.save()
def routepack_ticket_change(ticket: Ticket):
routepack = RoutePack.objects.get(id=ticket.ticket_data['t_id'])
if ticket.act_state == Ticket.TICKET_ACT_STATE_DRAFT:
routepack.state = RoutePack.RP_S_CREATE
routepack.save()