Compare commits

...

51 Commits

Author SHA1 Message Date
胡尧
b6b92ab1da ftp文件下载适配开发环境 2024-10-10 10:47:46 +08:00
胡尧
94f57629e5 增加空料架配送菜单权限 2024-10-09 17:23:03 +08:00
胡尧
e4c845a9f6 解决空料架配送不能正常下发AGV任务的问题 2024-10-09 14:08:38 +08:00
胡尧
d239509299 解决空料架配送不能正常下发AGV任务的问题 2024-10-09 13:53:49 +08:00
胡尧
457f0aa2ac 修复login页logo不显示的问题 2024-10-08 09:19:06 +08:00
胡嘉莹
84266364e3 Accept Merge Request #1381: (develop -> release/release_2.4)
Merge Request: 修改计划排程

Created By: @胡嘉莹
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1381?initial=true
2024-09-29 17:25:11 +08:00
管欢
ea88d8284a Accept Merge Request #1380: (feature/销售和排程添加消息推送 -> develop)
Merge Request: 域名获取修改

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1380
2024-09-29 17:09:47 +08:00
guanhuan
d2ec420f57 域名获取修改 2024-09-29 17:05:42 +08:00
guanhuan
97d33adabd 域名获取修改 2024-09-29 17:03:49 +08:00
胡尧
c11f3cc66c Merge branch 'develop' into release/release_2.4 2024-09-29 16:51:41 +08:00
廖丹龙
6b4a7e35a9 Accept Merge Request #1375: (feature/销售和排程添加消息推送 -> develop)
Merge Request: 价格计算

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1375
2024-09-29 16:48:53 +08:00
guanhuan
11100c9260 域名获取修改 2024-09-29 16:47:35 +08:00
胡嘉莹
941c3ca43a Accept Merge Request #1379: (feature/临时分支 -> develop)
Merge Request: 修改计划排程代码

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1379?initial=true
2024-09-29 16:47:10 +08:00
hujiaying
05f9528ca9 修改计划排程代码 2024-09-29 16:44:48 +08:00
杨金灵
b205945f65 Accept Merge Request #1378: (feature/修复待接单路径 -> develop)
Merge Request: 修复待接单路径

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1378?initial=true
2024-09-29 16:43:54 +08:00
jinling.yang
c1dc28488a 修复待接单路径 2024-09-29 16:42:32 +08:00
jinling.yang
547d6608e6 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-29 15:40:50 +08:00
jinling.yang
dacb3cc076 Merge branch 'feature/消息模版初始化添加相关模版' into develop 2024-09-29 15:33:51 +08:00
胡尧
282657fbca Merge branch 'release/release_2.4' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into release/release_2.4 2024-09-29 15:32:37 +08:00
杨金灵
7e516c6f0b Accept Merge Request #1377: (feature/消息模版初始化添加相关模版 -> develop)
Merge Request: 消息模版初始化添加相关模版

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1377
2024-09-29 15:31:28 +08:00
jinling.yang
34e2a49bef 注释部分不上的代码 2024-09-29 15:30:18 +08:00
jinling.yang
ff4bdd2f2d 还原代码 2024-09-29 15:27:27 +08:00
jinling.yang
b239fdf847 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-29 15:24:39 +08:00
jinling.yang
47feb4cf3c 消息模版初始化添加相关模版 2024-09-29 15:24:28 +08:00
胡嘉莹
63b732ff42 Accept Merge Request #1376: (develop -> release/release_2.4)
Merge Request: 排程计划bug合并

Created By: @胡嘉莹
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1376?initial=true
2024-09-29 11:42:53 +08:00
胡嘉莹
50d63c28d6 Accept Merge Request #1374: (feature/临时分支 -> develop)
Merge Request: 修改计划排程选择日期有生成量,不能排程问题

Created By: @胡嘉莹
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @胡嘉莹
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1374?initial=true
2024-09-29 10:36:32 +08:00
hujiaying
73b7ff7d1b 修改计划排程选择日期有生成量,不能排程问题 2024-09-29 10:33:19 +08:00
jinling.yang
ccdcd01372 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop
# Conflicts:
#	sf_message/__manifest__.py
2024-09-29 09:18:07 +08:00
liaodanlong
198296f0f8 价格计算 2024-09-27 18:04:39 +08:00
廖丹龙
f122343e31 Accept Merge Request #1373: (feature/销售和排程添加消息推送 -> develop)
Merge Request: 价格计算

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1373?initial=true
2024-09-27 18:02:25 +08:00
liaodanlong
82fa39f1a3 价格计算 2024-09-27 18:00:34 +08:00
廖丹龙
841e1b4ce2 Accept Merge Request #1372: (feature/销售和排程添加消息推送 -> develop)
Merge Request: d刀具标准库数据同步

Created By: @廖丹龙
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @廖丹龙
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1372?initial=true
2024-09-27 17:46:09 +08:00
liaodanlong
1ab62d7724 d刀具标准库数据同步 2024-09-27 17:43:47 +08:00
胡尧
28a46d395b Accept Merge Request #1371: (feature/程序用刀异常提醒 -> develop)
Merge Request: 增加日志

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1371
2024-09-27 15:19:21 +08:00
马广威
f8d957486b Accept Merge Request #1370: (feature/制造功能优化 -> develop)
Merge Request: 优化调整相关数据返回结构等

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1370
2024-09-27 14:47:16 +08:00
mgw
1866607967 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-09-27 14:41:41 +08:00
mgw
40efdf6f3b 隐藏status字段 2024-09-27 14:41:23 +08:00
胡尧
f910df3ce5 Accept Merge Request #1369: (feature/程序用刀异常提醒 -> develop)
Merge Request: 去掉多余的无效刀异常推送

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1369?initial=true
2024-09-27 14:39:55 +08:00
胡尧
95cc557577 Accept Merge Request #1368: (feature/程序用刀异常提醒 -> develop)
Merge Request: 程序用刀异常提醒

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1368?initial=true
2024-09-27 14:38:10 +08:00
mgw
fa78389f47 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-09-27 14:31:39 +08:00
mgw
f7381c43aa 调整url的获取方式;暂时屏蔽历史日志部分 2024-09-27 14:31:22 +08:00
mgw
76c5db61da 增加24h的oee参数 2024-09-27 14:13:57 +08:00
mgw
48ab891991 调整设备oee结构,去掉设备运行日志 2024-09-27 10:07:02 +08:00
mgw
c96ff3f5b4 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化 2024-09-27 09:20:36 +08:00
mgw
d84758232e 优化值为空时的逻辑 2024-09-27 09:20:19 +08:00
jinling.yang
27881589d4 Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop
# Conflicts:
#	sf_message/__manifest__.py
#	sf_message/models/sf_message_workorder.py
2024-09-27 09:10:19 +08:00
mgw
0340563749 筛选加工时间不为空的24h数据 2024-09-26 14:04:35 +08:00
mgw
1d4188df7e 增加24h的故障时间返回 2024-09-26 11:11:46 +08:00
mgw
bd2748659a 去掉关机率 2024-09-25 17:57:24 +08:00
jinling.yang
3ee233c0bc Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into develop 2024-09-25 17:45:34 +08:00
jinling.yang
d63081dffa 优化销售订单+工单逾期 2024-09-25 17:45:15 +08:00
25 changed files with 541 additions and 388 deletions

