oca-financial/odoo-bringout-oca-account-invoicing-account_billing/account_billing/tests/test_account_billing.py
2025-08-29 15:43:04 +02:00

201 lines
7.5 KiB
Python

# Copyright 2019 Ecosoft Co., Ltd (https://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo import fields
from odoo.exceptions import UserError, ValidationError
from odoo.tests import tagged
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
@tagged("post_install", "-at_install")
class TestAccountBilling(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.billing_model = cls.env["account.billing"]
cls.register_payments_model = cls.env["account.payment.register"]
cls.payment_term = cls.env.ref("account.account_payment_term_15days")
cls.partner_china_exp = cls.env.ref("base.res_partner_3")
cls.product = cls.env.ref("product.product_product_4")
cls.currency_usd_id = cls.env.ref("base.USD").id
# Activate multi currency
cls.env.ref("base.EUR").active = True
cls.currency_eur_id = cls.env.ref("base.EUR").id
cls.journal_bank = cls.company_data["default_journal_bank"]
cls.inv_1 = cls._create_invoice(
cls,
move_type="out_invoice",
invoice_amount=100,
currency_id=cls.currency_eur_id,
partner_id=cls.partner_a.id,
date_invoice=fields.Date.context_today(cls.env.user),
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
cls.inv_2 = cls._create_invoice(
cls,
move_type="out_invoice",
invoice_amount=200,
currency_id=cls.currency_eur_id,
partner_id=cls.partner_a.id,
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
cls.inv_3 = cls._create_invoice(
cls,
move_type="out_invoice",
invoice_amount=300,
currency_id=cls.currency_usd_id,
partner_id=cls.partner_a.id,
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
cls.inv_4 = cls._create_invoice(
cls,
move_type="out_invoice",
invoice_amount=400,
currency_id=cls.currency_eur_id,
partner_id=cls.partner_china_exp.id,
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
cls.inv_5 = cls._create_invoice(
cls,
move_type="out_invoice",
invoice_amount=500,
currency_id=cls.currency_usd_id,
partner_id=cls.partner_a.id,
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
cls.inv_6 = cls._create_invoice(
cls,
move_type="in_refund",
invoice_amount=500,
currency_id=cls.currency_usd_id,
partner_id=cls.partner_a.id,
payment_term_id=cls.payment_term.id,
auto_validate=True,
)
def create_payment(self, ctx):
register_payments = self.register_payments_model.with_context(**ctx).create(
{
"journal_id": self.journal_bank.id,
"payment_method_line_id": self.inbound_payment_method_line.id,
}
)
return register_payments.action_create_payments()
def test_1_invoice_partner(self):
# Test difference partner
invoices = self.inv_1 + self.inv_4
with self.assertRaises(UserError):
invoices.action_create_billing()
def test_2_invoice_currency(self):
# Test difference currency
invoices = self.inv_1 + self.inv_3
with self.assertRaises(UserError):
invoices.action_create_billing()
def test_3_validate_billing_state_not_open(self):
ctx = {"active_model": "account.move", "active_ids": [self.inv_1.id]}
self.create_payment(ctx)
with self.assertRaises(UserError):
self.inv_1.action_create_billing()
def test_4_create_billing_from_selected_invoices(self):
"""Create two invoices, post it and send context to Billing"""
ctx = {
"active_model": "account.move",
"active_ids": [self.inv_1.id, self.inv_2.id],
"bill_type": "out_invoice",
}
invoices = self.inv_1 + self.inv_2
action = invoices.action_create_billing()
customer_billing1 = self.billing_model.browse(action["res_id"])
self.assertEqual(customer_billing1.state, "draft")
# Threshold Date error
with self.assertRaises(ValidationError):
customer_billing1.validate_billing()
threshold_date_1 = customer_billing1.threshold_date + relativedelta(years=1)
customer_billing1.threshold_date = threshold_date_1
customer_billing1.validate_billing()
self.assertEqual(customer_billing1.state, "billed")
self.assertEqual(customer_billing1.invoice_related_count, 2)
customer_billing1.invoice_relate_billing_tree_view()
customer_billing1.action_cancel()
customer_billing1.action_cancel_draft()
invoices = self.inv_1 + self.inv_2
action = invoices.action_create_billing()
customer_billing2 = self.billing_model.browse(action["res_id"])
threshold_date_2 = customer_billing2.threshold_date + relativedelta(years=1)
customer_billing2.threshold_date = threshold_date_2
customer_billing2.validate_billing()
self.create_payment(ctx)
with self.assertRaises(ValidationError):
customer_billing2.action_cancel()
def test_5_create_billing_directly(self):
bill1 = self.billing_model.create(
{
"bill_type": "out_invoice",
"partner_id": self.partner_a.id,
"currency_id": self.currency_eur_id,
"threshold_date": datetime.now(),
"threshold_date_type": "invoice_date_due",
}
)
bill1.threshold_date = bill1.threshold_date + relativedelta(months=12)
# No lines
with self.assertRaises(UserError):
bill1.validate_billing()
bill1.compute_lines()
self.assertEqual(bill1.invoice_related_count, 2)
self.assertEqual(bill1.billing_line_ids.mapped("move_id.billing_ids"), bill1)
# Create billing type - supplier
bill2 = self.billing_model.create(
{
"bill_type": "in_invoice",
"partner_id": self.partner_a.id,
"currency_id": self.currency_usd_id,
"threshold_date": datetime.now(),
"threshold_date_type": "invoice_date_due",
}
)
bill2.threshold_date = bill2.threshold_date + relativedelta(months=12)
bill2.compute_lines()
bill2.validate_billing()
self.assertEqual(bill2.invoice_related_count, 1)
def test_6_check_billing_from_bills(self):
inv_1 = self._create_invoice(
move_type="in_invoice",
invoice_amount=100,
currency_id=self.currency_eur_id,
partner_id=self.partner_a.id,
payment_term_id=self.payment_term.id,
auto_validate=True,
)
inv_2 = inv_1.copy()
# Need to explicitly assign invoice date, not kept on copy
inv_2.invoice_date = fields.Date.today()
if inv_2.state != "posted":
inv_2.action_post()
invoices = inv_1 + inv_2
action = invoices.action_create_billing()
self.billing_model.browse(action["res_id"])