diff --git a/addons/pos_sale/models/pos_order.py b/addons/pos_sale/models/pos_order.py index a2ab6ccdf0f8b50b9d69db0c052755d282c6ed54..8643986f9051d4aa656d6744061217955dc7daaa 100644 --- a/addons/pos_sale/models/pos_order.py +++ b/addons/pos_sale/models/pos_order.py @@ -42,10 +42,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 59f7d6102ac62a83c76e39e2c26e482d63b4b187..76b99e1d0e5030585b6154b86d7a6fa0846267b5 100644 --- a/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js +++ b/addons/pos_sale/static/tests/helpers/ProductScreenTourMethods.js @@ -26,6 +26,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 4957ecd4ae49e4445a6e23a3beee3144db9137a7..9689d4db5e7a93f3952596b810be6637367fa418 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'); @@ -65,4 +66,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 0efaf216865cdd8ff6838b5eb4557113eb01e935..41312860197199e0f2626a5ba31db86aed9cb897 100644 --- a/addons/pos_sale/tests/test_pos_sale_flow.py +++ b/addons/pos_sale/tests/test_pos_sale_flow.py @@ -239,3 +239,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_session_cb() + 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)