View File

@@ -16,7 +16,7 @@
<!-- hide 登录页面 powerd by odoo 及管理数据库 --> <!-- hide 登录页面 powerd by odoo 及管理数据库 -->
<template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout"> <template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout">
<xpath expr="//div[@class='card-body']/div[last()]" position="replace"></xpath> <!-- <xpath expr="//div[@class='card-body']/div[last()]" position="replace"></xpath> -->
</template> </template>
<!-- 隐藏odoo版本信息 --> <!-- 隐藏odoo版本信息 -->

View File

@@ -30,7 +30,6 @@
'views/machine_info_present.xml', 'views/machine_info_present.xml',
'views/delivery_record.xml', 'views/delivery_record.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
'views/maintenance_views.xml',
], ],
'assets': { 'assets': {

View File

@@ -162,7 +162,7 @@ class Sf_Dashboard_Connect(http.Controller):
# 关机时长:初次上线时间 - 通电时间 # 关机时长:初次上线时间 - 通电时间
'power_off_time': power_off_time, 'power_off_time': power_off_time,
# 关机率:关机时长/初次上线时间 # 关机率:关机时长/初次上线时间
'power_off_rate': power_off_rate, # 'power_off_rate': power_off_rate,
'first_online_duration': first_online_duration, 'first_online_duration': first_online_duration,
# 停机时间:关机时间 - 运行时间 # 停机时间:关机时间 - 运行时间
# 停机时长:关机时间 - 初次上线时间 # 停机时长:关机时间 - 初次上线时间
@@ -187,11 +187,11 @@ class Sf_Dashboard_Connect(http.Controller):
""" """
res = {'status': 1, 'message': '成功', 'data': {}} res = {'status': 1, 'message': '成功', 'data': {}}
logging.info('前端请求日志数据的参数为:%s' % kw) logging.info('前端请求日志数据的参数为:%s' % kw)
try:
# 连接数据库 # 连接数据库
conn = psycopg2.connect(**db_config) conn = psycopg2.connect(**db_config)
cur = conn.cursor() cur = conn.cursor()
try:
machine_list = ast.literal_eval(kw['machine_list']) machine_list = ast.literal_eval(kw['machine_list'])
begin_time_str = kw['begin_time'].strip('"') begin_time_str = kw['begin_time'].strip('"')
end_time_str = kw['end_time'].strip('"') end_time_str = kw['end_time'].strip('"')
@@ -231,6 +231,12 @@ class Sf_Dashboard_Connect(http.Controller):
res['message'] = '前端请求日志数据失败,原因:%s' % e res['message'] = '前端请求日志数据失败,原因:%s' % e
return json.dumps(res) return json.dumps(res)
finally:
if cur:
cur.close()
if conn:
conn.close()
@http.route('/api/logs/page_data', type='http', auth='public', methods=['GET', 'POST'], @http.route('/api/logs/page_data', type='http', auth='public', methods=['GET', 'POST'],
csrf=False, cors="*") csrf=False, cors="*")
def logs_page_data(self, **kw): def logs_page_data(self, **kw):
@@ -242,11 +248,10 @@ class Sf_Dashboard_Connect(http.Controller):
res = {'status': 1, 'message': '成功', 'data': {}} res = {'status': 1, 'message': '成功', 'data': {}}
logging.info('前端请求日志数据的参数为:%s' % kw) logging.info('前端请求日志数据的参数为:%s' % kw)
try:
# 连接数据库 # 连接数据库
conn = psycopg2.connect(**db_config) conn = psycopg2.connect(**db_config)
cur = conn.cursor() cur = conn.cursor()
try:
# 获取并解析传递的参数 # 获取并解析传递的参数
machine_list = ast.literal_eval(kw.get('machine_list', '[]')) machine_list = ast.literal_eval(kw.get('machine_list', '[]'))
begin_time_str = kw.get('begin_time', '').strip('"') begin_time_str = kw.get('begin_time', '').strip('"')
@@ -848,10 +853,10 @@ class Sf_Dashboard_Connect(http.Controller):
''' '''
sql2 = ''' sql2 = '''
SELECT DISTINCT ON (alarm_time) alarm_time, alarm_repair_time SELECT DISTINCT ON (alarm_start_time) alarm_time, alarm_start_time
FROM device_data FROM device_data
WHERE device_name = %s AND alarm_time IS NOT NULL WHERE device_name = %s AND alarm_start_time IS NOT NULL
ORDER BY alarm_time, time; ORDER BY alarm_start_time, time;
''' '''
# 执行SQL命令 # 执行SQL命令
@@ -867,8 +872,11 @@ class Sf_Dashboard_Connect(http.Controller):
res['data'][item] = {'idle_count': row[0]} res['data'][item] = {'idle_count': row[0]}
alarm_count = [] alarm_count = []
for row in result2: for row in result2:
alarm_count.append(row[0]) alarm_count.append(row[1])
if row[0]:
total_alarm_time += abs(float(row[0])) total_alarm_time += abs(float(row[0]))
else:
total_alarm_time += 0.0
if len(list(set(alarm_count))) == 1: if len(list(set(alarm_count))) == 1:
if list(set(alarm_count))[0] is None: if list(set(alarm_count))[0] is None:
alarm_count_num = 0 alarm_count_num = 0
@@ -1233,17 +1241,24 @@ class Sf_Dashboard_Connect(http.Controller):
machine_list = ast.literal_eval(kw['machine_list']) machine_list = ast.literal_eval(kw['machine_list'])
time_threshold = datetime.now() - timedelta(days=1) time_threshold = datetime.now() - timedelta(days=1)
alarm_last_24_time = 0.0
def fetch_result_as_dict(cursor): def fetch_result_as_dict(cursor):
"""辅助函数:将查询结果转为字典""" """辅助函数:将查询结果转为字典"""
columns = [desc[0] for desc in cursor.description] columns = [desc[0] for desc in cursor.description]
return dict(zip(columns, cursor.fetchone())) if cursor.rowcount != 0 else None return dict(zip(columns, cursor.fetchone())) if cursor.rowcount != 0 else None
# 获取当前时间的时间戳
current_timestamp = datetime.now().timestamp()
for item in machine_list: for item in machine_list:
euipment_obj = request.env['maintenance.equipment'].sudo().search([('code', '=', item)])
# 机床上线时间段
first_online_duration = current_timestamp - euipment_obj.first_online_time.timestamp()
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute(""" cur.execute("""
SELECT * FROM device_data SELECT * FROM device_data
WHERE device_name = %s WHERE device_name = %s
AND device_state != '离线' AND device_state != '离线' AND process_time IS NOT NULL
ORDER BY time DESC ORDER BY time DESC
LIMIT 1; LIMIT 1;
""", (item,)) """, (item,))
@@ -1252,18 +1267,52 @@ class Sf_Dashboard_Connect(http.Controller):
cur.execute(""" cur.execute("""
SELECT * FROM device_data SELECT * FROM device_data
WHERE device_name = %s WHERE device_name = %s
AND device_state != '离线' AND time >= %s AND device_state != '离线' AND time >= %s AND process_time IS NOT NULL
ORDER BY time ASC ORDER BY time ASC
LIMIT 1; LIMIT 1;
""", (item, time_threshold)) """, (item, time_threshold))
last_24_time = fetch_result_as_dict(cur) last_24_time = fetch_result_as_dict(cur)
with conn.cursor() as cur:
cur.execute("""
SELECT COUNT(*)
FROM (
SELECT DISTINCT ON (idle_start_time) idle_start_time
FROM device_data
WHERE device_name = %s AND idle_start_time IS NOT NULL AND time >= %s
ORDER BY idle_start_time, time
) subquery;
""", (item, time_threshold))
idle_count = cur.fetchone()[0]
alarm_last_24_nums = []
with conn.cursor() as cur:
cur.execute("""
SELECT DISTINCT ON (alarm_start_time) alarm_time, alarm_start_time
FROM device_data
WHERE device_name = %s
AND alarm_start_time IS NOT NULL AND time >= %s;
""", (item, time_threshold))
results = cur.fetchall()
for result in results:
alarm_last_24_nums.append(result[1])
if result[0]:
if float(result[0]) >= 1000:
continue
alarm_last_24_time += float(result[0])
else:
alarm_last_24_time += 0.0
# 返回数据 # 返回数据
res['data'][item] = { res['data'][item] = {
'wait_time': last_all_time['run_time'] if last_all_time['run_time'] is not None else 0, '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, 'cut_time': last_all_time['process_time'] if last_all_time['process_time'] is not None else 0,
'cut_24_time': last_24_time['process_time'] if last_24_time['process_time'] is not None else 0, 'cut_24_time': last_24_time['process_time'] if last_24_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, 'power_on_time': last_all_time['power_on_time'] if last_all_time['power_on_time'] is not None else 0,
'power_on_24_time': last_24_time['power_on_time'] if last_24_time['power_on_time'] is not None else 0 'power_on_24_time': last_24_time['power_on_time'] if last_24_time['power_on_time'] is not None else 0,
'alarm_last_24_time': alarm_last_24_time,
'alarm_last_24_nums': len(list(set(alarm_last_24_nums))),
'idle_count': idle_count,
'first_online_time': first_online_duration,
} }
conn.close() conn.close()

View File

@@ -285,26 +285,6 @@ class Machine_ftp(models.Model):
# # 开动率 # # 开动率
run_rate = fields.Char('开动率', readonly=True) run_rate = fields.Char('开动率', readonly=True)
# 同步CNC设备到oee
def sync_oee(self):
"""
同步CNC设备到oee
:return:
"""
for record in self:
record.ensure_one()
cnc_oee_dict = {
'equipment_id': record.id,
'type_id': record.type_id.id,
'machine_tool_picture': record.machine_tool_picture,
'equipment_code': record.code,
'function_type': record.function_type,
}
if self.env['maintenance.equipment.oee.logs'].search([('equipment_id', '=', record.id)]):
self.env['maintenance.equipment.oee.logs'].write(cnc_oee_dict)
else:
self.env['maintenance.equipment.oee.logs'].create(cnc_oee_dict)
class WorkCenterBarcode(models.Model): class WorkCenterBarcode(models.Model):
""" """

View File

@@ -14,7 +14,7 @@
<group string='状态监控'> <group string='状态监控'>
<group> <group>
<!-- <field name="timestamp"/> --> <!-- <field name="timestamp"/> -->
<field name="status"/> <!-- <field name="status"/> -->
<field name="run_status"/> <field name="run_status"/>
<field name="run_time"/> <field name="run_time"/>
<field name="system_date"/> <field name="system_date"/>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0"?>
<odoo>
<!-- 修改设备列表视图-->
<record id="sf_machine_hr_equipment_view_tree_inherit" model="ir.ui.view">
<field name="name">sf.machine.hr.equipment.view.tree.inherit</field>
<field name="model">maintenance.equipment</field>
<field name="inherit_id" ref="maintenance.hr_equipment_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<button name="sync_oee" type="object" string="同步设备至OEE"/>
</header>
</xpath>
</field>
</record>
</odoo>

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re
import json import json
import datetime import datetime
import requests import requests
@@ -6,6 +7,42 @@ from odoo import api, fields, models, _
from odoo.exceptions import UserError from odoo.exceptions import UserError
def convert_to_seconds(time_str):
# 修改正则表达式,使 H、M、S 部分可选
if time_str is None:
return 0
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
if total_seconds == 0:
# return None
pattern = r"(?:(\d+)小时)?(?:(\d+)分钟)?(?:(\d+)秒)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
return total_seconds
else:
return None
return total_seconds
class SfMaintenanceEquipmentOEE(models.Model): class SfMaintenanceEquipmentOEE(models.Model):
_name = 'maintenance.equipment.oee' _name = 'maintenance.equipment.oee'
_description = '设备OEE' _description = '设备OEE'
@@ -22,18 +59,27 @@ class SfMaintenanceEquipmentOEE(models.Model):
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
("封存(报废)", "封存(报废)")], ("封存(报废)", "封存(报废)")],
default='正常', string="机床状态", related='equipment_id.state') default='正常', string="机床状态", related='equipment_id.state')
run_time = fields.Float('加工时长(h)')
equipment_time = fields.Float('开机时长(h)') online_time = fields.Char('开机时长(小时)', reaonly='True')
done_nums = fields.Integer('加工件数')
utilization_rate = fields.Char('可用率') offline_time = fields.Char('关机时长(小时)', reaonly='True')
fault_time = fields.Float('故障时长') idle_nums = fields.Integer('待机次数', reaonly='True')
fault_nums = fields.Integer('故障次数') # 待机时长
# 故障率
fault_rate = fields.Char('故障率') idle_time = fields.Char('待机时长(小时)', reaonly='True')
# 待机率
idle_rate = fields.Char('待机率(%)', reaonly='True')
work_time = fields.Char('加工时长(小时)', reaonly='True')
work_rate = fields.Char('可用率(%)', reaonly='True')
fault_time = fields.Char('故障时长(小时)', reaonly='True')
fault_rate = fields.Char('故障率(%)', reaonly='True')
fault_nums = fields.Integer('故障次数', reaonly='True')
# 设备故障日志 # 设备故障日志
sf_maintenance_logs_ids = fields.One2many('sf.maintenance.logs', 'maintenance_equipment_oee_id', '设备故障日志', sf_maintenance_logs_ids = fields.One2many('sf.maintenance.logs', 'maintenance_equipment_oee_id', '设备故障日志',
related='equipment_id.sf_maintenance_logs_ids') related='equipment_id.sf_maintenance_logs_ids')
oee_logs = fields.One2many('maintenance.equipment.oee.logs', 'equipment_oee_id', string='运行日志')
day_logs_detail = fields.Html('日运行日志详情') day_logs_detail = fields.Html('日运行日志详情')
history_logs_detail = fields.Html('历史运行日志详情') history_logs_detail = fields.Html('历史运行日志详情')
@@ -42,8 +88,13 @@ class SfMaintenanceEquipmentOEE(models.Model):
# 获取日志详情 # 获取日志详情
def get_day_logs(self): def get_day_logs(self):
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
print(base_url)
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
url = 'http://172.16.10.112:8069/api/logs/list' # url = 'http://172.16.10.112:8069/api/logs/list'
# url_time = 'http://localhost:9069/api/RunningTimeDetail'
url = base_url + '/api/logs/list'
url_time = base_url + '/api/RunningTimeDetail'
machine_list = [self.equipment_code] machine_list = [self.equipment_code]
begin_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 00:00:00' begin_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 00:00:00'
end_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 23:59:59' end_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 23:59:59'
@@ -55,11 +106,41 @@ class SfMaintenanceEquipmentOEE(models.Model):
"end_time": end_time "end_time": end_time
} }
data_time = {
"machine_list": str(machine_list)
}
print(data) print(data)
# 发送POST请求 # 发送POST请求
response = requests.post(url, json={}, data=data) response = requests.post(url, json={}, data=data)
print(response.json()) # 输出服务器返回的响应 response_time = requests.post(url_time, json={}, data=data_time)
# print(response.json()) # 输出服务器返回的响应
print(response_time.json())
if response_time.status_code == 200:
result_time = response_time.json()
real_dict = result_time['data'][self.equipment_code]
print('=', result_time)
if result_time['status'] == 1:
self.online_time = round((convert_to_seconds(real_dict['power_on_time']) - convert_to_seconds(
real_dict['power_on_24_time'])) / 3600, 2)
self.work_time = round(
(convert_to_seconds(real_dict['cut_time']) - convert_to_seconds(real_dict['cut_24_time'])) / 3600,
2)
self.offline_time = 24 - (float(self.online_time) if self.online_time else 0)
self.idle_time = float(self.online_time) - float(
self.work_time) if self.online_time and self.work_time else 0
self.idle_rate = round(
float(self.idle_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.work_rate = round(
float(self.work_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_time = (float(real_dict['alarm_last_24_time']) if real_dict[
'alarm_last_24_time'] else 0) / 3600
self.fault_rate = round(
float(self.fault_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_nums = real_dict['alarm_last_24_nums']
self.idle_nums = real_dict['idle_count']
if response.status_code == 200: if response.status_code == 200:
result = response.json() result = response.json()
print('============', result) print('============', result)
@@ -94,7 +175,10 @@ class SfMaintenanceEquipmentOEE(models.Model):
# 获取历史日志详情 # 获取历史日志详情
def get_history_logs(self): def get_history_logs(self):
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
url = 'http://172.16.10.112:8069/api/logs/list' base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
# url = 'http://172.16.10.112:8069/api/logs/list'
url = base_url + '/api/logs/list'
url_time = base_url + '/api/RunningTimeDetail'
machine_list = [self.equipment_code] machine_list = [self.equipment_code]
if not self.begin_time: if not self.begin_time:
raise UserError('请选择开始时间') raise UserError('请选择开始时间')

View File

@@ -67,6 +67,3 @@ access_sf_cutting_tool_type_admin_sf_group_equipment_user,sf_cutting_tool_type_a
access_sf_cutting_tool_type_group_purchase_director_sf_group_equipment_user,sf_cutting_tool_type_group_purchase_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_purchase_director_sf_group_equipment_user,sf_cutting_tool_type_group_purchase_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_sf_cutting_tool_type_group_sale_director_sf_group_equipment_user,sf_cutting_tool_type_group_sale_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_sale_director_sf_group_equipment_user,sf_cutting_tool_type_group_sale_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_sf_cutting_tool_type_group_plan_director_sf_group_equipment_user,sf_cutting_tool_type_group_plan_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_plan_director_sf_group_equipment_user,sf_cutting_tool_type_group_plan_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_maintenance_equipment_oee_logs,maintenance_equipment_oee_logs,model_maintenance_equipment_oee_logs,sf_maintenance.sf_group_equipment_manager,1,1,1,1
access_maintenance_equipment_oee_log_detail,maintenance_equipment_oee_log_detail,model_maintenance_equipment_oee_log_detail,sf_maintenance.sf_group_equipment_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
67
68
69

View File

@@ -8,13 +8,13 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="equipment_id"/> <field name="equipment_id"/>
<field name="equipment_time"/> <field name="online_time"/>
<field name="run_time"/> <field name="work_time"/>
<field name="done_nums"/> <field name="work_rate"/>
<field name="utilization_rate"/>
<field name="fault_time"/> <field name="fault_time"/>
<field name="fault_nums"/> <field name="fault_nums"/>
<field name="fault_rate"/> <field name="fault_rate"/>
</tree> </tree>
</field> </field>
</record> </record>
@@ -37,18 +37,47 @@
<group> <group>
<group> <group>
<field name="type_id" readonly="1"/> <group>
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/>
<field name="type_id"/>
<field name="state"/>
<field name="equipment_code"/> <field name="equipment_code"/>
<field name="equipment_time"/> </group>
<field name="run_time"/>
<field name="done_nums"/>
<field name="utilization_rate"/>
<field name="fault_time"/>
<field name="fault_nums"/>
</group> </group>
<group> <group>
<field name="machine_tool_picture" widget="image" readonly="1"/> <group>
<!-- <field name="state" nolabel="1"/> -->
<!-- <field name="state" string=""/> -->
</group> </group>
<group>
<field name="machine_tool_picture" widget="image" nolabel="1"/>
</group>
</group>
</group>
<group>
<group>
<group>
<field name="online_time" readonly="1"/>
<field name="offline_time" readonly="1"/>
<field name="fault_rate" readonly="1"/>
</group>
<group>
<field name="idle_nums" readonly="1"/>
<field name="fault_time" readonly="1"/>
<field name="fault_nums" readonly="1"/>
</group>
</group>
<group>
<group>
<field name="idle_time"/>
<field name="idle_rate"/>
</group>
<group>
<field name="work_time"/>
<field name="work_rate"/>
</group>
</group>
</group> </group>
<notebook> <notebook>
<page string="24H日志详情"> <page string="24H日志详情">
@@ -81,28 +110,28 @@
<!-- </div> --> <!-- </div> -->
<!-- </group> --> <!-- </group> -->
</page> </page>
<page string="历史日志详情"> <!-- <page string="历史日志详情"> -->
<group> <!-- <group> -->
<group> <!-- <group> -->
<group> <!-- <group> -->
<field name="begin_time"/> <!-- <field name="begin_time"/> -->
</group> <!-- </group> -->
<group> <!-- <group> -->
<field name="end_time"/> <!-- <field name="end_time"/> -->
</group> <!-- </group> -->
</group> <!-- </group> -->
<group> <!-- <group> -->
<group> <!-- <group> -->
<button name="get_history_logs" type="object" string="查看历史日志" t-attf-style="white-space:nowrap;"/> <!-- <button name="get_history_logs" type="object" string="查看历史日志" t-attf-style="white-space:nowrap;"/> -->
</group> <!-- </group> -->
<group> <!-- <group> -->
<button name="download_history_logs" type="object" string="下载历史日志" t-attf-style="white-space:nowrap;"/> <!-- <button name="download_history_logs" type="object" string="下载历史日志" t-attf-style="white-space:nowrap;"/> -->
</group> <!-- </group> -->
</group> <!-- </group> -->
</group> <!-- </group> -->
<field name="history_logs_detail"/> <!-- <field name="history_logs_detail"/> -->
</page> <!-- </page> -->
</notebook> </notebook>
</sheet> </sheet>
</form> </form>

View File

@@ -105,249 +105,6 @@
</field> </field>
</record> </record>
<!-- 设备运行日志 -->
<record id="view_maintenance_logs_run_tree" model="ir.ui.view">
<field name="name">maintenance.logs.run.tree</field>
<field name="model">maintenance.equipment.oee.logs</field>
<field name="arch" type="xml">
<tree>
<field name="equipment_id"/>
</tree>
</field>
</record>
<record id="view_maintenance_logs_run_form" model="ir.ui.view">
<field name="name">maintenance.logs.run.form</field>
<field name="model">maintenance.equipment.oee.logs</field>
<field name="arch" type="xml">
<!-- <form string="设备运行日志"> -->
<!-- <header> -->
<!-- <field name="equipment_id" readonly="1"/> -->
<!-- </header> -->
<!-- <sheet> -->
<!-- <div class="oe_title"> -->
<!-- <h1> -->
<!-- <field name="start_time" readonly="1"/> -->
<!-- </h1> -->
<!-- </div> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="stop_time" readonly="1"/> -->
<!-- <field name="duration" readonly="1"/> -->
<!-- <field name="oee" readonly="1"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="note"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- </sheet> -->
<!-- </form> -->
<form string="设备运行日志">
<!-- <header> -->
<!-- <field name="name" readonly="1"/> -->
<!-- </header> -->
<sheet>
<div class="oe_title">
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<group>
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/>
<field name="type_id"/>
<field name="state"/>
<field name="equipment_code"/>
<field name="function_type"/>
</group>
</group>
<group>
<group>
<!-- <field name="state" nolabel="1"/> -->
<field name="state" string=""/>
</group>
<group>
<field name="machine_tool_picture" widget="image" nolabel="1"/>
</group>
</group>
</group>
<group>
<group>
<group>
<field name="online_time" readonly="1"/>
<field name="offline_time" readonly="1"/>
<field name="fault_rate" readonly="1"/>
</group>
<group>
<field name="offline_nums" readonly="1"/>
<field name="fault_time" readonly="1"/>
<field name="fault_nums" readonly="1"/>
</group>
</group>
<group>
<group>
<field name="idle_time"/>
<field name="idle_rate"/>
</group>
<group>
<field name="work_time"/>
<field name="work_rate"/>
</group>
</group>
</group>
<notebook>
<page string="24H日志详情">
<!-- 筛选出24小时内的日志 -->
<!-- <field name="detail_ids" domain="[('time','&lt;',(datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))]"> -->
<field name="detail_ids" domain="[('state','ilike','加工')]">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
<!-- <field name="time"/> -->
<!-- <field name="state"/> -->
<!-- <field name="production_id"/> -->
<!-- </form> -->
</field>
</page>
<page string="历史日志详情">
<field name="detail_ids">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
<!-- <field name="time"/> -->
<!-- <field name="state"/> -->
<!-- <field name="production_id"/> -->
<!-- </form> -->
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- <record id="view_maintenance_logs_run_search" model="ir.ui.view"> -->
<!-- <field name="name">maintenance.logs.run.search</field> -->
<!-- <field name="model">maintenance.equipment.oee.logs</field> -->
<!-- <field name="arch" type="xml"> -->
<!-- <search> -->
<!-- <field name="equipment_id"/> -->
<!-- <field name="start_time"/> -->
<!-- <field name="stop_time"/> -->
<!-- <field name="duration"/> -->
<!-- <field name="oee"/> -->
<!-- <field name="note"/> -->
<!-- </search> -->
<!-- </field> -->
<!-- </record> -->
<!-- 设备运行日志详情 -->
<record id="view_maintenance_logs_run_detail_tree" model="ir.ui.view">
<field name="name">maintenance.logs.run.detail.tree</field>
<field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
</field>
</record>
<record id="view_maintenance_logs_run_detail_form" model="ir.ui.view">
<field name="name">maintenance.logs.run.detail.form</field>
<field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml">
<form string="设备运行日志详情">
<sheet>
<group>
<group>
<field name="state"/>
<!-- <field name="production_id"/> -->
</group>
<group>
<!-- <field name="sequence"/> -->
<field name="time"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- <record id="view_maintenance_logs_run_detail_search" model="ir.ui.view"> -->
<!-- <field name="name">maintenance.logs.run.detail.search</field> -->
<!-- <field name="model">maintenance.equipment.oee.logs.detail</field> -->
<!-- <field name="arch" type="xml"> -->
<!-- <search> -->
<!-- <field name="equipment_id"/> -->
<!-- <field name="start_time"/> -->
<!-- <field name="stop_time"/> -->
<!-- <field name="duration"/> -->
<!-- <field name="oee"/> -->
<!-- <field name="note"/> -->
<!-- </search> -->
<!-- </field> -->
<!-- </record> -->
<!-- 设备运行日志详情action -->
<!-- <record id="action_maintenance_logs_run_detail" model="ir.actions.act_window"> -->
<!-- <field name="name">设备运行日志详情</field> -->
<!-- <field name="type">ir.actions.act_window</field> -->
<!-- <field name="res_model">maintenance.equipment.oee.logs.detail</field> -->
<!-- <field name="view_mode">tree,form</field> -->
<!-- <field name="view_id" ref="view_maintenance_logs_run_detail_tree"/> -->
<!-- <field name="help" type="html"> -->
<!-- <p class="oe_view_nocontent_create"> -->
<!-- 设备运行日志详情 -->
<!-- </p> -->
<!-- </field> -->
<!-- -->
<!-- </record> -->
<record id="action_maintenance_logs_run" model="ir.actions.act_window">
<field name="name">设备运行日志</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">maintenance.equipment.oee.logs</field>
<!-- <field name="search_view_id" ref="view_maintenance_logs_run_search"/> -->
<field name="view_mode">tree,form</field>
<!-- <field name="view_mode">form</field> -->
<field name="view_id" ref="view_maintenance_logs_run_tree"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
设备运行日志
</p>
</field>
</record>
<menuitem name="设备运行日志" id="menu_maintenance_logs_run" parent="maintenance.menu_m_request"
sequence="10" action="action_maintenance_logs_run"/>
<!-- Action --> <!-- Action -->
<record id="action_maintenance_logs" model="ir.actions.act_window"> <record id="action_maintenance_logs" model="ir.actions.act_window">

View File

@@ -1,4 +1,5 @@
import datetime import datetime
import logging
from datetime import timedelta, time from datetime import timedelta, time
from collections import defaultdict from collections import defaultdict
from odoo import fields, models, api from odoo import fields, models, api
@@ -6,6 +7,8 @@ from odoo.addons.resource.models.resource import Intervals
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
import math import math
_logger = logging.getLogger(__name__)
class ResWorkcenter(models.Model): class ResWorkcenter(models.Model):
_name = "mrp.workcenter" _name = "mrp.workcenter"
@@ -163,6 +166,19 @@ class ResWorkcenter(models.Model):
else: else:
record.effective_working_hours_day = 0 record.effective_working_hours_day = 0
# 计算传入时间日有效工作时长
def _compute_effective_working_hours_day1(self, date):
effective_working_hours_day = 0
for record in self:
attendance_ids = [p for p in record.resource_calendar_id.attendance_ids if
p.dayofweek == self.get_current_day_of_week(date)]
if attendance_ids:
for attendance_id in attendance_ids:
if attendance_id.hour_from and attendance_id.hour_to:
effective_working_hours_day += attendance_id.hour_to - attendance_id.hour_from
return effective_working_hours_day
# 获取传入时间是星期几 # 获取传入时间是星期几
def get_current_day_of_week(self, datetime): def get_current_day_of_week(self, datetime):
day_num = datetime.weekday() day_num = datetime.weekday()
@@ -211,7 +227,12 @@ class ResWorkcenter(models.Model):
('state', 'not in', ['draft', 'cancel'])]) ('state', 'not in', ['draft', 'cancel'])])
if plan_ids: if plan_ids:
sum_qty = sum([p.product_qty for p in plan_ids]) sum_qty = sum([p.product_qty for p in plan_ids])
if sum_qty >= self.default_capacity: date_planned_working_hours = self._compute_effective_working_hours_day1(date_planned)
default_capacity = round(
self.production_line_hour_capacity * date_planned_working_hours, 2)
_logger.info('排程日期:%s,计划数量:%s,日产能:%s,日工时:%s' % (
date_planned, sum_qty, default_capacity, date_planned_working_hours))
if sum_qty >= default_capacity:
return False return False
return True return True

View File

@@ -1,5 +1,5 @@
import re import re
import json import json, tempfile
import logging import logging
import base64 import base64
import urllib.parse import urllib.parse
@@ -1527,7 +1527,8 @@ class CNCprocessing(models.Model):
# 将FTP的多面的程序单文件下载到临时目录 # 将FTP的多面的程序单文件下载到临时目录
def download_file_tmp(self, production_no, processing_panel): def download_file_tmp(self, production_no, processing_panel):
remotepath = os.path.join('/home/ftp/ftp_root/NC', production_no, 'return', processing_panel) remotepath = os.path.join('/home/ftp/ftp_root/NC', production_no, 'return', processing_panel)
serverdir = os.path.join('/tmp', production_no, 'return', processing_panel) tmp_path = tempfile.gettempdir()
serverdir = os.path.join(tmp_path, production_no, 'return', processing_panel)
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_resconfig['ftp_user'], ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp_resconfig['ftp_user'],
ftp_resconfig['ftp_password']) ftp_resconfig['ftp_password'])
@@ -1827,6 +1828,11 @@ class WorkPieceDelivery(models.Model):
else: else:
raise UserError("接驳站暂未反馈站点实时状态,请稍后再试") raise UserError("接驳站暂未反馈站点实时状态,请稍后再试")
def delivery_avg(self):
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
if is_agv_task_dispatch:
self._delivery_avg()
# 配送至avg小车 # 配送至avg小车
def _delivery_avg(self): def _delivery_avg(self):
config = self.env['res.config.settings'].get_values() config = self.env['res.config.settings'].get_values()
@@ -1886,7 +1892,7 @@ class WorkPieceDelivery(models.Model):
logging.info('delivery_item-name:%s' % delivery_item.name) logging.info('delivery_item-name:%s' % delivery_item.name)
delivery_item.write({ delivery_item.write({
'task_delivery_time': fields.Datetime.now(), 'task_delivery_time': fields.Datetime.now(),
'status': '待配送' 'status': '已下发'
}) })
if delivery_item.type == "上产线": if delivery_item.type == "上产线":
delivery_item.workorder_id.write({'is_delivery': True}) delivery_item.workorder_id.write({'is_delivery': True})

