[FIX] point_of_sale: create account move for shiplater pos order
Current behavior: When using FIFO/AVCO and automated valuation, the accounting entries for PoS orders where not correct if the ship later function was used and the order was not invoiced. The COGS entries were created with an amount of 0. But when the shipping was done nothing was done to correct the entries. Steps to reproduce: - Make sure you are using anglo saxon accounting - Create a product with automated valuation and FIFO/AVCO - Create a PoS order with the product - Validate the order using the ship later option but do not invoice it - The accounting entries for the expense are created with an amount of 0 (wich makes sense because the product is not shipped yet) - Validate the picking - The accounting entries is still the same. opw-3027579 closes odoo/odoo#116045 X-original-commit: 513c32b04aa6c06d58125ec8c4fb1b818f4a52e9 Signed-off-by: Trinh Jacky (trj) <trj@odoo.com> Signed-off-by: Engels Robin (roen) <roen@odoo.com>
This commit is contained in:
@@ -771,7 +771,7 @@ class PosSession(models.Model):
|
||||
signed_product_qty = move.product_qty
|
||||
if move._is_in():
|
||||
signed_product_qty *= -1
|
||||
amount = signed_product_qty * move.product_id._compute_average_price(0, move.product_qty, move)
|
||||
amount = signed_product_qty * move.product_id._compute_average_price(0, move.quantity_done, move)
|
||||
stock_expense[exp_key] = self._update_amounts(stock_expense[exp_key], {'amount': amount}, move.picking_id.date, force_company_currency=True)
|
||||
if move._is_in():
|
||||
stock_return[out_key] = self._update_amounts(stock_return[out_key], {'amount': amount}, move.picking_id.date, force_company_currency=True)
|
||||
@@ -800,7 +800,7 @@ class PosSession(models.Model):
|
||||
signed_product_qty = move.product_qty
|
||||
if move._is_in():
|
||||
signed_product_qty *= -1
|
||||
amount = signed_product_qty * move.product_id._compute_average_price(0, move.product_qty, move)
|
||||
amount = signed_product_qty * move.product_id._compute_average_price(0, move.quantity_done, move)
|
||||
stock_expense[exp_key] = self._update_amounts(stock_expense[exp_key], {'amount': amount}, move.picking_id.date, force_company_currency=True)
|
||||
if move._is_in():
|
||||
stock_return[out_key] = self._update_amounts(stock_return[out_key], {'amount': amount}, move.picking_id.date, force_company_currency=True)
|
||||
|
||||
@@ -100,6 +100,33 @@ class StockPicking(models.Model):
|
||||
pickings = self.filtered(lambda p: p.picking_type_id != p.picking_type_id.warehouse_id.pos_type_id)
|
||||
return super(StockPicking, pickings)._send_confirmation_email()
|
||||
|
||||
def _action_done(self):
|
||||
res = super()._action_done()
|
||||
if self.pos_order_id.shipping_date and not self.pos_order_id.to_invoice:
|
||||
order_cost = sum(line.total_cost for line in self.pos_order_id.lines)
|
||||
move_vals = {
|
||||
'journal_id': self.pos_order_id.sale_journal.id,
|
||||
'date': self.pos_order_id.date_order,
|
||||
'ref': self.pos_order_id.name,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'name': self.pos_order_id.name,
|
||||
'account_id': self.product_id.categ_id.property_account_income_categ_id.id,
|
||||
'debit': order_cost,
|
||||
'credit': 0.0,
|
||||
}),
|
||||
(0, 0, {
|
||||
'name': self.pos_order_id.name,
|
||||
'account_id': self.product_id.categ_id.property_account_expense_categ_id.id,
|
||||
'debit': 0.0,
|
||||
'credit': order_cost,
|
||||
})
|
||||
]
|
||||
}
|
||||
move = self.env['account.move'].create(move_vals)
|
||||
self.pos_order_id.write({'account_move': move.id})
|
||||
move.action_post()
|
||||
return res
|
||||
|
||||
class StockPickingType(models.Model):
|
||||
_inherit = 'stock.picking.type'
|
||||
@@ -111,7 +138,6 @@ class StockPickingType(models.Model):
|
||||
if picking_type == picking_type.warehouse_id.pos_type_id:
|
||||
picking_type.hide_reservation_method = True
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = 'procurement.group'
|
||||
|
||||
|
||||
@@ -224,3 +224,72 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
|
||||
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')
|
||||
|
||||
def test_cogs_with_ship_later_no_invoicing(self):
|
||||
# This test will check that the correct journal entries are created when a product in real time valuation
|
||||
# is sold using the ship later option and no invoice is created in a company using anglo-saxon
|
||||
self.pos_config.open_ui()
|
||||
current_session = self.pos_config.current_session_id
|
||||
self.cash_journal.loss_account_id = self.account
|
||||
current_session.set_cashbox_pos(0, None)
|
||||
|
||||
# I create a PoS order with 1 unit of New product at 450 EUR
|
||||
self.pos_order_pos0 = self.PosOrder.create({
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'pricelist_id': self.company.partner_id.property_product_pricelist.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'to_invoice': False,
|
||||
'shipping_date': '2023-01-01',
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 450,
|
||||
'discount': 0.0,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 450,
|
||||
'price_subtotal_incl': 450,
|
||||
})],
|
||||
'amount_total': 450,
|
||||
'amount_tax': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
})
|
||||
|
||||
# I make a payment to fully pay the order
|
||||
context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
|
||||
# I click on the validate button to register the payment.
|
||||
context_payment = {'active_id': self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# I close the current session to generate the journal entries
|
||||
current_session_id = self.pos_config.current_session_id
|
||||
current_session_id.post_closing_cash_details(450.0)
|
||||
current_session_id.close_session_from_ui()
|
||||
self.assertEqual(current_session_id.state, 'closed', 'Check that session is closed')
|
||||
|
||||
current_session.picking_ids.move_ids_without_package.quantity_done = 1
|
||||
current_session.picking_ids.button_validate()
|
||||
|
||||
# I test that the generated journal entries are correct.
|
||||
account_output = self.category.property_stock_account_output_categ_id
|
||||
expense_account = self.category.property_account_expense_categ_id
|
||||
aml = current_session._get_related_account_moves().line_ids
|
||||
aml_output = aml.filtered(lambda l: l.account_id.id == account_output.id)
|
||||
aml_expense = aml.filtered(lambda l: l.account_id.id == expense_account.id)
|
||||
|
||||
#Check the lines created after the picking validation
|
||||
self.assertEqual(aml_output[1].debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[1].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[0].credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
#Check the lines created by the PoS session
|
||||
self.assertEqual(aml_output[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[0].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[1].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[1].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
|
||||
Reference in New Issue
Block a user