Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] ACH Payment Unbalanced Entry #10

Open
wants to merge 22 commits into
base: 14.0-MIG-account_banking_ach_discount
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d0b82dc
[MIG][14.0] account_banking_ach_discount.
Murtaza-SerpentCS Feb 24, 2021
666ae2d
[FIX] account_banking_ach_discount: Missing required field 'communica…
max3903 Mar 8, 2021
2fae4e6
[FIX] account_banking_ach_discount
max3903 Mar 11, 2021
0761bc7
[FIX] account_banking_ach_discount
max3903 Mar 12, 2021
1f674ba
[FIX] account_banking_ach_discount
max3903 Mar 13, 2021
49b55ed
[FIX] Fixed issued of a reconcie functionlity.
AmmarOfficewalaSerpentCS Jul 9, 2021
2be02ad
[FIX] ACH Payment Unbalanced Entry
atchuthan Sep 1, 2021
1cbf3ff
[FIX] ACH Payment Unbalanced Entry - Fine Tuning
Vijaiy-Selvaraj Sep 14, 2021
79848fb
revert 49b55ed42a3fa7ba8b7f2188de549f14dc9ea58d
atchuthan Sep 14, 2021
d45aad3
[MIG][14.0] account_banking_ach_discount.
Murtaza-SerpentCS Feb 24, 2021
dc23349
[FIX] account_banking_ach_discount: Missing required field 'communica…
max3903 Mar 8, 2021
0b73ca7
[FIX] account_banking_ach_discount
max3903 Mar 11, 2021
c558030
[FIX] account_banking_ach_discount
max3903 Mar 12, 2021
c221278
[FIX] account_banking_ach_discount
max3903 Mar 13, 2021
2f2cb7a
[FIX] Fixed issued of a reconcie functionlity.
AmmarOfficewalaSerpentCS Jul 9, 2021
8da666a
[FIX] account_banking_ach_discount: Comparing apples and oranges
Sep 24, 2021
5fbcc95
[FIX] Fix the issue allowed tho pay non ACH IN/OUT payment.
Murtaza-OSI Sep 30, 2021
f70a04f
Merge branch '14.0-MIG-account_banking_ach_discount' into 14.0-MIG-ac…
atchuthan Oct 13, 2021
be607a9
[FIX] account_banking_ach_discount
murtuzasaleh Mar 2, 2022
df43dc3
[FIX]account_banking_ach_discount: fix manual discount case
Mar 2, 2022
92a2c27
[FIX] Improved code.
murtuzasaleh Mar 9, 2022
b2fa98f
[FIX] merge conflict
atchuthan Apr 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions account_banking_ach_discount/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

================================
OSI ACH-Batch Discount Connector
================================

This module will provide a discount functionality in ACH and batch ACH workflow.

Test Scenario:
==============

a. Single payment without discount

b. Single payment with discount

c. Single ACH payment with discount

d. Batch payment without discount

e. Batch payment with discount

f. Batch ACH payment without discount

g. Batch ACH payment with discount

Credits
=======

* Open Source Integrators <[email protected]>

Contributors
------------

* Bhavesh Odedra <[email protected]>
5 changes: 5 additions & 0 deletions account_banking_ach_discount/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
from . import wizard
25 changes: 25 additions & 0 deletions account_banking_ach_discount/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Discount on ACH batch payments",
"version": "14.0.1.0.0",
"license": "AGPL-3",
"author": "Open Source Integrators, Odoo Community Association (OCA)",
"category": "Accounting",
"maintainer": "Odoo Community Association (OCA)",
"website": "https://github.com/OCA/l10n-usa",
"development_status": "Beta",
"maintainers": ["bodedra"],
"depends": [
"account_payment_term_discount",
"account_payment_batch_process",
"account_payment_order",
"account_banking_ach_credit_transfer",
"account_banking_ach_direct_debit",
],
"data": [
"views/account_payment_view.xml",
"wizard/account_payment_register.xml",
],
}
7 changes: 7 additions & 0 deletions account_banking_ach_discount/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import account_payment
from . import account_move_line
from . import bank_payment_line
from . import account_payment_order
from . import account_move
104 changes: 104 additions & 0 deletions account_banking_ach_discount/models/account_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models


class AccountMove(models.Model):
_inherit = "account.move"

def _get_reconciled_info_JSON_values(self):
res = super(AccountMove, self)._get_reconciled_info_JSON_values()
inv_number = self.ref
if res:
flag = False
for item in res:
payment_lines = set()
for line in self.line_ids:
payment_lines.update(
line.mapped("matched_credit_ids.credit_move_id.id")
)
payment_lines.update(
line.mapped("matched_debit_ids.debit_move_id.id")
)
payment_move_line_ids = (
self.env["account.move.line"]
.browse(list(payment_lines))
.sorted()
)

for mvl in payment_move_line_ids:
# get bank payment line
if mvl.move_id and mvl.id == item["payment_id"]:
for pay_li in mvl.bank_payment_line_id.payment_line_ids:
# Get related payment line ref
if pay_li.communication == inv_number:
item["amount"] = pay_li.amount_currency
# for non-ach payment
# Deduct the discount only for the related payment.
# Discount is applied on the last payment (i.e. fully reconciled).
if (
not mvl.bank_payment_line_id
and mvl.move_id.id == self.id
and item["account_payment_id"] == mvl.payment_id.id
):
if mvl.full_reconcile_id and not flag:
item["amount"] = item["amount"] - self.discount_taken
flag = True

return res

