[FIX] point_of_sale: avoid to create new pickings after session closing
steps to reproduce: - configure your POS with anglosaxon accounting and "Update quantities in stock" at session closing and enable "Use QR code on ticket" - open the POS, sell a storable product and close the session - scan the QR code on the ticket to create an invoice - check the pickings on the session form view before this commit: - 2 pickings are created, one at session closing and one from the invoice after this commit: - if the session is closed, do not create a new picking opw-3592418 closes odoo/odoo#146077 X-original-commit: 486fa23e586c1dae490ffe0a91138d6f6dc6d824 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com> Signed-off-by: Nicolas Danhier (nda) <nda@odoo.com>
This commit is contained in:
@@ -890,7 +890,7 @@ class PosOrder(models.Model):
|
||||
raise UserError(_("You cannot invoice orders belonging to different companies."))
|
||||
self.write({'to_invoice': True})
|
||||
res = self._generate_pos_order_invoice()
|
||||
if self.company_id.anglo_saxon_accounting and self.session_id.update_stock_at_closing:
|
||||
if self.company_id.anglo_saxon_accounting and self.session_id.update_stock_at_closing and self.session_id.state != 'closed':
|
||||
self._create_order_picking()
|
||||
return res
|
||||
|
||||
|
||||
@@ -23,6 +23,58 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
||||
untax = res['total_excluded']
|
||||
return untax, sum(tax.get('amount', 0.0) for tax in res['taxes'])
|
||||
|
||||
def _create_pos_order_for_postponed_invoicing(self):
|
||||
# Create the order on the first of january.
|
||||
with freeze_time('2020-01-01'):
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'Dummy product',
|
||||
'type': 'product',
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
'taxes_id': self.tax_sale_a.ids,
|
||||
})
|
||||
self.pos_config.open_ui()
|
||||
pos_session = self.pos_config.current_session_id
|
||||
untax, atax = self.compute_tax(product, 500, 1)
|
||||
pos_order_data = {
|
||||
'data': {
|
||||
'amount_paid': untax + atax,
|
||||
'amount_return': 0,
|
||||
'amount_tax': atax,
|
||||
'amount_total': untax + atax,
|
||||
'date_order': fields.Datetime.to_string(fields.Datetime.now()),
|
||||
'fiscal_position_id': False,
|
||||
'lines': [(0, 0, {
|
||||
'discount': 0,
|
||||
'id': 42,
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': 500.0,
|
||||
'product_id': product.id,
|
||||
'price_subtotal': 500.0,
|
||||
'price_subtotal_incl': 575.0,
|
||||
'qty': 1,
|
||||
'tax_ids': [(6, 0, product.taxes_id.ids)]
|
||||
})],
|
||||
'name': 'Order 12345-123-1234',
|
||||
'partner_id': False,
|
||||
'pos_session_id': pos_session.id,
|
||||
'sequence_number': 2,
|
||||
'statement_ids': [(0, 0, {
|
||||
'amount': untax + atax,
|
||||
'name': fields.Datetime.now(),
|
||||
'payment_method_id': self.cash_payment_method.id
|
||||
})],
|
||||
'uid': '12345-123-1234',
|
||||
'user_id': self.env.uid
|
||||
},
|
||||
'id': '12345-123-1234',
|
||||
'to_invoice': False
|
||||
}
|
||||
pos_order_id = self.PosOrder.create_from_ui([pos_order_data])[0]['id']
|
||||
pos_order = self.env['pos.order'].browse(pos_order_id)
|
||||
# End the session. The order has been created without any invoice.
|
||||
self.pos_config.current_session_id.action_pos_session_closing_control()
|
||||
return pos_order
|
||||
|
||||
def test_order_refund(self):
|
||||
self.pos_config.open_ui()
|
||||
current_session = self.pos_config.current_session_id
|
||||
@@ -1175,55 +1227,9 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
||||
- Reconcile the receivable lines from the created misc entry with the ones from the created payment(s)
|
||||
"""
|
||||
# Create the order on the first of january.
|
||||
with freeze_time('2020-01-01'):
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'Dummy product',
|
||||
'type': 'product',
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
'taxes_id': self.tax_sale_a.ids,
|
||||
})
|
||||
self.pos_config.open_ui()
|
||||
pos_session = self.pos_config.current_session_id
|
||||
untax, atax = self.compute_tax(product, 500, 1)
|
||||
pos_order_data = {
|
||||
'data': {
|
||||
'amount_paid': untax + atax,
|
||||
'amount_return': 0,
|
||||
'amount_tax': atax,
|
||||
'amount_total': untax + atax,
|
||||
'date_order': fields.Datetime.to_string(fields.Datetime.now()),
|
||||
'fiscal_position_id': False,
|
||||
'lines': [(0, 0, {
|
||||
'discount': 0,
|
||||
'id': 42,
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': 500.0,
|
||||
'product_id': product.id,
|
||||
'price_subtotal': 500.0,
|
||||
'price_subtotal_incl': 575.0,
|
||||
'qty': 1,
|
||||
'tax_ids': [(6, 0, product.taxes_id.ids)]
|
||||
})],
|
||||
'name': 'Order 12345-123-1234',
|
||||
'partner_id': False,
|
||||
'pos_session_id': pos_session.id,
|
||||
'sequence_number': 2,
|
||||
'statement_ids': [(0, 0, {
|
||||
'amount': untax + atax,
|
||||
'name': fields.Datetime.now(),
|
||||
'payment_method_id': self.cash_payment_method.id
|
||||
})],
|
||||
'uid': '12345-123-1234',
|
||||
'user_id': self.env.uid
|
||||
},
|
||||
'id': '12345-123-1234',
|
||||
'to_invoice': False
|
||||
}
|
||||
pos_order_id = self.PosOrder.create_from_ui([pos_order_data])[0]['id']
|
||||
pos_order = self.env['pos.order'].browse(pos_order_id)
|
||||
# End the session. The order has been created without any invoice.
|
||||
self.pos_config.current_session_id.action_pos_session_closing_control()
|
||||
self.assertFalse(pos_order.account_move.exists())
|
||||
pos_order = self._create_pos_order_for_postponed_invoicing()
|
||||
self.assertFalse(pos_order.account_move.exists())
|
||||
|
||||
# Client is back on the 3rd, asks for an invoice.
|
||||
with freeze_time('2020-01-03'):
|
||||
# We set the partner on the order
|
||||
@@ -1259,6 +1265,23 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
||||
statement_receivable_line = statement.line_ids.filtered(lambda line: line.account_id == self.company_data['default_account_receivable'] and line.name == pos_order.session_id.name) # Because the payment method use the default receivable
|
||||
self.assertEqual(closing_entry_receivable_line.matching_number, statement_receivable_line.matching_number)
|
||||
|
||||
def test_sale_order_postponed_invoicing_anglosaxon(self):
|
||||
""" Test the flow of creating an invoice later, after the POS session has been closed and everything has been processed
|
||||
in the case of anglo-saxon accounting.
|
||||
"""
|
||||
self.env.company.anglo_saxon_accounting = True
|
||||
self.env.company.point_of_sale_update_stock_quantities = 'closing'
|
||||
pos_order = self._create_pos_order_for_postponed_invoicing()
|
||||
|
||||
with freeze_time('2020-01-03'):
|
||||
# We set the partner on the order
|
||||
pos_order.partner_id = self.partner1.id
|
||||
pos_order.action_pos_order_invoice()
|
||||
|
||||
picking_ids = pos_order.session_id.picking_ids
|
||||
# only one product is leaving stock
|
||||
self.assertEqual(sum(picking_ids.move_line_ids.mapped('quantity')), 1)
|
||||
|
||||
def test_order_pos_tax_same_as_company(self):
|
||||
"""Test that when the default_pos_receivable_account and the partner account_receivable are the same,
|
||||
payment are correctly reconciled and the invoice is correctly marked as paid.
|
||||
|
||||
Reference in New Issue
Block a user