View File

@@ -797,7 +797,7 @@
<field name="feeder_station_start_id" readonly="1" force_save="1"/> <field name="feeder_station_start_id" readonly="1" force_save="1"/>
<!-- <field name="type" readonly="1"/>--> <!-- <field name="type" readonly="1"/>-->
<field name="feeder_station_destination_id" readonly="1" force_save="1"/> <field name="feeder_station_destination_id" readonly="1" force_save="1"/>
<button name="button_delivery" type="object" string="配送" class="oe_highlight"/> <button name="delivery_avg" type="object" string="配送" class="oe_highlight"/>
<button name="action_delivery_history" type="object" class="btn btn-link text-info" icon="fa-history" <button name="action_delivery_history" type="object" class="btn btn-link text-info" icon="fa-history"
string="历史"/> string="历史"/>
</tree> </tree>

View File

@@ -11,10 +11,12 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify','stock', 'sf_tool_management', 'sf_manufacturing', 'sf_hr'], 'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock'],
'data': [ 'data': [
'data/bussiness_node.xml', 'data/bussiness_node.xml',
# 'data/cron_data.xml',
'data/template_data.xml', 'data/template_data.xml',
], ],
'test': [ 'test': [
], ],

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<!--销售订单-->
<record id="bussiness_pending_order" model="jikimo.message.bussiness.node"> <record id="bussiness_pending_order" model="jikimo.message.bussiness.node">
<field name="name">待接单</field> <field name="name">待接单</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
@@ -10,6 +11,17 @@
<field name="name">确认接单</field> <field name="name">确认接单</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
</record> </record>
<!-- <record id="bussiness_sale_order_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单逾期预警</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<!-- <record id="bussiness_sale_order_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单已逾期</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<record id="transfer_inventory" model="jikimo.message.bussiness.node"> <record id="transfer_inventory" model="jikimo.message.bussiness.node">
<field name="name">调拨入库</field> <field name="name">调拨入库</field>
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
@@ -30,9 +42,48 @@
<field name="name">坯料发料提醒</field> <field name="name">坯料发料提醒</field>
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
</record> </record>
<!--工单-->
<record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node"> <record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node">
<field name="name">工单已下发通知</field> <field name="name">工单已下发通知</field>
<field name="model">mrp.workorder</field> <field name="model">mrp.workorder</field>
</record> </record>
<!-- <record id="bussiness_mrp_workorder_pre_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_pre_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_cnc_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_cnc_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_surface_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_surface_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
</data> </data>
</odoo> </odoo>

