diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index f65487073fe..af28f991608 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1493,11 +1493,11 @@ class AccountInvoice(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'state' in init_values and self.state == 'paid' and self.type in ('out_invoice', 'out_refund'): - return 'account.mt_invoice_paid' + return self.env.ref('account.mt_invoice_paid') elif 'state' in init_values and self.state == 'open' and self.type in ('out_invoice', 'out_refund'): - return 'account.mt_invoice_validated' + return self.env.ref('account.mt_invoice_validated') elif 'state' in init_values and self.state == 'draft' and self.type in ('out_invoice', 'out_refund'): - return 'account.mt_invoice_created' + return self.env.ref('account.mt_invoice_created') return super(AccountInvoice, self)._track_subtype(init_values) def _amount_by_group(self): diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index c979480bf35..2c5d9d9f30c 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -390,7 +390,7 @@ class AccountVoucher(models.Model): @api.multi def _track_subtype(self, init_values): if 'state' in init_values: - return 'account_voucher.mt_voucher_state_change' + return self.env.ref('account_voucher.mt_voucher_state_change') return super(AccountVoucher, self)._track_subtype(init_values) diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 076ee98be60..f6dc16a9366 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -1095,13 +1095,13 @@ class Lead(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'stage_id' in init_values and self.probability == 100 and self.stage_id and self.stage_id.on_change: - return 'crm.mt_lead_won' + return self.env.ref('crm.mt_lead_won') elif 'active' in init_values and self.probability == 0 and not self.active: - return 'crm.mt_lead_lost' + return self.env.ref('crm.mt_lead_lost') elif 'stage_id' in init_values and self.stage_id and self.stage_id.sequence <= 1: - return 'crm.mt_lead_create' + return self.env.ref('crm.mt_lead_create') elif 'stage_id' in init_values: - return 'crm.mt_lead_stage' + return self.env.ref('crm.mt_lead_stage') return super(Lead, self)._track_subtype(init_values) @api.multi diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 7a00aea283f..1d03bc030f0 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -268,7 +268,7 @@ class FleetVehicle(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'driver_id' in init_values: - return 'fleet.mt_fleet_driver_updated' + return self.env.ref('fleet.mt_fleet_driver_updated') return super(FleetVehicle, self)._track_subtype(init_values) def open_assignation_logs(self): diff --git a/addons/hr_contract/models/hr_contract.py b/addons/hr_contract/models/hr_contract.py index bb30f94856e..a98bb326846 100644 --- a/addons/hr_contract/models/hr_contract.py +++ b/addons/hr_contract/models/hr_contract.py @@ -128,7 +128,7 @@ class Contract(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'state' in init_values and self.state == 'pending': - return 'hr_contract.mt_contract_pending' + return self.env.ref('hr_contract.mt_contract_pending') elif 'state' in init_values and self.state == 'close': - return 'hr_contract.mt_contract_close' + return self.env.ref('hr_contract.mt_contract_close') return super(Contract, self)._track_subtype(init_values) diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 5e511352c64..67c7c5ebb7a 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -595,11 +595,11 @@ class HrExpenseSheet(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'state' in init_values and self.state == 'approve': - return 'hr_expense.mt_expense_approved' + return self.env.ref('hr_expense.mt_expense_approved') elif 'state' in init_values and self.state == 'cancel': - return 'hr_expense.mt_expense_refused' + return self.env.ref('hr_expense.mt_expense_refused') elif 'state' in init_values and self.state == 'done': - return 'hr_expense.mt_expense_paid' + return self.env.ref('hr_expense.mt_expense_paid') return super(HrExpenseSheet, self)._track_subtype(init_values) def _message_auto_subscribe_followers(self, updated_values, subtype_ids): diff --git a/addons/hr_holidays/__manifest__.py b/addons/hr_holidays/__manifest__.py index a0e95455d20..9c765ea2596 100644 --- a/addons/hr_holidays/__manifest__.py +++ b/addons/hr_holidays/__manifest__.py @@ -26,8 +26,8 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p 'depends': ['hr', 'calendar', 'resource'], 'data': [ 'data/report_paperformat.xml', - 'data/hr_holidays_data.xml', 'data/mail_data.xml', + 'data/hr_holidays_data.xml', 'data/ir_cron_data.xml', 'security/hr_holidays_security.xml', diff --git a/addons/hr_holidays/data/hr_holidays_data.xml b/addons/hr_holidays/data/hr_holidays_data.xml index 57b2fdb57c5..44c4d53e151 100644 --- a/addons/hr_holidays/data/hr_holidays_data.xml +++ b/addons/hr_holidays/data/hr_holidays_data.xml @@ -8,6 +8,15 @@ black + + + + + + + Home Workings + lightgreen + @@ -16,6 +25,7 @@ no red + @@ -26,6 +36,7 @@ lavender + @@ -36,6 +47,7 @@ brown + diff --git a/addons/hr_holidays/data/mail_data.xml b/addons/hr_holidays/data/mail_data.xml index 2dc75bcb8c8..9b0a62f06c4 100644 --- a/addons/hr_holidays/data/mail_data.xml +++ b/addons/hr_holidays/data/mail_data.xml @@ -26,63 +26,32 @@ - - Approved + + Leave hr.leave - Request approved + Leave Request - - Refused + + Home Working hr.leave - - Request refused + Home Working + + + Sick Leave + hr.leave + Sick Leave + + + Unpaid Leave + hr.leave + Unpaid Leave - - Approved + + Allocation hr.leave.allocation - Request approved - - - Refused - hr.leave.allocation - - Request refused - - - - - Leaves Approved - hr.department - - - department_id - - - - Leaves Refused - hr.department - - - department_id - - - - Allocation Approved - hr.department - - - department_id - - - - Allocation Refused - hr.department - - - department_id - + Allocation Request \ No newline at end of file diff --git a/addons/hr_holidays/models/__init__.py b/addons/hr_holidays/models/__init__.py index 621aeccd08b..d391276412b 100644 --- a/addons/hr_holidays/models/__init__.py +++ b/addons/hr_holidays/models/__init__.py @@ -6,3 +6,4 @@ from . import hr from . import hr_leave from . import hr_leave_allocation from . import hr_leave_type +from . import mail_message_subtype \ No newline at end of file diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index b826f110b08..1ba9b220535 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -760,9 +760,8 @@ class HolidaysRequest(models.Model): @api.multi def _track_subtype(self, init_values): if 'state' in init_values and self.state == 'validate': - return 'hr_holidays.mt_leave_approved' - elif 'state' in init_values and self.state == 'refuse': - return 'hr_holidays.mt_leave_refused' + leave_notif_subtype = self.holiday_status_id.leave_notif_subtype_id + return leave_notif_subtype or self.env.ref('hr_holidays.mt_leave') return super(HolidaysRequest, self)._track_subtype(init_values) @api.multi diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 0c2037a50ef..b244558c151 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -544,9 +544,8 @@ class HolidaysAllocation(models.Model): @api.multi def _track_subtype(self, init_values): if 'state' in init_values and self.state == 'validate': - return 'hr_holidays.mt_leave_allocation_approved' - elif 'state' in init_values and self.state == 'refuse': - return 'hr_holidays.mt_leave_allocation_refused' + allocation_notif_subtype_id = self.holiday_status_id.allocation_notif_subtype_id + return allocation_notif_subtype_id or self.env.ref('hr_holidays.mt_leave_allocation') return super(HolidaysAllocation, self)._track_subtype(init_values) @api.multi diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index 828df4a5586..37087540776 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -83,6 +83,8 @@ class HolidaysType(models.Model): ('day', 'Day'), ('hour', 'Hours')], default='day', string='Take Leaves in', required=True) unpaid = fields.Boolean('Is Unpaid', default=False) + leave_notif_subtype_id = fields.Many2one('mail.message.subtype', string='Leave Notification Subtype') + allocation_notif_subtype_id = fields.Many2one('mail.message.subtype', string='Allocation Notification Subtype') @api.multi @api.constrains('validity_start', 'validity_stop') diff --git a/addons/hr_holidays/models/mail_message_subtype.py b/addons/hr_holidays/models/mail_message_subtype.py new file mode 100644 index 00000000000..78d0c394ad5 --- /dev/null +++ b/addons/hr_holidays/models/mail_message_subtype.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging + +from odoo import api, models + +_logger = logging.getLogger(__name__) + + +class MailMessageSubtype(models.Model): + _inherit = 'mail.message.subtype' + + def _get_department_subtype(self): + return self.search([ + ('res_model', '=', 'hr.department'), + ('parent_id', '=', self.id)]) + + def _update_department_subtype(self): + for subtype in self: + department_subtype = subtype._get_department_subtype() + if department_subtype: + department_subtype.write({ + 'name': subtype.name, + 'default': subtype.default, + }) + else: + department_subtype = self.create({ + 'name': subtype.name, + 'res_model': 'hr.department', + 'default': subtype.default or False, + 'parent_id': subtype.id, + 'relation_field': 'department_id', + }) + return department_subtype + + @api.model + def create(self, vals): + result = super(MailMessageSubtype, self).create(vals) + if result.res_model in ['hr.leave', 'hr.leave.allocation']: + result._update_department_subtype() + return result + + @api.multi + def write(self, vals): + result = super(MailMessageSubtype, self).write(vals) + self.filtered( + lambda subtype: subtype.res_model in ['hr.leave', 'hr.leave.allocation'] + )._update_department_subtype() + return result diff --git a/addons/hr_holidays/views/hr_leave_type_views.xml b/addons/hr_holidays/views/hr_leave_type_views.xml index c3bdc445ec0..5c9116cd90d 100644 --- a/addons/hr_holidays/views/hr_leave_type_views.xml +++ b/addons/hr_holidays/views/hr_leave_type_views.xml @@ -56,6 +56,16 @@ + + + + + + diff --git a/addons/hr_maintenance/models/equipment.py b/addons/hr_maintenance/models/equipment.py index d66f29fdfc6..f2537086174 100644 --- a/addons/hr_maintenance/models/equipment.py +++ b/addons/hr_maintenance/models/equipment.py @@ -65,7 +65,7 @@ class MaintenanceEquipment(models.Model): def _track_subtype(self, init_values): self.ensure_one() if ('employee_id' in init_values and self.employee_id) or ('department_id' in init_values and self.department_id): - return 'maintenance.mt_mat_assign' + return self.env.ref('maintenance.mt_mat_assign') return super(MaintenanceEquipment, self)._track_subtype(init_values) diff --git a/addons/hr_recruitment/models/hr_job.py b/addons/hr_recruitment/models/hr_job.py index 7f1510c19c3..1a73bab1f84 100644 --- a/addons/hr_recruitment/models/hr_job.py +++ b/addons/hr_recruitment/models/hr_job.py @@ -69,7 +69,7 @@ class Job(models.Model): @api.multi def _track_subtype(self, init_values): if 'state' in init_values and self.state == 'open': - return 'hr_recruitment.mt_job_new' + return self.env.ref('hr_recruitment.mt_job_new') return super(Job, self)._track_subtype(init_values) @api.multi diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py index f1b9aae9c0c..d52e0bb3a45 100644 --- a/addons/hr_recruitment/models/hr_recruitment.py +++ b/addons/hr_recruitment/models/hr_recruitment.py @@ -346,11 +346,11 @@ class Applicant(models.Model): def _track_subtype(self, init_values): record = self[0] if 'emp_id' in init_values and record.emp_id and record.emp_id.active: - return 'hr_recruitment.mt_applicant_hired' + return self.env.ref('hr_recruitment.mt_applicant_hired') elif 'stage_id' in init_values and record.stage_id and record.stage_id.sequence <= 1: - return 'hr_recruitment.mt_applicant_new' + return self.env.ref('hr_recruitment.mt_applicant_new') elif 'stage_id' in init_values and record.stage_id and record.stage_id.sequence > 1: - return 'hr_recruitment.mt_applicant_stage_changed' + return self.env.ref('hr_recruitment.mt_applicant_stage_changed') return super(Applicant, self)._track_subtype(init_values) @api.multi diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 47174571dcb..99328583a44 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -562,7 +562,7 @@ class MailThread(models.AbstractModel): :param init_values: the original values of the record; only modified fields are present in the dict :type init_values: dict - :returns: a subtype xml_id or False if no subtype is trigerred + :returns: a subtype browse record or False if no subtype is trigerred """ return False @@ -635,17 +635,15 @@ class MailThread(models.AbstractModel): continue # find subtypes and post messages or log if no subtype found - subtype_xmlid = False + subtype = False # By passing this key, that allows to let the subtype empty and so don't sent email because partners_to_notify from mail_message._notify will be empty if not self._context.get('mail_track_log_only'): - subtype_xmlid = record._track_subtype(dict((col_name, initial_values[record.id][col_name]) for col_name in changes)) - - if subtype_xmlid: - subtype_rec = self.env.ref(subtype_xmlid) # TDE FIXME check for raise if not found - if not (subtype_rec and subtype_rec.exists()): - _logger.debug('subtype %s not found' % subtype_xmlid) + subtype = record._track_subtype(dict((col_name, initial_values[record.id][col_name]) for col_name in changes)) + if subtype: + if not subtype.exists(): + _logger.debug('subtype "%s" not found' % subtype.name) continue - record.message_post(subtype=subtype_xmlid, tracking_value_ids=tracking_value_ids) + record.message_post(subtype_id=subtype.id, tracking_value_ids=tracking_value_ids) elif tracking_value_ids: record._message_log(tracking_value_ids=tracking_value_ids) diff --git a/addons/maintenance/models/maintenance.py b/addons/maintenance/models/maintenance.py index 719c912e038..4ea20b6e948 100644 --- a/addons/maintenance/models/maintenance.py +++ b/addons/maintenance/models/maintenance.py @@ -98,7 +98,7 @@ class MaintenanceEquipment(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'owner_user_id' in init_values and self.owner_user_id: - return 'maintenance.mt_mat_assign' + return self.env.ref('maintenance.mt_mat_assign') return super(MaintenanceEquipment, self)._track_subtype(init_values) @api.multi @@ -267,9 +267,9 @@ class MaintenanceRequest(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'stage_id' in init_values and self.stage_id.sequence <= 1: - return 'maintenance.mt_req_created' + return self.env.ref('maintenance.mt_req_created') elif 'stage_id' in init_values and self.stage_id.sequence > 1: - return 'maintenance.mt_req_status' + return self.env.ref('maintenance.mt_req_status') return super(MaintenanceRequest, self)._track_subtype(init_values) def _get_default_team_id(self): diff --git a/addons/project/models/project.py b/addons/project/models/project.py index dc1044defce..658444f2023 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -775,13 +775,13 @@ class Task(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'kanban_state_label' in init_values and self.kanban_state == 'blocked': - return 'project.mt_task_blocked' + return self.env.ref('project.mt_task_blocked') elif 'kanban_state_label' in init_values and self.kanban_state == 'done': - return 'project.mt_task_ready' + return self.env.ref('project.mt_task_ready') elif 'stage_id' in init_values and self.stage_id and self.stage_id.sequence <= 1: # start stage -> new - return 'project.mt_task_new' + return self.env.ref('project.mt_task_new') elif 'stage_id' in init_values: - return 'project.mt_task_stage' + return self.env.ref('project.mt_task_stage') return super(Task, self)._track_subtype(init_values) @api.multi diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index 9b13a39b6e3..829c1e86684 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -179,11 +179,11 @@ class PurchaseOrder(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'state' in init_values and self.state == 'purchase': - return 'purchase.mt_rfq_approved' + return self.env.ref('purchase.mt_rfq_approved') elif 'state' in init_values and self.state == 'to approve': - return 'purchase.mt_rfq_confirmed' + return self.env.ref('purchase.mt_rfq_confirmed') elif 'state' in init_values and self.state == 'done': - return 'purchase.mt_rfq_done' + return self.env.ref('purchase.mt_rfq_done') return super(PurchaseOrder, self)._track_subtype(init_values) @api.onchange('partner_id', 'company_id') diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 6246fa32ca4..560abb200a2 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -272,9 +272,9 @@ class SaleOrder(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'state' in init_values and self.state == 'sale': - return 'sale.mt_order_confirmed' + return self.env.ref('sale.mt_order_confirmed') elif 'state' in init_values and self.state == 'sent': - return 'sale.mt_order_sent' + return self.env.ref('sale.mt_order_sent') return super(SaleOrder, self)._track_subtype(init_values) @api.multi diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py index 07aa7be9a51..4e3c022a4b1 100644 --- a/addons/stock_landed_costs/models/stock_landed_cost.py +++ b/addons/stock_landed_costs/models/stock_landed_cost.py @@ -73,7 +73,7 @@ class LandedCost(models.Model): @api.multi def _track_subtype(self, init_values): if 'state' in init_values and self.state == 'done': - return 'stock_landed_costs.mt_stock_landed_cost_open' + return self.env.ref('stock_landed_costs.mt_stock_landed_cost_open') return super(LandedCost, self)._track_subtype(init_values) @api.multi diff --git a/addons/stock_picking_batch/models/stock_picking_batch.py b/addons/stock_picking_batch/models/stock_picking_batch.py index 18a3e9cb4b2..18592687d6b 100644 --- a/addons/stock_picking_batch/models/stock_picking_batch.py +++ b/addons/stock_picking_batch/models/stock_picking_batch.py @@ -106,7 +106,7 @@ class StockPickingBatch(models.Model): def _track_subtype(self, init_values): if 'state' in init_values: - return 'stock_picking_batch.mt_batch_state' + return self.env.ref('stock_picking_batch.mt_batch_state') return super(StockPickingBatch, self)._track_subtype(init_values) diff --git a/addons/test_mail/models/test_mail_models.py b/addons/test_mail/models/test_mail_models.py index 8ada6ed86c8..5ba9ff195e8 100644 --- a/addons/test_mail/models/test_mail_models.py +++ b/addons/test_mail/models/test_mail_models.py @@ -78,7 +78,7 @@ class MailTestFull(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'umbrella_id' in init_values and self.umbrella_id: - return 'test_mail.st_mail_test_full_umbrella_upd' + return self.env.ref('test_mail.st_mail_test_full_umbrella_upd') return super(MailTestFull, self)._track_subtype(init_values) diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py index 50e60db63c1..c9f9554b149 100644 --- a/addons/website_event/models/event.py +++ b/addons/website_event/models/event.py @@ -118,9 +118,9 @@ class Event(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'is_published' in init_values and self.is_published: - return 'website_event.mt_event_published' + return self.env.ref('website_event.mt_event_published') elif 'is_published' in init_values and not self.is_published: - return 'website_event.mt_event_unpublished' + return self.env.ref('website_event.mt_event_unpublished') return super(Event, self)._track_subtype(init_values) @api.multi diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py index 2f35e86bb0e..1c4758d50af 100644 --- a/addons/website_event_track/models/event_track.py +++ b/addons/website_event_track/models/event_track.py @@ -151,9 +151,9 @@ class Track(models.Model): def _track_subtype(self, init_values): self.ensure_one() if 'kanban_state' in init_values and self.kanban_state == 'blocked': - return 'website_event_track.mt_track_blocked' + return self.env.ref('website_event_track.mt_track_blocked') elif 'kanban_state' in init_values and self.kanban_state == 'done': - return 'website_event_track.mt_track_ready' + return self.env.ref('website_event_track.mt_track_ready') return super(Track, self)._track_subtype(init_values) @api.multi diff --git a/doc/reference/mixins.rst b/doc/reference/mixins.rst index d8c976ddaaa..af06849b435 100644 --- a/doc/reference/mixins.rst +++ b/doc/reference/mixins.rst @@ -331,7 +331,7 @@ can override the ``_track_subtype()`` function: # in cache self.ensure_one() if 'state' in init_values and self.state == 'confirmed': - return 'my_module.mt_state_change' # Full external id + return self.env.ref('my_module.mt_state_change') return super(BusinessTrip, self)._track_subtype(init_values)