Accept Merge Request #1301: (feature/优化制造功能 -> develop)

Merge Request: 优化dashboard接口,及装夹bug

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1301?initial=true
This commit is contained in:
马广威
2024-09-13 10:40:58 +08:00
committed by Coding
6 changed files with 441 additions and 35 deletions

View File

@@ -6,7 +6,7 @@ import base64
import logging import logging
import psycopg2 import psycopg2
from datetime import datetime, timedelta from datetime import datetime, timedelta
from odoo import http from odoo import http, fields
from odoo.http import request from odoo.http import request
# 数据库连接配置 # 数据库连接配置
@@ -15,14 +15,18 @@ db_config = {
"user": "postgres", "user": "postgres",
"password": "postgres", "password": "postgres",
"port": "5432", "port": "5432",
"host": "172.16.10.98" "host": "172.16.10.113"
} }
def convert_to_seconds(time_str): def convert_to_seconds(time_str):
# 修改正则表达式,使 H、M、S 部分可选 # 修改正则表达式,使 H、M、S 部分可选
if time_str is None:
return 0
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?" pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
match = re.match(pattern, time_str) match = re.match(pattern, time_str)
if match: if match:
@@ -66,7 +70,7 @@ class Sf_Dashboard_Connect(http.Controller):
# 获取当前时间的时间戳 # 获取当前时间的时间戳
current_timestamp = datetime.now().timestamp() current_timestamp = datetime.now().timestamp()
print(current_timestamp) # print(current_timestamp)
# tem_list = [ # tem_list = [
# "XT-GNJC-WZZX-X800-Y550-Z550-T24-A5-1", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-3", # "XT-GNJC-WZZX-X800-Y550-Z550-T24-A5-1", "XT-GNJC-LSZX-X800-Y550-Z550-T24-A3-3",
@@ -162,7 +166,8 @@ class Sf_Dashboard_Connect(http.Controller):
'first_online_duration': first_online_duration, 'first_online_duration': first_online_duration,
# 停机时间:关机时间 - 运行时间 # 停机时间:关机时间 - 运行时间
# 停机时长:关机时间 - 初次上线时间 # 停机时长:关机时间 - 初次上线时间
'img': f'data:image/png;base64,{machine_data.machine_tool_picture.decode("utf-8")}', # 'img': f'data:image/png;base64,{machine_data.machine_tool_picture.decode("utf-8")}',
'img': f'https://xt.sf.jikimo.com/equipment/get_image/{machine_data.id}',
'equipment_type': machine_data.category_id.name, 'equipment_type': machine_data.category_id.name,
}) })
@@ -194,7 +199,7 @@ class Sf_Dashboard_Connect(http.Controller):
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S') 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') end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
print('begin_time: %s' % begin_time) # print('begin_time: %s' % begin_time)
for item in machine_list: for item in machine_list:
sql = ''' sql = '''
@@ -275,7 +280,7 @@ class Sf_Dashboard_Connect(http.Controller):
res = {'Succeed': True} res = {'Succeed': True}
line_list_obj = request.env['sf.production.line'].sudo().search([('name', 'ilike', 'CNC')]) line_list_obj = request.env['sf.production.line'].sudo().search([('name', 'ilike', 'CNC')])
line_list = list(map(lambda x: x.name, line_list_obj)) line_list = list(map(lambda x: x.name, line_list_obj))
print('line_list: %s' % line_list) # print('line_list: %s' % line_list)
res['LineList'] = line_list res['LineList'] = line_list
except Exception as e: except Exception as e:
@@ -300,21 +305,40 @@ class Sf_Dashboard_Connect(http.Controller):
try: try:
plan_obj = request.env['sf.production.plan'].sudo() plan_obj = request.env['sf.production.plan'].sudo()
production_obj = request.env['mrp.production'].sudo()
line_list = ast.literal_eval(kw['line_list']) line_list = ast.literal_eval(kw['line_list'])
print('line_list: %s' % line_list) # print('line_list: %s' % line_list)
for line in 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_total_counts = production_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'not in', ['cancel']),
('active', '=', True)])
# 工单完成量 # 工单完成量
plan_data_finish_counts = plan_obj.search_count( plan_data_finish_counts = plan_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'in', ['finished'])]) [('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
# 工单计划量 # # 工单计划量
plan_data_plan_counts = plan_obj.search_count( # plan_data_plan_counts = plan_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'not in', ['finished'])]) # [('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'])]) plan_data = plan_obj.search([
('production_line_id.name', '=', line),
])
# 过滤出那些检测结果状态为 '返工' 或 '报废' 的记录
faulty_plans = plan_data.filtered(lambda p: any(
result.test_results in ['返工', '报废'] for result in p.production_id.detection_result_ids
))
# 查找制造订单取消与归档的数量
cancel_order_count = production_obj.search_count(
[('production_line_id.name', '=', line), ('state', 'in', ['cancel']),
('active', '=', False)])
# 计算符合条件的记录数量
# plan_data_fault_counts = len(faulty_plans) + cancel_order_count
plan_data_fault_counts = len(faulty_plans)
# 工单返工数量 # 工单返工数量
@@ -326,17 +350,76 @@ class Sf_Dashboard_Connect(http.Controller):
(plan_data_finish_counts / plan_data_total_counts if plan_data_total_counts > 0 else 0), 3) (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 plan_data_progress_deviation = plan_data_total_counts - plan_data_finish_counts - plan_data_fault_counts
# 完成记录
plan_data_finish_orders = plan_obj.search(
[('production_line_id.name', '=', line), ('state', 'in', ['finished'])])
# # 检测量
# detection_nums = 0
# for i in plan_data_finish_orders:
# print('i: %s' % i)
# if i.production_id.detection_result_ids:
# detection_nums += 1
#
# print('detection_nums: %s' % detection_nums)
# 检测量
detection_data = len(
plan_data_finish_orders.mapped('production_id.detection_result_ids').filtered(lambda r: r))
# 检测合格量
pass_nums = plan_data_finish_orders.filtered(lambda p: any(
result.test_results in ['合格'] for result in p.production_id.detection_result_ids
))
# 质量合格率
pass_rate = 1
if pass_nums:
pass_rate = round(
(len(pass_nums) / detection_data if len(plan_data_finish_orders) > 0 else 0), 3)
# 返工率
rework_rate = round(
(plan_data_rework_counts / plan_data_finish_counts if plan_data_finish_counts > 0 else 0), 3)
# 交付准时率
delay_num = 0
for plan in plan_data_finish_orders:
sale_obj = request.env['sale.order'].sudo().search([('name', '=', plan.origin)])
if sale_obj:
if sale_obj.deadline_of_delivery and plan.actual_end_time:
# 将 deadline_of_delivery 转换为字符串
date_as_string = sale_obj.deadline_of_delivery.strftime('%Y-%m-%d')
# 然后使用 strptime 将字符串转换为 datetime 对象
date_as_datetime = datetime.strptime(date_as_string, '%Y-%m-%d')
# 将 actual_end_time 转换为 datetime 对象
datetime_value = fields.Datetime.from_string(plan.actual_end_time)
# 给 datetime_value 加1天
new_datetime_value = datetime_value + timedelta(days=1)
# 比较 new_datetime_value 和 date_as_datetime 的大小
if new_datetime_value.date() > date_as_datetime.date():
delay_num += 1
delay_rate = round((delay_num / plan_data_finish_counts if plan_data_finish_counts > 0 else 0), 3)
on_time_rate = 1 - delay_rate
if plan_data: if plan_data:
data = { data = {
'plan_data_total_counts': plan_data_total_counts, 'plan_data_total_counts': plan_data_total_counts,
'plan_data_finish_counts': plan_data_finish_counts, 'plan_data_finish_counts': plan_data_finish_counts,
'plan_data_plan_counts': plan_data_plan_counts, 'plan_data_plan_counts': plan_data_total_counts,
'plan_data_fault_counts': plan_data_fault_counts, 'plan_data_fault_counts': plan_data_fault_counts,
'nopass_orders_counts': detection_data - len(pass_nums),
'finishe_rate': finishe_rate, 'finishe_rate': finishe_rate,
'plan_data_progress_deviation': plan_data_progress_deviation, 'plan_data_progress_deviation': plan_data_progress_deviation,
'plan_data_rework_counts': plan_data_rework_counts 'plan_data_rework_counts': plan_data_rework_counts,
'on_time_rate': on_time_rate,
'detection_data': detection_data,
'pass_rate': pass_rate
} }
res['data'][line] = data res['data'][line] = data
@@ -363,7 +446,28 @@ class Sf_Dashboard_Connect(http.Controller):
end_time_str = kw['end_time'].strip('"') end_time_str = kw['end_time'].strip('"')
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S') 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') end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
print('line_list: %s' % line_list) # print('line_list: %s' % line_list)
print('kw', kw)
time_unit = kw.get('time_unit', 'day').strip('"') # 默认单位为天
print('time_unit: %s' % time_unit)
# 日期或小时循环生成器根据time_unit决定是按天还是按小时
def get_time_intervals(start_time, end_time, time_unit):
intervals = []
current_time = start_time
if time_unit == 'hour':
delta = timedelta(hours=1)
else:
delta = timedelta(days=1)
while current_time < end_time:
next_time = current_time + delta
# 确保最后一个时间段不会超出end_time
if next_time > end_time:
next_time = end_time
intervals.append((current_time, next_time))
current_time = next_time
return intervals
def get_date_list(start_date, end_date): def get_date_list(start_date, end_date):
date_list = [] date_list = []
@@ -374,10 +478,33 @@ class Sf_Dashboard_Connect(http.Controller):
return date_list return date_list
for line in line_list: for line in line_list:
date_list = get_date_list(begin_time, end_time) date_field_name = 'actual_end_time' # 替换为你模型中的实际字段名
order_counts = [] order_counts = []
date_field_name = 'actual_end_time' # 替换为你模型中的实际字段名 if time_unit == 'hour':
time_intervals = get_time_intervals(begin_time, end_time, time_unit)
print('============================= %s' % time_intervals)
time_count_dict = {}
for time_interval in time_intervals:
start_time, end_time = time_interval
# print(start_time, end_time)
orders = plan_obj.search([('production_line_id.name', '=', line), ('state', 'in', ['finished']),
(date_field_name, '>=', start_time.strftime('%Y-%m-%d 00:00:00')),
(date_field_name, '<', end_time.strftime('%Y-%m-%d 00:00:00'))
])
# 使用小时和分钟作为键,确保每个小时的数据有独立的键
key = start_time.strftime('%H:%M:%S') # 只取小时:分钟:秒作为键
time_count_dict[key] = len(orders)
# order_counts.append()
res['data'][line] = {
'finish_order_nums': time_count_dict,
'plan_order_nums': 28
}
return json.dumps(res)
date_list = get_date_list(begin_time, end_time)
for date in date_list: for date in date_list:
next_day = date + timedelta(days=1) next_day = date + timedelta(days=1)
@@ -487,7 +614,7 @@ class Sf_Dashboard_Connect(http.Controller):
end_time_str = kw['end_time'].strip('"') end_time_str = kw['end_time'].strip('"')
begin_time = datetime.strptime(begin_time_str, '%Y-%m-%d %H:%M:%S') 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') end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
print('line_list: %s' % line_list) # print('line_list: %s' % line_list)
not_done_data = [] not_done_data = []
done_data = [] done_data = []
final_data = {} final_data = {}
@@ -495,11 +622,16 @@ class Sf_Dashboard_Connect(http.Controller):
for line in line_list: for line in line_list:
# 未完成订单 # 未完成订单
not_done_orders = plan_obj.search( not_done_orders = plan_obj.search(
[('production_line_id.name', '=', line), ('state', 'not in', ['finished'])]) [('production_line_id.name', '=', line), ('state', 'not in', ['finished']),
print(not_done_orders) ('production_id.state', 'not in', ['cancel']), ('active', '=', True)
])
# print(not_done_orders)
# 完成订单 # 完成订单
finish_orders = plan_obj.search([('production_line_id.name', '=', line), ('state', 'in', ['finished'])]) finish_orders = plan_obj.search([
print(finish_orders) ('production_line_id.name', '=', line), ('state', 'in', ['finished']),
('production_id.state', 'not in', ['cancel']), ('active', '=', True)
])
# print(finish_orders)
# 获取所有未完成订单的ID列表 # 获取所有未完成订单的ID列表
order_ids = [order.id for order in not_done_orders] order_ids = [order.id for order in not_done_orders]
@@ -622,11 +754,11 @@ class Sf_Dashboard_Connect(http.Controller):
# 执行SQL命令 # 执行SQL命令
cur.execute(sql, (item,)) cur.execute(sql, (item,))
result = cur.fetchall() result = cur.fetchall()
print('result========', result) # print('result========', result)
cur.execute(sql2, (item,)) cur.execute(sql2, (item,))
result2 = cur.fetchall() result2 = cur.fetchall()
print('result2========', result2) # print('result2========', result2)
# #
for row in result: for row in result:
res['data'][item] = {'idle_count': row[0]} res['data'][item] = {'idle_count': row[0]}
@@ -682,7 +814,7 @@ class Sf_Dashboard_Connect(http.Controller):
# 执行SQL命令 # 执行SQL命令
cur.execute(sql) cur.execute(sql)
result = cur.fetchall() result = cur.fetchall()
print('result', result) # print('result', result)
# 将查询结果转换为字典列表 # 将查询结果转换为字典列表
data = [] data = []
@@ -830,3 +962,222 @@ class Sf_Dashboard_Connect(http.Controller):
# 返回数据 # 返回数据
res['data'] = oee_data res['data'] = oee_data
return json.dumps(res) return json.dumps(res)
@http.route(['/equipment/get_image/<int:record_id>'], type='http', auth="public", website=True)
def get_image(self, record_id, **kwargs):
# 获取模型中的记录
record = request.env['maintenance.equipment'].sudo().browse(record_id)
# 获取图片字段的数据
image_data_base64 = record.machine_tool_picture
if image_data_base64:
# 将Base64解码为二进制数据
image_data_binary = base64.b64decode(image_data_base64)
# 返回图片数据并设置正确的Content-Type
return request.make_response(image_data_binary, headers=[('Content-Type', 'image/png')])
else:
# 如果没有图片数据返回404
return request.not_found()
# 设备运行率
@http.route('/api/RunningTime', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
def RunningTime(self, **kw):
"""
获取设备运行时长
"""
res = {'status': 1, 'message': '成功', 'data': {}}
# 连接数据库
conn = psycopg2.connect(**db_config)
# 获取请求的机床数据
machine_list = ast.literal_eval(kw['machine_list'])
def fetch_result_as_dict(cursor):
"""辅助函数:将查询结果转为字典"""
columns = [desc[0] for desc in cursor.description]
return dict(zip(columns, cursor.fetchone())) if cursor.rowcount != 0 else None
# 初始化当天、当月和有记录以来的总时长
day_total_running_time = 0
day_total_process_time = 0
day_work_rate = 0
month_total_running_time = 0
month_total_process_time = 0
month_work_rate = 0
all_time_total_running_time = 0
all_time_total_process_time = 0
all_time_work_rate = 0
for item in machine_list:
# 获取当天第一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND time::date = CURRENT_DATE
AND device_state != '离线'
ORDER BY time ASC
LIMIT 1;
""", (item,))
first_today = fetch_result_as_dict(cur)
# print("当天第一条记录(非离线):", first_today)
# 获取当天最新一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND time::date = CURRENT_DATE
AND device_state != '离线'
ORDER BY time DESC
LIMIT 1;
""", (item,))
last_today = fetch_result_as_dict(cur)
# print("当天最新一条记录(非离线):", last_today)
# 计算当天运行时长
if first_today and last_today:
running_time = convert_to_seconds(last_today['run_time']) - convert_to_seconds(first_today['run_time'])
process_time = convert_to_seconds(last_today['process_time']) - convert_to_seconds(
first_today['process_time'])
day_total_running_time += abs(running_time)
day_total_process_time += abs(process_time)
# 获取当月第一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND EXTRACT(YEAR FROM time) = EXTRACT(YEAR FROM CURRENT_DATE)
AND EXTRACT(MONTH FROM time) = EXTRACT(MONTH FROM CURRENT_DATE)
AND device_state != '离线'
ORDER BY time ASC
LIMIT 1;
""", (item,))
first_month = fetch_result_as_dict(cur)
# print("当月第一条记录(非离线):", first_month)
# 获取当月最新一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND EXTRACT(YEAR FROM time) = EXTRACT(YEAR FROM CURRENT_DATE)
AND EXTRACT(MONTH FROM time) = EXTRACT(MONTH FROM CURRENT_DATE)
AND device_state != '离线'
ORDER BY time DESC
LIMIT 1;
""", (item,))
last_month = fetch_result_as_dict(cur)
# print("当月最新一条记录(非离线):", last_month)
# 计算当月运行时长
if first_month and last_month:
month_running_time = convert_to_seconds(last_month['run_time']) - convert_to_seconds(
first_month['run_time'])
month_process_time = convert_to_seconds(last_month['process_time']) - convert_to_seconds(
first_month['process_time'])
month_total_running_time += abs(month_running_time)
month_total_process_time += abs(month_process_time)
# 获取有记录以来的第一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND device_state != '离线'
ORDER BY time ASC
LIMIT 1;
""", (item,))
first_all_time = fetch_result_as_dict(cur)
# print("有记录以来的第一条记录(非离线):", first_all_time)
# 获取有记录以来的最新一条记录排除device_state等于离线的记录
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND device_state != '离线'
ORDER BY time DESC
LIMIT 1;
""", (item,))
last_all_time = fetch_result_as_dict(cur)
# print("有记录以来的最新一条记录(非离线):", last_all_time)
# 计算有记录以来的运行时长
if first_all_time and last_all_time:
all_time_running_time = convert_to_seconds(last_all_time['run_time']) - convert_to_seconds(
first_all_time['run_time'])
all_time_process_time = convert_to_seconds(last_all_time['process_time']) - convert_to_seconds(
first_all_time['process_time'])
all_time_total_running_time += abs(all_time_running_time)
all_time_total_process_time += abs(all_time_process_time)
# 计算当天工作效率
if day_total_running_time > day_total_process_time:
day_work_rate = day_total_process_time / day_total_running_time if day_total_running_time != 0 else 0
else:
day_work_rate = day_total_running_time / day_total_process_time if day_total_process_time != 0 else 0
print("当天工作效率: %s" % day_work_rate)
# 计算当月工作效率
if month_total_running_time > month_total_process_time:
month_work_rate = month_total_process_time / month_total_running_time if month_total_running_time != 0 else 0
else:
month_work_rate = month_total_running_time / month_total_process_time if month_total_process_time != 0 else 0
print("当月工作效率: %s" % month_work_rate)
# 计算有记录以来的工作效率
if all_time_total_running_time > all_time_total_process_time:
all_time_work_rate = all_time_total_process_time / all_time_total_running_time if all_time_total_running_time != 0 else 0
else:
all_time_work_rate = all_time_total_running_time / all_time_total_process_time if all_time_total_process_time != 0 else 0
print("有记录以来的工作效率: %s" % all_time_work_rate)
conn.close()
# 返回数据
res['data']['day_work_rate'] = day_work_rate
res['data']['month_work_rate'] = month_work_rate
res['data']['all_time_work_rate'] = all_time_work_rate
return json.dumps(res)
# 设备运行时长
@http.route('/api/RunningTimeDetail', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
def RunningTimeDetail(self, **kw):
"""
获取
"""
res = {'status': 1, 'message': '成功', 'data': {}}
# 连接数据库
conn = psycopg2.connect(**db_config)
# 获取请求的机床数据
machine_list = ast.literal_eval(kw['machine_list'])
def fetch_result_as_dict(cursor):
"""辅助函数:将查询结果转为字典"""
columns = [desc[0] for desc in cursor.description]
return dict(zip(columns, cursor.fetchone())) if cursor.rowcount != 0 else None
for item in machine_list:
with conn.cursor() as cur:
cur.execute("""
SELECT * FROM device_data
WHERE device_name = %s
AND device_state != '离线'
ORDER BY time DESC
LIMIT 1;
""", (item,))
last_all_time = fetch_result_as_dict(cur)
# 返回数据
res['data'][item] = {
'wait_time': last_all_time['run_time'] if last_all_time['run_time'] is not None else 0,
'cut_time': last_all_time['process_time'] if last_all_time['process_time'] is not None else 0,
'power_on_time': last_all_time['power_on_time'] if last_all_time['power_on_time'] is not None else 0
}
conn.close()
return json.dumps(res)

View File

@@ -16,6 +16,7 @@ class ResBFMConfigSettings(models.TransientModel):
# ("https://bfm.jikimo.com", "正式环境(https://bfm.jikimo.com)")], string='bfm环境', store=True) # ("https://bfm.jikimo.com", "正式环境(https://bfm.jikimo.com)")], string='bfm环境', store=True)
bfm_url_new = fields.Char('业务平台环境路径', placeholder='请输入当前对应的业务平台环境路径') bfm_url_new = fields.Char('业务平台环境路径', placeholder='请输入当前对应的业务平台环境路径')
get_check_file_path = fields.Char('获取检查文件路径', default='')
@api.model @api.model
def get_values(self): def get_values(self):
@@ -26,9 +27,11 @@ class ResBFMConfigSettings(models.TransientModel):
values = super(ResBFMConfigSettings, self).get_values() values = super(ResBFMConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
bfm_url_new = config.get_param('bfm_url_new', default='') bfm_url_new = config.get_param('bfm_url_new', default='')
get_check_file_path = config.get_param('get_check_file_path', default='')
values.update( values.update(
bfm_url_new=bfm_url_new, bfm_url_new=bfm_url_new,
get_check_file_path=get_check_file_path
) )
return values return values
@@ -36,3 +39,4 @@ class ResBFMConfigSettings(models.TransientModel):
super(ResBFMConfigSettings, self).set_values() super(ResBFMConfigSettings, self).set_values()
ir_config = self.env['ir.config_parameter'].sudo() ir_config = self.env['ir.config_parameter'].sudo()
ir_config.set_param("bfm_url_new", self.bfm_url_new or "") ir_config.set_param("bfm_url_new", self.bfm_url_new or "")
ir_config.set_param("get_check_file_path", self.get_check_file_path or "")

View File

@@ -18,6 +18,21 @@
<field name="bfm_url_new" string="业务平台访问地址"/> <field name="bfm_url_new" string="业务平台访问地址"/>
</div> </div>
</div> </div>
<!-- </div> -->
</div>
</div>
</div>
<div>
<h2>获取检测报告服务配置</h2>
<div class="row mt16 o_settings_container" id="jd_api">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="get_check_file_path" />
<field name="get_check_file_path" string="检测报告服务地址"/>
</div>
</div>
<!-- </div> --> <!-- </div> -->
</div> </div>
</div> </div>

View File

@@ -414,12 +414,10 @@ class ResMrpWorkOrder(models.Model):
# 获取三次元检测点数据 # 获取三次元检测点数据
def get_three_check_datas(self): def get_three_check_datas(self):
factory_nick_name = 'XT'
ftp_resconfig = self.env['res.config.settings'].get_values() ftp_resconfig = self.env['res.config.settings'].get_values()
ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']),
ftp_resconfig['ftp_user'], ftp_resconfig['ftp_user'],
ftp_resconfig['ftp_password']) ftp_resconfig['ftp_password'])
# ftp.connect()
local_dir_path = '/ftp/before' local_dir_path = '/ftp/before'
os.makedirs(local_dir_path, exist_ok=True) os.makedirs(local_dir_path, exist_ok=True)
@@ -428,6 +426,17 @@ class ResMrpWorkOrder(models.Model):
logging.info('local_file_path:%s' % local_file_path) logging.info('local_file_path:%s' % local_file_path)
remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/' + local_filename remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/' + local_filename
logging.info('remote_path:%s' % remote_path) logging.info('remote_path:%s' % remote_path)
# if not ftp.file_exists(remote_path):
paload_data = {
"filename": local_filename
}
if not ftp_resconfig['get_check_file_path']:
raise UserError('请先配置获取检测报告地址')
url = ftp_resconfig['get_check_file_path'] + '/get/check/report'
response = requests.post(url, json=paload_data)
logging.info('response:%s' % response.json())
if response.json().get('detail'):
raise UserError(response.json().get('detail'))
if not ftp.file_exists(remote_path): if not ftp.file_exists(remote_path):
raise UserError(f"文件不存在: {remote_path}") raise UserError(f"文件不存在: {remote_path}")
@@ -540,6 +549,7 @@ class ResMrpWorkOrder(models.Model):
raise UserError('PT10点未测或数据错误') raise UserError('PT10点未测或数据错误')
self.data_state = True self.data_state = True
self.getcenter()
return True return True
@@ -1169,7 +1179,7 @@ class ResMrpWorkOrder(models.Model):
if not record.rfid_code and record.is_rework is False: if not record.rfid_code and record.is_rework is False:
raise UserError("请扫RFID码进行绑定") raise UserError("请扫RFID码进行绑定")
if record.is_rework is False: if record.is_rework is False:
if not record.material_center_point and record.X_deviation_angle > 0: if not record.material_center_point or record.X_deviation_angle <= 0:
raise UserError("坯料中心点为空或X偏差角度小于等于0") raise UserError("坯料中心点为空或X偏差角度小于等于0")
record.process_state = '待加工' record.process_state = '待加工'
# record.write({'process_state': '待加工'}) # record.write({'process_state': '待加工'})

