From b772cb4e1a51e51444ad01815cb7004888d988bb Mon Sep 17 00:00:00 2001
From: roen-odoo <roen@odoo.com>
Date: Thu, 11 May 2023 12:31:21 +0000
Subject: [PATCH] [FIX] pos_sale: downpayment refund correctly added to origin
 order

Current behavior:
When you refund a downpayment in the PoS, the downpayment is not added
to the original order.

Steps to reproduce:
- Create an order in the sales app
- Open the PoS and make a downpayment for the order
- Refund the downpayment you just made
- Go back to the original order in the sales app, the downpayment is
  correctly added, but the refund of the downpayment is not added.
- The order should contain : The original product, the downpayment and
  the refund of the downpayment.

opw-3275708

closes odoo/odoo#125357

X-original-commit: 02a67b42071e5be14975b8aa745b37ff0e9e9e46
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
Signed-off-by: Robin Engels (roen) <roen@odoo.com>
---
 addons/pos_sale/models/pos_order.py           |  7 +++--
 .../tests/helpers/ProductScreenTourMethods.js | 21 ++++++++++++++
 .../static/tests/tours/pos_sale_tours.js      | 23 +++++++++++++++
 addons/pos_sale/tests/test_pos_sale_flow.py   | 28 +++++++++++++++++++
 4 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/addons/pos_sale/models/pos_order.py b/addons/pos_sale/models/pos_order.py
index 84b8ae61c58d..44302ca6706e 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 b24abaca629b..170e45758e2c 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 5611761491d7..f43d75f6665a 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 4aee005bb682..25182cc501a8 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)
-- 
GitLab