View File

@@ -0,0 +1,160 @@
<odoo>
<data noupdate="1">
<record model="ir.cron" id="ir_cron_sale_order_overdue_warning">
<field name="name">销售订单逾期预警</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_sale_order_overdue">
<field name="name">销售订单已逾期</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">
<field name="name">装夹预调工单逾期预警</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue">
<field name="name">工单已逾期</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
</data>
</odoo>

View File

@@ -1,6 +1,32 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record id="template_pending_order" model="jikimo.message.template">
<field name="name">待接单</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_pending_order"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待接单提醒:
单号:销售订单[{{name}}]({{url}})
事项:请确认是否接单。
</field>
</record>
<record id="template_to_be_confirm" model="jikimo.message.template">
<field name="name">确认接单</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_to_be_confirm"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待排程提醒:
单号:产品[{{product_id}}]({{url}})
事项:{{mrp_production_count}}个制造订单待计划排程
</field>
</record>
<record id="template_material_purchase_remind" model="jikimo.message.template"> <record id="template_material_purchase_remind" model="jikimo.message.template">
<field name="name">坯料采购提醒</field> <field name="name">坯料采购提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/> <field name="model_id" ref="purchase.model_purchase_order"/>

View File

@@ -19,9 +19,7 @@ class SFMessagePurchase(models.Model):
return contents return contents
def request_url(self, id): def request_url(self, id):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('purchase.purchase_form_action').id action_id = self.env.ref('purchase.purchase_form_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_website_payment')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_website_payment')]).id
# 查询参数 # 查询参数
@@ -31,5 +29,5 @@ class SFMessagePurchase(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -40,21 +40,34 @@ class SFMessageSale(models.Model):
# 继承并重写jikimo.message.dispatch的_get_message() # 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
res = super(SFMessageSale, self)._get_message(message_queue_ids) contents = []
new_res = [] url = self.env['ir.config_parameter'].get_param('web.base.url')
processed_messages = set() # 用于跟踪已经处理过的消息
for item in message_queue_ids: for item in message_queue_ids:
if item.message_template_id.bussiness_node_id.name == '确认接单': # 待接单的处理
if item.message_template_id.bussiness_node_id.name == '待接单':
content = super(SFMessageSale, self)._get_message(item)
action_id = self.env.ref('sale.action_quotations_with_onboarding').id
url = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}"
content = content[0].replace('{{url}}', url)
contents.append(content)
# 确认接单的处理
elif item.message_template_id.bussiness_node_id.name == '确认接单':
content = super(SFMessageSale, self)._get_message(item)
sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))]) sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))])
if len(sale_order_line) == 1: product = sale_order_line[0].product_id.name if len(sale_order_line) == 1 else '%s...' % \
product = sale_order_line[0].product_id.name sale_order_line[
elif len(sale_order_line) > 1: 0].product_id.name
product = '%s...' % sale_order_line[0].product_id.name action_id = self.env.ref('sf_plan.sf_production_plan_action1').id
for message in res: url = f"{url}/web#view_type=list&action={action_id}"
message_text = message.replace('{{product_id}}', product) content = content[0].replace('{{product_id}}', product).replace('{{url}}', url)
if message_text not in processed_messages: contents.append(content)
new_res.append(message_text) return contents
processed_messages.add(message_text)
if new_res: # # 销售订单逾期预警
res = new_res # def _overdue_warning_func(self):
return res # sale_order_
# return 1
#
# # 销售订单已逾期
# def _overdue_func(self):
# return 1