def _prepare_discount_move_line(self, vals):
valid = False
for invoice in self:
if (
invoice.invoice_payment_term_id
and invoice.invoice_payment_term_id.is_discount
and invoice.invoice_payment_term_id.line_ids
):
discount_information = (
invoice.invoice_payment_term_id._check_payment_term_discount(
invoice, invoice.date_invoice
)
)
discount_amt = discount_information[0]
discount_account_id = discount_information[1]
if discount_amt > 0.0:
vals.update(
{
"account_id": discount_account_id,
"move_id": invoice.id,
"bank_payment_line_id": False,
"name": "Early Pay Discount",
}
)
if invoice.type == "out_invoice":
vals.update({"credit": 0.0, "debit": discount_amt})
valid = True
elif invoice.type == "in_invoice":
vals.update({"credit": discount_amt, "debit": 0.0})
valid = True
if valid:
return vals
else:
return {}

def _prepare_writeoff_move_line(self, payment_line, vals):
for invoice in self:
note = ""
if payment_line.reason_code:
note = payment_line.reason_code.display_name + ": "
if payment_line.note:
note += payment_line.note
vals.update(
{
"account_id": payment_line.writeoff_account_id.id,
"bank_payment_line_id": False,
"name": note,
"move_id": invoice.id,
}
)
if invoice.move_type == "out_invoice":
vals.update({"credit": 0.0, "debit": payment_line.payment_difference})
elif invoice.move_type == "in_invoice":
vals.update({"credit": payment_line.payment_difference, "debit": 0.0})
return vals
41 changes: 41 additions & 0 deletions account_banking_ach_discount/models/account_move_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import models


class AccountMoveLine(models.Model):
_inherit = "account.move.line"

def _prepare_payment_line_vals(self, payment_order):
vals = super(AccountMoveLine, self)._prepare_payment_line_vals(payment_order)
invoice = self.move_id
amount_currency = vals.get("amount_currency")
# No discount for open invoices
if (
("payment_line_state" in self._context
and self._context.get("payment_line_state") != "open")
or self._context.get("is_new_order")
or self._context.get("is_update_order")
):
if (
invoice
and invoice.invoice_payment_term_id
and invoice.invoice_payment_term_id.is_discount
and invoice.invoice_payment_term_id.line_ids
):
discount_information = (
invoice.invoice_payment_term_id._check_payment_term_discount(
invoice,
self._context.get("payment_date") or invoice.invoice_date,
)
)
discount_amt = discount_information[0]
vals.update(
{
"discount_amount": discount_amt,
"amount_currency": amount_currency - discount_amt,
"writeoff_account_id": discount_information[1]
}
)
return vals
95 changes: 95 additions & 0 deletions account_banking_ach_discount/models/account_payment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models
from odoo.exceptions import UserError


class AccountPayment(models.Model):
_inherit = "account.payment"

def action_validate_invoice_payment(self):
# Check if Invoices have ACH IN/OUT payment method, to avoid any
# conflict
valid = False
if self.filtered(lambda p: p.payment_method_id.code in ("ACH-In", "ACH-Out")):
valid = True
if any(len(record.invoice_ids) != 1 for record in self):
# For multiple invoices, there is account.register.payments wizard
raise UserError(
_(
"This method should only be called to process a "
"single invoice's payment."
)
)
if valid:
for payment in self:
payment_method = payment.payment_method_id
if payment_method:
if payment_method.code in ("ACH-In", "ACH-Out"):
# Update invoice with Payment mode
if not payment.reconciled_invoice_ids.payment_mode_id:
payment_mode_id = self.env["account.payment.mode"].search(
[
("payment_type", "=", payment.payment_type),
("payment_method_id", "=", payment_method.id),
("payment_order_ok", "=", True),
],
limit=1,
)
if payment_mode_id:
payment.reconciled_invoice_ids.write(
{"payment_mode_id": payment_mode_id.id}
)
payment.reconciled_invoice_ids.move_id.line_ids.write(
{"payment_mode_id": payment_mode_id.id}
)
action = (
payment.reconciled_invoice_ids.create_account_payment_line()
)
payment.unlink()
return action
res = super(AccountPayment, self).action_validate_invoice_payment()
return res


class AccountPaymentLine(models.Model):
_inherit = "account.payment.line"

discount_amount = fields.Monetary(currency_field="currency_id", readonly=True)
total_amount = fields.Monetary(currency_field="currency_id", readonly=True)
payment_difference_handling = fields.Selection(
[("open", "Keep open"), ("reconcile", "Mark invoice as fully paid")],
default="reconcile",
string="Action",
copy=False,
)
writeoff_account_id = fields.Many2one(
"account.account",
string="Account",
domain=[("deprecated", "!=", True)],
copy=False,
)
reason_code = fields.Many2one("payment.adjustment.reason", string="Reason Code")
note = fields.Text("Note")
payment_difference = fields.Float(string="Payment Difference")
move_id = fields.Many2one(
"account.move", related="move_line_id.move_id", store=True
)

@api.onchange("amount_currency")
def _onchange_amount_currency(self):
for line in self:
if line.total_amount:
line.discount_amount = line.payment_difference = round(
(line.total_amount - line.amount_currency), 2
)
if not line.total_amount and not line.payment_difference:
line.total_amount = line.amount_currency
@api.model
def same_fields_payment_line_and_bank_payment_line(self):
res = super(
AccountPaymentLine, self
).same_fields_payment_line_and_bank_payment_line()
res.append("discount_amount")
return res
Loading