[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>
This commit is contained in:
wan
2019-08-02 10:03:44 +00:00
parent 49a97305b1
commit 6edb18be0d
4 changed files with 82 additions and 14 deletions
+1
View File
@@ -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
@@ -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
+1
View File
@@ -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],
}
+56 -14
View File
@@ -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')