# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.account.tests.common import AccountTestInvoicingCommon from odoo.tests import tagged, Form from odoo import Command, fields from odoo.exceptions import UserError from datetime import timedelta from freezegun import freeze_time import pytz @tagged('-at_install', 'post_install') class TestPurchase(AccountTestInvoicingCommon): @classmethod def setUpClass(cls): super().setUpClass() cls.company_data_2 = cls.setup_other_company() def test_date_planned(self): """Set a date planned on 2 PO lines. Check that the PO date_planned is the earliest PO line date planned. Change one of the dates so it is even earlier and check that the date_planned is set to this earlier date. """ po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 with po.order_line.new() as po_line: po_line.product_id = self.product_b po_line.product_qty = 10 po_line.price_unit = 200 po = po.save() # Check that the same date is planned on both PO lines. self.assertNotEqual(po.order_line[0].date_planned, False) self.assertAlmostEqual(po.order_line[0].date_planned, po.order_line[1].date_planned, delta=timedelta(seconds=10)) self.assertAlmostEqual(po.order_line[0].date_planned, po.date_planned, delta=timedelta(seconds=10)) orig_date_planned = po.order_line[0].date_planned # Set an earlier date planned on a PO line and check that the PO expected date matches it. new_date_planned = orig_date_planned - timedelta(hours=1) po.order_line[0].date_planned = new_date_planned self.assertAlmostEqual(po.order_line[0].date_planned, po.date_planned, delta=timedelta(seconds=10)) # Set an even earlier date planned on the other PO line and check that the PO expected date matches it. # Also check that the other PO line's date planned is not modified. new_date_planned_2 = orig_date_planned - timedelta(hours=72) po_form = Form(po) with po_form.order_line.edit(1) as po_line: po_line.date_planned = new_date_planned_2 po = po_form.save() self.assertAlmostEqual(po.order_line[1].date_planned, po.date_planned, delta=timedelta(seconds=10)) self.assertAlmostEqual(po.order_line[0].date_planned, new_date_planned, delta=timedelta(seconds=10)) def test_date_planned_2(self): """ Check that the date_planned of the onchange is correctly applied: Create a PO, change its date_planned to tommorow and check that the date_planned of the lines are updated. Create a new line (this will update the date_planned of the PO but should not alter the other lines). """ po = self.env['purchase.order'].create({ 'partner_id': self.partner_a.id, 'order_line': [Command.create({ 'name': self.product_a.name, 'product_id': self.product_a.id, 'product_uom_qty': 10, 'product_uom': self.product_a.uom_id.id, 'price_unit': 1, })], }) with Form(po) as po_form: po_form.date_planned = fields.Datetime.now() + timedelta(days=1) self.assertEqual(po.order_line.date_planned, po.date_planned) with Form(po) as po_form: with po_form.order_line.new() as new_line: new_line.product_id = self.product_b new_line.product_qty = 10 new_line.price_unit = 200 self.assertEqual(po.order_line[1].date_planned, po.date_planned) self.assertNotEqual(po.order_line[0].date_planned, po.date_planned) def test_purchase_order_sequence(self): PurchaseOrder = self.env['purchase.order'].with_context(tracking_disable=True) company = self.env.user.company_id self.env['ir.sequence'].search([ ('code', '=', 'purchase.order'), ]).write({ 'use_date_range': True, 'prefix': 'PO/%(range_year)s/', }) vals = { 'partner_id': self.partner_a.id, 'company_id': company.id, 'currency_id': company.currency_id.id, 'date_order': '2019-01-01', } purchase_order = PurchaseOrder.create(vals.copy()) self.assertTrue(purchase_order.name.startswith('PO/2019/')) vals['date_order'] = '2020-01-01' purchase_order = PurchaseOrder.create(vals.copy()) self.assertTrue(purchase_order.name.startswith('PO/2020/')) # In EU/BXL tz, this is actually already 01/01/2020 vals['date_order'] = '2019-12-31 23:30:00' purchase_order = PurchaseOrder.with_context(tz='Europe/Brussels').create(vals.copy()) self.assertTrue(purchase_order.name.startswith('PO/2020/')) def test_reminder_1(self): """Set to send reminder tomorrow, check if a reminder can be send to the partner. """ # set partner to send reminder in Company 2 self.partner_a.with_company(self.company_data_2['company']).receipt_reminder_email = True self.partner_a.with_company(self.company_data_2['company']).reminder_date_before_receipt = 1 # Create the PO in Company 1 self.env.user.tz = 'Europe/Brussels' po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 with po.order_line.new() as po_line: po_line.product_id = self.product_b po_line.product_qty = 10 po_line.price_unit = 200 # set to send reminder today date_planned = fields.Datetime.now().replace(hour=23, minute=0) + timedelta(days=2) po.date_planned = date_planned po = po.save() po.button_confirm() # Check that reminder is not set in Company 1 and the mail will not be sent self.assertEqual(po.company_id, self.company) self.assertFalse(po.receipt_reminder_email) self.assertEqual(po.reminder_date_before_receipt, 1, "The default value should be taken from the company") old_messages = po.message_ids po._send_reminder_mail() messages_send = po.message_ids - old_messages self.assertFalse(messages_send) # Set to send reminder in Company 1 self.partner_a.receipt_reminder_email = True self.partner_a.reminder_date_before_receipt = 2 # Invalidate the cache to ensure that the computed fields are recomputed self.env.invalidate_all() self.assertTrue(po.receipt_reminder_email) self.assertEqual(po.reminder_date_before_receipt, 2) # check date_planned is correctly set self.assertEqual(po.date_planned, date_planned) po_tz = pytz.timezone(po.user_id.tz) localized_date_planned = po.date_planned.astimezone(po_tz) self.assertEqual(localized_date_planned, po.get_localized_date_planned()) # Ensure that the function get_localized_date_planned can accept a date in string format self.assertEqual(localized_date_planned, po.get_localized_date_planned(po.date_planned.strftime('%Y-%m-%d %H:%M:%S'))) # check vendor is a message recipient self.assertTrue(po.partner_id in po.message_partner_ids) # check reminder send old_messages = po.message_ids po._send_reminder_mail() messages_send = po.message_ids - old_messages self.assertTrue(messages_send) self.assertTrue(po.partner_id in messages_send.mapped('partner_ids')) # check confirm button + date planned localized in message old_messages = po.message_ids po.confirm_reminder_mail() messages_send = po.message_ids - old_messages self.assertTrue(po.mail_reminder_confirmed) self.assertEqual(len(messages_send), 1) self.assertIn(str(localized_date_planned.date()), messages_send.body) def test_reminder_2(self): """Set to send reminder tomorrow, check if no reminder can be send. """ po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 with po.order_line.new() as po_line: po_line.product_id = self.product_b po_line.product_qty = 10 po_line.price_unit = 200 # set to send reminder tomorrow po.date_planned = fields.Datetime.now() + timedelta(days=2) po = po.save() self.partner_a.receipt_reminder_email = True self.partner_a.reminder_date_before_receipt = 1 po.button_confirm() # check vendor is a message recipient self.assertTrue(po.partner_id in po.message_partner_ids) old_messages = po.message_ids po._send_reminder_mail() messages_send = po.message_ids - old_messages # check no reminder send self.assertFalse(messages_send) def test_update_date_planned(self): po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 po_line.date_planned = '2020-06-06 00:00:00' with po.order_line.new() as po_line: po_line.product_id = self.product_b po_line.product_qty = 10 po_line.price_unit = 200 po_line.date_planned = '2020-06-06 00:00:00' po = po.save() po.button_confirm() # update first line po._update_date_planned_for_lines([(po.order_line[0], fields.Datetime.today())]) self.assertEqual(po.order_line[0].date_planned, fields.Datetime.today()) activity = self.env['mail.activity'].search([ ('summary', '=', 'Date Updated'), ('res_model_id', '=', 'purchase.order'), ('res_id', '=', po.id), ]) self.assertTrue(activity) self.assertIn( '
partner_a modified receipt dates for the following products:
\n' '- product_a from 2020-06-06 to %s
' % fields.Date.today(), activity.note, ) # update second line po._update_date_planned_for_lines([(po.order_line[1], fields.Datetime.today())]) self.assertEqual(po.order_line[1].date_planned, fields.Datetime.today()) self.assertIn( 'partner_a modified receipt dates for the following products:
\n' '- product_a from 2020-06-06 to %(today)s
\n' '- product_b from 2020-06-06 to %(today)s
' % {'today': fields.Date.today()}, activity.note, ) def test_compute_packaging_00(self): """Create a PO and use packaging. Check we suggested suitable packaging according to the product_qty. Also check product_qty or product_packaging are correctly calculated when one of them changed. """ # Required for `product_packaging_qty` to be visible in the view self.env.user.groups_id += self.env.ref('product.group_stock_packaging') packaging_single = self.env['product.packaging'].create({ 'name': "I'm a packaging", 'product_id': self.product_a.id, 'qty': 1.0, }) packaging_dozen = self.env['product.packaging'].create({ 'name': "I'm also a packaging", 'product_id': self.product_a.id, 'qty': 12.0, }) po = self.env['purchase.order'].create({ 'partner_id': self.partner_a.id, }) po_form = Form(po) with po_form.order_line.new() as line: line.product_id = self.product_a line.product_qty = 1.0 po_form.save() self.assertEqual(po.order_line.product_packaging_id, packaging_single) self.assertEqual(po.order_line.product_packaging_qty, 1.0) with po_form.order_line.edit(0) as line: line.product_packaging_qty = 2.0 po_form.save() self.assertEqual(po.order_line.product_qty, 2.0) with po_form.order_line.edit(0) as line: line.product_qty = 24.0 po_form.save() self.assertEqual(po.order_line.product_packaging_id, packaging_dozen) self.assertEqual(po.order_line.product_packaging_qty, 2.0) with po_form.order_line.edit(0) as line: line.product_packaging_qty = 1.0 po_form.save() self.assertEqual(po.order_line.product_qty, 12) # Do the same test but without form, to check the `product_packaging_id` and `product_packaging_qty` are set # without manual call to compute po = self.env['purchase.order'].create({ 'partner_id': self.partner_a.id, 'order_line': [ Command.create({'product_id': self.product_a.id, 'product_qty': 1.0}), ] }) self.assertEqual(po.order_line.product_packaging_id, packaging_single) self.assertEqual(po.order_line.product_packaging_qty, 1.0) po.order_line.product_packaging_qty = 2.0 self.assertEqual(po.order_line.product_qty, 2.0) po.order_line.product_qty = 24.0 self.assertEqual(po.order_line.product_packaging_id, packaging_dozen) self.assertEqual(po.order_line.product_packaging_qty, 2.0) po.order_line.product_packaging_qty = 1.0 self.assertEqual(po.order_line.product_qty, 12) def test_compute_packaging_01(self): """Create a PO and use packaging in a multicompany environment. Ensure any suggested packaging matches the PO's. """ company1 = self.company_data['company'] company2 = self.company_data_2['company'] generic_single_pack = self.env['product.packaging'].create({ 'name': "single pack", 'product_id': self.product_a.id, 'qty': 1.0, 'company_id': False, }) company2_pack_of_10 = self.env['product.packaging'].create({ 'name': "pack of 10 by Company 2", 'product_id': self.product_a.id, 'qty': 10.0, 'company_id': company2.id, }) po1 = self.env['purchase.order'].with_company(company1).create({ 'partner_id': self.partner_a.id, 'order_line': [ Command.create({'product_id': self.product_a.id, 'product_qty': 10.0}), ] }) self.assertEqual(po1.order_line.product_packaging_id, generic_single_pack) self.assertEqual(po1.order_line.product_packaging_qty, 10.0) # verify that with the right company, we can get the other packaging po2 = self.env['purchase.order'].with_company(company2).create({ 'partner_id': self.partner_a.id, 'order_line': [ Command.create({'product_id': self.product_a.id, 'product_qty': 10.0}), ] }) self.assertEqual(po2.order_line.product_packaging_id, company2_pack_of_10) self.assertEqual(po2.order_line.product_packaging_qty, 1.0) def test_with_different_uom(self): """ This test ensures that the unit price is correctly computed""" # Required for `product_uom` to be visibile in the view self.env.user.groups_id += self.env.ref('uom.group_uom') uom_units = self.env.ref('uom.product_uom_unit') uom_dozens = self.env.ref('uom.product_uom_dozen') uom_pairs = self.env['uom.uom'].create({ 'name': 'Pairs', 'category_id': uom_units.category_id.id, 'uom_type': 'bigger', 'factor_inv': 2, 'rounding': 1, }) product_data = { 'name': 'SuperProduct', 'type': 'consu', 'uom_id': uom_units.id, 'uom_po_id': uom_pairs.id, 'standard_price': 100 } product_01 = self.env['product.product'].create(product_data) product_02 = self.env['product.product'].create(product_data) po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_a with po_form.order_line.new() as po_line: po_line.product_id = product_01 with po_form.order_line.new() as po_line: po_line.product_id = product_02 po_line.product_uom = uom_dozens po = po_form.save() self.assertEqual(po.order_line[0].price_unit, 200) self.assertEqual(po.order_line[1].price_unit, 1200) def test_on_change_quantity_description(self): """ When a user changes the quantity of a product in a purchase order it should not change the description if the descritpion was changed by the user before """ self.env.user.write({'company_id': self.company_data['company'].id}) po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as pol: pol.product_id = self.product_a pol.product_qty = 1 pol.name = "New custom description" pol.product_qty += 1 self.assertEqual(pol.name, "New custom description") def test_purchase_multicurrency(self): """ Purchase order lines should keep unit price precision of products Also the products having prices in different currencies should be correctly handled when creating a purchase order i-e product having a price of 100 usd and when purchasing in EUR company the correct conversion should be applied """ self.env['decimal.precision'].search([ ('name', '=', 'Product Price'), ]).digits = 5 product = self.env['product.product'].create({ 'name': 'product_test', 'uom_id': self.env.ref('uom.product_uom_unit').id, 'lst_price': 10.0, 'standard_price': 0.12345, }) currency = self.env['res.currency'].create({ 'name': 'Dark Chocolate Coin', 'symbol': '🍫', 'rounding': 0.001, 'position': 'after', 'currency_unit_label': 'Dark Choco', 'currency_subunit_label': 'Dark Cacao Powder', }) currency_rate = self.env['res.currency.rate'].create({ 'name': '2016-01-01', 'rate': 2, 'currency_id': currency.id, 'company_id': self.env.company.id, }) po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_a with po_form.order_line.new() as po_line: po_line.product_id = product purchase_order_usd = po_form.save() self.assertEqual(purchase_order_usd.order_line.price_unit, product.standard_price, "Value shouldn't be rounded $") self.assertEqual(purchase_order_usd.amount_total_cc, purchase_order_usd.amount_total, "Company Total should be 0.14$") po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_a po_form.currency_id = currency with po_form.order_line.new() as po_line: po_line.product_id = product purchase_order_coco = po_form.save() self.assertEqual(purchase_order_coco.order_line.price_unit, currency_rate.rate * product.standard_price, "Value shouldn't be rounded 🍫") self.assertEqual(purchase_order_coco.amount_total_cc, round(purchase_order_coco.amount_total / currency_rate.rate, 2), "Company Total should be 0.14$, since 1$ = 0.5🍫") #check if the correct currency is set on the purchase order by comparing the expected price and actual price company_a = self.company_data['company'] company_b = self.company_data_2['company'] company_b.currency_id = currency self.env['res.currency.rate'].create({ 'name': '2023-01-01', 'rate': 2, 'currency_id': currency.id, 'company_id': company_b.id, }) product_b = self.env['product.product'].with_company(company_a).create({ 'name': 'product_2', 'uom_id': self.env.ref('uom.product_uom_unit').id, 'standard_price': 0.0, }) self.assertEqual(product_b.cost_currency_id, company_a.currency_id, 'The cost currency should be the one set on' ' the company') product_b = product_b.with_company(company_b) self.assertEqual(product_b.cost_currency_id, currency, 'The cost currency should be the one set on the company,' ' as the product is now opened in another company') product_b.supplier_taxes_id = False product_b.update({'standard_price': 10.0}) #create a purchase order with the product from company B order_b = self.env['purchase.order'].with_company(company_b).create({ 'partner_id': self.partner_a.id, 'order_line': [(0, 0, { 'product_id': product_b.id, 'product_qty': 1, 'product_uom': self.env.ref('uom.product_uom_unit').id, })], }) self.assertEqual(order_b.order_line.price_unit, 10.0, 'The price unit should be 10.0') self.assertEqual(order_b.amount_total_cc, order_b.amount_total, 'Company Total should be 10.0$') def test_discount_and_price_update_on_quantity_change(self): """ Purchase order line price and discount should update accordingly based on quantity """ product = self.env['product.product'].create({ 'name': 'Product', 'standard_price': 12, 'seller_ids': [ Command.create({ 'partner_id': self.partner_a.id, 'min_qty': 10, 'price': 10, 'discount': 10, }), Command.create({ 'partner_id': self.partner_a.id, 'min_qty': 20, 'price': 10, 'discount': 15, }) ] }) purchase_order = self.env['purchase.order'].with_company(self.company_data['company']).create({ 'partner_id': self.partner_a.id, 'order_line': [Command.create({ 'product_id': product.id, 'product_uom': product.uom_po_id.id, })], }) po_line = purchase_order.order_line po_line.product_qty = 10 self.assertEqual(po_line.discount, 10, "first seller should be selected so discount should be 10") self.assertEqual(po_line.price_subtotal, 90, "0.1 discount applied price should be 90") po_line.product_qty = 22 self.assertEqual(po_line.discount, 15, "second seller should be selected so discount should be 15") self.assertEqual(po_line.price_subtotal, 187, "0.15 discount applied price should be 187") po_line.product_qty = 2 self.assertEqual(po_line.discount, 0, "no seller should be selected so discount should be 0") self.assertEqual(po_line.price_subtotal, 24, "No seller") def test_purchase_not_creating_useless_product_vendor(self): """ This test ensures that the product vendor is not created when the product is not set on the purchase order line. """ #create a contact of type contact contact = self.env['res.partner'].create({ 'name': 'Contact', 'type': 'contact', }) #create a contact of type Delivery Address lnked to the contact delivery_address = self.env['res.partner'].create({ 'name': 'Delivery Address', 'type': 'delivery', 'parent_id': contact.id, }) #create a product that use the delivery address as vendor product = self.env['product.product'].create({ 'name': 'Product A', 'seller_ids': [(0, 0, { 'partner_id': delivery_address.id, 'min_qty': 1.0, 'price': 1.0, })] }) #create a purchase order with the delivery address as partner po_form = Form(self.env['purchase.order']) po_form.partner_id = delivery_address with po_form.order_line.new() as po_line: po_line.product_id = product po_line.product_qty = 1.0 po = po_form.save() po.button_confirm() self.assertEqual(po.order_line.product_id.seller_ids.mapped('partner_id'), delivery_address) def test_supplier_list_in_product_with_multicompany(self): """ Check that a different supplier list can be added to a product for each company. """ company_a = self.company_data['company'] company_b = self.company_data_2['company'] product = self.env['product.product'].create({ 'name': 'product_test', }) # create a purchase order in the company A self.env['purchase.order'].with_company(company_a).create({ 'partner_id': self.partner_a.id, 'order_line': [(0, 0, { 'product_id': product.id, 'product_qty': 1, 'product_uom': self.env.ref('uom.product_uom_unit').id, 'price_unit': 1, })], }).button_confirm() self.assertEqual(product.seller_ids[0].partner_id, self.partner_a) self.assertEqual(product.seller_ids[0].company_id, company_a) # switch to the company B self.env['purchase.order'].with_company(company_b).create({ 'partner_id': self.partner_b.id, 'order_line': [(0, 0, { 'product_id': product.id, 'product_qty': 1, 'product_uom': self.env.ref('uom.product_uom_unit').id, 'price_unit': 2, })], }).button_confirm() product = product.with_company(company_b) self.assertEqual(product.seller_ids[0].partner_id, self.partner_b) self.assertEqual(product.seller_ids[0].company_id, company_b) # Switch to the company A and check that the vendor list is still the same product = product.with_company(company_a) self.assertEqual(product.seller_ids[0].partner_id, self.partner_a) self.assertEqual(product.seller_ids[0].company_id, company_a) product._invalidate_cache() self.assertEqual(product.seller_ids[0].partner_id, self.partner_a) self.assertEqual(product.seller_ids[0].company_id, company_a) def test_discount_po_line_vendorpricelist(self): """ Set a discount in VendorPriceList and check if that discount comes in po line and if vendor select a product which is not present in vendorPriceList then it should be created. """ po = Form(self.env['purchase.order']) po.partner_id = self.partner_a with po.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 po_line.discount = 20 po = po.save() po.button_confirm() supplierinfo_id = self.env['product.supplierinfo'].search([ ('partner_id', '=', self.partner_a.id), ('product_tmpl_id', '=', self.product_a.product_tmpl_id.id), ], limit=1) self.assertTrue(supplierinfo_id) self.assertEqual(supplierinfo_id.discount, 20) # checking the same discount self.env['product.supplierinfo'].create({ 'partner_id': self.partner_b.id, 'product_tmpl_id': self.product_a.product_tmpl_id.id, 'min_qty': 1, 'price': 100, 'discount': 30, }) po1 = Form(self.env['purchase.order']) po1.partner_id = self.partner_b with po1.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po1 = po1.save() self.assertEqual(po1.order_line[0].price_unit, 100) self.assertEqual(po1.order_line[0].discount, 30) def test_orderline_supplierinfo_description(self): supplierinfo_vals = { 'partner_id': self.partner_a.id, 'min_qty': 1, 'product_id': self.product_a.id, 'product_tmpl_id': self.product_a.product_tmpl_id.id, } self.env["product.supplierinfo"].create([ { **supplierinfo_vals, 'price': 10, 'product_name': 'Name 1', 'product_code': 'Code 1', }, { **supplierinfo_vals, 'price': 20, 'product_name': 'Name 2', 'product_code': 'Code 2', }, { 'partner_id': self.partner_a.id, 'min_qty': 1, 'product_id': self.product_b.id, 'product_tmpl_id': self.product_b.product_tmpl_id.id, 'price': 5, 'product_name': 'Name 3', 'product_code': 'Code 3', } ]) po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_a with po_form.order_line.new() as line: line.product_id = self.product_a line.product_qty = 1 po = po_form.save() self.assertEqual(po.order_line.name, '[Code 1] Name 1') with po_form.order_line.edit(0) as line: line.product_id = self.product_b po = po_form.save() self.assertEqual(po.order_line.name, '[Code 3] Name 3') def test_purchase_order_line_product_taxes_on_branch(self): """ Check taxes populated on PO lines from product on branch company. Taxes from the branch company should be taken with a fallback on parent company. """ # create the following branch hierarchy: # Parent company # |----> Branch X # |----> Branch XX company = self.env.company branch_x = self.env['res.company'].create({ 'name': 'Branch X', 'country_id': company.country_id.id, 'parent_id': company.id, }) branch_xx = self.env['res.company'].create({ 'name': 'Branch XX', 'country_id': company.country_id.id, 'parent_id': branch_x.id, }) # create taxes for the parent company and its branches tax_groups = self.env['account.tax.group'].create([{ 'name': 'Tax Group', 'company_id': company.id, }, { 'name': 'Tax Group X', 'company_id': branch_x.id, }, { 'name': 'Tax Group XX', 'company_id': branch_xx.id, }]) tax_a = self.env['account.tax'].create({ 'name': 'Tax A', 'type_tax_use': 'purchase', 'amount_type': 'percent', 'amount': 10, 'tax_group_id': tax_groups[0].id, 'company_id': company.id, }) tax_b = self.env['account.tax'].create({ 'name': 'Tax B', 'type_tax_use': 'purchase', 'amount_type': 'percent', 'amount': 15, 'tax_group_id': tax_groups[0].id, 'company_id': company.id, }) tax_x = self.env['account.tax'].create({ 'name': 'Tax X', 'type_tax_use': 'purchase', 'amount_type': 'percent', 'amount': 20, 'tax_group_id': tax_groups[1].id, 'company_id': branch_x.id, }) tax_xx = self.env['account.tax'].create({ 'name': 'Tax XX', 'type_tax_use': 'purchase', 'amount_type': 'percent', 'amount': 25, 'tax_group_id': tax_groups[2].id, 'company_id': branch_xx.id, }) # create several products with different taxes combination product_all_taxes = self.env['product.product'].create({ 'name': 'Product all taxes', 'supplier_taxes_id': [Command.set((tax_a + tax_b + tax_x + tax_xx).ids)], }) product_no_xx_tax = self.env['product.product'].create({ 'name': 'Product no tax from XX', 'supplier_taxes_id': [Command.set((tax_a + tax_b + tax_x).ids)], }) product_no_branch_tax = self.env['product.product'].create({ 'name': 'Product no tax from branch', 'supplier_taxes_id': [Command.set((tax_a + tax_b).ids)], }) product_no_tax = self.env['product.product'].create({ 'name': 'Product no tax', 'supplier_taxes_id': [], }) # create a PO from Branch XX po_form = Form(self.env['purchase.order'].with_company(branch_xx)) po_form.partner_id = self.partner_a # add 4 PO lines with the different products: # - Product all taxes => tax from Branch XX should be set # - Product no tax from XX => tax from Branch X should be set # - Product no tax from branch => 2 taxes from parent company should be set # - Product no tax => no tax should be set with po_form.order_line.new() as line: line.product_id = product_all_taxes with po_form.order_line.new() as line: line.product_id = product_no_xx_tax with po_form.order_line.new() as line: line.product_id = product_no_branch_tax with po_form.order_line.new() as line: line.product_id = product_no_tax po = po_form.save() self.assertRecordValues(po.order_line, [ {'product_id': product_all_taxes.id, 'taxes_id': tax_xx.ids}, {'product_id': product_no_xx_tax.id, 'taxes_id': tax_x.ids}, {'product_id': product_no_branch_tax.id, 'taxes_id': (tax_a + tax_b).ids}, {'product_id': product_no_tax.id, 'taxes_id': []}, ]) @freeze_time('2024-07-08') def test_description_price__date_depending_on_vendor(self): """ Test that the description and the price are updated accordingly when the vendor is changed. """ self.product_a.seller_ids = [ Command.create({ 'partner_id': self.partner_a.id, 'min_qty': 1, 'price': 5, 'product_code': 'Vendor A', 'delay': 5, }), Command.create({ 'partner_id': self.partner_b.id, 'min_qty': 1, 'price': 10, 'product_code': 'Vendor B', 'delay': 6, }), ] self.assertFalse(False) # Create PO and set vendor A po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner_a with po_form.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 10 po = po_form.save() self.assertEqual(po.order_line.price_unit, 5) self.assertEqual(po.order_line.name, '[Vendor A] product_a') self.assertEqual(po.order_line.product_qty, 10) self.assertEqual(po.order_line.date_planned, fields.Datetime.now() + timedelta(days=5)) po.partner_id = self.partner_b self.assertEqual(po.order_line.price_unit, 10) self.assertEqual(po.order_line.name, '[Vendor B] product_a') self.assertEqual(po.order_line.product_qty, 10) self.assertEqual(po.order_line.date_planned, fields.Datetime.now() + timedelta(days=6)) def test_merge_purchase_order(self): PurchaseOrder = self.env['purchase.order'] user_1 = self.env['res.users'].search([])[0] user_2 = self.env['res.users'].search([])[1] payment_term_id_1 = self.env['account.payment.term'].search([])[0] payment_term_id_2 = self.env['account.payment.term'].search([])[1] incoterm_id_1 = self.env['account.incoterms'].search([])[0] incoterm_id_2 = self.env['account.incoterms'].search([])[1] po_1 = Form(PurchaseOrder) po_1.partner_id = self.partner_a po_1.partner_ref = "azure" po_1.origin = "s0003" po_1.user_id = user_1 po_1.payment_term_id = payment_term_id_1 with po_1.order_line.new() as po_line: po_line.product_id = self.product_a po_line.product_qty = 1 po_line.price_unit = 100 po_1 = po_1.save() po_1.incoterm_id = incoterm_id_1 po_2 = Form(PurchaseOrder) po_2.partner_id = self.partner_a po_2.partner_ref = "wood corner" po_2.origin = "s0004" po_2.user_id = user_2 po_2.payment_term_id = payment_term_id_2 with po_2.order_line.new() as po_line_1: po_line_1.product_id = self.product_a po_line_1.product_qty = 5 po_line_1.price_unit = 100 with po_2.order_line.new() as po_line_2: po_line_2.product_id = self.product_b po_line_2.product_qty = 5 po_line_2.price_unit = 500 po_2 = po_2.save() po_2.incoterm_id = incoterm_id_2 with self.assertRaises(UserError) as context: PurchaseOrder.browse([po_1.id]).action_merge() self.assertEqual(context.exception.args[0], "Please select at least two purchase orders with state RFQ and RFQ sent to merge.") selected_purchase_orders = po_1 | po_2 selected_purchase_orders.action_merge() self.assertTrue(po_2.state == 'cancel') self.assertEqual(po_1.order_line[0].product_qty, 6) self.assertEqual(po_1.partner_ref, "azure, wood corner") self.assertEqual(po_1.origin, "s0003, s0004") self.assertEqual(po_1.user_id, user_1) self.assertEqual(po_1.payment_term_id, payment_term_id_1) self.assertEqual(po_1.incoterm_id, incoterm_id_1) def test_vendor_price_by_purchase_order_company(self): """ Test that in case a vendor has multiple price for two company A and B, and the purchase_order.company_id != env.company_id the price of chosen is the one of the company specified in the purchase order """ company_a = self.env.company company_b = self.env['res.company'].create({'name': 'Saucisson Inc.'}) self.env.company = company_a self.product_a.write({ 'seller_ids': [ Command.create({ 'partner_id': self.partner_a, 'product_code': 'A', 'company_id': company_a.id, 'price': 10.0, }), Command.create({ 'partner_id': self.partner_a, 'product_code': 'B', 'company_id': company_b.id, 'price': 15.0, }), ] }) po = self.env['purchase.order'].with_context(allowed_company_ids=[company_a.id, company_b.id]).with_company(company_b).create({ 'partner_id': self.partner_a.id, 'company_id': company_b.id, 'order_line': [Command.create({ 'name': self.product_a.name, 'product_id': self.product_a.id, })], }) self.assertEqual(po.amount_untaxed, 15.0) po.company_id = company_a.id self.assertEqual(po.amount_untaxed, 10.0)