优化销售订单逾期
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
'data/bussiness_node.xml',
|
'data/bussiness_node.xml',
|
||||||
'data/cron_data.xml',
|
'data/cron_data.xml',
|
||||||
'data/template_data.xml',
|
'data/template_data.xml',
|
||||||
|
'views/sf_message_sale_view.xml',
|
||||||
|
|
||||||
],
|
],
|
||||||
'test': [
|
'test': [
|
||||||
|
|||||||
@@ -26,31 +26,31 @@
|
|||||||
<field name="active" eval="True"/>
|
<field name="active" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">
|
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
|
||||||
<field name="name">装夹预调工单逾期预警</field>
|
<!-- <field name="name">装夹预调工单逾期预警</field>-->
|
||||||
<field name="model_id" ref="model_mrp_workorder"/>
|
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
|
||||||
<field name="state">code</field>
|
<!-- <field name="state">code</field>-->
|
||||||
<field name="code">model._overdue_warning_func()</field>
|
<!-- <field name="code">model._overdue_warning_func()</field>-->
|
||||||
<field name="interval_number">1</field>
|
<!-- <field name="interval_number">1</field>-->
|
||||||
<field name="interval_type">minutes</field>
|
<!-- <field name="interval_type">minutes</field>-->
|
||||||
<field name="numbercall">-1</field>
|
<!-- <field name="numbercall">-1</field>-->
|
||||||
<field name="doall" eval="False"/>
|
<!-- <field name="doall" eval="False"/>-->
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<!-- <field name="user_id" ref="base.user_root"/>-->
|
||||||
<field name="active" eval="True"/>
|
<!-- <field name="active" eval="True"/>-->
|
||||||
</record>
|
<!-- </record>-->
|
||||||
|
|
||||||
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue">
|
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue">-->
|
||||||
<field name="name">工单已逾期</field>
|
<!-- <field name="name">工单已逾期</field>-->
|
||||||
<field name="model_id" ref="model_mrp_workorder"/>
|
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
|
||||||
<field name="state">code</field>
|
<!-- <field name="state">code</field>-->
|
||||||
<field name="code">model._overdue_func()</field>
|
<!-- <field name="code">model._overdue_func()</field>-->
|
||||||
<field name="interval_number">1</field>
|
<!-- <field name="interval_number">1</field>-->
|
||||||
<field name="interval_type">minutes</field>
|
<!-- <field name="interval_type">minutes</field>-->
|
||||||
<field name="numbercall">-1</field>
|
<!-- <field name="numbercall">-1</field>-->
|
||||||
<field name="doall" eval="False"/>
|
<!-- <field name="doall" eval="False"/>-->
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<!-- <field name="user_id" ref="base.user_root"/>-->
|
||||||
<field name="active" eval="True"/>
|
<!-- <field name="active" eval="True"/>-->
|
||||||
</record>
|
<!-- </record>-->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
|
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
|
||||||
<!-- <field name="name">工单逾期预警</field>-->
|
<!-- <field name="name">工单逾期预警</field>-->
|
||||||
|
|||||||
@@ -22,9 +22,8 @@
|
|||||||
<field name="bussiness_node_id" ref="bussiness_to_be_confirm"/>
|
<field name="bussiness_node_id" ref="bussiness_to_be_confirm"/>
|
||||||
<field name="msgtype">markdown</field>
|
<field name="msgtype">markdown</field>
|
||||||
<field name="urgency">normal</field>
|
<field name="urgency">normal</field>
|
||||||
<field name="content">### 待排程提醒:
|
<field name="content">### 销售订单逾期预警
|
||||||
单号:产品[{{product_id}}]({{url}})
|
事项:共有{{sale_warning_num}}个销售订单有逾期风险
|
||||||
事项:{{mrp_production_count}}个制造订单待计划排程
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -36,8 +35,7 @@
|
|||||||
<field name="msgtype">markdown</field>
|
<field name="msgtype">markdown</field>
|
||||||
<field name="urgency">normal</field>
|
<field name="urgency">normal</field>
|
||||||
<field name="content">### 待排程提醒:
|
<field name="content">### 待排程提醒:
|
||||||
单号:销售订单[{{names}}]({{url}})
|
事项:共有{{sale_overdue_num}}个销售订单已逾期
|
||||||
事项:共有{{production_count}}个制造订单未加工完成,订单有逾期风险
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ class SFMessageSale(models.Model):
|
|||||||
_name = 'sale.order'
|
_name = 'sale.order'
|
||||||
_inherit = ['sale.order', 'jikimo.message.dispatch']
|
_inherit = ['sale.order', 'jikimo.message.dispatch']
|
||||||
|
|
||||||
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
|
|
||||||
|
|
||||||
def create(self, vals_list):
|
def create(self, vals_list):
|
||||||
res = super(SFMessageSale, self).create(vals_list)
|
res = super(SFMessageSale, self).create(vals_list)
|
||||||
if res:
|
if res:
|
||||||
@@ -45,8 +43,8 @@ class SFMessageSale(models.Model):
|
|||||||
def _get_message(self, message_queue_ids):
|
def _get_message(self, message_queue_ids):
|
||||||
contents = []
|
contents = []
|
||||||
url = self.env['ir.config_parameter'].get_param('web.base.url')
|
url = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||||
|
i = 0
|
||||||
for item in message_queue_ids:
|
for item in message_queue_ids:
|
||||||
i = 0
|
|
||||||
# 待接单的处理
|
# 待接单的处理
|
||||||
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)
|
content = super(SFMessageSale, self)._get_message(item)
|
||||||
@@ -66,30 +64,71 @@ class SFMessageSale(models.Model):
|
|||||||
content = content[0].replace('{{product_id}}', product).replace('{{url}}', url)
|
content = content[0].replace('{{product_id}}', product).replace('{{url}}', url)
|
||||||
contents.append(content)
|
contents.append(content)
|
||||||
elif item.message_template_id.bussiness_node_id.name == '销售订单逾期预警':
|
elif item.message_template_id.bussiness_node_id.name == '销售订单逾期预警':
|
||||||
sale_order_warning = self.sudo().search([('delivery_warning', '=', 'warning'),('id','=',int(item.res_id))])
|
current_time = datetime.now()
|
||||||
# if sale_order_warning:
|
time_range = timedelta(minutes=2)
|
||||||
# i++
|
for reminder_time in item.message_template_id.reminder_time_ids:
|
||||||
#
|
content = item.message_template_id.content
|
||||||
# if i>1
|
target_time = current_time.replace(hour=reminder_time, minute=0, second=0, microsecond=0)
|
||||||
|
if target_time - time_range <= current_time <= target_time + time_range:
|
||||||
|
print("当前时间在12点02分以内")
|
||||||
|
sale_order_warning = self.sudo().search(
|
||||||
|
[('delivery_warning', '=', 'warning'), ('id', '=', int(item.res_id))])
|
||||||
|
if sale_order_warning:
|
||||||
|
i += 1
|
||||||
|
if i >= 1:
|
||||||
|
content = content.replace('{{sale_warning_num}}', i).replace('{{url}}', url)
|
||||||
|
contents.append(content)
|
||||||
|
elif item.message_template_id.bussiness_node_id.name == '销售订单已逾期':
|
||||||
|
current_time = datetime.now()
|
||||||
|
time_range = timedelta(minutes=2)
|
||||||
|
for reminder_time in item.message_template_id.reminder_time_ids:
|
||||||
|
content = item.message_template_id.content
|
||||||
|
target_time = current_time.replace(hour=reminder_time, minute=0, second=0, microsecond=0)
|
||||||
|
if target_time - time_range <= current_time <= target_time + time_range:
|
||||||
|
print("当前时间在12点02分以内")
|
||||||
|
sale_order_overdue = self.sudo().search(
|
||||||
|
[('delivery_warning', '=', 'overdue'), ('id', '=', int(item.res_id))])
|
||||||
|
if sale_order_overdue:
|
||||||
|
i += 1
|
||||||
|
if i >= 1:
|
||||||
|
content = content.replace('{{sale_overdue_num}}', i).replace('{{url}}', url)
|
||||||
|
contents.append(content)
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
# # 销售订单逾期预警
|
# # 销售订单逾期预警
|
||||||
|
|
||||||
def _overdue_warning_func(self):
|
def _overdue_warning_func(self):
|
||||||
today = fields.Date.today()
|
today = fields.Date.today()
|
||||||
deadline_check = today + timedelta(days=2)
|
deadline_check = today + timedelta(days=2)
|
||||||
sale_order = self.sudo().search([('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False)])
|
sale_order = self.sudo().search([('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False)])
|
||||||
for item in sale_order:
|
for item in sale_order:
|
||||||
if deadline_check < item.deadline_of_delivery:
|
production = self.env['mrp.production'].search([('origin', '=', item.name)])
|
||||||
item.delivery_warning = '告警'
|
if len(production.filtered(
|
||||||
else:
|
lambda p: p.state not in ['done', 'scrap'])) != item.mrp_production_count:
|
||||||
item.delivery_warning = '正常'
|
if deadline_check < item.deadline_of_delivery:
|
||||||
|
item.delivery_warning = 'warning'
|
||||||
|
elif len(production.filtered(
|
||||||
|
lambda p: p.state in ['done', 'scrap'])) == item.mrp_production_count:
|
||||||
|
if deadline_check < item.deadline_of_delivery and item.delivery_status == 'pending':
|
||||||
|
item.delivery_warning = 'warning'
|
||||||
sale_order_warning = self.sudo().search([('delivery_warning', '=', 'warning')])
|
sale_order_warning = self.sudo().search([('delivery_warning', '=', 'warning')])
|
||||||
if sale_order_warning:
|
if sale_order_warning:
|
||||||
if
|
|
||||||
sale_order_warning.add_queue('销售订单逾期预警')
|
sale_order_warning.add_queue('销售订单逾期预警')
|
||||||
|
|
||||||
|
# 销售订单已逾期 订单交期(交货日期)-当前日期时间≤0(未交货完成的销售订单)
|
||||||
# 销售订单已逾期
|
|
||||||
def _overdue_func(self):
|
def _overdue_func(self):
|
||||||
return 1
|
today = fields.Date.today()
|
||||||
|
sale_order = self.sudo().search([('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False)])
|
||||||
|
for item in sale_order:
|
||||||
|
delta = item.deadline_of_delivery - today
|
||||||
|
production = self.env['mrp.production'].search([('origin', '=', item.name)])
|
||||||
|
if len(production.filtered(
|
||||||
|
lambda p: p.state not in ['done', 'scrap'])) != item.mrp_production_count:
|
||||||
|
if delta <= timedelta(days=0):
|
||||||
|
item.delivery_warning = 'overdue'
|
||||||
|
elif len(production.filtered(
|
||||||
|
lambda p: p.state in ['done', 'scrap'])) == item.mrp_production_count:
|
||||||
|
if delta <= timedelta(days=0):
|
||||||
|
item.delivery_warning = 'overdue'
|
||||||
|
sale_order_overdue = self.sudo().search([('delivery_warning', '=', 'overdue')])
|
||||||
|
if sale_order_overdue:
|
||||||
|
sale_order_overdue.add_queue('销售订单已逾期')
|
||||||
|
|||||||
10
sf_message/views/sf_message_sale_view.xml
Normal file
10
sf_message/views/sf_message_sale_view.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- © <2016> <top hy>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- © <2016> <top hy>
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
|
||||||
|
|
||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
|
|
||||||
<record id="sf_message_template_view_form" model="ir.ui.view">
|
|
||||||
<field name="name">sf.message.template.view.form</field>
|
|
||||||
<field name="model">message.template</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="消息模板">
|
|
||||||
<sheet>
|
|
||||||
<div class="oe_title">
|
|
||||||
<label for="name"/>
|
|
||||||
<h1>
|
|
||||||
<field name="name" class="w-100" required="1"/>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<group>
|
|
||||||
<!-- <field name="type"/>-->
|
|
||||||
<field name="notify_model_id"/>
|
|
||||||
<field name="content" widget="html" class="oe-bordered-editor"
|
|
||||||
options="{'style-inline': true, 'codeview': true, 'dynamic_placeholder': true}"/>
|
|
||||||
<field name="description"/>
|
|
||||||
<field name="msgtype"/>
|
|
||||||
<field name="notification_department_id"/>
|
|
||||||
<field name="notification_employee_ids" widget="many2many_tags"/>
|
|
||||||
</group>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sf_message_template_view_tree" model="ir.ui.view">
|
|
||||||
<field name="name">sf.message.template.view.tree</field>
|
|
||||||
<field name="model">message.template</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree string="消息模板">
|
|
||||||
<field name="name"/>
|
|
||||||
<!-- <field name="type"/>-->
|
|
||||||
<field name="content"/>
|
|
||||||
<field name="msgtype"/>
|
|
||||||
<field name="notification_department_id"/>
|
|
||||||
<field name="notification_employee_ids" widget="many2many_tags"/>
|
|
||||||
<field name="description"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sf_message_template_search_view" model="ir.ui.view">
|
|
||||||
<field name="name">sf.message.template.search.view</field>
|
|
||||||
<field name="model">message.template</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<search>
|
|
||||||
<field name="name" string="模糊搜索"
|
|
||||||
filter_domain="['|','|',('name','like',self),('description','like',self)]"/>
|
|
||||||
<field name="name"/>
|
|
||||||
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
|
|
||||||
</search>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!--定义单证类型视图动作-->
|
|
||||||
<record id="sf_message_template_action" model="ir.actions.act_window">
|
|
||||||
<field name="name">消息模板</field>
|
|
||||||
<field name="res_model">message.template</field>
|
|
||||||
<field name="view_mode">tree,form</field>
|
|
||||||
<field name="view_id" ref="sf_message_template_view_tree"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<menuitem id="msg_set_menu" name="消息设置" parent="base.menu_administration" sequence="1"/>
|
|
||||||
<menuitem id="sf_message_template_send_menu" name="消息模板" parent="msg_set_menu"
|
|
||||||
action="sf_message_template_action" sequence="1"/>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -55,6 +55,9 @@ class ReSaleOrder(models.Model):
|
|||||||
store=True, readonly=False, copy=False, precompute=True,
|
store=True, readonly=False, copy=False, precompute=True,
|
||||||
states=READONLY_FIELD_STATES, default=fields.Datetime.now)
|
states=READONLY_FIELD_STATES, default=fields.Datetime.now)
|
||||||
|
|
||||||
|
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效')
|
||||||
|
|
||||||
|
|
||||||
# 业务平台分配工厂后在智能工厂先创建销售订单
|
# 业务平台分配工厂后在智能工厂先创建销售订单
|
||||||
def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address,
|
def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address,
|
||||||
deadline_of_delivery, payments_way, pay_way):
|
deadline_of_delivery, payments_way, pay_way):
|
||||||
|
|||||||
@@ -67,7 +67,8 @@
|
|||||||
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
||||||
</field>
|
</field>
|
||||||
<field name="payment_term_id" position="after">
|
<field name="payment_term_id" position="after">
|
||||||
<field name="deadline_of_delivery" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="picking_ids"/>
|
||||||
|
<field name="deadline_of_delivery" />
|
||||||
<field name="payments_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="payments_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
||||||
<field name="pay_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="pay_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
||||||
<!-- <field name="schedule_status" readonly="1"/> -->
|
<!-- <field name="schedule_status" readonly="1"/> -->
|
||||||
@@ -78,6 +79,7 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='price_subtotal']" position="after">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='price_subtotal']" position="after">
|
||||||
<field name="remark"/>
|
<field name="remark"/>
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="attributes">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="attributes">
|
||||||
<attribute name="options">{'no_create': True}</attribute>
|
<attribute name="options">{'no_create': True}</attribute>
|
||||||
@@ -180,6 +182,20 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="sale_order_view_search_inherit_sale_message" model="ir.ui.view">
|
||||||
|
<field name="name">sale.order.message.search.view</field>
|
||||||
|
<field name="model">sale.order</field>
|
||||||
|
<field name="inherit_id" ref="sale.sale_order_view_search_inherit_sale"/>
|
||||||
|
<field name="mode">primary</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//filter[@name='upselling']" position="after">
|
||||||
|
<separator/>
|
||||||
|
<filter string="预警" name="filter_order_warning" domain="[('delivery_warning', '=', 'warning')]"/>
|
||||||
|
<filter string="逾期" name="filter_order_overdue" domain="[('delivery_warning', '=', 'overdue')]"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="view_order_tree_inherit_sf" model="ir.ui.view">
|
<record id="view_order_tree_inherit_sf" model="ir.ui.view">
|
||||||
<field name="name">sale.order.tree</field>
|
<field name="name">sale.order.tree</field>
|
||||||
<field name="model">sale.order</field>
|
<field name="model">sale.order</field>
|
||||||
@@ -189,18 +205,15 @@
|
|||||||
<!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> -->
|
<!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> -->
|
||||||
<attribute name="default_order">create_date desc</attribute>
|
<attribute name="default_order">create_date desc</attribute>
|
||||||
<attribute name="create">False</attribute>
|
<attribute name="create">False</attribute>
|
||||||
|
<attribute name="decoration-warning">delivery_warning == 'warning'</attribute>
|
||||||
|
<attribute name="decoration-danger">delivery_warning == 'overdue'</attribute>
|
||||||
</tree>
|
</tree>
|
||||||
<field name="name" position="attributes">
|
<field name="name" position="attributes">
|
||||||
<attribute name="string">订单号</attribute>
|
<attribute name="string">订单号</attribute>
|
||||||
</field>
|
</field>
|
||||||
<!-- <field name="amount_total" position="after"> -->
|
<field name="amount_total" position="after">
|
||||||
<!-- <field name="schedule_status" widget="badge" -->
|
<field name="delivery_warning" invisible="1"/>
|
||||||
<!-- decoration-success="schedule_status == 'received'" -->
|
</field>
|
||||||
<!-- decoration-warning="schedule_status == 'to process'" -->
|
|
||||||
<!-- decoration-danger="schedule_status == 'to receive'" -->
|
|
||||||
<!-- decoration-muted="schedule_status == 'to process'" -->
|
|
||||||
<!-- decoration-info="schedule_status == 'to schedule'"/> -->
|
|
||||||
<!-- </field> -->
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -225,10 +238,18 @@
|
|||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale.product_template_action" model="ir.actions.act_window">
|
<record id="sale.product_template_action" model="ir.actions.act_window">
|
||||||
<field name="context">{"search_default_categ_id":1,
|
<field name="context">{"search_default_categ_id":1,
|
||||||
"search_default_filter_to_sell":1,"sale_multi_pricelist_product_template": 1}
|
"search_default_filter_to_sell":1,"sale_multi_pricelist_product_template": 1}
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="sale.action_orders" model="ir.actions.act_window">
|
||||||
|
<field name="search_view_id" ref="sale_order_view_search_inherit_sale_message"/>
|
||||||
|
<field name="context">{ 'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1}
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
Reference in New Issue
Block a user