diff --git a/addons/pos_sale/models/pos_order.py b/addons/pos_sale/models/pos_order.py index 84b8ae61c58dad758c326e0c9c0631bfa82665bd..44302ca6706e93d3d90bfebcd44dcc9290ac935c 100644 --- a/addons/pos_sale/models/pos_order.py +++ b/addons/pos_sale/models/pos_order.py @@ -48,10 +48,11 @@ class PosOrder(models.Model): def create_from_ui(self, orders, draft=False): order_ids = super(PosOrder, self).create_from_ui(orders, draft) for order in self.sudo().browse([o['id'] for o in order_ids]): - for line in order.lines.filtered(lambda l: l.product_id == order.config_id.down_payment_product_id and l.qty > 0 and l.sale_order_origin_id): - sale_lines = line.sale_order_origin_id.order_line + for line in order.lines.filtered(lambda l: l.product_id == order.config_id.down_payment_product_id and l.qty != 0 and (l.sale_order_origin_id or l.refunded_orderline_id.sale_order_origin_id)): + sale_lines = line.sale_order_origin_id.order_line or line.refunded_orderline_id.sale_order_origin_id.order_line + sale_order_origin = line.sale_order_origin_id or line.refunded_orderline_id.sale_order_origin_id sale_line = self.env['sale.order.line'].create({ - 'order_id': line.sale_order_origin_id.id, + 'order_id': sale_order_origin.id, 'product_id': line.product_id.id, 'price_unit': line.price_unit, 'product_uom_qty': 0, diff --git a/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js b/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js index b24abaca629b0ec9539a5a2d9c1b9d623c3dd196..170e45758e2ca806d77582f5c673902f90aaaf24 100644 --- a/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js +++ b/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js @@ -39,6 +39,27 @@ odoo.define('pos_sale.tour.ProductScreenTourMethods', function (require) { } ]; } + + downPaymentFirstOrder() { + return [ + { + content: `select order`, + trigger: `.order-row .col.name:first`, + }, + { + content: `click on select the order`, + trigger: `.selection-item:contains('Apply a down payment')`, + }, + { + content: `click on +10 button`, + trigger: `.mode-button.add:contains('+10')`, + }, + { + content: `click on ok button`, + trigger: `.button.confirm`, + } + ]; + } } return createTourMethods('ProductScreen', DoExt, Check, Execute); }); diff --git a/addons/pos_sale/static/tests/tours/pos_sale_tours.js b/addons/pos_sale/static/tests/tours/pos_sale_tours.js index 5611761491d72a1d1507ec48dc8c760e16af6b68..f43d75f6665aa6ea9eae66726444ce9f48d4ceb8 100644 --- a/addons/pos_sale/static/tests/tours/pos_sale_tours.js +++ b/addons/pos_sale/static/tests/tours/pos_sale_tours.js @@ -5,6 +5,7 @@ odoo.define('pos_sale.tour', function (require) { const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods'); const { ProductScreen } = require('pos_sale.tour.ProductScreenTourMethods'); const { ReceiptScreen } = require('point_of_sale.tour.ReceiptScreenTourMethods'); + const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods'); const { getSteps, startSteps } = require('point_of_sale.tour.utils'); const Tour = require('web_tour.tour'); @@ -74,4 +75,26 @@ odoo.define('pos_sale.tour', function (require) { Chrome.do.clickTicketButton(); Tour.register('PosSettleOrderRealTime', { test: true, url: '/pos/ui' }, getSteps()); + + startSteps(); + + ProductScreen.do.clickQuotationButton(); + ProductScreen.do.downPaymentFirstOrder(); + ProductScreen.do.clickPayButton(); + PaymentScreen.do.clickPaymentMethod('Cash'); + PaymentScreen.do.clickValidate(); + ReceiptScreen.do.clickNextOrder(); + ProductScreen.do.clickRefund(); + // Filter should be automatically 'Paid'. + TicketScreen.check.filterIs('Paid'); + TicketScreen.do.selectOrder('-0001'); + TicketScreen.do.clickOrderline('Down Payment'); + TicketScreen.do.pressNumpad('1'); + TicketScreen.do.confirmRefund(); + ProductScreen.do.clickPayButton(); + PaymentScreen.do.clickPaymentMethod('Cash'); + PaymentScreen.do.clickValidate(); + ReceiptScreen.do.clickNextOrder(); + + Tour.register('PosRefundDownpayment', { test: true, url: '/pos/ui' }, getSteps()); }); diff --git a/addons/pos_sale/tests/test_pos_sale_flow.py b/addons/pos_sale/tests/test_pos_sale_flow.py index 4aee005bb682a2eae337a35501d6104a328f9943..25182cc501a8f55a3c9835f85fc06c1897fa083e 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -228,3 +228,31 @@ class TestPoSSale(TestPointOfSaleHttpCommon): self.assertEqual(pos_order.picking_ids.move_line_ids[1].qty_done, 2) self.assertEqual(pos_order.picking_ids.move_line_ids[1].location_id.id, self.shelf_2.id) self.assertEqual(sale_order.order_line.move_ids.move_lines_count, 0) + + def test_downpayment_refund(self): + #create a sale order + sale_order = self.env['sale.order'].create({ + 'partner_id': self.env.ref('base.res_partner_2').id, + 'order_line': [(0, 0, { + 'product_id': self.product_a.id, + 'name': self.product_a.name, + 'product_uom_qty': 1, + 'price_unit': 100, + 'product_uom': self.product_a.uom_id.id + })], + }) + sale_order.action_confirm() + #set downpayment product in pos config + self.downpayment_product = self.env['product.product'].create({ + 'name': 'Down Payment', + 'available_in_pos': True, + 'type': 'service', + }) + self.main_pos_config.write({ + 'down_payment_product_id': self.downpayment_product.id, + }) + self.main_pos_config.open_ui() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'PosRefundDownpayment', login="accountman") + self.assertEqual(len(sale_order.order_line), 3) + self.assertEqual(sale_order.order_line[1].qty_invoiced, 1) + self.assertEqual(sale_order.order_line[2].qty_invoiced, -1)