View File

@@ -52,9 +52,7 @@ class SFMessageStockPicking(models.Model):
return res return res
def request_url(self): def request_url(self):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('stock.stock_picking_type_action').id action_id = self.env.ref('stock.stock_picking_type_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数 # 查询参数
@@ -63,5 +61,5 @@ class SFMessageStockPicking(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -40,9 +40,7 @@ class SFMessageWork(models.Model):
return contents return contents
def request_url(self): def request_url(self):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id
# 查询参数 # 查询参数
@@ -51,5 +49,6 @@ class SFMessageWork(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
import os import os
import tempfile
import json import json
import base64 import base64
from odoo import http from odoo import http
@@ -23,6 +24,7 @@ class Sf_Mrs_Connect(http.Controller):
datas = request.httprequest.data datas = request.httprequest.data
ret = json.loads(datas) ret = json.loads(datas)
ret = json.loads(ret['result']) ret = json.loads(ret['result'])
tmp_path = tempfile.gettempdir()
logging.info('下发编程单:%s' % ret) logging.info('下发编程单:%s' % ret)
domain = [('programming_no', '=', ret['programming_no'])] domain = [('programming_no', '=', ret['programming_no'])]
if ret['manufacturing_type'] == 'scrap': if ret['manufacturing_type'] == 'scrap':
@@ -32,7 +34,7 @@ class Sf_Mrs_Connect(http.Controller):
if productions: if productions:
# 拉取所有加工面的程序文件 # 拉取所有加工面的程序文件
for r in ret['processing_panel'].split(','): for r in ret['processing_panel'].split(','):
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r) program_path_tmp_r = os.path.join(tmp_path, ret['folder_name'], 'return', r)
if os.path.exists(program_path_tmp_r): if os.path.exists(program_path_tmp_r):
files_r = os.listdir(program_path_tmp_r) files_r = os.listdir(program_path_tmp_r)
if files_r: if files_r:
@@ -75,7 +77,7 @@ class Sf_Mrs_Connect(http.Controller):
if cnc_workorder: if cnc_workorder:
# program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test', # program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
# panel) # panel)
program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel) program_path_tmp_panel = os.path.join(tmp_path, ret['folder_name'], 'return', panel)
logging.info('program_path_tmp_panel:%s' % program_path_tmp_panel) logging.info('program_path_tmp_panel:%s' % program_path_tmp_panel)
files_panel = os.listdir(program_path_tmp_panel) files_panel = os.listdir(program_path_tmp_panel)
if files_panel: if files_panel:

View File

@@ -18,7 +18,7 @@ class OrderPrice(models.Model):
return True return True
except ValueError: except ValueError:
return False return False
@api.depends('sale_order_id.remark') @api.depends('sale_order_id.order_line.remark')
def _compute_bfm_amount_total(self): def _compute_bfm_amount_total(self):
for record in self: for record in self:
amount_total = 0 amount_total = 0

View File

@@ -3013,8 +3013,7 @@ class CuttingToolBasicParameters(models.Model):
}) })
if 'basic_parameters_cutter_head' in result['cutting_tool_basic_parameters_yesterday_list']: if 'basic_parameters_cutter_head' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_head']: if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_head']:
basic_parameters_cutter_head_list = json.loads( basic_parameters_cutter_head_list = result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_head']
result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_head'])
if basic_parameters_cutter_head_list: if basic_parameters_cutter_head_list:
for cutter_head_item in basic_parameters_cutter_head_list: for cutter_head_item in basic_parameters_cutter_head_list:
cutter_head = self.search( cutter_head = self.search(

View File

@@ -339,7 +339,7 @@
name="空料架配送" name="空料架配送"
sequence="11" sequence="11"
action="sf_manufacturing.sf_workpiece_delivery_empty_racks_act" action="sf_manufacturing.sf_workpiece_delivery_empty_racks_act"
groups="base.group_system" groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user"
parent="mrp.menu_mrp_manufacturing" parent="mrp.menu_mrp_manufacturing"
/> />
<!-- <menuitem --> <!-- <menuitem -->