19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -1,9 +1,10 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.fields import Command
from odoo import Command
from odoo.exceptions import AccessError
from odoo.tests import Form, tagged, users
from .common import TestSaleCommon
from odoo.addons.sale.tests.common import TestSaleCommon
@tagged('post_install', '-at_install')
@ -31,6 +32,8 @@ class TestSaleOrderCreditLimit(TestSaleCommon):
'currency_id': buck_currency.id,
})
cls.company_data_2 = cls.setup_other_company()
cls.sales_user = cls.company_data['default_user_salesman']
cls.sales_user.write({
'login': "notaccountman",
@ -41,9 +44,114 @@ class TestSaleOrderCreditLimit(TestSaleCommon):
'partner_id': cls.partner_a.id,
})
def test_credit_limit_multi_company(self):
# multi-company setup
company2 = self.company_data_2['company']
# Activate the Credit Limit feature
company2.account_use_credit_limit = True
# Create and confirm a SO for that company
sale_order = company2.env['sale.order'].create({
'company_id': company2.id,
'partner_id': self.partner_a.id,
'partner_invoice_id': self.partner_a.id,
'partner_shipping_id': self.partner_a.id,
'order_line': [Command.create({
'product_id': self.company_data_2['product_order_no'].id,
'price_unit': 1000.0,
})],
})
self.assertEqual(self.partner_a.with_company(company2).credit_to_invoice, 0.0)
sale_order.action_confirm()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertEqual(self.partner_a.with_company(company2).credit_to_invoice, 1000.0)
partner_a_multi_company = self.partner_a.with_context(allowed_company_ids=[self.env.company.id, company2.id])
self.assertEqual(partner_a_multi_company.credit_to_invoice, 0.0)
self.assertEqual(self.partner_a.credit_to_invoice, 0.0)
def test_warning_on_invoice_with_downpayment(self):
# Activate the Credit Limit feature and set a value for partner_a.
self.env.company.account_use_credit_limit = True
self.partner_a.credit_limit = 1000.0
# Create and confirm a SO to reach (but not exceed) partner_a's credit limit.
sale_order = self.empty_order
sale_order.write({
'order_line': [Command.create({
'name': self.company_data['product_order_no'].name,
'product_id': self.company_data['product_order_no'].id,
'product_uom_qty': 1,
'price_unit': 1000.0,
'tax_ids': False,
})]
})
# Check that partner_a's credit and credit_to_invoice is 0.0.
self.assertEqual(self.partner_a.credit, 0.0)
self.assertEqual(self.partner_a.credit_to_invoice, 0.0)
# Make sure partner_a's credit_to_invoice includes the newly confirmed SO.
sale_order.action_confirm()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertEqual(self.partner_a.credit, 0.0)
self.assertEqual(self.partner_a.credit_to_invoice, 1000.0)
# Create a 50% down payment invoice.
self.env['sale.advance.payment.inv'].with_context({
'active_model': 'sale.order',
'active_ids': [sale_order.id],
'active_id': sale_order.id,
'default_journal_id': self.company_data['default_journal_sale'].id,
}).create({
'advance_payment_method': 'percentage',
'amount': 50,
}).create_invoices()
invoice = sale_order.invoice_ids
# Check that the warning does not appear even though we are creating an invoice
# that should bring partner_a's credit above its limit.
self.assertEqual(invoice.partner_credit_warning, '')
# Make the down payment invoice amount larger than the Amount to Invoice
# and check that the warning appears with the correct amounts,
# i.e. 1.500 instead of 2.500 (1.000 SO + 1.500 down payment invoice).
invoice.invoice_line_ids.quantity = 3
self.assertEqual(
invoice.partner_credit_warning,
"partner_a has reached its credit limit of: $\xa01,000.00\n"
"Total amount due (including this document): $\xa01,500.00"
)
invoice.invoice_line_ids.quantity = 1
invoice.action_post()
# Create a credit note reversing the invoice
self.env['account.move.reversal'].with_company(self.env.company).with_context(
active_model="account.move",
active_ids=invoice.ids,
).create({
'journal_id': invoice.journal_id.id,
}).reverse_moves()
credit_note = sale_order.invoice_ids[1]
credit_note.action_post()
# Check that the credit note is accounted for correctly for the amount_to_invoice
self.assertEqual(sale_order.amount_to_invoice, sale_order.amount_total)
def test_credit_limit_multicurrency(self):
self.partner_a.credit_limit = 50
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 0.0,
}])
order = self.empty_order
order.write({
'pricelist_id': self.buck_pricelist.id,
@ -52,7 +160,7 @@ class TestSaleOrderCreditLimit(TestSaleCommon):
'product_id': self.company_data['product_order_no'].id,
'product_uom_qty': 1,
'price_unit': 45.0,
'tax_id': False,
'tax_ids': False,
})
]
})
@ -65,37 +173,221 @@ class TestSaleOrderCreditLimit(TestSaleCommon):
'product_id': self.company_data['product_order_no'].id,
'product_uom_qty': 1,
'price_unit': 65.0,
'tax_id': False,
'tax_ids': False,
})
],
})
self.assertEqual(order.amount_total / order.currency_rate, 55)
self.assertEqual(
order.partner_credit_warning,
"partner_a has reached its Credit Limit of : $\xa050.00\n"
"Total amount due (including this document) : $\xa055.00"
"partner_a has reached its credit limit of: $\xa050.00\n"
"Total amount due (including this document): $\xa055.00"
)
# Make sure partner_a's credit_to_invoice includes the newly confirmed SO in the correct currency
order.action_confirm()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 55.0,
}])
# Make sure the invoice amount is converted correctly for the warning
invoice = order._create_invoices(final=True)
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertEqual(
invoice.partner_credit_warning,
"partner_a has reached its credit limit of: $\xa050.00\n"
"Total amount due (including this document): $\xa055.00"
)
# Make sure the invoice amount is converted correctly for the partner.credit computation
invoice.action_post()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 55.0,
'credit_to_invoice': 0.0,
}])
def test_invoice_independent_of_credit_to_invoice(self):
# Activate the Credit Limit feature and set a value for partner_a.
self.env.company.account_use_credit_limit = True
self.partner_a.credit_limit = 1000.0
# Create and confirm a SO to reach (but not exceed) partner_a's credit limit.
sale_order = self.empty_order
sale_order.write({
'order_line': [Command.create({
'product_id': self.company_data['product_order_no'].id,
'price_unit': 1000.0,
})]
})
# Check that partner_a's credit and credit_to_invoice is 0.0.
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 0.0,
}])
# Make sure partner_a's credit_to_invoice includes the newly confirmed SO.
sale_order.action_confirm()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 1000.0,
}])
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_line_ids': [(0, 0, {
'name': 'test line',
'quantity': 1,
'price_unit': 100.0, # <= 1000 (sales order amount_total)
'tax_ids': False,
})],
})
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 1000.0,
}])
self.assertEqual(
invoice.partner_credit_warning,
"partner_a has reached its credit limit of: $\xa01,000.00\n"
"Total amount due (including sales orders and this document): $\xa01,100.00"
)
invoice.invoice_line_ids[0].price_unit = 2000 # > 1000 (sales order amount_total)
self.assertEqual(
invoice.partner_credit_warning,
"partner_a has reached its credit limit of: $\xa01,000.00\n"
"Total amount due (including sales orders and this document): $\xa03,000.00"
)
invoice.action_post()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 2000.0,
'credit_to_invoice': 1000.0,
}])
def test_credit_limit_and_warning_overinvoiced_sales_order(self):
# Activate the Credit Limit feature and set a value for partner_a.
self.env.company.account_use_credit_limit = True
self.partner_a.credit_limit = 1000.0
# Create 2 SOs
self.empty_order.write({
'order_line': [Command.create({
'product_id': self.company_data['product_order_no'].id,
'price_unit': 1000.0,
})]
})
sale_orders = self.empty_order + self.empty_order.copy()
# Check that partner_a's credit and credit_to_invoice is 0.0.
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 0.0,
}])
for order in sale_orders:
order.action_confirm()
# Make sure partner_a's credit_to_invoice includes the newly confirmed SOs.
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 0.0,
'credit_to_invoice': 2000.0,
}])
# Invoice 1 of the SOs.
sale_order = sale_orders[0]
self.assertEqual(sale_order.amount_to_invoice, 1000.0)
invoice = sale_order._create_invoices(final=True)
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertEqual(invoice.amount_total, 1000.0)
# Modify the amount of the invoice to be greater than the amount of the (single) SO.
invoice.invoice_line_ids[0].price_unit = 2000.0
# Confirming the invoice will reduce the credit_to_invoice by 1000.
# This is since the amount of the sales order it originates from is 1000 and
# the amount of the invoice is more than 1000.
self.assertEqual(
invoice.partner_credit_warning,
"partner_a has reached its credit limit of: $\xa01,000.00\n"
"Total amount due (including sales orders and this document): $\xa03,000.00"
)
# Check that confirming the invoice changes the credit amounts as described above.
invoice.action_post()
self.partner_a.invalidate_recordset(['credit', 'credit_to_invoice'])
self.assertRecordValues(self.partner_a, [{
'credit': 2000.0,
'credit_to_invoice': 1000.0,
}])
@users('notaccountman')
def test_credit_limit_access(self):
"""Ensure credit warning gets displayed without Accounting access."""
self.empty_order.user_id = self.env.user
self.empty_order.partner_id.credit_limit = self.product_a.list_price
self.empty_order.user_id = self.env.user # it's our order now
order = self.empty_order.with_env(self.env)
for group in self.partner_a._fields['credit'].groups.split(','):
self.assertFalse(self.env.user.has_group(group))
# Ensure we don't have access to accounting fields
with self.assertRaises(AccessError, msg="We shouldn't have access to credit"):
order.partner_id.credit_limit = 1e12
order.sudo().partner_id.credit_limit = self.product_a.list_price
with Form(self.empty_order.with_env(self.env)) as order_form:
with Form(order) as order_form:
with order_form.order_line.new() as sol:
sol.product_id = self.product_a
sol.tax_id.clear()
sol.tax_ids.clear()
self.assertFalse(
order_form.partner_credit_warning,
"No credit warning should be displayed (yet)",
)
with order_form.order_line.edit(0) as sol:
sol.tax_id.add(self.product_a.taxes_id)
sol.tax_ids.add(self.tax_sale_a)
self.assertTrue(
order_form.partner_credit_warning,
"Credit warning should be displayed",
)
def test_commercial_partner_credit(self):
"""Ensure that credit to invoice gets computed on partners' companies."""
company_a = self.env['res.partner'].create({
'name': "Company A",
'is_company': True,
'credit_limit': 10000.0,
'child_ids': [
Command.link(self.partner_a.id),
Command.create({
'name': "Company A Invoice",
'type': 'invoice',
}),
],
})
invoice_partner = company_a.child_ids.filtered(lambda p: p.type == 'invoice')
order = self.empty_order
order.order_line = [Command.create({
'product_id': self.company_data['product_order_no'].id,
'price_unit': 600.0,
'tax_ids': False,
})]
orders = order + order.copy({'partner_invoice_id': invoice_partner.id})
orders.action_confirm()
self.assertFalse(
self.partner_a.credit_to_invoice,
"Credit should only apply to the commercial entity",
)
self.assertFalse(company_a.credit)
self.assertEqual(company_a.credit_to_invoice, 1200.0)
invoices = orders._create_invoices()
invoices.action_post()
company_a.invalidate_recordset()
self.assertFalse(company_a.credit_to_invoice)
self.assertEqual(company_a.credit, 1200.0)