Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复报废
# Conflicts: # sf_manufacturing/models/mrp_workorder.py
This commit is contained in:
3
sf_hr/__init__.py
Normal file
3
sf_hr/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
22
sf_hr/__manifest__.py
Normal file
22
sf_hr/__manifest__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': '机企猫智能工厂 员工管理',
|
||||
'version': '1.0',
|
||||
'summary': '智能工厂员工模块',
|
||||
'sequence': 1,
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['hr'],
|
||||
'data': [
|
||||
'views/hr_employee.xml',
|
||||
],
|
||||
'demo': [
|
||||
],
|
||||
'qweb': [
|
||||
],
|
||||
'license': 'LGPL-3',
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'auto_install': False,
|
||||
}
|
||||
2
sf_hr/models/__init__.py
Normal file
2
sf_hr/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
0
sf_hr/security/ir.model.access.csv
Normal file
0
sf_hr/security/ir.model.access.csv
Normal file
|
|
15
sf_hr/views/hr_employee.xml
Normal file
15
sf_hr/views/hr_employee.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_form_employee_extend" model="ir.ui.view">
|
||||
<field name="name">employee_form</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group//field[@name='work_email']" position="attributes">
|
||||
<attribute name="required">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -173,49 +173,6 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
res['message'] = '前端请求机床数据失败,原因:%s' % e
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
# @http.route('/api/logs/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False,
|
||||
# cors="*")
|
||||
# def logs_list(self, **kw):
|
||||
# """
|
||||
# 拿到日志数据返回给大屏展示
|
||||
# :param kw:
|
||||
# :return:
|
||||
# """
|
||||
# res = {'status': 1, 'message': '成功', 'data': []}
|
||||
# logging.info('前端请求日志数据的参数为:%s' % kw)
|
||||
#
|
||||
# try:
|
||||
# # 获取请求的日志数据
|
||||
# logs_obj = request.env['maintenance.equipment.oee.log.detail'].sudo()
|
||||
# # 获取请求的机床数据
|
||||
# machine_list = ast.literal_eval(kw['machine_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('begin_time: %s' % begin_time)
|
||||
# for item in machine_list:
|
||||
# log_datas = logs_obj.search(
|
||||
# [('equipment_code', '=', item), ('time', '>=', begin_time), ('time', '<=', end_time)])
|
||||
# print('log_datas: %s' % log_datas)
|
||||
# for log_data in log_datas:
|
||||
# res['data'].append({
|
||||
# 'equipment_code': log_data.equipment_code,
|
||||
# 'time': log_data.time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
# 'state': log_data.state
|
||||
#
|
||||
# })
|
||||
#
|
||||
# return json.JSONEncoder().encode(res)
|
||||
#
|
||||
# except Exception as e:
|
||||
# logging.info('前端请求日志数据失败,原因:%s' % e)
|
||||
# res['status'] = -1
|
||||
# res['message'] = '前端请求日志数据失败,原因:%s' % e
|
||||
# return json.JSONEncoder().encode(res)
|
||||
|
||||
@http.route('/api/logs/list', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def logs_list(self, **kw):
|
||||
"""
|
||||
@@ -227,9 +184,9 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
logging.info('前端请求日志数据的参数为:%s' % kw)
|
||||
|
||||
try:
|
||||
# 获取请求的日志数据
|
||||
logs_obj = request.env['maintenance.equipment.oee.log.detail'].sudo()
|
||||
# 获取请求的机床数据
|
||||
# 连接数据库
|
||||
conn = psycopg2.connect(**db_config)
|
||||
cur = conn.cursor()
|
||||
machine_list = ast.literal_eval(kw['machine_list'])
|
||||
begin_time_str = kw['begin_time'].strip('"')
|
||||
end_time_str = kw['end_time'].strip('"')
|
||||
@@ -240,19 +197,25 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
print('begin_time: %s' % begin_time)
|
||||
|
||||
for item in machine_list:
|
||||
log_datas = logs_obj.search(
|
||||
[('equipment_code', '=', item), ('time', '>=', begin_time), ('time', '<=', end_time)])
|
||||
print('log_datas: %s' % log_datas)
|
||||
sql = '''
|
||||
SELECT time, device_state, program_name
|
||||
FROM device_data
|
||||
WHERE device_name = %s AND time >= %s AND time <= %s
|
||||
ORDER BY time ASC;
|
||||
'''
|
||||
# 执行SQL命令,使用参数绑定
|
||||
cur.execute(sql, (item, begin_time, end_time))
|
||||
results = cur.fetchall()
|
||||
|
||||
# 将数据按照 equipment_code 进行分组
|
||||
if item not in res['data']:
|
||||
res['data'][item] = []
|
||||
|
||||
for log_data in log_datas:
|
||||
for result in results:
|
||||
res['data'][item].append({
|
||||
'time': log_data.time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'state': log_data.state,
|
||||
'production_name': log_data.production_name,
|
||||
'time': result[0].strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'state': result[1],
|
||||
'production_name': result[2],
|
||||
})
|
||||
|
||||
return json.dumps(res) # 注意使用 json.dumps 而不是直接用 json.JSONEncoder().encode()
|
||||
@@ -624,7 +587,7 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
|
||||
# 查询pg库来获得待机次数
|
||||
@http.route('/api/IdleAlarmCount', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def idle_count(self, **kw):
|
||||
def idle_alarm_count(self, **kw):
|
||||
"""
|
||||
查询设备的待机次数
|
||||
"""
|
||||
@@ -637,69 +600,50 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
try:
|
||||
# 获取请求的机床数据
|
||||
machine_list = ast.literal_eval(kw['machine_list'])
|
||||
idle_times = []
|
||||
idle_dict = {}
|
||||
|
||||
total_alarm_time = 0
|
||||
alarm_count_num = 0
|
||||
for item in machine_list:
|
||||
sql = '''
|
||||
SELECT idle_start_time,alarm_time,alarm_repair_time FROM device_data WHERE device_name = %s;
|
||||
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
|
||||
ORDER BY idle_start_time, time
|
||||
) subquery;
|
||||
'''
|
||||
|
||||
sql2 = '''
|
||||
SELECT DISTINCT ON (alarm_time) alarm_time, alarm_repair_time
|
||||
FROM device_data
|
||||
WHERE device_name = %s AND alarm_time IS NOT NULL
|
||||
ORDER BY alarm_time, time;
|
||||
|
||||
'''
|
||||
# 执行SQL命令
|
||||
cur.execute(sql, (item,))
|
||||
result = cur.fetchall()
|
||||
# # print('result', result)
|
||||
#
|
||||
# # 将查询结果添加到idle_times列表中
|
||||
# idle_times = [row[0] for row in result if row[0] is not None]
|
||||
#
|
||||
# # 对结果去重
|
||||
# unique_idle_times = set(idle_times)
|
||||
# # print('unique_idle_times', unique_idle_times)
|
||||
#
|
||||
# # 统计去重后的数量
|
||||
# idle_count = len(unique_idle_times)
|
||||
# # idle_dict[item] = idle_count
|
||||
#
|
||||
# res['data'][item] = idle_count
|
||||
|
||||
total_alarm_time = 0
|
||||
alarm_count = 0
|
||||
alarm_time_list = []
|
||||
idle_times = []
|
||||
alarm_times = []
|
||||
print('result========', result)
|
||||
|
||||
cur.execute(sql2, (item,))
|
||||
result2 = cur.fetchall()
|
||||
print('result2========', result2)
|
||||
#
|
||||
for row in result:
|
||||
idle_start_time = row[0]
|
||||
alarm_time = row[1]
|
||||
alarm_repair_time = row[2]
|
||||
|
||||
alarm_time_list.append(alarm_time) # 将时长累加,以秒为单位
|
||||
idle_times.append(idle_start_time)
|
||||
# if alarm_repair_time is not None:
|
||||
# alarm_times.append(alarm_repair_time)
|
||||
alarm_times.append(alarm_repair_time)
|
||||
|
||||
# 对结果去重
|
||||
unique_total_alarm_time = set(alarm_time_list)
|
||||
unique_idle_times = set(idle_times)
|
||||
unique_alarm_times = set(alarm_times)
|
||||
|
||||
# 统计去重后的数量
|
||||
idle_count = len(unique_idle_times)
|
||||
|
||||
for alarm_time in unique_total_alarm_time:
|
||||
if alarm_time is not None:
|
||||
total_alarm_time += abs(float(alarm_time))
|
||||
|
||||
alarm_count = len(unique_alarm_times) if unique_alarm_times else 0
|
||||
alarm_count = alarm_count if total_alarm_time else 0
|
||||
|
||||
# 存储待机次数和总待机时长(单位:秒)
|
||||
res['data'][item] = {
|
||||
'idle_count': idle_count,
|
||||
'total_alarm_time': total_alarm_time / 3600, # 以秒为单位
|
||||
'alarm_count': alarm_count
|
||||
}
|
||||
res['data'][item] = {'idle_count': row[0]}
|
||||
alarm_count = []
|
||||
for row in result2:
|
||||
alarm_count.append(row[0])
|
||||
total_alarm_time += abs(float(row[0]))
|
||||
if len(list(set(alarm_count))) == 1:
|
||||
if list(set(alarm_count))[0] is None:
|
||||
alarm_count_num = 0
|
||||
else:
|
||||
alarm_count_num = 1
|
||||
else:
|
||||
alarm_count_num = len(list(set(alarm_count)))
|
||||
res['data'][item]['total_alarm_time'] = total_alarm_time / 3600
|
||||
res['data'][item]['alarm_count_num'] = alarm_count_num
|
||||
|
||||
# 返回统计结果
|
||||
return json.dumps(res)
|
||||
@@ -712,7 +656,7 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
|
||||
# 查询pg库来获得异常情况
|
||||
@http.route('/api/alarm/logs', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def idle_count(self, **kw):
|
||||
def alarm_logs(self, **kw):
|
||||
"""
|
||||
查询设备的异常情况
|
||||
"""
|
||||
@@ -764,3 +708,110 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
finally:
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# 设备oee
|
||||
@http.route('/api/OEE', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def OEE(self, **kw):
|
||||
"""
|
||||
获取产线等oee
|
||||
"""
|
||||
res = {'status': 1, 'message': '成功', 'data': {}}
|
||||
logging.info('前端请求oee数据的参数为:%s' % kw)
|
||||
|
||||
try:
|
||||
count_oee = 1
|
||||
workcenter_obj = request.env['mrp.workcenter'].sudo()
|
||||
workcenter_list = ast.literal_eval(kw['workcenter_list'])
|
||||
print('workcenter_list: %s' % workcenter_list)
|
||||
for line in workcenter_list:
|
||||
res['data'][line] = workcenter_obj.search([('name', '=', line)]).oee
|
||||
count_oee *= workcenter_obj.search([('name', '=', line)]).oee
|
||||
res['data']['综合oee'] = count_oee / 1000000
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
|
||||
return json.dumps(res)
|
||||
|
||||
# # 查询某段时间的设备oee
|
||||
# @http.route('/api/OEEByTime', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
# def OEEByTime(self, **kw):
|
||||
# """
|
||||
# 获取某段时间的oee
|
||||
# """
|
||||
# res = {'status': 1, 'message': '成功', 'data': {}}
|
||||
# logging.info('前端请求获取某段时间的oee的参数为:%s' % kw)
|
||||
# workcenter_list = ast.literal_eval(kw['workcenter_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('workcenter_list: %s' % workcenter_list)
|
||||
# # 连接数据库
|
||||
# conn = psycopg2.connect(**db_config)
|
||||
# cur = conn.cursor()
|
||||
# # 查询并计算OEE平均值
|
||||
# oee_data = {}
|
||||
# for workcenter in workcenter_list:
|
||||
# cur.execute("""
|
||||
# SELECT AVG(oee) as avg_oee
|
||||
# FROM oee_data
|
||||
# WHERE workcenter_name = %s
|
||||
# AND time BETWEEN %s AND %s
|
||||
# """, (workcenter, begin_time, end_time))
|
||||
#
|
||||
# result = cur.fetchone()
|
||||
# avg_oee = result[0] if result else 0.0
|
||||
# oee_data[workcenter] = avg_oee
|
||||
#
|
||||
# # 返回数据
|
||||
# res['data'] = oee_data
|
||||
# return json.dumps(res)
|
||||
|
||||
@http.route('/api/OEEByTime', type='http', auth='public', methods=['GET', 'POST'], csrf=False, cors="*")
|
||||
def OEEByTime(self, **kw):
|
||||
"""
|
||||
获取某段时间的oee,根据用户指定的时间单位(day或hour)返回对应的平均值
|
||||
"""
|
||||
res = {'status': 1, 'message': '成功', 'data': {}}
|
||||
logging.info('前端请求获取某段时间的oee的参数为:%s' % kw)
|
||||
|
||||
# 获取并解析参数
|
||||
workcenter_list = ast.literal_eval(kw['workcenter_list'])
|
||||
begin_time_str = kw['begin_time'].strip('"')
|
||||
end_time_str = kw['end_time'].strip('"')
|
||||
time_unit = kw.get('time_unit', 'day') # 默认单位为天
|
||||
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')
|
||||
|
||||
# 连接数据库
|
||||
conn = psycopg2.connect(**db_config)
|
||||
cur = conn.cursor()
|
||||
|
||||
# 根据时间单位选择不同的时间格式
|
||||
if time_unit == 'hour':
|
||||
time_format = 'YYYY-MM-DD HH24:00:00'
|
||||
else: # 默认为'day'
|
||||
time_format = 'YYYY-MM-DD'
|
||||
|
||||
# 查询并计算OEE平均值
|
||||
oee_data = {}
|
||||
for workcenter in workcenter_list:
|
||||
cur.execute(f"""
|
||||
SELECT to_char(time, '{time_format}') as time_unit, AVG(oee) as avg_oee
|
||||
FROM oee_data
|
||||
WHERE workcenter_name = %s
|
||||
AND time BETWEEN %s AND %s
|
||||
GROUP BY time_unit
|
||||
ORDER BY time_unit
|
||||
""", (workcenter, begin_time, end_time))
|
||||
|
||||
results = cur.fetchall()
|
||||
oee_data[workcenter] = {row[0]: row[1] for row in results}
|
||||
|
||||
# 关闭数据库连接
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# 返回数据
|
||||
res['data'] = oee_data
|
||||
return json.dumps(res)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
'views/model_type_view.xml',
|
||||
'views/agv_setting_views.xml',
|
||||
'views/sf_maintenance_equipment.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@ from . import res_user
|
||||
from . import production_line_base
|
||||
from . import agv_setting
|
||||
from . import agv_scheduling
|
||||
from . import res_config_setting
|
||||
|
||||
@@ -231,7 +231,9 @@ class AgvScheduling(models.Model):
|
||||
rec.site_state = '空闲'
|
||||
rec.end_site_id = agv_task_route.end_site_id.id
|
||||
rec.agv_route_id = agv_task_route.id
|
||||
# rec._delivery_avg()
|
||||
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
|
||||
if is_agv_task_dispatch:
|
||||
rec._delivery_avg()
|
||||
# 更新接驳站状态
|
||||
rec.env['sf.agv.site'].update_site_state({rec.end_site_id.name: '占用'}, False)
|
||||
|
||||
|
||||
@@ -123,7 +123,12 @@ class MrpProduction(models.Model):
|
||||
# 上传零件图纸
|
||||
part_drawing = fields.Binary('零件图纸')
|
||||
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
||||
@api.depends('product_id.manual_quotation')
|
||||
def _compute_manual_quotation(self):
|
||||
for item in self:
|
||||
item.manual_quotation = item.product_id.manual_quotation
|
||||
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
|
||||
is_scrap = fields.Boolean('是否报废', default=False)
|
||||
is_remanufacture = fields.Boolean('是否重新制造', default=False)
|
||||
remanufacture_count = fields.Integer("重新制造订单数量", compute='_compute_remanufacture_production_ids')
|
||||
|
||||
@@ -41,6 +41,7 @@ class ResWorkcenter(models.Model):
|
||||
|
||||
oee_target = fields.Float(
|
||||
string='OEE Target', help="Overall Effective Efficiency Target in percentage", default=90, tracking=True)
|
||||
oee = fields.Float(compute='_compute_oee', help='Overall Equipment Effectiveness, based on the last month', store=True)
|
||||
|
||||
time_start = fields.Float('Setup Time', tracking=True)
|
||||
time_stop = fields.Float('Cleanup Time', tracking=True)
|
||||
|
||||
@@ -60,7 +60,12 @@ class ResMrpWorkOrder(models.Model):
|
||||
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
|
||||
# state = fields.Selection(selection_add=[('to be detected', "待检测"), ('rework', '返工')], tracking=True)
|
||||
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
||||
@api.depends('production_id.manual_quotation')
|
||||
def _compute_manual_quotation(self):
|
||||
for item in self:
|
||||
item.manual_quotation = item.production_id.manual_quotation
|
||||
|
||||
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
|
||||
|
||||
def _compute_working_users(self):
|
||||
super()._compute_working_users()
|
||||
@@ -1154,10 +1159,12 @@ class ResMrpWorkOrder(models.Model):
|
||||
def button_finish(self):
|
||||
for record in self:
|
||||
if record.routing_type == '装夹预调':
|
||||
# if not record.material_center_point or record.X_deviation_angle <= 0:
|
||||
# raise UserError("请对前置三元检测定位参数进行计算定位")
|
||||
if not record.material_center_point or record.X_deviation_angle <= 0:
|
||||
raise UserError("请对前置三元检测定位参数进行计算定位")
|
||||
if not record.rfid_code and record.is_rework is False:
|
||||
raise UserError("请扫RFID码进行绑定")
|
||||
if not record.material_center_point or record.X_deviation_angle <= 0:
|
||||
raise UserError("请对前置三元检测定位参数进行计算定位")
|
||||
record.process_state = '待加工'
|
||||
# record.write({'process_state': '待加工'})
|
||||
record.production_id.process_state = '待加工'
|
||||
|
||||
22
sf_manufacturing/models/res_config_setting.py
Normal file
22
sf_manufacturing/models/res_config_setting.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
is_agv_task_dispatch = fields.Boolean('是否下发AGV任务', default=False)
|
||||
|
||||
@api.model
|
||||
def get_values(self):
|
||||
values = super(ResConfigSettings, self).get_values()
|
||||
config = self.env['ir.config_parameter'].sudo()
|
||||
is_agv_task_dispatch = config.get_param('is_agv_task_dispatch')
|
||||
values.update(
|
||||
is_agv_task_dispatch=is_agv_task_dispatch,
|
||||
)
|
||||
return values
|
||||
|
||||
def set_values(self):
|
||||
super(ResConfigSettings, self).set_values()
|
||||
config = self.env['ir.config_parameter'].sudo()
|
||||
config.set_param("is_agv_task_dispatch", self.is_agv_task_dispatch or False)
|
||||
@@ -218,7 +218,7 @@
|
||||
<xpath expr="//label[1]" position="before">
|
||||
<field name='routing_type' readonly="1"/>
|
||||
<field name='process_state' attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name="rfid_code" force_save="1" readonly="0" cache="True"
|
||||
<field name="rfid_code" force_save="1" readonly="1" cache="True"
|
||||
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
|
||||
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
|
||||
</xpath>
|
||||
|
||||
24
sf_manufacturing/views/res_config_settings_views.xml
Normal file
24
sf_manufacturing/views/res_config_settings_views.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="res_config_settings_view_form_sf_sync" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.sf_sync</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='agv_config']/div" position="after">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="is_agv_task_dispatch"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<div class="text-muted">
|
||||
<label for="is_agv_task_dispatch"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -109,11 +109,19 @@ class WorkpieceDeliveryWizard(models.TransientModel):
|
||||
)
|
||||
# 如果关联了工件配送单,则修改状态为已下发
|
||||
if self.delivery_ids:
|
||||
self.delivery_ids.write({
|
||||
val = {
|
||||
'status': '已下发',
|
||||
'agv_scheduling_id': scheduling.id,
|
||||
'feeder_station_start_id': scheduling.start_site_id.id,
|
||||
})
|
||||
}
|
||||
# 如果agv任务已经下发,则修改工件配送单信息
|
||||
if scheduling.state == '配送中':
|
||||
val.update({
|
||||
'feeder_station_destination_id': scheduling.end_site_id.id,
|
||||
'route_id': scheduling.agv_route_id.id,
|
||||
'task_delivery_time': fields.Datetime.now()
|
||||
})
|
||||
self.delivery_ids.write(val)
|
||||
|
||||
# 如果是解除装夹工单,则需要处理工单逻辑
|
||||
for item in self.workorder_ids:
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<h2>AGV参数配置</h2>
|
||||
<div class="row mt16 o_settings_container">
|
||||
<div class="row mt16 o_settings_container" id="agv_config">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane"/>
|
||||
<div class="o_setting_right_pane">
|
||||
|
||||
@@ -130,6 +130,9 @@
|
||||
<field name="signature" position="attributes">
|
||||
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
||||
</field>
|
||||
<xpath expr="//button[@name='action_cancel']" position="attributes">
|
||||
<attribute name="string">拒绝接单</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user