增加工单相关接口
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
import re
|
||||
import ast
|
||||
import json
|
||||
import base64
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
@@ -151,9 +152,10 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
'first_online_duration': first_online_duration,
|
||||
# 停机时间:关机时间 - 运行时间
|
||||
# 停机时长:关机时间 - 初次上线时间
|
||||
'img': base64.b64encode(machine_data.machine_tool_picture).decode('utf-8'),
|
||||
})
|
||||
|
||||
return json.JSONEncoder().encode(res)
|
||||
return json.dumps(res)
|
||||
except Exception as e:
|
||||
logging.info('前端请求机床数据失败,原因:%s' % e)
|
||||
res['status'] = -1
|
||||
@@ -282,3 +284,254 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
||||
logging.info('CNCList error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
# 返回产线列表
|
||||
|
||||
@http.route('/api/LineList', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
|
||||
|
||||
cors="*")
|
||||
def LineList(self, **kw):
|
||||
"""
|
||||
获取产线列表
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
|
||||
try:
|
||||
res = {'Succeed': True}
|
||||
line_list_obj = request.env['sf.production.line'].sudo().search([('name', 'ilike', 'CNC')])
|
||||
line_list = list(map(lambda x: x.name, line_list_obj))
|
||||
print('line_list: %s' % line_list)
|
||||
res['LineList'] = line_list
|
||||
|
||||
except Exception as e:
|
||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
||||
logging.info('LineList error:%s' % e)
|
||||
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
# 获取产线产量相关
|
||||
|
||||
@http.route('/api/LineProduct', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
|
||||
|
||||
cors="*")
|
||||
def LineProduct(self, **kw):
|
||||
"""
|
||||
获取产线产量相关
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
res = {'status': 1, 'message': '成功', 'data': {}}
|
||||
logging.info('前端请求产线产量数据的参数为:%s' % kw)
|
||||
|
||||
try:
|
||||
plan_obj = request.env['sf.production.plan'].sudo()
|
||||
line_list = ast.literal_eval(kw['line_list'])
|
||||
print('line_list: %s' % line_list)
|
||||
for line in line_list:
|
||||
plan_data = plan_obj.search([('production_line_id.name', '=', line)])
|
||||
# 工单总量
|
||||
plan_data_total_counts = plan_obj.search_count([('production_line_id.name', '=', line)])
|
||||
# 工单完成量
|
||||
plan_data_finish_counts = plan_obj.search_count(
|
||||
[('production_line_id.name', '=', line), ('state', 'not in', ['draft'])])
|
||||
# 工单计划量
|
||||
plan_data_plan_counts = plan_obj.search_count(
|
||||
[('production_line_id.name', '=', line), ('state', 'not in', ['finished'])])
|
||||
# 工单不良累计
|
||||
plan_data_fault_counts = plan_obj.search_count(
|
||||
[('production_line_id.name', '=', line), ('production_id.state', 'in', ['scrap', 'cancel'])])
|
||||
# 工单完成率
|
||||
finishe_rate = round(
|
||||
(plan_data_finish_counts / plan_data_total_counts if plan_data_total_counts > 0 else 0), 3)
|
||||
|
||||
# 工单进度偏差
|
||||
plan_data_progress_deviation = plan_data_finish_counts - plan_data_plan_counts
|
||||
|
||||
if plan_data:
|
||||
data = {
|
||||
'plan_data_total_counts': plan_data_total_counts,
|
||||
'plan_data_finish_counts': plan_data_finish_counts,
|
||||
'plan_data_plan_counts': plan_data_plan_counts,
|
||||
'plan_data_fault_counts': plan_data_fault_counts,
|
||||
'finishe_rate': finishe_rate,
|
||||
'plan_data_progress_deviation': plan_data_progress_deviation,
|
||||
}
|
||||
res['data'][line] = data
|
||||
|
||||
return json.dumps(res) # 注意使用 json.dumps 而不是直接用 json.JSONEncoder().encode()
|
||||
|
||||
except Exception as e:
|
||||
logging.info('前端请求产线产量数据失败,原因:%s' % e)
|
||||
res['status'] = -1
|
||||
res['message'] = '前端请求产线产量数据失败,原因:%s' % e
|
||||
return json.dumps(res)
|
||||
|
||||
# 日完成量统计
|
||||
class DailyFinishCount(http.Controller):
|
||||
@http.route('/api/DailyFinishCount', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def DailyFinishCount(self, **kw):
|
||||
"""
|
||||
获取日完成量统计
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
res = {'status': 1, 'message': '成功', 'data': []}
|
||||
plan_obj = request.env['sf.production.plan'].sudo()
|
||||
line_list = ast.literal_eval(kw['line_list'])
|
||||
begin_time_str = kw['begin_time'].strip('"')
|
||||
end_time_str = kw['end_time'].strip('"')
|
||||
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
|
||||
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
|
||||
print('line_list: %s' % line_list)
|
||||
|
||||
def get_date_list(start_date, end_date):
|
||||
date_list = []
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
date_list.append(current_date)
|
||||
current_date += timedelta(days=1)
|
||||
return date_list
|
||||
|
||||
for line in line_list:
|
||||
date_list = get_date_list(begin_time, end_time)
|
||||
order_counts = []
|
||||
|
||||
date_field_name = 'actual_end_time' # 替换为你模型中的实际字段名
|
||||
|
||||
for date in date_list:
|
||||
next_day = date + timedelta(days=1)
|
||||
orders = plan_obj.search([('production_line_id.name', '=', line), ('state', 'not in', ['draft']),
|
||||
(date_field_name, '>=', date.strftime('%Y-%m-%d 00:00:00')),
|
||||
(date_field_name, '<', next_day.strftime('%Y-%m-%d 00:00:00'))
|
||||
])
|
||||
order_counts.append({
|
||||
'date': date.strftime('%Y-%m-%d'),
|
||||
'order_count': len(orders)
|
||||
})
|
||||
|
||||
res['data'] = order_counts
|
||||
return json.dumps(res)
|
||||
|
||||
# # 实时产量
|
||||
# @http.route('/api/RealTimeProduct', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
# def RealTimeProduct(self, **kw):
|
||||
# """
|
||||
# 获取实时产量
|
||||
# :param kw:
|
||||
# :return:
|
||||
# """
|
||||
#
|
||||
# def get_real_time_product(line_list):
|
||||
# res = {'status': 1, 'message': '成功', 'data': []}
|
||||
# plan_obj = request.env['sf.production.plan'].sudo()
|
||||
# for line in line_list:
|
||||
# plan_data = plan_obj.search([('production_line_id.name', '=', line)])
|
||||
|
||||
# 工单明细
|
||||
@http.route('/api/OrderDetail', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def OrderDetail(self, **kw):
|
||||
"""
|
||||
获取工单明细
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
|
||||
res = {'status': 1, 'message': '成功', 'not_done_data': [], 'done_data': []}
|
||||
plan_obj = request.env['sf.production.plan'].sudo()
|
||||
line_list = ast.literal_eval(kw['line_list'])
|
||||
begin_time_str = kw['begin_time'].strip('"')
|
||||
end_time_str = kw['end_time'].strip('"')
|
||||
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S')
|
||||
end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
|
||||
print('line_list: %s' % line_list)
|
||||
|
||||
for line in line_list:
|
||||
# 未完成订单
|
||||
not_done_orders = plan_obj.search(
|
||||
[('production_line_id.name', '=', line), ('state', 'not in', ['finished'])])
|
||||
print(not_done_orders)
|
||||
# 完成订单
|
||||
finish_orders = plan_obj.search([('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
|
||||
print(finish_orders)
|
||||
|
||||
# 获取所有未完成订单的ID列表
|
||||
order_ids = [order.id for order in not_done_orders]
|
||||
# 获取所有已完成订单的ID列表
|
||||
finish_order_ids = [order.id for order in finish_orders]
|
||||
|
||||
# 对ID进行排序
|
||||
sorted_order_ids = sorted(order_ids)
|
||||
|
||||
finish_sorted_order_ids = sorted(finish_order_ids)
|
||||
|
||||
# 创建ID与序号的对应关系
|
||||
id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(sorted_order_ids)}
|
||||
|
||||
finish_id_to_sequence = {order_id: index + 1 for index, order_id in enumerate(finish_sorted_order_ids)}
|
||||
|
||||
# # 输出结果或进一步处理
|
||||
# for order_id, sequence in id_to_sequence.items():
|
||||
# print(f"Order ID: {order_id} - Sequence: {sequence}")
|
||||
|
||||
for order in not_done_orders:
|
||||
blank_name = ''
|
||||
try:
|
||||
blank_name = order.production_id.move_raw_ids[0].product_id.name
|
||||
except:
|
||||
continue
|
||||
# blank_name = 'R-S00109-1 [碳素结构钢 Q235-118.0 * 72.0 * 21.0]'
|
||||
# 正则表达式
|
||||
material_pattern = r'\[(.*?)-' # 从 [ 开始,碰到 - 停止
|
||||
dimensions = blank_name.split('-')[-1].split(']')[0]
|
||||
|
||||
# 匹配材料名称
|
||||
material_match = re.search(material_pattern, blank_name)
|
||||
material = material_match.group(1) if material_match else 'No match found'
|
||||
|
||||
state_dict = {
|
||||
'draft': '待排程',
|
||||
'done': '已排程',
|
||||
'processing': '生产中',
|
||||
'finished': '已完成'
|
||||
}
|
||||
|
||||
line_dict = {
|
||||
'sequence': id_to_sequence[order.id],
|
||||
'workorder_name': order.name,
|
||||
'blank_name': blank_name,
|
||||
'material': material,
|
||||
'dimensions': dimensions,
|
||||
'order_qty': order.product_qty,
|
||||
'state': state_dict[order.state],
|
||||
|
||||
}
|
||||
res['not_done_data'].append(line_dict)
|
||||
|
||||
for finish_order in finish_orders:
|
||||
blank_name = ''
|
||||
try:
|
||||
blank_name = finish_order.production_id.move_raw_ids[0].product_id.name
|
||||
except:
|
||||
continue
|
||||
|
||||
material_pattern = r'\[(.*?)-' # 从 [ 开始,碰到 - 停止
|
||||
dimensions = blank_name.split('-')[-1].split(']')[0]
|
||||
|
||||
# 匹配材料名称
|
||||
material_match = re.search(material_pattern, blank_name)
|
||||
material = material_match.group(1) if material_match else 'No match found'
|
||||
|
||||
line_dict = {
|
||||
'sequence': finish_id_to_sequence[finish_order.id],
|
||||
'workorder_name': finish_order.name,
|
||||
'blank_name': blank_name,
|
||||
'material': material,
|
||||
'dimensions': dimensions,
|
||||
'order_qty': finish_order.product_qty,
|
||||
'finish_time': finish_order.actual_end_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
|
||||
}
|
||||
res['done_data'].append(line_dict)
|
||||
|
||||
return json.dumps(res)
|
||||
|
||||
Reference in New Issue
Block a user