Skip to content

Commit

Permalink
#fix
Browse files Browse the repository at this point in the history
  • Loading branch information
dc-oerp committed Jul 4, 2024
1 parent ff04b73 commit ac994db
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 94 deletions.
65 changes: 10 additions & 55 deletions account_payment_widget_amount/models/account_move_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# Copyright 2024 OERP Canada <https://www.oerp.ca>

from odoo import api, models
from odoo.tools import float_compare


class AccountMove(models.Model):
Expand All @@ -25,59 +24,15 @@ class AccountMoveLine(models.Model):
_inherit = "account.move.line"

@api.model
def _prepare_reconciliation_partials(self, vals_list):
am_model = self.env["account.move"]
aml_model = self.env["account.move.line"]
partials = super()._prepare_reconciliation_partials(vals_list=vals_list)
def _prepare_reconciliation_single_partial(
self, debit_values, credit_values, shadowed_aml_values=None
):
# update paid amount from front end
if self.env.context.get("paid_amount", 0.0):
total_paid = self.env.context.get("paid_amount", 0.0)
current_am = am_model.browse(self.env.context.get("move_id"))
current_aml = aml_model.browse(self.env.context.get("line_id"))
decimal_places = current_am.company_id.currency_id.decimal_places
if current_am.currency_id.id != current_am.company_currency_id.id:
total_paid = current_am.currency_id._convert(
total_paid,
current_aml.currency_id,
current_am.company_id,
current_aml.date,
)
for partial in partials[0]:
debit_line = self.browse(partial.get("debit_move_id"))
credit_line = self.browse(partial.get("credit_move_id"))
different_currency = (
debit_line.currency_id.id != credit_line.currency_id.id
)
to_apply = min(total_paid, partial.get("amount", 0.0))
partial.update(
{
"amount": to_apply,
}
)
if different_currency:
partial.update(
{
"debit_amount_currency": credit_line.company_currency_id._convert(
to_apply,
debit_line.currency_id,
credit_line.company_id,
credit_line.date,
),
"credit_amount_currency": debit_line.company_currency_id._convert(
to_apply,
credit_line.currency_id,
debit_line.company_id,
debit_line.date,
),
}
)
else:
partial.update(
{
"debit_amount_currency": to_apply,
"credit_amount_currency": to_apply,
}
)
total_paid -= to_apply
if float_compare(total_paid, 0.0, precision_digits=decimal_places) <= 0:
break
return partials
credit_values["amount_residual"] = credit_values[
"amount_residual_currency"
] = total_paid
return super()._prepare_reconciliation_single_partial(
debit_values, credit_values, shadowed_aml_values=shadowed_aml_values
)
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
/** @odoo-module **/

import {patch} from "@web/core/utils/patch";
import {_t} from "@web/core/l10n/translation";
import {AccountPaymentField} from "@account/components/account_payment_field/account_payment_field";
import {patch} from "@web/core/utils/patch";
import {localization} from "@web/core/l10n/localization";
import {useService} from "@web/core/utils/hooks";

const {Component} = owl;

class PaymentAmountPopOver extends Component {}
PaymentAmountPopOver.template = "PaymentAmountPopOver";

