# -*- 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 from odoo.tests.common import Form @tagged('post_install', '-at_install') class TestPurchaseToInvoice(AccountTestInvoicingCommon): @classmethod def setUpClass(cls): super(TestPurchaseToInvoice, cls).setUpClass() uom_unit = cls.env.ref('uom.product_uom_unit') uom_hour = cls.env.ref('uom.product_uom_hour') cls.product_order = cls.env['product.product'].create({ 'name': "Zed+ Antivirus", 'standard_price': 235.0, 'list_price': 280.0, 'type': 'consu', 'uom_id': uom_unit.id, 'uom_po_id': uom_unit.id, 'purchase_method': 'purchase', 'default_code': 'PROD_ORDER', 'taxes_id': False, }) cls.service_deliver = cls.env['product.product'].create({ 'name': "Cost-plus Contract", 'standard_price': 200.0, 'list_price': 180.0, 'type': 'service', 'uom_id': uom_unit.id, 'uom_po_id': uom_unit.id, 'purchase_method': 'receive', 'default_code': 'SERV_DEL', 'taxes_id': False, }) cls.service_order = cls.env['product.product'].create({ 'name': "Prepaid Consulting", 'standard_price': 40.0, 'list_price': 90.0, 'type': 'service', 'uom_id': uom_hour.id, 'uom_po_id': uom_hour.id, 'purchase_method': 'purchase', 'default_code': 'PRE-PAID', 'taxes_id': False, }) cls.product_deliver = cls.env['product.product'].create({ 'name': "Switch, 24 ports", 'standard_price': 55.0, 'list_price': 70.0, 'type': 'consu', 'uom_id': uom_unit.id, 'uom_po_id': uom_unit.id, 'purchase_method': 'receive', 'default_code': 'PROD_DEL', 'taxes_id': False, }) def test_vendor_bill_delivered(self): """Test if a order of product invoiced by delivered quantity can be correctly invoiced.""" purchase_order = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, }) PurchaseOrderLine = self.env['purchase.order.line'].with_context(tracking_disable=True) pol_prod_deliver = PurchaseOrderLine.create({ 'name': self.product_deliver.name, 'product_id': self.product_deliver.id, 'product_qty': 10.0, 'product_uom': self.product_deliver.uom_id.id, 'price_unit': self.product_deliver.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) pol_serv_deliver = PurchaseOrderLine.create({ 'name': self.service_deliver.name, 'product_id': self.service_deliver.id, 'product_qty': 10.0, 'product_uom': self.service_deliver.uom_id.id, 'price_unit': self.service_deliver.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) purchase_order.button_confirm() self.assertEqual(purchase_order.invoice_status, "no") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 0.0) purchase_order.order_line.qty_received = 5 self.assertEqual(purchase_order.invoice_status, "to invoice") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 5) self.assertEqual(line.qty_invoiced, 0.0) purchase_order.action_create_invoice() self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 5) def test_vendor_bill_ordered(self): """Test if a order of product invoiced by ordered quantity can be correctly invoiced.""" purchase_order = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, }) PurchaseOrderLine = self.env['purchase.order.line'].with_context(tracking_disable=True) pol_prod_order = PurchaseOrderLine.create({ 'name': self.product_order.name, 'product_id': self.product_order.id, 'product_qty': 10.0, 'product_uom': self.product_order.uom_id.id, 'price_unit': self.product_order.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) pol_serv_order = PurchaseOrderLine.create({ 'name': self.service_order.name, 'product_id': self.service_order.id, 'product_qty': 10.0, 'product_uom': self.service_order.uom_id.id, 'price_unit': self.service_order.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) purchase_order.button_confirm() self.assertEqual(purchase_order.invoice_status, "to invoice") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 10) self.assertEqual(line.qty_invoiced, 0.0) purchase_order.order_line.qty_received = 5 self.assertEqual(purchase_order.invoice_status, "to invoice") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 10) self.assertEqual(line.qty_invoiced, 0.0) purchase_order.action_create_invoice() self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 10) def test_vendor_bill_delivered_return(self): """Test when return product, a order of product invoiced by delivered quantity can be correctly invoiced.""" purchase_order = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, }) PurchaseOrderLine = self.env['purchase.order.line'].with_context(tracking_disable=True) pol_prod_deliver = PurchaseOrderLine.create({ 'name': self.product_deliver.name, 'product_id': self.product_deliver.id, 'product_qty': 10.0, 'product_uom': self.product_deliver.uom_id.id, 'price_unit': self.product_deliver.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) pol_serv_deliver = PurchaseOrderLine.create({ 'name': self.service_deliver.name, 'product_id': self.service_deliver.id, 'product_qty': 10.0, 'product_uom': self.service_deliver.uom_id.id, 'price_unit': self.service_deliver.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) purchase_order.button_confirm() purchase_order.order_line.qty_received = 10 purchase_order.action_create_invoice() self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 10) purchase_order.order_line.qty_received = 5 self.assertEqual(purchase_order.invoice_status, "to invoice") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, -5) self.assertEqual(line.qty_invoiced, 10) purchase_order.action_create_invoice() self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 5) def test_vendor_bill_ordered_return(self): """Test when return product, a order of product invoiced by ordered quantity can be correctly invoiced.""" purchase_order = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, }) PurchaseOrderLine = self.env['purchase.order.line'].with_context(tracking_disable=True) pol_prod_order = PurchaseOrderLine.create({ 'name': self.product_order.name, 'product_id': self.product_order.id, 'product_qty': 10.0, 'product_uom': self.product_order.uom_id.id, 'price_unit': self.product_order.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) pol_serv_order = PurchaseOrderLine.create({ 'name': self.service_order.name, 'product_id': self.service_order.id, 'product_qty': 10.0, 'product_uom': self.service_order.uom_id.id, 'price_unit': self.service_order.list_price, 'order_id': purchase_order.id, 'taxes_id': False, }) purchase_order.button_confirm() purchase_order.order_line.qty_received = 10 purchase_order.action_create_invoice() self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 10) purchase_order.order_line.qty_received = 5 self.assertEqual(purchase_order.invoice_status, "invoiced") for line in purchase_order.order_line: self.assertEqual(line.qty_to_invoice, 0.0) self.assertEqual(line.qty_invoiced, 10) def test_vendor_severals_bills_and_multicurrency(self): """ This test ensures that, when adding several PO to a bill, if they are expressed with different currency, the amount of each AML is converted to the bill's currency """ PurchaseOrderLine = self.env['purchase.order.line'] PurchaseBillUnion = self.env['purchase.bill.union'] ResCurrencyRate = self.env['res.currency.rate'] usd = self.env.ref('base.USD') eur = self.env.ref('base.EUR') purchase_orders = [] ResCurrencyRate.create({'currency_id': usd.id, 'rate': 1}) ResCurrencyRate.create({'currency_id': eur.id, 'rate': 2}) for currency in [usd, eur]: po = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, 'currency_id': currency.id, }) pol_prod_order = PurchaseOrderLine.create({ 'name': self.product_order.name, 'product_id': self.product_order.id, 'product_qty': 1, 'product_uom': self.product_order.uom_id.id, 'price_unit': 1000, 'order_id': po.id, 'taxes_id': False, }) po.button_confirm() pol_prod_order.write({'qty_received': 1}) purchase_orders.append(po) move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice')) move_form.purchase_vendor_bill_id = PurchaseBillUnion.browse(-purchase_orders[0].id) move_form.purchase_vendor_bill_id = PurchaseBillUnion.browse(-purchase_orders[1].id) move = move_form.save() amls = move.line_ids.filtered(lambda l: l.account_internal_group == 'expense') self.assertEqual(move.amount_total, 1500) self.assertEqual(move.currency_id, usd) self.assertEqual(len(amls), 2) self.assertEqual(amls[0].amount_currency, 1000) self.assertEqual(amls[1].amount_currency, 500) def test_product_price_decimal_accuracy(self): self.env['ir.model.data'].xmlid_to_object('product.decimal_price').digits = 3 self.env.company.currency_id.rounding = 0.01 po = self.env['purchase.order'].with_context(tracking_disable=True).create({ 'partner_id': self.partner_a.id, 'order_line': [(0, 0, { 'name': self.product_a.name, 'product_id': self.product_a.id, 'product_qty': 12, 'product_uom': self.product_a.uom_id.id, 'price_unit': 0.001, 'taxes_id': False, })] }) po.button_confirm() po.order_line.qty_received = 12 move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice')) move_form.purchase_vendor_bill_id = self.env['purchase.bill.union'].browse(-po.id) move = move_form.save() self.assertEqual(move.amount_total, 0.01)