forked from Mapan/odoo17e
111 lines
6.4 KiB
Python
111 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import logging
|
|
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AccountDebitNote(models.TransientModel):
|
|
"""
|
|
Add Debit Note wizard: when you want to correct an invoice with a positive amount.
|
|
Opposite of a Credit Note, but different from a regular invoice as you need the link to the original invoice.
|
|
In some cases, also used to cancel Credit Notes
|
|
"""
|
|
_name = 'account.debit.note'
|
|
_inherit = 'account.debit.note'
|
|
_description = 'Add Debit Note wizard'
|
|
|
|
l10n_cl_edi_reference_doc_code = fields.Selection([
|
|
('1', '1. Cancels Referenced Document'),
|
|
('2', '2. Corrects Referenced Document Text'),
|
|
('3', '3. Corrects Referenced Document Amount')
|
|
], string='SII Reference Code')
|
|
l10n_cl_original_text = fields.Char('Original Text', help='This is the text that is intended to be changed')
|
|
l10n_cl_corrected_text = fields.Char('New Corrected Text', help='This is the text that should say')
|
|
|
|
def _l10n_cl_get_reverse_doc_type(self, move):
|
|
if move.partner_id.l10n_cl_sii_taxpayer_type == '4' or move.partner_id.country_id.code != "CL":
|
|
return self.env['l10n_latam.document.type'].search([('code', '=', '111'), ('country_id.code', '=', "CL")], limit=1)
|
|
return self.env['l10n_latam.document.type'].search([('code', '=', '56'), ('country_id.code', '=', "CL")], limit=1)
|
|
|
|
def _get_opposite_tax_tag(self, line):
|
|
# If we are making a debit note over a credit note, we need to use the reverse or opposite tax tag, for the
|
|
# tax line and for the base line. get_tax_tags do the job, provided you pass the False value as the first
|
|
# argument of the method.
|
|
# the approach of getting the tax tags from the repartition line works only for the tax line and not for
|
|
# the base line, since there is no repartition line for the base line.
|
|
if line.tax_line_id:
|
|
return [[6, 0, line.tax_line_id.get_tax_tags(False, 'tax').ids]]
|
|
elif line.account_id.account_type not in ['asset_receivable', 'liability_payable']:
|
|
return [[6, 0, line.tax_ids.get_tax_tags(False, 'base').ids]]
|
|
return [[5]]
|
|
|
|
def _get_repartition_line(self, line):
|
|
if line.tax_repartition_line_id.document_type == 'refund':
|
|
# for credit notes (refund) as originating document, we need to get the opposite repartition line
|
|
return line.tax_repartition_line_id.tax_id.invoice_repartition_line_ids.filtered(
|
|
lambda x: x.repartition_type == line.tax_repartition_line_id.repartition_type)
|
|
# otherwise, the repartition line is the same as the originating doc (invoice for example)
|
|
return line.tax_repartition_line_id
|
|
|
|
def _prepare_default_values(self, move):
|
|
# I would like to add the following line, because there is no case where you need to copy the lines
|
|
# except for reverting a credit note, and this case is not included in the base code of credit note.
|
|
# The only motivation to comment it is to prevent the test to fail.
|
|
# self.copy_lines = True if self.l10n_cl_edi_reference_doc_code == '1' else False
|
|
default_values = super(AccountDebitNote, self)._prepare_default_values(move)
|
|
if move.company_id.account_fiscal_country_id.code != "CL" or not move.journal_id.l10n_latam_use_documents:
|
|
return default_values
|
|
reverse_move_latam_doc_type = self._l10n_cl_get_reverse_doc_type(move)
|
|
default_values['invoice_origin'] = '%s %s' % (move.l10n_latam_document_type_id.doc_code_prefix,
|
|
move.l10n_latam_document_number)
|
|
default_values['l10n_latam_document_type_id'] = reverse_move_latam_doc_type.id
|
|
default_values['l10n_cl_reference_ids'] = [[0, 0, {
|
|
'move_id': move.id,
|
|
'origin_doc_number': move.l10n_latam_document_number,
|
|
'l10n_cl_reference_doc_type_id': move.l10n_latam_document_type_id.id,
|
|
'reference_doc_code': self.l10n_cl_edi_reference_doc_code,
|
|
'reason': self.reason,
|
|
'date': move.invoice_date, }, ], ]
|
|
if self.l10n_cl_edi_reference_doc_code == '1':
|
|
# this is needed to reverse a credit note: we must include the same items we have in the credit note
|
|
# if we make this with traditional "with_context(internal_type='debit_note').copy(default=default_values)
|
|
# the values will appear negative in the debit note
|
|
default_values['line_ids'] = [[5, 0, 0]]
|
|
for line in move.line_ids.filtered(lambda x: x.display_type in ('product', 'tax', 'payment_term')):
|
|
default_values['line_ids'].append([0, 0, {
|
|
'product_id': line.product_id.id,
|
|
'account_id': line.account_id.id,
|
|
'analytic_distribution': line.analytic_distribution,
|
|
'name': line.name,
|
|
'quantity': line.quantity,
|
|
'price_unit': line.price_unit,
|
|
'tax_repartition_line_id': self._get_repartition_line(line).id,
|
|
'tax_ids': [[6, 0, line.tax_ids.ids]],
|
|
'tax_tag_ids': self._get_opposite_tax_tag(line),
|
|
'discount': line.discount,
|
|
'display_type': line.display_type,
|
|
}, ])
|
|
elif self.l10n_cl_edi_reference_doc_code == '2':
|
|
default_values['line_ids'] = [[5, 0, 0], [0, 0, {
|
|
'account_id': move.journal_id.default_account_id.id,
|
|
'name': _('Where it says: %s should say: %s',
|
|
self._context.get('default_l10n_cl_original_text'),
|
|
self._context.get('default_l10n_cl_corrected_text')),
|
|
'quantity': 1,
|
|
'price_unit': 0.0,
|
|
}]]
|
|
return default_values
|
|
|
|
def create_debit(self):
|
|
for move in self.move_ids.filtered(
|
|
lambda r: r.company_id.account_fiscal_country_id.code == "CL" and
|
|
r.move_type in ['out_invoice', 'out_refund'] and
|
|
r.l10n_cl_journal_point_of_sale_type == 'online' and
|
|
r.l10n_cl_dte_status not in ['accepted', 'objected']
|
|
):
|
|
raise UserError(_('You can add a debit note only if the %s is accepted or objected by SII. ', move.name))
|
|
return super(AccountDebitNote, self).create_debit()
|