[MOV] account, purchase: move thread code in its own section
Purpose is to better isolate MailThread related methods in those huge files containing lot of code. Better have them located in a sub-section in order to have all mail code at the same place. Task-2710804 (Mail: Clean Mail.Thread API) Part-of: odoo/odoo#82167
This commit is contained in:
@@ -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'] = '<div><div><h3>%s</h3></div>%s</div>' % (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'] = '<div><div><h3>%s</h3></div>%s</div>' % (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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user