account_invoice_send.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models, _
  4. from odoo.addons.mail.wizard.mail_compose_message import _reopen
  5. from odoo.exceptions import UserError
  6. from odoo.tools.misc import get_lang
  7. class AccountInvoiceSend(models.TransientModel):
  8. _name = 'account.invoice.send'
  9. _inherits = {'mail.compose.message':'composer_id'}
  10. _description = 'Account Invoice Send'
  11. is_email = fields.Boolean('Email', default=lambda self: self.env.company.invoice_is_email)
  12. invoice_without_email = fields.Text(compute='_compute_invoice_without_email', string='invoice(s) that will not be sent')
  13. is_print = fields.Boolean('Print', default=lambda self: self.env.company.invoice_is_print)
  14. printed = fields.Boolean('Is Printed', default=False)
  15. invoice_ids = fields.Many2many('account.move', 'account_move_account_invoice_send_rel', string='Invoices')
  16. composer_id = fields.Many2one('mail.compose.message', string='Composer', required=True, ondelete='cascade')
  17. template_id = fields.Many2one(
  18. 'mail.template', 'Use template',
  19. domain="[('model', '=', 'account.move')]"
  20. )
  21. # Technical field containing a textual representation of the selected move types,
  22. # if multiple. It is used to inform the user in the window in such case.
  23. move_types = fields.Char(
  24. string='Move types',
  25. compute='_compute_move_types',
  26. readonly=True)
  27. @api.model
  28. def default_get(self, fields):
  29. res = super(AccountInvoiceSend, self).default_get(fields)
  30. res_ids = self._context.get('active_ids')
  31. invoices = self.env['account.move'].browse(res_ids).filtered(lambda move: move.is_invoice(include_receipts=True))
  32. if not invoices:
  33. raise UserError(_("You can only send invoices."))
  34. composer = self.env['mail.compose.message'].create({
  35. 'composition_mode': 'comment' if len(res_ids) == 1 else 'mass_mail',
  36. })
  37. res.update({
  38. 'invoice_ids': res_ids,
  39. 'composer_id': composer.id,
  40. })
  41. return res
  42. @api.onchange('invoice_ids')
  43. def _compute_composition_mode(self):
  44. for wizard in self:
  45. wizard.composer_id.composition_mode = 'comment' if len(wizard.invoice_ids) == 1 else 'mass_mail'
  46. @api.onchange('invoice_ids')
  47. def _compute_move_types(self):
  48. for wizard in self:
  49. move_types = False
  50. if len(wizard.invoice_ids) > 1:
  51. moves = self.env['account.move'].browse(self.env.context.get('active_ids'))
  52. # Get the move types of all selected moves and see if there is more than one of them.
  53. # If so, we'll display a warning on the next window about it.
  54. move_types_set = set(m.type_name for m in moves)
  55. if len(move_types_set) > 1:
  56. move_types = ', '.join(move_types_set)
  57. wizard.move_types = move_types
  58. @api.onchange('template_id')
  59. def onchange_template_id(self):
  60. for wizard in self:
  61. if wizard.composer_id:
  62. wizard.composer_id.template_id = wizard.template_id.id
  63. wizard._compute_composition_mode()
  64. wizard.composer_id._onchange_template_id_wrapper()
  65. @api.onchange('is_email')
  66. def onchange_is_email(self):
  67. if self.is_email:
  68. res_ids = self._context.get('active_ids')
  69. if not self.composer_id:
  70. self.composer_id = self.env['mail.compose.message'].create({
  71. 'composition_mode': 'comment' if len(res_ids) == 1 else 'mass_mail',
  72. 'template_id': self.template_id.id
  73. })
  74. else:
  75. self.composer_id.composition_mode = 'comment' if len(res_ids) == 1 else 'mass_mail'
  76. self.composer_id.template_id = self.template_id.id
  77. self._compute_composition_mode()
  78. self.composer_id._onchange_template_id_wrapper()
  79. @api.onchange('is_email')
  80. def _compute_invoice_without_email(self):
  81. for wizard in self:
  82. if wizard.is_email and len(wizard.invoice_ids) > 1:
  83. invoices = self.env['account.move'].search([
  84. ('id', 'in', self.env.context.get('active_ids')),
  85. ('partner_id.email', '=', False)
  86. ])
  87. if invoices:
  88. wizard.invoice_without_email = "%s\n%s" % (
  89. _("The following invoice(s) will not be sent by email, because the customers don't have email address."),
  90. "\n".join([i.name for i in invoices])
  91. )
  92. else:
  93. wizard.invoice_without_email = False
  94. else:
  95. wizard.invoice_without_email = False
  96. def _send_email(self):
  97. if self.is_email:
  98. # with_context : we don't want to reimport the file we just exported.
  99. self.composer_id.with_context(no_new_invoice=True,
  100. mail_notify_author=self.env.user.partner_id in self.composer_id.partner_ids,
  101. mailing_document_based=True,
  102. )._action_send_mail()
  103. if self.env.context.get('mark_invoice_as_sent'):
  104. #Salesman send posted invoice, without the right to write
  105. #but they should have the right to change this flag
  106. self.mapped('invoice_ids').sudo().write({'is_move_sent': True})
  107. for invoice in self.invoice_ids:
  108. prioritary_attachments = invoice.attachment_ids.filtered(lambda x: x.mimetype.endswith('pdf'))
  109. if prioritary_attachments:
  110. invoice.with_context(tracking_disable=True).sudo().write({'message_main_attachment_id': prioritary_attachments[0].id})
  111. def _print_document(self):
  112. """ to override for each type of models that will use this composer."""
  113. self.ensure_one()
  114. action = self.invoice_ids.action_invoice_print()
  115. action.update({'close_on_report_download': True})
  116. return action
  117. def send_and_print_action(self):
  118. self.ensure_one()
  119. # Send the mails in the correct language by splitting the ids per lang.
  120. # This should ideally be fixed in mail_compose_message, so when a fix is made there this whole commit should be reverted.
  121. # basically self.body (which could be manually edited) extracts self.template_id,
  122. # which is then not translated for each customer.
  123. if self.composition_mode == 'mass_mail' and self.template_id:
  124. active_ids = self.env.context.get('active_ids', self.res_id)
  125. active_records = self.env[self.model].browse(active_ids)
  126. langs = set(active_records.mapped('partner_id.lang'))
  127. for lang in langs:
  128. active_ids_lang = active_records.filtered(lambda r: r.partner_id.lang == lang).ids
  129. self_lang = self.with_context(active_ids=active_ids_lang, lang=get_lang(self.env, lang).code)
  130. self_lang.onchange_template_id()
  131. self_lang._send_email()
  132. else:
  133. active_record = self.env[self.model].browse(self.res_id)
  134. lang = get_lang(self.env, active_record.partner_id.lang).code
  135. self.with_context(lang=lang)._send_email()
  136. if self.is_print:
  137. return self._print_document()
  138. return {'type': 'ir.actions.act_window_close'}
  139. def save_as_template(self):
  140. self.ensure_one()
  141. self.composer_id.action_save_as_template()
  142. self.template_id = self.composer_id.template_id.id
  143. action = _reopen(self, self.id, self.model, context=self._context)
  144. action.update({'name': _('Send Invoice')})
  145. return action