View File

@@ -513,6 +513,11 @@
</xpath> </xpath>
<xpath expr="//form//header" position="inside">
<button type="object" class="oe_highlight" name="get_three_check_datas" string="获取数据"
attrs='{"invisible": [("state","!=","progress")]}'/>
</xpath>
<xpath expr="//page[1]" position="before"> <xpath expr="//page[1]" position="before">
<field name="results" invisible="1"/> <field name="results" invisible="1"/>

View File

@@ -18,7 +18,8 @@ class sf_production_plan(models.Model):
('draft', '待排程'), ('draft', '待排程'),
('done', '已排程'), ('done', '已排程'),
('processing', '加工中'), ('processing', '加工中'),
('finished', '已完成') ('finished', '已完成'),
('cancel', '已取消')
], string='状态', tracking=True) ], string='状态', tracking=True)
state_order = fields.Integer(compute='_compute_state_order', store=True) state_order = fields.Integer(compute='_compute_state_order', store=True)
@@ -37,7 +38,7 @@ class sf_production_plan(models.Model):
_order = 'state_order asc, write_date desc' _order = 'state_order asc, write_date desc'
name = fields.Char(string='制造订单') name = fields.Char(string='制造订单')
# active = fields.Boolean(string='已归档', default=True) active = fields.Boolean(string='已归档', default=True)
# selected = fields.Boolean(default=False) # selected = fields.Boolean(default=False)
# order_number = fields.Char(string='订单号') # order_number = fields.Char(string='订单号')
order_deadline = fields.Datetime(string='订单交期') order_deadline = fields.Datetime(string='订单交期')
@@ -385,3 +386,23 @@ class machine_work_schedule(models.Model):
_description = '机台作业计划' _description = '机台作业计划'
name = fields.Char(string='机台名') name = fields.Char(string='机台名')
class MrpProductionInheritForPlan(models.Model):
_inherit = 'mrp.production'
def button_cancel(self):
# 调用父类的取消操作
res = super(MrpProductionInheritForPlan, self).button_cancel()
# 更新 sf.production.plan 模型的 state 为 'cancel'
self.env['sf.production.plan'].search([('production_id', '=', self.id)]).write({'state': 'cancel'})
return res
def toggle_active(self):
# 调用父类方法切换 active 状态
res = super(MrpProductionInheritForPlan, self).toggle_active()
self.env['sf.production.plan'].search(
[('production_id', '=', self.id), '|', ('active', '=', False), ('active', '=', True)]).write(
{'active': self.active})
return res