mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
[13.0][MIG] account_document_reversal
This commit is contained in:
@@ -4,12 +4,16 @@
|
|||||||
{
|
{
|
||||||
"name": "Account Document Reversal",
|
"name": "Account Document Reversal",
|
||||||
"summary": "Create reversed journal entries when cancel document",
|
"summary": "Create reversed journal entries when cancel document",
|
||||||
"version": "12.0.1.0.0",
|
"version": "13.0.1.0.0",
|
||||||
"author": "Ecosoft," "Eficent," "Odoo Community Association (OCA)",
|
"author": "Ecosoft," "Eficent," "Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/account-financial-tools",
|
"website": "https://github.com/OCA/account-financial-tools",
|
||||||
"category": "Accounting & Finance",
|
"category": "Accounting & Finance",
|
||||||
"depends": ["account_cancel"],
|
"depends": ["account"],
|
||||||
"data": ["wizard/reverse_account_document_wizard.xml", "views/account_view.xml",],
|
"data": ["wizard/reverse_account_document_wizard.xml",
|
||||||
|
"views/account_view.xml",
|
||||||
|
"views/account_move_view.xml",
|
||||||
|
"views/account_payment_view.xml",
|
||||||
|
],
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"application": False,
|
"application": False,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from . import account
|
from . import account
|
||||||
from . import account_document_reversal
|
from . import account_document_reversal
|
||||||
from . import account_invoice
|
|
||||||
from . import account_payment
|
from . import account_payment
|
||||||
from . import account_bank_statement
|
from . import account_bank_statement
|
||||||
from . import account_move
|
from . import account_move
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class AccountJournal(models.Model):
|
|||||||
|
|
||||||
cancel_method = fields.Selection(
|
cancel_method = fields.Selection(
|
||||||
[
|
[
|
||||||
("normal", "Normal (delete journal entries if exists)"),
|
("normal", "Normal (remove journal entries)"),
|
||||||
("reversal", "Reversal (create reversed journal entries)"),
|
("reversal", "Reversal (create reversed journal entries)"),
|
||||||
],
|
],
|
||||||
string="Cancel Method",
|
string="Cancel Method",
|
||||||
@@ -30,9 +30,6 @@ class AccountJournal(models.Model):
|
|||||||
help="Journal in this field will show in reversal wizard as default",
|
help="Journal in this field will show in reversal wizard as default",
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _compute_is_cancel_reversal(self):
|
def _compute_is_cancel_reversal(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.is_cancel_reversal = (
|
rec.is_cancel_reversal = rec.cancel_method == "reversal"
|
||||||
rec.update_posted and rec.cancel_method == "reversal"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from odoo import _, api, models
|
from odoo import _, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
@@ -8,11 +8,10 @@ class AccountPayment(models.Model):
|
|||||||
_name = "account.bank.statement.line"
|
_name = "account.bank.statement.line"
|
||||||
_inherit = ["account.bank.statement.line", "account.document.reversal"]
|
_inherit = ["account.bank.statement.line", "account.document.reversal"]
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def button_cancel_reconciliation(self):
|
def button_cancel_reconciliation(self):
|
||||||
""" If cancel method is to reverse, use document reversal wizard """
|
""" If cancel method is to reverse, use document reversal wizard """
|
||||||
cancel_reversal = all(
|
cancel_reversal = all(
|
||||||
self.mapped("journal_entry_ids.move_id." "journal_id.is_cancel_reversal")
|
self.mapped("journal_entry_ids.move_id.journal_id.is_cancel_reversal")
|
||||||
)
|
)
|
||||||
states = self.mapped("statement_id.state")
|
states = self.mapped("statement_id.state")
|
||||||
if cancel_reversal:
|
if cancel_reversal:
|
||||||
@@ -21,46 +20,35 @@ class AccountPayment(models.Model):
|
|||||||
return self.reverse_document_wizard()
|
return self.reverse_document_wizard()
|
||||||
return super().button_cancel_reconciliation()
|
return super().button_cancel_reconciliation()
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_document_reversal(self, date=None, journal_id=None):
|
def action_document_reversal(self, date=None, journal_id=None):
|
||||||
""" Reverse all moves related to this statement + delete payment """
|
""" Reverse all moves related to this statement + delete payment """
|
||||||
# This part is from button_cancel_reconciliation()
|
# This part is from button_cancel_reconciliation()
|
||||||
aml_to_unbind = self.env["account.move.line"]
|
aml_to_unbind = self.env['account.move.line']
|
||||||
aml_to_cancel = self.env["account.move.line"]
|
aml_to_cancel = self.env['account.move.line']
|
||||||
payment_to_unreconcile = self.env["account.payment"]
|
payment_to_unreconcile = self.env['account.payment']
|
||||||
payment_to_cancel = self.env["account.payment"]
|
payment_to_cancel = self.env['account.payment']
|
||||||
for st_line in self:
|
for st_line in self:
|
||||||
aml_to_unbind |= st_line.journal_entry_ids
|
aml_to_unbind |= st_line.journal_entry_ids
|
||||||
for line in st_line.journal_entry_ids:
|
for line in st_line.journal_entry_ids:
|
||||||
payment_to_unreconcile |= line.payment_id
|
payment_to_unreconcile |= line.payment_id
|
||||||
if (
|
if st_line.move_name and line.payment_id.payment_reference == st_line.move_name:
|
||||||
st_line.move_name
|
#there can be several moves linked to a statement line but maximum one created by the line itself
|
||||||
and line.payment_id.payment_reference == st_line.move_name
|
|
||||||
):
|
|
||||||
# there can be several moves linked to a statement line but
|
|
||||||
# maximum one created by the line itself
|
|
||||||
aml_to_cancel |= line
|
aml_to_cancel |= line
|
||||||
payment_to_cancel |= line.payment_id
|
payment_to_cancel |= line.payment_id
|
||||||
aml_to_unbind = aml_to_unbind - aml_to_cancel
|
aml_to_unbind = aml_to_unbind - aml_to_cancel
|
||||||
|
|
||||||
if aml_to_unbind:
|
if aml_to_unbind:
|
||||||
aml_to_unbind.write({"statement_line_id": False})
|
aml_to_unbind.write({'statement_line_id': False})
|
||||||
|
|
||||||
payment_to_unreconcile = payment_to_unreconcile - payment_to_cancel
|
payment_to_unreconcile = payment_to_unreconcile - payment_to_cancel
|
||||||
if payment_to_unreconcile:
|
if payment_to_unreconcile:
|
||||||
payment_to_unreconcile.unreconcile()
|
payment_to_unreconcile.unreconcile()
|
||||||
# --
|
# --
|
||||||
|
|
||||||
# Set all moves to unreconciled
|
# Find account moves to cancel reversal
|
||||||
aml_to_cancel.filtered(lambda x: x.account_id.reconcile).remove_move_reconcile()
|
|
||||||
moves = aml_to_cancel.mapped("move_id")
|
moves = aml_to_cancel.mapped("move_id")
|
||||||
# Important to remove relation with move.line before reverse
|
|
||||||
aml_to_cancel.write(
|
|
||||||
{"payment_id": False, "statement_id": False, "statement_line_id": False}
|
|
||||||
)
|
|
||||||
# Create reverse entries
|
# Create reverse entries
|
||||||
moves.reverse_moves(date, journal_id)
|
moves._cancel_reversal(journal_id)
|
||||||
# Delete related payments
|
# Set cancel related payments
|
||||||
if payment_to_cancel:
|
payment_to_cancel.write({"state": "cancelled"})
|
||||||
payment_to_cancel.unlink()
|
|
||||||
# Unlink from statement line
|
|
||||||
self.write({"move_name": False})
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,12 +1,28 @@
|
|||||||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from odoo import api, models
|
from odoo import api, models, fields
|
||||||
|
|
||||||
|
|
||||||
class AccountDocumentReversal(models.AbstractModel):
|
class AccountDocumentReversal(models.AbstractModel):
|
||||||
_name = "account.document.reversal"
|
_name = "account.document.reversal"
|
||||||
_description = "Abstract Module for Document Reversal"
|
_description = "Abstract Module for Document Reversal"
|
||||||
|
|
||||||
|
is_cancel_reversal = fields.Boolean(
|
||||||
|
string="Use Cancel Reversal",
|
||||||
|
compute="_compute_is_cancel_reversal",
|
||||||
|
)
|
||||||
|
# reversal_move_ids = fields.Many2many(
|
||||||
|
# comodel_name="account.move",
|
||||||
|
# help="Cancelled journal entries",
|
||||||
|
# )
|
||||||
|
|
||||||
|
def _compute_is_cancel_reversal(self):
|
||||||
|
for rec in self:
|
||||||
|
if "journal_id" in rec:
|
||||||
|
rec.is_cancel_reversal = rec.journal_id.is_cancel_reversal
|
||||||
|
else:
|
||||||
|
rec.is_cancel_reversal = False
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def reverse_document_wizard(self):
|
def reverse_document_wizard(self):
|
||||||
""" Return Wizard to Cancel Document """
|
""" Return Wizard to Cancel Document """
|
||||||
@@ -16,7 +32,6 @@ class AccountDocumentReversal(models.AbstractModel):
|
|||||||
vals = action.read()[0]
|
vals = action.read()[0]
|
||||||
return vals
|
return vals
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_document_reversal(self, date=None, journal_id=None):
|
def action_document_reversal(self, date=None, journal_id=None):
|
||||||
""" Reverse with following guildeline,
|
""" Reverse with following guildeline,
|
||||||
- Check existing document state / raise warning
|
- Check existing document state / raise warning
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
|
||||||
from odoo import _, api, models
|
|
||||||
from odoo.exceptions import UserError, ValidationError
|
|
||||||
|
|
||||||
|
|
||||||
class AccountInvoice(models.Model):
|
|
||||||
_name = "account.invoice"
|
|
||||||
_inherit = ["account.invoice", "account.document.reversal"]
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_invoice_cancel(self):
|
|
||||||
""" If cancel method is to reverse, use document reversal wizard
|
|
||||||
* Draft invoice, fall back to standard invoice cancel
|
|
||||||
* Non draft, must be fully open (not even partial reconciled) to cancel
|
|
||||||
"""
|
|
||||||
cancel_reversal = all(self.mapped("journal_id.is_cancel_reversal"))
|
|
||||||
states = self.mapped("state")
|
|
||||||
if cancel_reversal and "draft" not in states:
|
|
||||||
if not all(st == "open" for st in states) or (
|
|
||||||
self.mapped("move_id.line_ids.matched_debit_ids")
|
|
||||||
| self.mapped("move_id.line_ids.matched_credit_ids")
|
|
||||||
):
|
|
||||||
raise UserError(
|
|
||||||
_(
|
|
||||||
"Only fully unpaid invoice can be cancelled.\n"
|
|
||||||
"To cancel this invoice, make sure all payment(s) "
|
|
||||||
"are also cancelled."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return self.reverse_document_wizard()
|
|
||||||
return super().action_invoice_cancel()
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_document_reversal(self, date=None, journal_id=None):
|
|
||||||
""" Reverse all moves related to this invoice + set state to cancel """
|
|
||||||
# Check document state
|
|
||||||
if "cancel" in self.mapped("state"):
|
|
||||||
raise ValidationError(_("You are trying to cancel the cancelled document"))
|
|
||||||
MoveLine = self.env["account.move.line"]
|
|
||||||
move_lines = MoveLine.search([("invoice_id", "in", self.ids)])
|
|
||||||
moves = move_lines.mapped("move_id")
|
|
||||||
# Set all moves to unreconciled
|
|
||||||
move_lines.filtered(lambda x: x.account_id.reconcile).remove_move_reconcile()
|
|
||||||
# Important to remove relation with move.line before reverse
|
|
||||||
move_lines.write({"invoice_id": False})
|
|
||||||
# Create reverse entries
|
|
||||||
moves.reverse_moves(date, journal_id)
|
|
||||||
# Set state cancelled and unlink with account.move
|
|
||||||
self.write(
|
|
||||||
{
|
|
||||||
"move_id": False,
|
|
||||||
"move_name": False,
|
|
||||||
"reference": False,
|
|
||||||
"state": "cancel",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
@@ -1,26 +1,79 @@
|
|||||||
# Copyright 2019 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2019 Eficent Business and IT Consulting Services, S.L.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class AccountMove(models.Model):
|
class AccountMove(models.Model):
|
||||||
_name = "account.move"
|
_name = "account.move"
|
||||||
_inherit = ["account.move", "account.document.reversal"]
|
_inherit = ["account.move", "account.document.reversal"]
|
||||||
|
|
||||||
is_cancel_reversal = fields.Boolean(
|
cancel_reversal = fields.Boolean(
|
||||||
string="Use Cancel Reversal", related="journal_id.is_cancel_reversal",
|
string="Cancel Reversal",
|
||||||
|
default=False, copy=False,
|
||||||
|
help="This document is being cancelled by using reversal method",
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
def button_cancel_reversal(self):
|
||||||
def button_cancel(self):
|
return self.reverse_document_wizard()
|
||||||
""" Do not allow using this button for cancel with reversal """
|
|
||||||
cancel_reversal = any(self.mapped("is_cancel_reversal"))
|
def button_draft(self):
|
||||||
if cancel_reversal:
|
for rec in self:
|
||||||
raise ValidationError(
|
if rec.is_cancel_reversal and rec.state != "cancel":
|
||||||
_(
|
raise UserError(_("Cannot set to draft!"))
|
||||||
"This action is not allowed for cancel with reversal.\n"
|
return super().button_draft()
|
||||||
"Please use Reverse Entry."
|
|
||||||
)
|
def action_document_reversal(self, date=None, journal_id=None):
|
||||||
)
|
# Check document readiness
|
||||||
return super().button_cancel()
|
valid_state = len(self.mapped("state")) == 1 and \
|
||||||
|
list(set(self.mapped("state")))[0] == "posted"
|
||||||
|
if not valid_state:
|
||||||
|
raise UserError(
|
||||||
|
_("Only posted document can be cancelled (reversal)"))
|
||||||
|
if self.mapped("line_ids.matched_debit_ids") | self.mapped("line_ids.matched_credit_ids"):
|
||||||
|
raise UserError(
|
||||||
|
_("Only fully unpaid invoice can be cancelled.\n"
|
||||||
|
"To cancel this invoice, make sure all payment(s) "
|
||||||
|
"are also cancelled."))
|
||||||
|
# Create reverse entries
|
||||||
|
self._cancel_reversal(journal_id)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _cancel_reversal(self, journal_id):
|
||||||
|
self.mapped("line_ids").filtered(
|
||||||
|
lambda x: x.account_id.reconcile).remove_move_reconcile()
|
||||||
|
Reversal = self.env["account.move.reversal"]
|
||||||
|
ctx = {"active_ids": self.ids, "active_model": "account.move"}
|
||||||
|
res = Reversal.with_context(ctx).default_get([])
|
||||||
|
res.update({"journal_id": journal_id,
|
||||||
|
"refund_method": "cancel",
|
||||||
|
"move_type": "entry", })
|
||||||
|
reversal = Reversal.create(res)
|
||||||
|
reversal.with_context(cancel_reversal=True).reverse_moves()
|
||||||
|
|
||||||
|
def _reverse_moves(self, default_values_list=None, cancel=False):
|
||||||
|
""" Set flag on the moves and the reversal moves being reversed """
|
||||||
|
if self._context.get("cancel_reversal"):
|
||||||
|
self.write({"cancel_reversal": True})
|
||||||
|
reverse_moves = super()._reverse_moves(default_values_list, cancel)
|
||||||
|
if self._context.get("cancel_reversal"):
|
||||||
|
reverse_moves.write({"cancel_reversal": True})
|
||||||
|
return reverse_moves
|
||||||
|
|
||||||
|
def _reverse_move_vals(self, default_values, cancel=True):
|
||||||
|
""" Reverse with cancel reversal, always use move_type = entry """
|
||||||
|
if self._context.get("cancel_reversal"):
|
||||||
|
default_values.update({"type": "entry"})
|
||||||
|
return super()._reverse_move_vals(default_values, cancel)
|
||||||
|
|
||||||
|
|
||||||
|
class AccountMoveLine(models.Model):
|
||||||
|
_inherit = "account.move.line"
|
||||||
|
|
||||||
|
def remove_move_reconcile(self):
|
||||||
|
""" For move with cancel_reversal = True, freeze it """
|
||||||
|
if not self._context.get("cancel_reversal") and \
|
||||||
|
any(self.mapped("move_id").mapped("cancel_reversal")):
|
||||||
|
raise UserError(_("This document was cancelled and freezed,\n"
|
||||||
|
"unreconcilation not allowed."))
|
||||||
|
return super().remove_move_reconcile()
|
||||||
|
|||||||
@@ -1,38 +1,37 @@
|
|||||||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from odoo import _, api, models
|
from odoo import _, api, models, fields
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class AccountPayment(models.Model):
|
class AccountPayment(models.Model):
|
||||||
_name = "account.payment"
|
_name = "account.payment"
|
||||||
_inherit = ["account.payment", "account.document.reversal"]
|
_inherit = ["account.payment", "account.document.reversal"]
|
||||||
|
|
||||||
@api.multi
|
def cancel_reversal(self):
|
||||||
def cancel(self):
|
|
||||||
""" If cancel method is to reverse, use document reversal wizard """
|
|
||||||
cancel_reversal = all(
|
|
||||||
self.mapped("move_line_ids.move_id.journal_id.is_cancel_reversal")
|
|
||||||
)
|
|
||||||
states = self.mapped("state")
|
|
||||||
if cancel_reversal and "draft" not in states:
|
|
||||||
return self.reverse_document_wizard()
|
return self.reverse_document_wizard()
|
||||||
return super().cancel()
|
|
||||||
|
|
||||||
@api.multi
|
def action_draft(self):
|
||||||
|
""" Case cancel reversal, set to draft allowed only when no moves """
|
||||||
|
for rec in self:
|
||||||
|
if rec.is_cancel_reversal and rec.move_line_ids:
|
||||||
|
raise UserError(_("Cannot set to draft!"))
|
||||||
|
return super().action_draft()
|
||||||
|
|
||||||
def action_document_reversal(self, date=None, journal_id=None):
|
def action_document_reversal(self, date=None, journal_id=None):
|
||||||
""" Reverse all moves related to this payment + set state to cancel """
|
""" Reverse all moves related to this payment + set state to cancel """
|
||||||
# Check document state
|
# Check document readiness
|
||||||
if "cancelled" in self.mapped("state"):
|
valid_state = len(self.mapped("state")) == 1 and \
|
||||||
raise ValidationError(_("You are trying to cancel the cancelled document"))
|
list(set(self.mapped("state")))[0] == "posted"
|
||||||
move_lines = self.mapped("move_line_ids")
|
if not valid_state:
|
||||||
|
raise UserError(
|
||||||
|
_("Only validated document can be cancelled (reversal)"))
|
||||||
|
# Find moves to get reversed
|
||||||
|
move_lines = self.mapped("move_line_ids").filtered(
|
||||||
|
lambda x: x.journal_id == self.mapped("journal_id")[0])
|
||||||
moves = move_lines.mapped("move_id")
|
moves = move_lines.mapped("move_id")
|
||||||
# Set all moves to unreconciled
|
|
||||||
move_lines.filtered(lambda x: x.account_id.reconcile).remove_move_reconcile()
|
|
||||||
# Important to remove relation with move.line before reverse
|
|
||||||
move_lines.write({"payment_id": False})
|
|
||||||
# Create reverse entries
|
# Create reverse entries
|
||||||
moves.reverse_moves(date, journal_id)
|
moves._cancel_reversal(journal_id)
|
||||||
# Set state cancelled and unlink with account.move
|
# Set state cancelled and unlink with account.move
|
||||||
self.write({"move_name": False, "state": "cancelled"})
|
self.write({"state": "cancelled"})
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
from . import test_invoice_reversal
|
# from . import test_invoice_reversal
|
||||||
from . import test_payment_reversal
|
# from . import test_payment_reversal
|
||||||
|
|||||||
37
account_document_reversal/views/account_move_view.xml
Normal file
37
account_document_reversal/views/account_move_view.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="view_move_form" model="ir.ui.view">
|
||||||
|
<field name="name">account.move.form.inherit</field>
|
||||||
|
<field name="model">account.move</field>
|
||||||
|
<field
|
||||||
|
name="inherit_id"
|
||||||
|
ref="account.view_move_form"
|
||||||
|
/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<field name="state" position="before">
|
||||||
|
<field name="is_cancel_reversal" invisible="1" />
|
||||||
|
<field name="cancel_reversal" invisible="1"/>
|
||||||
|
</field>
|
||||||
|
<button name="button_cancel" position="after">
|
||||||
|
<button name="button_cancel_reversal" string="Cancel Entry" type="object" groups="account.group_account_invoice"
|
||||||
|
attrs="{'invisible': ['|', '|', ('state', '!=', 'posted'), ('is_cancel_reversal', '=', False), ('cancel_reversal', '=', True)]}"/>
|
||||||
|
</button>
|
||||||
|
<field name="id" position="before">
|
||||||
|
<widget name="web_ribbon" title="Cancelled" attrs="{'invisible': ['|', ('cancel_reversal', '=', False), ('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"/>
|
||||||
|
</field>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_account_invoice_filter" model="ir.ui.view">
|
||||||
|
<field name="name">view.account.invoice.filter</field>
|
||||||
|
<field name="model">account.move</field>
|
||||||
|
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<filter name="unpaid" position="after">
|
||||||
|
<filter name="cancelled" string="Cancelled" domain="['|', ('state', '=', 'cancel'), ('cancel_reversal', '=', True)]"/>
|
||||||
|
</filter>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
18
account_document_reversal/views/account_payment_view.xml
Normal file
18
account_document_reversal/views/account_payment_view.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="view_account_payment_form" model="ir.ui.view">
|
||||||
|
<field name="name">view.account.payment.form</field>
|
||||||
|
<field name="model">account.payment</field>
|
||||||
|
<field name="inherit_id" ref="account.view_account_payment_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<field name="state" position="before">
|
||||||
|
<field name="is_cancel_reversal" invisible="1" />
|
||||||
|
</field>
|
||||||
|
<button name="cancel" position="after">
|
||||||
|
<button name="cancel_reversal" attrs="{'invisible': ['|', ('state', '!=', 'posted'), ('is_cancel_reversal', '=', False)]}" string="Cancel" type="object"/>
|
||||||
|
</button>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
@@ -1,49 +1,30 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="view_account_journal_form_inherit" model="ir.ui.view">
|
|
||||||
|
<record id="view_account_journal_form" model="ir.ui.view">
|
||||||
<field name="name">account.journal.form</field>
|
<field name="name">account.journal.form</field>
|
||||||
<field name="model">account.journal</field>
|
<field name="model">account.journal</field>
|
||||||
<field
|
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||||
name="inherit_id"
|
|
||||||
ref="account_cancel.view_account_journal_form_inherit"
|
|
||||||
/>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="update_posted" position="after">
|
<xpath expr="//page[@name='advanced_settings']/group" position="inside">
|
||||||
|
<group name="cancel_option" string="Cancel Option">
|
||||||
<field
|
<field
|
||||||
name="cancel_method"
|
name="cancel_method"
|
||||||
groups="base.group_no_one"
|
groups="base.group_no_one"
|
||||||
widget="radio"
|
widget="radio"
|
||||||
attrs="{'invisible': [('update_posted', '=', False)]}"
|
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="use_different_journal"
|
name="use_different_journal"
|
||||||
attrs="{'invisible': ['|', ('update_posted', '=', False), ('cancel_method', '!=', 'reversal')]}"
|
attrs="{'invisible': [('cancel_method', '!=', 'reversal')]}"
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="reversal_journal_id"
|
name="reversal_journal_id"
|
||||||
widget="selection"
|
widget="selection"
|
||||||
attrs="{'invisible': ['|', '|', ('update_posted', '=', False), ('cancel_method', '!=', 'reversal'), ('use_different_journal', '=', False)]}"
|
attrs="{'invisible': [('cancel_method', '!=', 'reversal'), ('use_different_journal', '=', False)]}"
|
||||||
/>
|
/>
|
||||||
</field>
|
</group>
|
||||||
</field>
|
</xpath>
|
||||||
</record>
|
|
||||||
<record id="view_move_form_inherit_account_cancel" model="ir.ui.view">
|
|
||||||
<field name="name">account.move.form.inherit</field>
|
|
||||||
<field name="model">account.move</field>
|
|
||||||
<field
|
|
||||||
name="inherit_id"
|
|
||||||
ref="account_cancel.view_move_form_inherit_account_cancel"
|
|
||||||
/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<field name="state" position="before">
|
|
||||||
<field name="is_cancel_reversal" invisible="1" />
|
|
||||||
</field>
|
|
||||||
<button name="button_cancel" position="attributes">
|
|
||||||
<attribute
|
|
||||||
name="attrs"
|
|
||||||
>{'invisible': ['|', ('state', '!=', 'posted'), ('is_cancel_reversal', '=', True)]}</attribute>
|
|
||||||
<attribute name="states" />
|
|
||||||
</button>
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -38,10 +38,9 @@ class ReverseAccountDocument(models.TransientModel):
|
|||||||
res["journal_id"] = journal.reversal_journal_id.id
|
res["journal_id"] = journal.reversal_journal_id.id
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_cancel(self):
|
def action_cancel(self):
|
||||||
model = self._context.get("active_model")
|
model = self._context.get("active_model")
|
||||||
active_ids = self._context.get("active_ids")
|
active_ids = self._context.get("active_ids")
|
||||||
documents = self.env[model].browse(active_ids)
|
documents = self.env[model].browse(active_ids)
|
||||||
documents.action_document_reversal(self.date, self.journal_id)
|
documents.action_document_reversal(self.date, self.journal_id.id)
|
||||||
return {"type": "ir.actions.act_window_close"}
|
return {"type": "ir.actions.act_window_close"}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
<record id="action_view_reverse_account_document" model="ir.actions.act_window">
|
<record id="action_view_reverse_account_document" model="ir.actions.act_window">
|
||||||
<field name="name">Document Cancel</field>
|
<field name="name">Document Cancel</field>
|
||||||
<field name="res_model">reverse.account.document</field>
|
<field name="res_model">reverse.account.document</field>
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="view_id" ref="view_reverse_account_document" />
|
<field name="view_id" ref="view_reverse_account_document" />
|
||||||
<field name="target">new</field>
|
<field name="target">new</field>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
@@ -0,0 +1 @@
|
|||||||
|
../../../../account_document_reversal
|
||||||
6
setup/account_document_reversal/setup.py
Normal file
6
setup/account_document_reversal/setup.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import setuptools
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
setup_requires=['setuptools-odoo'],
|
||||||
|
odoo_addon=True,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user