110 lines
6.1 KiB
Python
110 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import Command, fields
|
|
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
|
from odoo.tests import tagged, Form
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestReleaseToPayInvoice(AccountTestInvoicingCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.user.group_ids |= cls.quick_ref('purchase.group_purchase_user')
|
|
cls.partner = cls.env['res.partner'].create({'name': 'Zizizapartner'})
|
|
cls.product = cls.env['product.product'].create({
|
|
'name': 'VR Computer',
|
|
'standard_price': 2500.0,
|
|
'list_price': 2899.0,
|
|
'type': 'service',
|
|
'default_code': 'VR-01',
|
|
'weight': 1.0,
|
|
'purchase_method': 'receive',
|
|
})
|
|
cls.other_currency = cls.setup_other_currency('HRK', rounding=0.001)
|
|
|
|
def check_release_to_pay_scenario(self, ordered_qty, scenario, invoicing_policy='receive', order_price=500.0):
|
|
""" Generic test function to check that each use scenario behaves properly.
|
|
"""
|
|
self.product.purchase_method = invoicing_policy
|
|
|
|
purchase_order = self.env['purchase.order'].create({
|
|
'partner_id': self.partner.id,
|
|
'order_line': [
|
|
(0, 0, {
|
|
'name': self.product.name,
|
|
'product_id': self.product.id,
|
|
'product_qty': ordered_qty,
|
|
'product_uom_id': self.product.uom_id.id,
|
|
'price_unit': order_price,
|
|
'date_planned': fields.Datetime.now(),
|
|
})]
|
|
})
|
|
purchase_order.button_confirm()
|
|
|
|
invoices_list = []
|
|
purchase_line = purchase_order.order_line[-1]
|
|
AccountMove = self.env['account.move'].with_context(default_move_type='in_invoice')
|
|
for (action, params) in scenario:
|
|
if action == 'invoice':
|
|
# <field name="purchase_id" invisible="1"/>
|
|
move_form = Form(AccountMove.with_context(default_purchase_id=purchase_order.id))
|
|
with move_form.invoice_line_ids.edit(0) as line_form:
|
|
if 'price' in params:
|
|
line_form.price_unit = params['price']
|
|
if 'qty' in params:
|
|
line_form.quantity = params['qty']
|
|
new_invoice = move_form.save()
|
|
new_invoice.write({'invoice_line_ids': [
|
|
Command.create({'display_type': 'line_section', 'name': 'Section'}),
|
|
Command.create({'display_type': 'line_note', 'name': 'Note'}),
|
|
]})
|
|
invoices_list.append(new_invoice)
|
|
|
|
self.assertEqual(new_invoice.release_to_pay, params['rslt'], "Wrong invoice release to pay status for scenario " + str(scenario))
|
|
|
|
elif action == 'receive':
|
|
purchase_line.write({'qty_received': params['qty']}) # as the product is a service, its recieved quantity is set manually
|
|
|
|
if 'rslt' in params:
|
|
for (invoice_index, status) in params['rslt']:
|
|
self.assertEqual(invoices_list[invoice_index].release_to_pay, status, "Wrong invoice release to pay status for scenario " + str(scenario))
|
|
|
|
def test_3_way_match(self):
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 5, 'rslt': 'yes'})], invoicing_policy='purchase')
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 10, 'rslt': 'yes'})], invoicing_policy='purchase')
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 10, 'rslt': 'yes'})], invoicing_policy='purchase')
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 5, 'rslt': 'yes'}), ('receive',{'qty': 5}), ('invoice', {'qty': 6, 'rslt': 'exception'})], invoicing_policy='purchase')
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 10, 'rslt': 'yes'}), ('invoice', {'qty': 10, 'rslt': 'no'})], invoicing_policy='purchase')
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 5, 'rslt': 'yes'})])
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 10, 'rslt': 'exception'})])
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 5, 'rslt': 'no'})])
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 5, 'rslt': 'no'}), ('receive', {'qty': 5, 'rslt': [(-1, 'yes')]})])
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 5, 'rslt': 'no'}), ('receive', {'qty': 3, 'rslt': [(-1, 'exception')]})])
|
|
self.check_release_to_pay_scenario(10, [('invoice', {'qty': 5, 'rslt': 'no'}), ('receive', {'qty': 10, 'rslt': [(-1, 'yes')]})])
|
|
|
|
# Special use case : a price change between order and invoice should always put the bill in exception
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 5, 'rslt': 'exception', 'price':42})])
|
|
self.check_release_to_pay_scenario(10, [('receive',{'qty': 5}), ('invoice', {'qty': 5, 'rslt': 'exception', 'price':42})], invoicing_policy='purchase')
|
|
|
|
def test_amount_currency_edit(self):
|
|
"""
|
|
Ensure that editing the `amount_currency` of a journal item on an invoice is possible.
|
|
In 17.0 changes to Binary fields and web_save were made (related to context key 'bin_size').
|
|
They led to tracebacks in the flow tested here.
|
|
"""
|
|
move_form = Form(self.env['account.move'].with_context(default_move_type='out_invoice'))
|
|
move_form.invoice_date = fields.Date.from_string('2023-01-01')
|
|
move_form.partner_id = self.partner_a
|
|
move_form.currency_id = self.other_currency
|
|
with move_form.invoice_line_ids.new() as line_form:
|
|
line_form.quantity = 1
|
|
line_form.price_unit = 10
|
|
move_form.save()
|
|
with move_form.line_ids.edit(0) as line_form:
|
|
line_form.amount_currency = -30
|
|
move_form.save()
|
|
self.assertEqual(move_form.line_ids.edit(0).amount_currency, -30)
|