patch(AccountPaymentField.prototype, {
setup() {
super.setup();
this.widgetPopover = useService("popover");
this.orm = useService("orm");
},
async popoverPartialOutstanding(ev, id) {
var self = this;
for (var i = 0; i < this.props.value.content.length; i++) {
var k = this.props.value.content[i];
for (
var i = 0;
i <
this.props.record.data.invoice_outstanding_credits_debits_widget.content
.length;
i++
) {
var k =
this.props.record.data.invoice_outstanding_credits_debits_widget
.content[i];
if (k.id === id) {
self.popoverCloseFn = self.popover.add(
this.popoverCloseFn = this.widgetPopover.add(
ev.currentTarget,
PaymentAmountPopOver,
{
title: self.env._t("Enter the payment amount"),
title: _t("Enter the payment amount"),
id: id,
amount: k.amount_formatted,
placeholder: k.amount_formatted,
move_id: self.move_id,
move_id: this.props.record.data.id,
_onOutstandingCreditAssign:
self._onOutstandingCreditAssign.bind(self),
this._onOutstandingCreditAssign.bind(this),
},
{
position: localization.direction === "rtl" ? "bottom" : "left",
Expand All @@ -35,21 +50,21 @@ patch(AccountPaymentField.prototype, {
}
},
async _onOutstandingCreditAssign(ev) {
var self = this;
var id = parseInt($(ev.target).data("id"));
var move_id = parseInt($(ev.target).data("move_id"));
var payment_amount =
parseFloat(document.getElementById("paid_amount").value) || 0.0;
var context = {
paid_amount: payment_amount,
paid_amount: -payment_amount,
};
await this.orm
.call("account.move", "js_assign_outstanding_line", [move_id, id], {
context: context,
})
.then(function () {
self.closePopover();
});
await this.orm.call(
"account.move",
"js_assign_outstanding_line",
[move_id, id],
{context: context}
);
this.popoverCloseFn();
this.popoverCloseFn = null;
await this.props.record.model.root.load();
this.props.record.model.notify();
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Copyright 2017-2021 ForgeFlow S.L.
# Copyright 2024 OERP Canada <https://www.oerp.ca>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import time

from odoo.tests.common import TransactionCase
Expand Down Expand Up @@ -142,7 +146,7 @@ def test_01(self):
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 0.0)
self.assertEqual(invoice.amount_residual, 100.0)
self.assertFalse(payment_ml.reconciled)
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
Expand Down Expand Up @@ -213,10 +217,10 @@ def test_02(self):
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 0.0)
self.assertEqual(invoice.payment_state, "paid")
self.assertEqual(invoice.amount_residual, 100.0)
self.assertEqual(invoice.payment_state, "partial")
self.assertFalse(payment_ml.reconciled)
self.assertEqual(payment_ml.amount_residual, -900.0)
self.assertEqual(payment_ml.amount_residual, -950.0)

def test_03(self):
"""Tests that I can create an refund invoice in foreign currency,
Expand Down Expand Up @@ -252,6 +256,7 @@ def test_03(self):
],
}
)

# Open invoice
invoice.action_post()
# Create a payment
Expand All @@ -274,33 +279,33 @@ def test_03(self):
payment_ml = payment.line_ids.filtered(
lambda line: line.account_id == self.account_receivable
)
# We pay 100 in the currency of the invoice. Which means that in
# company currency we are paying 50.
# We collect 100 in the currency of the refund. Which means that in
# company currency we are reconciling 50.
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 0.0)
self.assertEqual(invoice.payment_state, "paid")
self.assertEqual(invoice.amount_residual, 100.0)
self.assertEqual(invoice.payment_state, "partial")
self.assertFalse(payment_ml.reconciled)
self.assertEqual(payment_ml.amount_residual, 900.0)
self.assertEqual(payment_ml.amount_residual, 950.0)

def test_04(self):
"""Tests that I can create an invoice in company currency,
register a payment in company currency, and then reconcile the full
payment to the invoice without specifying paid_amount in the context.
register a payment in foreign currency, and then reconcile part
of the payment to the invoice.
I expect:
- The residual amount of the invoice is reduced to zero.
- The residual amount of the payment is reduced to zero.
- Both the invoice and payment are fully reconciled.
- The residual amount of the invoice is reduced by the amount assigned.
- The residual amount of the payment is reduced by the amount assigned.
"""
self.company.currency_id.rate_ids = False
invoice = self.account_move_model.create(
{
"move_type": "out_invoice",
"name": "Test Customer Invoice",
"journal_id": self.sale_journal.id,
"partner_id": self.partner.id,
"company_id": self.company.id,
"currency_id": self.company.currency_id.id,
"move_type": "out_invoice",
"invoice_line_ids": [
(
0,
Expand All @@ -316,9 +321,11 @@ def test_04(self):
],
}
)

# Open invoice
invoice.action_post()
# Create a payment
# Create a payment for 1000 of foreign currency, which translates
# to 500 in company currency.
payment = self.account_payment_model.create(
{
"payment_type": "inbound",
Expand All @@ -327,8 +334,8 @@ def test_04(self):
).id,
"partner_type": "customer",
"partner_id": self.partner.id,
"amount": 200.0,
"currency_id": self.company.currency_id.id,
"amount": 1000.0,
"currency_id": self.new_usd.id,
"date": time.strftime("%Y-%m-%d"),
"journal_id": self.bank_journal.id,
"company_id": self.company.id,
Expand All @@ -338,9 +345,87 @@ def test_04(self):
payment_ml = payment.line_ids.filtered(
lambda line: line.account_id == self.account_receivable
)
# Assign the payment to the invoice without specifying paid_amount
invoice.js_assign_outstanding_line(payment_ml.id)
# We pay 100 in the currency of the invoice, which is the
# company currency
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 100.0)
self.assertEqual(invoice.payment_state, "partial")
self.assertFalse(payment_ml.reconciled)
self.assertEqual(payment_ml.amount_residual, -400.0)
self.assertEqual(payment_ml.amount_residual_currency, -800.0)
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 0.0)
self.assertEqual(payment_ml.amount_residual, 0.0)
self.assertTrue(payment_ml.reconciled)
self.assertIn(invoice.payment_state, ("paid", "in_payment"))
self.assertEqual(payment_ml.amount_residual, -300.0)
self.assertEqual(payment_ml.amount_residual_currency, -600.0)

def test_05(self):
"""Tests that I can create a vendor bill in company currency,
register a payment in company currency, and then reconcile part
of the payment to the bill.
I expect:
- The residual amount of the invoice is reduced by the amount assigned.
- The residual amount of the payment is reduced by the amount assigned.
"""
invoice = self.account_move_model.create(
{
"name": "Test Vendor Bill",
"move_type": "in_invoice",
"journal_id": self.purchase_journal.id,
"partner_id": self.partner.id,
"company_id": self.company.id,
"invoice_date": time.strftime("%Y-%m-%d"),
"currency_id": self.company.currency_id.id,
"invoice_line_ids": [
(
0,
0,
{
"name": "Line 1",
"price_unit": 200.0,
"account_id": self.account_expense.id,
"quantity": 1,
"tax_ids": False,
},
)
],
}
)

# Open invoice
invoice.action_post()
# Create a payment
payment = self.account_payment_model.create(
{
"payment_type": "outbound",
"payment_method_id": self.env.ref(
"account.account_payment_method_manual_out"
).id,
"partner_type": "supplier",
"partner_id": self.partner.id,
"amount": 1000.0,
"currency_id": self.company.currency_id.id,
"date": time.strftime("%Y-%m-%d"),
"journal_id": self.bank_journal.id,
"company_id": self.company.id,
}
)
payment.action_post()
payment_ml = payment.line_ids.filtered(
lambda line: line.account_id == self.account_payable
)
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 100.0)
self.assertFalse(payment_ml.reconciled)
invoice.with_context(paid_amount=100.0).js_assign_outstanding_line(
payment_ml.id
)
self.assertEqual(invoice.amount_residual, 0.0)
self.assertIn(invoice.payment_state, ("paid", "in_payment"))
self.assertFalse(payment_ml.reconciled)

0 comments on commit ac994db

Please sign in to comment.