diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index a8484dba4d2..d7b9de5bd9e 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -2346,41 +2346,6 @@ class AccountMove(models.Model):
result.append((move.id, name))
return result
- def _creation_subtype(self):
- # OVERRIDE
- if self.move_type in ('out_invoice', 'out_refund', 'out_receipt'):
- return self.env.ref('account.mt_invoice_created')
- else:
- return super(AccountMove, self)._creation_subtype()
-
- def _track_subtype(self, init_values):
- # OVERRIDE to add custom subtype depending of the state.
- self.ensure_one()
-
- if not self.is_invoice(include_receipts=True):
- if self.payment_id and 'state' in init_values:
- self.payment_id._message_track(['state'], {self.payment_id.id: init_values})
- return super(AccountMove, self)._track_subtype(init_values)
-
- if 'payment_state' in init_values and self.payment_state == 'paid':
- return self.env.ref('account.mt_invoice_paid')
- elif 'state' in init_values and self.state == 'posted' and self.is_sale_document(include_receipts=True):
- return self.env.ref('account.mt_invoice_validated')
- return super(AccountMove, self)._track_subtype(init_values)
-
- def _creation_message(self):
- # OVERRIDE
- if not self.is_invoice(include_receipts=True):
- return super()._creation_message()
- return {
- 'out_invoice': _('Invoice Created'),
- 'out_refund': _('Credit Note Created'),
- 'in_invoice': _('Vendor Bill Created'),
- 'in_refund': _('Refund Created'),
- 'out_receipt': _('Sales Receipt Created'),
- 'in_receipt': _('Purchase Receipt Created'),
- }[self.move_type]
-
# -------------------------------------------------------------------------
# RECONCILIATION METHODS
# -------------------------------------------------------------------------
@@ -2857,59 +2822,6 @@ class AccountMove(models.Model):
'views': [(self.env.ref('account.view_move_tree').id, 'tree'), (False, 'form')],
}
- @api.model
- def message_new(self, msg_dict, custom_values=None):
- # OVERRIDE
- # Add custom behavior when receiving a new invoice through the mail's gateway.
- if (custom_values or {}).get('move_type', 'entry') not in ('out_invoice', 'in_invoice'):
- return super().message_new(msg_dict, custom_values=custom_values)
-
- def is_internal_partner(partner):
- # Helper to know if the partner is an internal one.
- return partner.user_ids and all(user.has_group('base.group_user') for user in partner.user_ids)
-
- extra_domain = False
- if custom_values.get('company_id'):
- extra_domain = ['|', ('company_id', '=', custom_values['company_id']), ('company_id', '=', False)]
-
- # Search for partners in copy.
- cc_mail_addresses = email_split(msg_dict.get('cc', ''))
- followers = [partner for partner in self._mail_find_partner_from_emails(cc_mail_addresses, extra_domain) if partner]
-
- # Search for partner that sent the mail.
- from_mail_addresses = email_split(msg_dict.get('from', ''))
- senders = partners = [partner for partner in self._mail_find_partner_from_emails(from_mail_addresses, extra_domain) if partner]
-
- # Search for partners using the user.
- if not senders:
- senders = partners = list(self._mail_search_on_user(from_mail_addresses))
-
- if partners:
- # Check we are not in the case when an internal user forwarded the mail manually.
- if is_internal_partner(partners[0]):
- # Search for partners in the mail's body.
- body_mail_addresses = set(email_re.findall(msg_dict.get('body')))
- partners = [partner for partner in self._mail_find_partner_from_emails(body_mail_addresses, extra_domain) if not is_internal_partner(partner)]
-
- # Little hack: Inject the mail's subject in the body.
- if msg_dict.get('subject') and msg_dict.get('body'):
- msg_dict['body'] = '
' % (msg_dict['subject'], msg_dict['body'])
-
- # Create the invoice.
- values = {
- 'name': '/', # we have to give the name otherwise it will be set to the mail's subject
- 'invoice_source_email': from_mail_addresses[0],
- 'partner_id': partners and partners[0].id or False,
- }
- move_ctx = self.with_context(default_move_type=custom_values['move_type'], default_journal_id=custom_values['journal_id'])
- move = super(AccountMove, move_ctx).message_new(msg_dict, custom_values=values)
- move._compute_name() # because the name is given, we need to recompute in case it is the first invoice of the journal
-
- # Assign followers.
- all_followers_ids = set(partner.id for partner in followers + senders + partners if is_internal_partner(partner))
- move.message_subscribe(list(all_followers_ids))
- return move
-
def post(self):
warnings.warn(
"RedirectWarning method 'post()' is a deprecated alias to 'action_post()' or _post()",
@@ -3403,6 +3315,92 @@ class AccountMove(models.Model):
return rslt
+ def _get_create_invoice_from_attachment_decoders(self):
+ """ Returns a list of method that are able to create an invoice from an attachment and a priority.
+
+ :returns: A list of tuples (priority, method) where method takes an attachment as parameter.
+ """
+ return []
+
+ def _get_update_invoice_from_attachment_decoders(self, invoice):
+ """ Returns a list of method that are able to create an invoice from an attachment and a priority.
+
+ :param invoice: The invoice on which to update the data.
+ :returns: A list of tuples (priority, method) where method takes an attachment as parameter.
+ """
+ return []
+
+ @api.depends('move_type', 'partner_id', 'company_id')
+ def _compute_narration(self):
+ use_invoice_terms = self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms')
+ for move in self.filtered(lambda am: not am.narration):
+ if not use_invoice_terms or not move.is_sale_document(include_receipts=True):
+ move.narration = False
+ else:
+ if not move.company_id.terms_type == 'html':
+ narration = move.company_id.invoice_terms if not is_html_empty(move.company_id.invoice_terms) else ''
+ else:
+ baseurl = self.env.company.get_base_url() + '/terms'
+ narration = _('Terms & Conditions: %s', baseurl)
+ move.narration = narration or False
+
+ # ------------------------------------------------------------
+ # MAIL.THREAD
+ # ------------------------------------------------------------
+
+ @api.model
+ def message_new(self, msg_dict, custom_values=None):
+ # OVERRIDE
+ # Add custom behavior when receiving a new invoice through the mail's gateway.
+ if (custom_values or {}).get('move_type', 'entry') not in ('out_invoice', 'in_invoice'):
+ return super().message_new(msg_dict, custom_values=custom_values)
+
+ def is_internal_partner(partner):
+ # Helper to know if the partner is an internal one.
+ return partner.user_ids and all(user.has_group('base.group_user') for user in partner.user_ids)
+
+ extra_domain = False
+ if custom_values.get('company_id'):
+ extra_domain = ['|', ('company_id', '=', custom_values['company_id']), ('company_id', '=', False)]
+
+ # Search for partners in copy.
+ cc_mail_addresses = email_split(msg_dict.get('cc', ''))
+ followers = [partner for partner in self._mail_find_partner_from_emails(cc_mail_addresses, extra_domain) if partner]
+
+ # Search for partner that sent the mail.
+ from_mail_addresses = email_split(msg_dict.get('from', ''))
+ senders = partners = [partner for partner in self._mail_find_partner_from_emails(from_mail_addresses, extra_domain) if partner]
+
+ # Search for partners using the user.
+ if not senders:
+ senders = partners = list(self._mail_search_on_user(from_mail_addresses))
+
+ if partners:
+ # Check we are not in the case when an internal user forwarded the mail manually.
+ if is_internal_partner(partners[0]):
+ # Search for partners in the mail's body.
+ body_mail_addresses = set(email_re.findall(msg_dict.get('body')))
+ partners = [partner for partner in self._mail_find_partner_from_emails(body_mail_addresses, extra_domain) if not is_internal_partner(partner)]
+
+ # Little hack: Inject the mail's subject in the body.
+ if msg_dict.get('subject') and msg_dict.get('body'):
+ msg_dict['body'] = '' % (msg_dict['subject'], msg_dict['body'])
+
+ # Create the invoice.
+ values = {
+ 'name': '/', # we have to give the name otherwise it will be set to the mail's subject
+ 'invoice_source_email': from_mail_addresses[0],
+ 'partner_id': partners and partners[0].id or False,
+ }
+ move_ctx = self.with_context(default_move_type=custom_values['move_type'], default_journal_id=custom_values['journal_id'])
+ move = super(AccountMove, move_ctx).message_new(msg_dict, custom_values=values)
+ move._compute_name() # because the name is given, we need to recompute in case it is the first invoice of the journal
+
+ # Assign followers.
+ all_followers_ids = set(partner.id for partner in followers + senders + partners if is_internal_partner(partner))
+ move.message_subscribe(list(all_followers_ids))
+ return move
+
def _message_post_after_hook(self, new_message, message_values):
# OVERRIDE
# When posting a message, check the attachment to see if it's an invoice and update with the imported data.
@@ -3437,34 +3435,40 @@ class AccountMove(models.Model):
return res
- def _get_create_invoice_from_attachment_decoders(self):
- """ Returns a list of method that are able to create an invoice from an attachment and a priority.
+ def _creation_subtype(self):
+ # OVERRIDE
+ if self.move_type in ('out_invoice', 'out_refund', 'out_receipt'):
+ return self.env.ref('account.mt_invoice_created')
+ else:
+ return super(AccountMove, self)._creation_subtype()
- :returns: A list of tuples (priority, method) where method takes an attachment as parameter.
- """
- return []
+ def _track_subtype(self, init_values):
+ # OVERRIDE to add custom subtype depending of the state.
+ self.ensure_one()
- def _get_update_invoice_from_attachment_decoders(self, invoice):
- """ Returns a list of method that are able to create an invoice from an attachment and a priority.
+ if not self.is_invoice(include_receipts=True):
+ if self.payment_id and 'state' in init_values:
+ self.payment_id._message_track(['state'], {self.payment_id.id: init_values})
+ return super(AccountMove, self)._track_subtype(init_values)
- :param invoice: The invoice on which to update the data.
- :returns: A list of tuples (priority, method) where method takes an attachment as parameter.
- """
- return []
+ if 'payment_state' in init_values and self.payment_state == 'paid':
+ return self.env.ref('account.mt_invoice_paid')
+ elif 'state' in init_values and self.state == 'posted' and self.is_sale_document(include_receipts=True):
+ return self.env.ref('account.mt_invoice_validated')
+ return super(AccountMove, self)._track_subtype(init_values)
- @api.depends('move_type', 'partner_id', 'company_id')
- def _compute_narration(self):
- use_invoice_terms = self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms')
- for move in self.filtered(lambda am: not am.narration):
- if not use_invoice_terms or not move.is_sale_document(include_receipts=True):
- move.narration = False
- else:
- if not move.company_id.terms_type == 'html':
- narration = move.company_id.invoice_terms if not is_html_empty(move.company_id.invoice_terms) else ''
- else:
- baseurl = self.env.company.get_base_url() + '/terms'
- narration = _('Terms & Conditions: %s', baseurl)
- move.narration = narration or False
+ def _creation_message(self):
+ # OVERRIDE
+ if not self.is_invoice(include_receipts=True):
+ return super()._creation_message()
+ return {
+ 'out_invoice': _('Invoice Created'),
+ 'out_refund': _('Credit Note Created'),
+ 'in_invoice': _('Vendor Bill Created'),
+ 'in_refund': _('Refund Created'),
+ 'out_receipt': _('Sales Receipt Created'),
+ 'in_receipt': _('Purchase Receipt Created'),
+ }[self.move_type]
class AccountMoveLine(models.Model):
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index 3d2dc6d67ca..e3fece18edf 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -289,18 +289,6 @@ class PurchaseOrder(models.Model):
del line[2]['date_planned']
return result
- def _track_subtype(self, init_values):
- self.ensure_one()
- if 'state' in init_values and self.state == 'purchase':
- if init_values['state'] == 'to approve':
- return self.env.ref('purchase.mt_rfq_approved')
- return self.env.ref('purchase.mt_rfq_confirmed')
- elif 'state' in init_values and self.state == 'to approve':
- return self.env.ref('purchase.mt_rfq_confirmed')
- elif 'state' in init_values and self.state == 'done':
- return self.env.ref('purchase.mt_rfq_done')
- return super(PurchaseOrder, self)._track_subtype(init_values)
-
def _get_report_base_filename(self):
self.ensure_one()
return 'Purchase Order-%s' % (self.name)
@@ -353,6 +341,32 @@ class PurchaseOrder(models.Model):
return {'warning': warning}
return {}
+ # ------------------------------------------------------------
+ # MAIL.THREAD
+ # ------------------------------------------------------------
+
+ @api.returns('mail.message', lambda value: value.id)
+ def message_post(self, **kwargs):
+ if self.env.context.get('mark_rfq_as_sent'):
+ self.filtered(lambda o: o.state == 'draft').write({'state': 'sent'})
+ return super(PurchaseOrder, self.with_context(mail_post_autofollow=self.env.context.get('mail_post_autofollow', True))).message_post(**kwargs)
+
+ def _track_subtype(self, init_values):
+ self.ensure_one()
+ if 'state' in init_values and self.state == 'purchase':
+ if init_values['state'] == 'to approve':
+ return self.env.ref('purchase.mt_rfq_approved')
+ return self.env.ref('purchase.mt_rfq_confirmed')
+ elif 'state' in init_values and self.state == 'to approve':
+ return self.env.ref('purchase.mt_rfq_confirmed')
+ elif 'state' in init_values and self.state == 'done':
+ return self.env.ref('purchase.mt_rfq_done')
+ return super(PurchaseOrder, self)._track_subtype(init_values)
+
+ # ------------------------------------------------------------
+ # ACTIONS
+ # ------------------------------------------------------------
+
def action_rfq_send(self):
'''
This function opens a window to compose an email, with the edi purchase template message loaded by default
@@ -410,12 +424,6 @@ class PurchaseOrder(models.Model):
'context': ctx,
}
- @api.returns('mail.message', lambda value: value.id)
- def message_post(self, **kwargs):
- if self.env.context.get('mark_rfq_as_sent'):
- self.filtered(lambda o: o.state == 'draft').write({'state': 'sent'})
- return super(PurchaseOrder, self.with_context(mail_post_autofollow=self.env.context.get('mail_post_autofollow', True))).message_post(**kwargs)
-
def print_quotation(self):
self.write({'state': "sent"})
return self.env.ref('purchase.report_purchase_quotation').report_action(self)