summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwan <wan@odoo.com>2019-08-01 13:41:50 +0000
committerwan <wan@odoo.com>2019-08-02 10:03:44 +0000
commit6edb18be0d58a77c760668c006307ddf7dfd4935 (patch)
tree1c4e557d732bf905ae8eb3e4ce58d7c17e0dcbea
parent49a97305b1f214b7d27f3de3bd0a91b6c551f8cd (diff)
[FIX] point_of_sale: anglo saxon price unit when invoicing before closing the session
Task 2041208 1. I create a product with fifo and real_time valuation (make sure the invoicing policy is 'delivered' and make it available in pos). 2. set the cost of the product to be 5.0 and sale price to be 10.0. 3. I update its inventory and set 5 items. -> total valuation of 25. 4. I change the cost of the product to 1.0. 5. I update again the quantity to 10, making the valuation of the product to 30.0. 6. I configure point of sale to allow invoicing. 7. Open a pos session then sell 7 items of the product (invoice the order). 8. Since the product is fifo, this means that the cost of goods sold is 5 * 5.0 + 2 * 1.0 = 27.0. 9. The correct expense account line should have balance of 27.0. 10. The correct output account line should have balance of -27.0 Followp of https://github.com/odoo/odoo/pull/35335 There was missing the part when an invoice is created from the POS When the invoice is created from action_pos_order_invoice, it only contains invoice_line_ids. The stock valuation lines are present when the account.move is posted through addons/stock_account/models/account_move.py post method. That method requires _stock_account_get_anglo_saxon_price_unit to give the average unit price if it comes from a pos.order, just like it does when a sale.order. closes odoo/odoo#35379 Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
-rw-r--r--addons/point_of_sale/models/__init__.py1
-rw-r--r--addons/point_of_sale/models/account_move.py24
-rw-r--r--addons/point_of_sale/models/pos_order.py1
-rw-r--r--addons/point_of_sale/tests/test_anglo_saxon.py70
4 files changed, 82 insertions, 14 deletions
diff --git a/addons/point_of_sale/models/__init__.py b/addons/point_of_sale/models/__init__.py
index 5cc88b2c693..c7acfe82075 100644
--- a/addons/point_of_sale/models/__init__.py
+++ b/addons/point_of_sale/models/__init__.py
@@ -4,6 +4,7 @@
from . import account_bank_statement
from . import account_journal
from . import account_tax
+from . import account_move
from . import barcode_rule
from . import chart_template
from . import digest
diff --git a/addons/point_of_sale/models/account_move.py b/addons/point_of_sale/models/account_move.py
new file mode 100644
index 00000000000..bc8efd2e5a5
--- /dev/null
+++ b/addons/point_of_sale/models/account_move.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class AccountMove(models.Model):
+ _inherit = 'account.move'
+
+ pos_order_ids = fields.One2many('pos.order', 'account_move')
+
+
+class AccountMoveLine(models.Model):
+ _inherit = 'account.move.line'
+
+ def _stock_account_get_anglo_saxon_price_unit(self):
+ self.ensure_one()
+ if not self.product_id:
+ return self.price_unit
+ price_unit = super(AccountMoveLine, self)._stock_account_get_anglo_saxon_price_unit()
+ order = self.move_id.pos_order_ids
+ if order:
+ price_unit = - order._get_pos_anglo_saxon_price_unit(self.product_id, self.move_id.partner_id.id, self.quantity)
+ return price_unit
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index ed3b41420bc..ce992ea4fcf 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -650,6 +650,7 @@ class PosOrder(models.Model):
# considering partner's sale pricelist's currency
'currency_id': order.pricelist_id.currency_id.id,
'invoice_user_id': order.user_id.id,
+ 'invoice_date': fields.Date.today(),
'fiscal_position_id': order.fiscal_position_id.id,
'invoice_line_ids': [(0, None, order._prepare_invoice_line(line)) for line in order.lines],
}
diff --git a/addons/point_of_sale/tests/test_anglo_saxon.py b/addons/point_of_sale/tests/test_anglo_saxon.py
index aea6a6c44bc..b56f9217697 100644
--- a/addons/point_of_sale/tests/test_anglo_saxon.py
+++ b/addons/point_of_sale/tests/test_anglo_saxon.py
@@ -20,14 +20,16 @@ class TestAngloSaxonCommon(common.TransactionCase):
self.partner = self.env.ref('base.res_partner_1')
self.category = self.env.ref('product.product_category_1')
self.category = self.category.copy({'name': 'New category','property_valuation': 'real_time'})
- account_type_rcv = self.env['account.account.type'].create({'name': 'RCV type', 'type': 'receivable'})
- account_type_oth = self.env['account.account.type'].create({'name': 'RCV type', 'type': 'other'})
+ account_type_rcv = self.env.ref('account.data_account_type_receivable')
+ account_type_inc = self.env.ref('account.data_account_type_revenue')
+ account_type_exp = self.env.ref('account.data_account_type_expenses')
self.account = self.env['account.account'].create({'name': 'Receivable', 'code': 'RCV00' , 'user_type_id': account_type_rcv.id, 'reconcile': True})
- account_expense = self.env['account.account'].create({'name': 'Expense', 'code': 'EXP00' , 'user_type_id': account_type_oth.id, 'reconcile': True})
- account_output = self.env['account.account'].create({'name': 'Output', 'code': 'OUT00' , 'user_type_id': account_type_oth.id, 'reconcile': True})
- account_valuation = self.env['account.account'].create({'name': 'Valuation', 'code': 'STV00', 'user_type_id': account_type_oth.id, 'reconcile': True})
+ account_expense = self.env['account.account'].create({'name': 'Expense', 'code': 'EXP00' , 'user_type_id': account_type_exp.id, 'reconcile': True})
+ account_income = self.env['account.account'].create({'name': 'Income', 'code': 'INC00' , 'user_type_id': account_type_inc.id, 'reconcile': True})
+ account_output = self.env['account.account'].create({'name': 'Output', 'code': 'OUT00' , 'user_type_id': account_type_exp.id, 'reconcile': True})
+ account_valuation = self.env['account.account'].create({'name': 'Valuation', 'code': 'STV00', 'user_type_id': account_type_exp.id, 'reconcile': True})
self.partner.property_account_receivable_id = self.account
- self.category.property_account_income_categ_id = self.account
+ self.category.property_account_income_categ_id = account_income
self.category.property_account_expense_categ_id = account_expense
self.category.property_stock_account_input_categ_id = self.account
self.category.property_stock_account_output_categ_id = account_output
@@ -39,11 +41,12 @@ class TestAngloSaxonCommon(common.TransactionCase):
self.company.anglo_saxon_accounting = True
self.product.categ_id = self.category
self.product.property_account_expense_id = account_expense
- self.product.property_account_income_id = self.account
+ self.product.property_account_income_id = account_income
sale_journal = self.env['account.journal'].create({'name': 'POS journal', 'type': 'sale', 'code': 'POS00'})
self.pos_config.journal_id = sale_journal
self.cash_journal = self.env['account.journal'].create({'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'})
- self.pos_config.invoice_journal_id = False
+ self.sale_journal = self.env['account.journal'].create({'name': 'SALE journal', 'type': 'sale', 'code': 'INV00'})
+ self.pos_config.invoice_journal_id = self.sale_journal
self.pos_config.journal_ids = [self.cash_journal.id]
@@ -116,7 +119,10 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
self.assertEqual(aml_output.credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_expense.debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
- def test_2041208(self):
+ def _prepare_pos_order(self):
+ """ Set the cost method of `self.product` as FIFO. Receive 5@5 and 5@1 and
+ create a `pos.order` record selling 7 units @ 450.
+ """
# check fifo Costing Method of product.category
self.product.categ_id.property_cost_method = 'fifo'
self.product.standard_price = 5.0
@@ -137,7 +143,7 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
self.pos_config.open_session_cb()
self.pos_config.module_account = True
- self.pos_order_pos0 = self.PosOrder.create({
+ pos_order_values = {
'company_id': self.company.id,
'partner_id': self.partner.id,
'pricelist_id': self.company.partner_id.property_product_pricelist.id,
@@ -155,19 +161,55 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
'amount_tax': 0,
'amount_paid': 0,
'amount_return': 0,
+ }
+
+ return self.PosOrder.create(pos_order_values)
+
+ def test_fifo_valuation_no_invoice(self):
+ """Register a payment and validate a session after selling a fifo
+ product without making an invoice for the customer"""
+ pos_order_pos0 = self._prepare_pos_order()
+ context_make_payment = {"active_ids": [pos_order_pos0.id], "active_id": pos_order_pos0.id}
+ self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
+ 'amount': 7 * 450.0,
})
- context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
+ # register the payment
+ context_payment = {'active_id': pos_order_pos0.id}
+ self.pos_make_payment_0.with_context(context_payment).check()
+
+ # validate the session
+ current_session_id = self.pos_config.current_session_id
+ current_session_id.action_pos_session_validate()
+
+ # check the anglo saxon move lines
+ line = pos_order_pos0.account_move.line_ids.filtered(lambda l: l.debit and l.account_id == self.category.property_account_expense_categ_id)
+ self.assertEqual(pos_order_pos0.account_move.journal_id, self.pos_config.journal_id)
+ self.assertEqual(line.debit, 27, 'As it is a fifo product, the move\'s value should be 5*5 + 2*1')
+
+ def test_fifo_valuation_with_invoice(self):
+ """Register a payment and validate a session after selling a fifo
+ product and make an invoice for the customer"""
+ pos_order_pos0 = self._prepare_pos_order()
+ context_make_payment = {"active_ids": [pos_order_pos0.id], "active_id": pos_order_pos0.id}
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
'amount': 7 * 450.0,
'journal_id': self.cash_journal.id,
})
- # I click on the validate button to register the payment.
- context_payment = {'active_id': self.pos_order_pos0.id}
+ # register the payment
+ context_payment = {'active_id': pos_order_pos0.id}
self.pos_make_payment_0.with_context(context_payment).check()
+
+ # Create the customer invoice
+ pos_order_pos0.action_pos_order_invoice()
+ pos_order_pos0.account_move.post()
+
+ # validate the session
current_session_id = self.pos_config.current_session_id
current_session_id.action_pos_session_validate()
- line = self.pos_order_pos0.account_move.line_ids.filtered(lambda l: l.debit and l.account_id == self.category.property_account_expense_categ_id)
+ # check the anglo saxon move lines
+ line = pos_order_pos0.account_move.line_ids.filtered(lambda l: l.debit and l.account_id == self.category.property_account_expense_categ_id)
+ self.assertEqual(pos_order_pos0.account_move.journal_id, self.pos_config.invoice_journal_id)
self.assertEqual(line.debit, 27, 'As it is a fifo product, the move\'s value should be 5*5 + 2*1')