[FIX] point_of_sale: ship later with multiple expense account

Current behavior:
If you had 2 products with different expense account and using real-time
inventory valuation, there was an error when validating the picking.
This was happening because move_vals we were trying to assign multiple
moves to one pos_order here https://github.com/odoo/odoo/blob/95cec6ea3daebce6491cc2a8a69d9688322989ba/addons/point_of_sale/models/stock_picking.py#L155

The account move is actually reserved for the invoicing of the order.
So we just need to remove that line.

Steps to reproduce:
- Create a product with expense account A
- Create a product with expense account B
- Make sure both products are set to real-time inventory valuation
- Activate ship later in the PoS
- Open the PoS and add both products to the order
- Validate the order with ship later and no invoice
- Close the PoS and try to validate the picking of the order.

opw-3428033

closes odoo/odoo#136254

X-original-commit: a2c8ea0adbd93cb9d178977f73e93492e84dfec3
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
Signed-off-by: Robin Engels (roen) <roen@odoo.com>
This commit is contained in:
roen-odoo
2023-09-22 11:56:05 +00:00
parent f60be08753
commit f022fffc3a
4 changed files with 99 additions and 14 deletions
+2 -1
View File
@@ -1468,7 +1468,8 @@ class PosSession(models.Model):
# we are querying over the account.move.line because its 'ref' is indexed.
# And yes, we are only concern for split bank payment methods.
diff_lines_ref = [self._get_diff_account_move_ref(pm) for pm in self.payment_method_ids if pm.type == 'bank' and pm.split_transactions]
return self.env['account.move.line'].search([('ref', 'in', diff_lines_ref)]).mapped('move_id')
cost_move_lines = ['pos_order_'+str(rec.id) for rec in self.order_ids]
return self.env['account.move.line'].search([('ref', 'in', diff_lines_ref + cost_move_lines)]).mapped('move_id')
def _get_related_account_moves(self):
pickings = self.picking_ids | self.order_ids.mapped('picking_ids')
+1 -2
View File
@@ -136,7 +136,7 @@ class StockPicking(models.Model):
move_vals.append({
'journal_id': rec.pos_order_id.sale_journal.id,
'date': rec.pos_order_id.date_order,
'ref': rec.pos_order_id.name,
'ref': 'pos_order_'+str(rec.pos_order_id.id),
'line_ids': [
(0, 0, {
'name': rec.pos_order_id.name,
@@ -153,7 +153,6 @@ class StockPicking(models.Model):
],
})
move = self.env['account.move'].create(move_vals)
rec.pos_order_id.write({'account_move': move.id})
move.action_post()
return res
+11 -11
View File
@@ -289,18 +289,18 @@ class TestAngloSaxonFlow(TestAngloSaxonCommon):
self.assertEqual(len(aml_output), 3, "There should be 3 output account move lines")
# 2 moves in POS journal (Pos order + manual entry at delivery)
self.assertEqual(aml_output[:2].move_id.journal_id, self.pos_config.journal_id)
self.assertEqual(len(aml_output.move_id.filtered(lambda l: l.journal_id == self.pos_config.journal_id)), 2)
# 1 move in stock journal (delivery from stock layers)
self.assertEqual(aml_output[2].move_id.journal_id, self.category.property_stock_journal)
self.assertEqual(len(aml_output.move_id.filtered(lambda l: l.journal_id == self.category.property_stock_journal)), 1)
#Check the lines created after the picking validation
self.assertEqual(aml_output[0].credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_output[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_output[2].debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_output[2].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_expense[0].debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_expense[0].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
#Check the lines created by the PoS session
self.assertEqual(aml_output[1].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_output[2].credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_output[2].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
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[1].debit, self.product.standard_price, "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")
#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[0].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
self.assertEqual(aml_expense[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
@@ -1692,3 +1692,88 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
aml = session_id.move_id.line_ids.filtered(lambda x: x.account_id == self.account1 and x.tax_ids == self.tax1)
self.assertEqual(aml.price_total, 220)
self.assertEqual(aml.price_subtotal, 200)
def test_multi_exp_account_real_time(self):
#Create a real time valuation product category
self.real_time_categ = self.env['product.category'].create({
'name': 'test category',
'parent_id': False,
'property_cost_method': 'fifo',
'property_valuation': 'real_time',
})
#Create 2 accounts to be used for each product
self.account1 = self.env['account.account'].create({
'name': 'Account 1',
'code': 'AC1',
'reconcile': True,
'account_type': 'expense',
})
self.account2 = self.env['account.account'].create({
'name': 'Account 1',
'code': 'AC2',
'reconcile': True,
'account_type': 'expense',
})
self.product_a = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'categ_id': self.real_time_categ.id,
'property_account_expense_id': self.account1.id,
'property_account_income_id': self.account1.id,
})
self.product_b = self.env['product.product'].create({
'name': 'Product B',
'type': 'product',
'categ_id': self.real_time_categ.id,
'property_account_expense_id': self.account2.id,
'property_account_income_id': self.account2.id,
})
#Create an order with the 2 products
self.pos_config.open_ui()
order = self.PosOrder.create({
'company_id': self.env.company.id,
'session_id': self.pos_config.current_session_id.id,
'partner_id': self.partner1.id,
'lines': [(0, 0, {
'name': "OL/0001",
'product_id': self.product_a.id,
'price_unit': 100,
'discount': 0,
'qty': 1,
'tax_ids': [],
'price_subtotal': 100,
'price_subtotal_incl': 100,
}), (0, 0, {
'name': "OL/0002",
'product_id': self.product_b.id,
'price_unit': 100,
'discount': 0,
'qty': 1,
'tax_ids': [],
'price_subtotal': 100,
'price_subtotal_incl': 100,
})],
'pricelist_id': self.pos_config.pricelist_id.id,
'amount_paid': 200.0,
'amount_total': 200.0,
'amount_tax': 0.0,
'amount_return': 0.0,
'to_invoice': False,
'shipping_date': fields.Date.today(),
})
#make payment
payment_context = {"active_ids": order.ids, "active_id": order.id}
order_payment = self.PosMakePayment.with_context(**payment_context).create({
'amount': order.amount_total,
'payment_method_id': self.cash_payment_method.id
})
order_payment.with_context(**payment_context).check()
self.pos_config.current_session_id.action_pos_session_closing_control()
order.picking_ids._action_done()
moves = self.env['account.move'].search([('ref', '=', f'pos_order_{order.id}')])
self.assertEqual(len(moves), 2)