diff --git a/l10n_br_account_payment_order/constants.py b/l10n_br_account_payment_order/constants.py index ded7cea713e4..e92196d7c103 100644 --- a/l10n_br_account_payment_order/constants.py +++ b/l10n_br_account_payment_order/constants.py @@ -463,7 +463,8 @@ ("liquidada", "Liquidada"), ("baixa", "Baixa Simples"), ("baixa_liquidacao", "Baixa por Liquidação fora do CNAB"), - ("nao_pagamento", "Baixa por Não Pagamento/Inadimplência") + ("nao_pagamento", "Baixa por Não Pagamento/Inadimplência"), + ("fatura_cancelada", "Baixa por Cancelamento da Fatura") ] BOLETO_ESPECIE = [ diff --git a/l10n_br_account_payment_order/models/account_invoice.py b/l10n_br_account_payment_order/models/account_invoice.py index ec558ec3c757..eac03cdb3221 100644 --- a/l10n_br_account_payment_order/models/account_invoice.py +++ b/l10n_br_account_payment_order/models/account_invoice.py @@ -4,7 +4,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import _, api, fields, models -from odoo.exceptions import UserError class AccountInvoice(models.Model): @@ -60,54 +59,16 @@ def _onchange_payment_mode_id(self): } ) - # TODO: Criar um movimento de baixa - def _remove_payment_order_line(self, _raise=True): - """ Try to search payment orders related to the account move of this - invoice, we can't remove a payment.order.line / bank.line of a invoice - that already sent to the bank. - - The only way to do that is to say that you want to cancel it. - - Creating a new move of "BAIXA/ESTORNO" - - :param _raise: - :return: - """ - financial_move_line_ids = self.financial_move_line_ids - payment_order_ids = self.env['account.payment.order'] - - payment_order_ids |= self.env['account.payment.order'].search([ - ('payment_line_ids.move_line_id', 'in', financial_move_line_ids.ids), - ]) - - if payment_order_ids: - draft_cancel_payment_order_ids = payment_order_ids.filtered( - lambda p: p.state in ('draft', 'cancel') - ) - if payment_order_ids - draft_cancel_payment_order_ids: - if _raise: - raise UserError(_( - 'A fatura não pode ser cancelada pois a mesma já se ' - 'encontra exportada por uma ordem de pagamento. \n', - 'Envie um novo lançamento solicitando a Baixa/Cancelamento' - )) - - for po_id in draft_cancel_payment_order_ids: - p_line_id = self.env['account.payment.line'] - for line in financial_move_line_ids: - p_line_id |= self.env['account.payment.line'].search([ - ('order_id', '=', po_id.id), - ('move_line_id', '=', line.id)]) - po_id.payment_line_ids -= p_line_id - @api.multi def action_invoice_cancel(self): - """ Before cancel the invoice, check if this invoice have any payment order - related to it. - :return: - """ for record in self: - record._remove_payment_order_line() + if record.payment_mode_id.payment_method_code in \ + ('240', '400', '500'): + for line in record.move_id.line_ids: + # Verificar a situação do CNAB para apenas apagar + # a linha ou mandar uma solicitação de Baixa + line.update_cnab_for_cancel_invoice() + return super().action_invoice_cancel() @api.multi @@ -206,11 +167,15 @@ def create_payment_outside_cnab(self, amount_payment): change_tittle_value_line = line break + reason_write_off = (('Movement Instruction Code Updated for Request' \ + ' to Write Off, because payment of %s done outside CNAB.') + % amount_payment) + payment_situation = 'baixa_liquidacao' for line in applicable_lines: if line == change_tittle_value_line: - line._create_cnab_change_tittle_value() + line.create_cnab_change_tittle_value() else: - line._create_cnab_writte_off() + line.create_cnab_write_off(reason_write_off, payment_situation) @api.multi def invoice_validate(self): @@ -219,7 +184,6 @@ def invoice_validate(self): if filtered_invoice_ids: for filtered_invoice_id in filtered_invoice_ids: # Criando Ordem de Pagto Automaticamente - # TODO: deveria ser um parametro ? if filtered_invoice_id.payment_mode_id.payment_order_ok: filtered_invoice_id.create_account_payment_line() return result @@ -263,3 +227,38 @@ def register_payment( receivable_id.residual = inv.residual return res + + @api.multi + def action_cancel(self): + # TODO: Não está chamando o super, devido problema mais abaixo, + # verificar se é possível + moves = self.env['account.move'] + for inv in self: + if inv.move_id: + moves += inv.move_id + #unreconcile all journal items of the invoice, since the + # cancellation will unlink them anyway + inv.move_id.line_ids.filtered( + lambda x: x.account_id.reconcile).remove_move_reconcile() + + # First, set the invoices as cancelled and detach the move ids + self.write({'state': 'cancel', 'move_id': False}) + if moves: + # second, invalidate the move(s) + moves.button_cancel() + # delete the move this invoice was pointing to + # Note that the corresponding move_lines and move_reconciles + # will be automatically deleted too + + # TODO: No caso de Ordens de Pagto vinculadas devido o + # ondelet=restrict no campo move_line_id do account.payment.line + # não é possível Cancelar uma Invoice que já tenha uma Ordem de + # Pagto confirmada, acontece erro devido o unlink abaixo, a forma + # encontrada até agora é não apagar as que forem referentes a um + # CNAB. Verificar se o mesmo problema acontece no uso + # internacional e se na migração isso pode ser resolvido + # de uma melhor forma. + if self.payment_mode_id.payment_method_code not in \ + ('240', '400', '500'): + moves.unlink() + return True diff --git a/l10n_br_account_payment_order/models/account_move.py b/l10n_br_account_payment_order/models/account_move.py index 0d658ddd9163..2a7bbfd9c9a5 100644 --- a/l10n_br_account_payment_order/models/account_move.py +++ b/l10n_br_account_payment_order/models/account_move.py @@ -20,21 +20,3 @@ class AccountMove(models.Model): is_cnab = fields.Boolean( string='Is CNAB ?' ) - - @api.multi - def unlink(self): - for record in self: - payment_line_ids = record.line_ids.mapped("payment_line_ids") - if any( - state not in ("draft", "cancel") - for state in payment_line_ids.mapped("state") - ): - raise ValidationError( - _( - "Não foi possível cancelar a fatura, pois existem linhas " - "de pagamentos ativas vinculadas ao lançamento de diário" - "dela." - ) - ) - payment_line_ids.unlink() - return super().unlink() diff --git a/l10n_br_account_payment_order/models/l10n_br_cnab_change_methods.py b/l10n_br_account_payment_order/models/l10n_br_cnab_change_methods.py index 45e02fd6af2f..c0da27e14f83 100644 --- a/l10n_br_account_payment_order/models/l10n_br_cnab_change_methods.py +++ b/l10n_br_account_payment_order/models/l10n_br_cnab_change_methods.py @@ -138,6 +138,32 @@ def _msg_error_cnab_missing(self, payment_mode_name, missing): " check if should have." ) % (payment_mode_name, missing)) + def _cnab_already_start(self): + + result = False + # Se existir uma Ordem já gerada, exportada ou concluída + # significa que o processo desse CNAB já foi iniciado no Banco + cnab_already_start = self.payment_line_ids.filtered( + lambda t: t.order_id.state in ('generated', 'uploaded', 'done')) + + if cnab_already_start: + result = True + + return result + + def update_cnab_for_cancel_invoice(self): + + cnab_already_start = self._cnab_already_start() + if cnab_already_start: + reason_write_off = ( + ('Movement Instruction Code Updated for Request to Write Off,' + ' because Invoice %s was Cancel.') % self.invoice_id.name) + payment_situation = 'fatura_cancelada' + self.create_cnab_write_off(reason_write_off, payment_situation) + else: + # Processo de CNAB ainda não iniciado a linha será apenas excluida + self.payment_line_ids.unlink() + def _get_cnab_date_maturity(self, new_date): """ CNAB - Instrução de Alteração da Data de Vencimento. @@ -239,13 +265,13 @@ def _create_cnab_not_payment(self, payorder, new_payorder, reason): # Registra as Alterações na Fatura self._msg_cnab_payment_order_at_invoice(new_payorder, payorder, reason) - def _create_cnab_writte_off(self): + def create_cnab_write_off(self, reason, payment_situation): """ CNAB - Instrução de Baixar de Título. """ if not self.invoice_id.payment_mode_id.cnab_write_off_code_id: self._msg_error_cnab_missing( - self.payment_mode_id.name, 'Writte Off Code') + self.payment_mode_id.name, 'Write Off Code') # Checar se existe uma Instrução de CNAB ainda a ser enviada self._check_cnab_instruction_to_be_send() @@ -254,16 +280,15 @@ def _create_cnab_writte_off(self): self.mov_instruction_code_id = \ self.payment_mode_id.cnab_write_off_code_id - self.payment_situation = 'baixa_liquidacao' - reason = 'Movement Instruction Code Updated for Request' \ - ' to Write Off, because payment done in another way.' + self.payment_situation = payment_situation + self.create_payment_line_from_move_line(payorder) self.cnab_state = 'added_paid' # Registra as Alterações na Fatura self._msg_cnab_payment_order_at_invoice(new_payorder, payorder, reason) - def _create_cnab_change_tittle_value(self): + def create_cnab_change_tittle_value(self): """ CNAB - Alteração do Valor do Título. """