优化agv及新增中控日志调用
This commit is contained in:
@@ -8,7 +8,7 @@ from odoo.http import request
|
|||||||
|
|
||||||
class Manufacturing_Connect(http.Controller):
|
class Manufacturing_Connect(http.Controller):
|
||||||
|
|
||||||
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||||
cors="*")
|
cors="*")
|
||||||
def get_Work_Info(self, **kw):
|
def get_Work_Info(self, **kw):
|
||||||
"""
|
"""
|
||||||
@@ -21,6 +21,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/GetWoInfo'})
|
||||||
logging.info('RfidCode:%s' % ret['RfidCode'])
|
logging.info('RfidCode:%s' % ret['RfidCode'])
|
||||||
if 'RfidCode' in ret:
|
if 'RfidCode' in ret:
|
||||||
workorder = request.env['mrp.workorder'].sudo().search([('rfid_code', '=', ret['RfidCode'])])
|
workorder = request.env['mrp.workorder'].sudo().search([('rfid_code', '=', ret['RfidCode'])])
|
||||||
@@ -60,6 +62,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/GetShiftPlan'})
|
||||||
if 'ProductionLine' in ret:
|
if 'ProductionLine' in ret:
|
||||||
workorder_ids = request.env['mrp.workorder'].sudo().get_plan_workorder(ret['ProductionLine'])
|
workorder_ids = request.env['mrp.workorder'].sudo().get_plan_workorder(ret['ProductionLine'])
|
||||||
else:
|
else:
|
||||||
@@ -113,6 +117,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/QcCheck'})
|
||||||
logging.info('RfidCode:%s' % ret['RfidCode'])
|
logging.info('RfidCode:%s' % ret['RfidCode'])
|
||||||
if 'RfidCode' in ret:
|
if 'RfidCode' in ret:
|
||||||
workorder = request.env['mrp.workorder'].sudo().search(
|
workorder = request.env['mrp.workorder'].sudo().search(
|
||||||
@@ -150,6 +156,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': ['工单已开始']}
|
res = {'Succeed': True, 'Datas': ['工单已开始']}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/FeedBackStart'})
|
||||||
production_id = ret['BillId']
|
production_id = ret['BillId']
|
||||||
routing_type = ret['CraftId']
|
routing_type = ret['CraftId']
|
||||||
equipment_id = ret["DeviceId"]
|
equipment_id = ret["DeviceId"]
|
||||||
@@ -193,6 +201,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': ['工单已结束']}
|
res = {'Succeed': True, 'Datas': ['工单已结束']}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/FeedBackEnd'})
|
||||||
production_id = ret['BillId']
|
production_id = ret['BillId']
|
||||||
routing_type = ret['CraftId']
|
routing_type = ret['CraftId']
|
||||||
workorder = request.env['mrp.workorder'].sudo().search(
|
workorder = request.env['mrp.workorder'].sudo().search(
|
||||||
@@ -237,6 +247,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True}
|
res = {'Succeed': True}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/PartQualityInspect'})
|
||||||
production_id = ret['BillId']
|
production_id = ret['BillId']
|
||||||
routing_type = ret['CraftId']
|
routing_type = ret['CraftId']
|
||||||
workorder = request.env['mrp.workorder'].sudo().search(
|
workorder = request.env['mrp.workorder'].sudo().search(
|
||||||
@@ -293,6 +305,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/CMMProgDolod'})
|
||||||
if 'RfidCode' in ret:
|
if 'RfidCode' in ret:
|
||||||
logging.info('RfidCode:%s' % ret['RfidCode'])
|
logging.info('RfidCode:%s' % ret['RfidCode'])
|
||||||
workorder = request.env['mrp.workorder'].sudo().search(
|
workorder = request.env['mrp.workorder'].sudo().search(
|
||||||
@@ -331,6 +345,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/NCProgDolod'})
|
||||||
if 'RfidCode' in ret:
|
if 'RfidCode' in ret:
|
||||||
logging.info('RfidCode:%s' % ret['RfidCode'])
|
logging.info('RfidCode:%s' % ret['RfidCode'])
|
||||||
workorder = request.env['mrp.workorder'].sudo().search(
|
workorder = request.env['mrp.workorder'].sudo().search(
|
||||||
@@ -370,6 +386,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True, 'Datas': []}
|
res = {'Succeed': True, 'Datas': []}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
|
||||||
logging.info('LocationChange_ret===========:%s' % ret)
|
logging.info('LocationChange_ret===========:%s' % ret)
|
||||||
RfidCode = ret['RfidCode']
|
RfidCode = ret['RfidCode']
|
||||||
ChangeType = ret['ChangeType']
|
ChangeType = ret['ChangeType']
|
||||||
@@ -426,6 +444,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True}
|
res = {'Succeed': True}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/AGVToProduct'})
|
||||||
logging.info('ret:%s' % ret)
|
logging.info('ret:%s' % ret)
|
||||||
if 'DeviceId' in ret:
|
if 'DeviceId' in ret:
|
||||||
logging.info('DeviceId:%s' % ret['DeviceId'])
|
logging.info('DeviceId:%s' % ret['DeviceId'])
|
||||||
@@ -477,6 +497,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True}
|
res = {'Succeed': True}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/AGVDownProduct'})
|
||||||
logging.info('ret:%s' % ret)
|
logging.info('ret:%s' % ret)
|
||||||
if 'DeviceId' in ret:
|
if 'DeviceId' in ret:
|
||||||
logging.info('DeviceId:%s' % ret['DeviceId'])
|
logging.info('DeviceId:%s' % ret['DeviceId'])
|
||||||
@@ -538,6 +560,8 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
res = {'Succeed': True}
|
res = {'Succeed': True}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
|
request.env['center_control.interface.log'].sudo().create(
|
||||||
|
{'content': ret, 'name': 'AutoDeviceApi/EquipmentBaseCoordinate'})
|
||||||
if 'DeviceId' in ret:
|
if 'DeviceId' in ret:
|
||||||
equipment = request.env['maintenance.equipment'].sudo().search('name', '=', ret['DeviceId'])
|
equipment = request.env['maintenance.equipment'].sudo().search('name', '=', ret['DeviceId'])
|
||||||
if equipment:
|
if equipment:
|
||||||
|
|||||||
@@ -49,3 +49,13 @@ class AgvTaskRoute(models.Model):
|
|||||||
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号')
|
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号')
|
||||||
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')
|
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Center_controlInterfaceLog(models.Model):
|
||||||
|
_name = 'center_control.interface.log'
|
||||||
|
_description = '中控接口调用日志'
|
||||||
|
|
||||||
|
name = fields.Char('接口名称')
|
||||||
|
content = fields.Char('接口内容')
|
||||||
|
interface_call_date = fields.Datetime("调用时间", default=fields.Datetime.now, readonly=True)
|
||||||
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|||||||
@@ -951,6 +951,9 @@ class CNCprocessing(models.Model):
|
|||||||
if workpiece_delivery:
|
if workpiece_delivery:
|
||||||
for item in workpiece_delivery:
|
for item in workpiece_delivery:
|
||||||
item.is_cnc_program_down = True
|
item.is_cnc_program_down = True
|
||||||
|
if item.workorder_id.state == 'waiting':
|
||||||
|
item.workorder_id.state = 'ready'
|
||||||
|
|
||||||
# cnc_workorder.time_ids.date_end = datetime.now()
|
# cnc_workorder.time_ids.date_end = datetime.now()
|
||||||
# cnc_workorder.button_finish()
|
# cnc_workorder.button_finish()
|
||||||
|
|
||||||
@@ -1184,6 +1187,8 @@ class WorkPieceDelivery(models.Model):
|
|||||||
num = 0
|
num = 0
|
||||||
for item in self:
|
for item in self:
|
||||||
num += 1
|
num += 1
|
||||||
|
if production_type is None:
|
||||||
|
production_type = item.type
|
||||||
if item.type == "运送空料架":
|
if item.type == "运送空料架":
|
||||||
if num >= 2:
|
if num >= 2:
|
||||||
raise UserError('仅选择一条路线进行配送,请重新选择')
|
raise UserError('仅选择一条路线进行配送,请重新选择')
|
||||||
@@ -1201,8 +1206,6 @@ class WorkPieceDelivery(models.Model):
|
|||||||
is_not_route += 1
|
is_not_route += 1
|
||||||
else:
|
else:
|
||||||
raise UserError('请选择【任务路线】再进行配送')
|
raise UserError('请选择【任务路线】再进行配送')
|
||||||
if production_type is None:
|
|
||||||
production_type = item.type
|
|
||||||
if production_type != item.type:
|
if production_type != item.type:
|
||||||
raise UserError('请选择类型为%s的制造订单进行配送' % production_type)
|
raise UserError('请选择类型为%s的制造订单进行配送' % production_type)
|
||||||
if down_status != item.status:
|
if down_status != item.status:
|
||||||
@@ -1228,8 +1231,7 @@ class WorkPieceDelivery(models.Model):
|
|||||||
raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认')
|
raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认')
|
||||||
if is_not_route >= 1:
|
if is_not_route >= 1:
|
||||||
raise UserError('您所选择制造订单的【任务路线】不一致,请重新确认')
|
raise UserError('您所选择制造订单的【任务路线】不一致,请重新确认')
|
||||||
# is_free = self._check_avgsite_state()
|
is_free = self._check_avgsite_state()
|
||||||
is_free = True
|
|
||||||
if is_free is True:
|
if is_free is True:
|
||||||
if delivery_ids:
|
if delivery_ids:
|
||||||
return {
|
return {
|
||||||
@@ -1243,6 +1245,7 @@ class WorkPieceDelivery(models.Model):
|
|||||||
'default_production_ids': [(6, 0, production_ids)],
|
'default_production_ids': [(6, 0, production_ids)],
|
||||||
'default_destination_production_line_id': same_production_line_id,
|
'default_destination_production_line_id': same_production_line_id,
|
||||||
'default_route_id': same_route_id,
|
'default_route_id': same_route_id,
|
||||||
|
'default_type': production_type,
|
||||||
}}
|
}}
|
||||||
else:
|
else:
|
||||||
if self.type == '运送空料架':
|
if self.type == '运送空料架':
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import os
|
|||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
# from OCC.Extend.DataExchange import read_step_file
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
# from OCC.Extend.DataExchange import write_stl_file
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
|
|
||||||
|
|
||||||
class ResProductMo(models.Model):
|
class ResProductMo(models.Model):
|
||||||
|
|||||||
@@ -132,4 +132,5 @@ access_maintenance_equipment_tool_group_plan_dispatch,maintenance.equipment.tool
|
|||||||
access_sf_workpiece_delivery_group_plan_dispatch,sf.workpiece.delivery,sf_manufacturing.model_sf_workpiece_delivery,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_workpiece_delivery_group_plan_dispatch,sf.workpiece.delivery,sf_manufacturing.model_sf_workpiece_delivery,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
|
|
||||||
access_sf_agv_site_group_sf_order_user,sf_agv_site_group_sf_order_user,model_sf_agv_site,sf_base.group_sf_order_user,1,1,1,0
|
access_sf_agv_site_group_sf_order_user,sf_agv_site_group_sf_order_user,model_sf_agv_site,sf_base.group_sf_order_user,1,1,1,0
|
||||||
access_sf_agv_task_route_group_sf_order_user,sf_agv_task_route_group_sf_order_user,model_sf_agv_task_route,sf_base.group_sf_order_user,1,1,1,0
|
access_sf_agv_task_route_group_sf_order_user,sf_agv_task_route_group_sf_order_user,model_sf_agv_task_route,sf_base.group_sf_order_user,1,1,1,0
|
||||||
|
access_center_control_interface_log_admin,center_control_interface_log_admin,model_center_control_interface_log,base.group_system,1,1,1,0
|
||||||
|
@@ -55,4 +55,34 @@
|
|||||||
sequence="13"
|
sequence="13"
|
||||||
action="action_agv_task_route_form"/>
|
action="action_agv_task_route_form"/>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="center_control_interface_logging_tree_view">
|
||||||
|
<field name="model">center_control.interface.log</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="Logs" create="0" edit="0" delete="0">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="content"/>
|
||||||
|
<field name="interface_call_date"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="center_control_interface_logging_search_view">
|
||||||
|
<field name="model">center_control.interface.log</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Logs">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="interface_call_date"/>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.actions.act_window" id="center_control_interface_logging_act">
|
||||||
|
<field name="name">中控调用日志</field>
|
||||||
|
<field name="res_model">center_control.interface.log</field>
|
||||||
|
<field name="view_mode">tree</field>
|
||||||
|
</record>
|
||||||
|
<menuitem parent="base.next_id_9" id="center_control_interface_logging_menu"
|
||||||
|
action="center_control_interface_logging_act"/>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<field name="delivery_ids" invisible="True"/>
|
<field name="delivery_ids" invisible="True"/>
|
||||||
<field name="workorder_id" invisible="True"/>
|
<field name="workorder_id" invisible="True"/>
|
||||||
<field name="type" invisible="True"/>
|
<field name="type" invisible="True"/>
|
||||||
<group>
|
<group attrs="{'invisible': [('type', 'in', ['运送空料架'])]}">
|
||||||
<field name="production_ids" readonly="1" widget="many2many_tags" string="制造订单号"/>
|
<field name="production_ids" readonly="1" widget="many2many_tags" string="制造订单号"/>
|
||||||
<div class="o_address_format">
|
<div class="o_address_format">
|
||||||
<lable for="rfid_code"></lable>
|
<lable for="rfid_code"></lable>
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
<button name="recognize_production" string="识别" type="object" class="oe_highlight"/>
|
<button name="recognize_production" string="识别" type="object" class="oe_highlight"/>
|
||||||
</div>
|
</div>
|
||||||
<field name="destination_production_line_id" readonly="1"/>
|
<field name="destination_production_line_id" readonly="1"/>
|
||||||
<field name="route_id" required="1"/>
|
<field name="route_id"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group attrs="{'invisible': [('type', 'in', ['运送空料架'])]}">
|
||||||
<field name="feeder_station_start_id" focesave="1" readonly="1"/>
|
<field name="feeder_station_start_id" focesave="1" readonly="1"/>
|
||||||
<field name="feeder_station_destination_id" focesave="1" readonly="1"/>
|
<field name="feeder_station_destination_id" focesave="1" readonly="1"/>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class WorkpieceDeliveryWizard(models.TransientModel):
|
|||||||
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
|
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
|
||||||
|
|
||||||
def confirm(self):
|
def confirm(self):
|
||||||
|
if self.type != '运送空料架':
|
||||||
|
if not self.route_id:
|
||||||
|
raise UserError('请选择路线')
|
||||||
if self.workorder_id:
|
if self.workorder_id:
|
||||||
self.workorder_id.workpiece_delivery_ids[0]._delivery_avg()
|
self.workorder_id.workpiece_delivery_ids[0]._delivery_avg()
|
||||||
else:
|
else:
|
||||||
@@ -69,7 +72,8 @@ class WorkpieceDeliveryWizard(models.TransientModel):
|
|||||||
'context': {
|
'context': {
|
||||||
'default_delivery_ids': [(6, 0, self.delivery_ids.ids)],
|
'default_delivery_ids': [(6, 0, self.delivery_ids.ids)],
|
||||||
'default_production_ids': [(6, 0, self.production_ids.ids)],
|
'default_production_ids': [(6, 0, self.production_ids.ids)],
|
||||||
'default_route_id': self.delivery_ids[0].route_id.id
|
'default_route_id': self.delivery_ids[0].route_id.id,
|
||||||
|
'default_type': self.delivery_ids[0].type
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@api.onchange('route_id')
|
@api.onchange('route_id')
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ from datetime import datetime
|
|||||||
import requests
|
import requests
|
||||||
from odoo import http
|
from odoo import http
|
||||||
from odoo.http import request
|
from odoo.http import request
|
||||||
# from OCC.Extend.DataExchange import read_step_file
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
# from OCC.Extend.DataExchange import write_stl_file
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
from odoo.exceptions import ValidationError, UserError
|
from odoo.exceptions import ValidationError, UserError
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import os
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from stl import mesh
|
from stl import mesh
|
||||||
# from OCC.Core.GProp import GProp_GProps
|
# from OCC.Core.GProp import GProp_GProps
|
||||||
# from OCC.Extend.DataExchange import read_step_file
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
# from OCC.Extend.DataExchange import write_stl_file
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
|
|||||||
Reference in New Issue
Block a user