From 6404daedcb41e67769e1be374f6778d08f69e923 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Mon, 22 Jul 2024 09:53:34 +0200 Subject: [PATCH] [IMP] rma_sale: operation required The rma operation is required in the portal, and it makes sense for it to be required in the sales wizard as well --- rma/README.rst | 66 ++++++++++++----------- rma/models/rma.py | 1 + rma/readme/CONTRIBUTORS.md | 2 + rma/static/description/index.html | 12 +++-- rma/tests/test_rma.py | 29 +++++++--- rma/wizard/stock_picking_return.py | 19 +++++++ rma/wizard/stock_picking_return_views.xml | 10 +++- 7 files changed, 94 insertions(+), 45 deletions(-) diff --git a/rma/README.rst b/rma/README.rst index 03cfcc8b..872a70b1 100644 --- a/rma/README.rst +++ b/rma/README.rst @@ -87,16 +87,16 @@ To use this module, you need to: quantity to another RMA, preview the RMA in the website. All of these operations can be done by clicking on the buttons in the status bar. - - If you click on 'To Refund' button, a refund will be created, and - it will be accessible via the smart button labeled Refund. The RMA - will be set automatically to 'Refunded' state when the refund is - validated. - - If you click on 'Replace' or 'Return to customer' button instead, a - popup wizard will guide you to create a Delivery order to the - client and this order will be accessible via the smart button - labeled Delivery. The RMA will be set automatically to 'Replaced' - or 'Returned' state when the RMA quantity is equal or lower than - the quantity in done delivery orders linked to it. + - If you click on 'To Refund' button, a refund will be created, and + it will be accessible via the smart button labeled Refund. The RMA + will be set automatically to 'Refunded' state when the refund is + validated. + - If you click on 'Replace' or 'Return to customer' button instead, + a popup wizard will guide you to create a Delivery order to the + client and this order will be accessible via the smart button + labeled Delivery. The RMA will be set automatically to 'Replaced' + or 'Returned' state when the RMA quantity is equal or lower than + the quantity in done delivery orders linked to it. 6. You can also finish the RMA without further ado. To do so click on the *Finish* button. A wizard will ask you for the reason from a @@ -117,10 +117,10 @@ An RMA can also be created from a return of a delivery order: There are Optional RMA Teams that can be used for: - - Organize RMAs in sections. - - Subscribe users to notifications. - - Create RMAs from incoming mail to special aliases (See - configuration section). + - Organize RMAs in sections. + - Subscribe users to notifications. + - Create RMAs from incoming mail to special aliases (See + configuration section). To create an RMA Team (RMA Responsible user level required): @@ -128,8 +128,8 @@ To create an RMA Team (RMA Responsible user level required): 2. Create a new team and assign a name, a responsible and members. 3. Subscribe users to notifications, that can be of these subtypes: - - RMA draft. When a new RMA is created. - - Notes, Debates, Activities. As in standard Odoo. + - RMA draft. When a new RMA is created. + - Notes, Debates, Activities. As in standard Odoo. 4. In the list view, use the cross handle to sort RMA Teams. The top team will be the default one if no team is set. @@ -137,12 +137,12 @@ To create an RMA Team (RMA Responsible user level required): Known issues / Roadmap ====================== -- As soon as the picking is selected, the user should select the move, - but perhaps stock.move \_rec_name could be improved to better show - what the product of that move is. -- Add RMA reception and/or RMA delivery on several steps - 2 or 3 - like - normal receptions/deliveries. It should be a separate option inside - the warehouse definition. +- As soon as the picking is selected, the user should select the move, + but perhaps stock.move \_rec_name could be improved to better show + what the product of that move is. +- Add RMA reception and/or RMA delivery on several steps - 2 or 3 - + like normal receptions/deliveries. It should be a separate option + inside the warehouse definition. Bug Tracker =========== @@ -165,20 +165,22 @@ Authors Contributors ------------ -- `Tecnativa `__: +- `Tecnativa `__: - - Ernesto Tejeda - - Pedro M. Baeza - - David Vidal - - Víctor Martínez + - Ernesto Tejeda + - Pedro M. Baeza + - David Vidal + - Víctor Martínez -- Chafique Delli -- Giovanni Serra - Ooops -- `APSL-Nagarro `__: +- Chafique Delli +- Giovanni Serra - Ooops +- `APSL-Nagarro `__: - - Antoni Marroig + - Antoni Marroig -- Michael Tietz (MT Software) mtietz@mt-software.de +- Michael Tietz (MT Software) mtietz@mt-software.de +- Jacques-Etienne Baudoux - BCIM je@bcim.be +- Souheil Bejaoui - ACSONE SA/NV souheil.bejaoui@acsone.eu Maintainers ----------- diff --git a/rma/models/rma.py b/rma/models/rma.py index 41e2d9ee..9c36e500 100644 --- a/rma/models/rma.py +++ b/rma/models/rma.py @@ -856,6 +856,7 @@ class Rma(models.Model): "partner_invoice_id", "product_id", "location_id", + "operation_id", ] for record in self: desc = "" diff --git a/rma/readme/CONTRIBUTORS.md b/rma/readme/CONTRIBUTORS.md index 801eb97b..6a7b4808 100644 --- a/rma/readme/CONTRIBUTORS.md +++ b/rma/readme/CONTRIBUTORS.md @@ -8,3 +8,5 @@ - [APSL-Nagarro](https://www.apsl.tech): - Antoni Marroig \<\> - Michael Tietz (MT Software) +- Jacques-Etienne Baudoux - BCIM +- Souheil Bejaoui - ACSONE SA/NV diff --git a/rma/static/description/index.html b/rma/static/description/index.html index 9dd89673..11f3dc75 100644 --- a/rma/static/description/index.html +++ b/rma/static/description/index.html @@ -439,8 +439,8 @@ operations can be done by clicking on the buttons in the status bar.
    it will be accessible via the smart button labeled Refund. The RMA will be set automatically to ‘Refunded’ state when the refund is validated. -
  • If you click on ‘Replace’ or ‘Return to customer’ button instead, a -popup wizard will guide you to create a Delivery order to the +
  • If you click on ‘Replace’ or ‘Return to customer’ button instead, +a popup wizard will guide you to create a Delivery order to the client and this order will be accessible via the smart button labeled Delivery. The RMA will be set automatically to ‘Replaced’ or ‘Returned’ state when the RMA quantity is equal or lower than @@ -494,9 +494,9 @@ team will be the default one if no team is set.
  • As soon as the picking is selected, the user should select the move, but perhaps stock.move _rec_name could be improved to better show what the product of that move is.
  • -
  • Add RMA reception and/or RMA delivery on several steps - 2 or 3 - like -normal receptions/deliveries. It should be a separate option inside -the warehouse definition.
  • +
  • Add RMA reception and/or RMA delivery on several steps - 2 or 3 - +like normal receptions/deliveries. It should be a separate option +inside the warehouse definition.
@@ -532,6 +532,8 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
  • Michael Tietz (MT Software) mtietz@mt-software.de
  • +
  • Jacques-Etienne Baudoux - BCIM je@bcim.be
  • +
  • Souheil Bejaoui - ACSONE SA/NV souheil.bejaoui@acsone.eu
  • diff --git a/rma/tests/test_rma.py b/rma/tests/test_rma.py index 6eb0987f..1bd39979 100644 --- a/rma/tests/test_rma.py +++ b/rma/tests/test_rma.py @@ -71,8 +71,11 @@ class TestRma(BaseCommon): cls.warehouse = cls.env.ref("stock.warehouse0") # Ensure grouping cls.env.company.rma_return_grouping = True + cls.operation = cls.env.ref("rma.rma_operation_replace") - def _create_rma(self, partner=None, product=None, qty=None, location=None): + def _create_rma( + self, partner=None, product=None, qty=None, location=None, operation=None + ): vals = {} if partner: vals["partner_id"] = partner.id @@ -82,14 +85,17 @@ class TestRma(BaseCommon): vals["product_uom_qty"] = qty if location: vals["location_id"] = location.id - + if operation: + vals["operation_id"] = operation.id + elif operation is None: + vals["operation_id"] = self.operation.id vals["user_id"] = self.env.user.id return self.env["rma"].create(vals) def _create_confirm_receive( - self, partner=None, product=None, qty=None, location=None + self, partner=None, product=None, qty=None, location=None, operation=None ): - rma = self._create_rma(partner, product, qty, location) + rma = self._create_rma(partner, product, qty, location, operation) rma.action_confirm() rma.reception_move_id.quantity = rma.product_uom_qty rma.reception_move_id.picking_id.button_validate() @@ -221,19 +227,26 @@ class TestRmaCase(TestRma): self.assertEqual(rma.product_uom, self.product.uom_id) def test_ensure_required_fields_on_confirm(self): - rma = self._create_rma() + rma = self._create_rma(operation=False) with self.assertRaises(ValidationError) as e: rma.action_confirm() self.assertEqual( e.exception.args[0], - "Required field(s):\nCustomer\nShipping Address\nInvoice Address\nProduct", + "Required field(s):\nCustomer\nShipping Address\nInvoice Address\nProduct" + "\nRequested operation", ) rma.partner_id = self.partner.id with self.assertRaises(ValidationError) as e: rma.action_confirm() - self.assertEqual(e.exception.args[0], "Required field(s):\nProduct") + self.assertEqual( + e.exception.args[0], "Required field(s):\nProduct\nRequested operation" + ) rma.product_id = self.product.id rma.location_id = self.rma_loc.id + with self.assertRaises(ValidationError) as e: + rma.action_confirm() + self.assertEqual(e.exception.args[0], "Required field(s):\nRequested operation") + rma.operation_id = self.operation rma.action_confirm() self.assertEqual(rma.state, "confirmed") @@ -670,6 +683,7 @@ class TestRmaCase(TestRma): ) ) stock_return_picking_form.create_rma = True + stock_return_picking_form.rma_operation_id = self.operation return_wizard = stock_return_picking_form.save() picking_action = return_wizard.create_returns() # Each origin move is linked to a different RMA @@ -698,6 +712,7 @@ class TestRmaCase(TestRma): rma_form.move_id = origin_delivery.move_ids.filtered( lambda r: r.product_id == self.product ) + rma_form.operation_id = self.operation rma = rma_form.save() rma.action_confirm() rma.reception_move_id.quantity = 10 diff --git a/rma/wizard/stock_picking_return.py b/rma/wizard/stock_picking_return.py index 7c7ca364..3bed8265 100644 --- a/rma/wizard/stock_picking_return.py +++ b/rma/wizard/stock_picking_return.py @@ -11,6 +11,20 @@ from odoo.tools import float_compare class ReturnPickingLine(models.TransientModel): _inherit = "stock.return.picking.line" + rma_operation_id = fields.Many2one( + comodel_name="rma.operation", + string="Operation", + compute="_compute_rma_operation_id", + store=True, + readonly=False, + ) + + @api.depends("wizard_id.rma_operation_id") + def _compute_rma_operation_id(self): + for rec in self: + if rec.wizard_id.rma_operation_id: + rec.rma_operation_id = rec.wizard_id.rma_operation_id + def _prepare_rma_vals(self): self.ensure_one() return { @@ -19,6 +33,7 @@ class ReturnPickingLine(models.TransientModel): "product_uom_qty": self.quantity, "product_uom": self.product_id.uom_id.id, "location_id": self.wizard_id.location_id.id or self.move_id.location_id.id, + "operation_id": self.rma_operation_id.id, } @@ -30,6 +45,10 @@ class ReturnPicking(models.TransientModel): rma_location_ids = fields.Many2many( comodel_name="stock.location", compute="_compute_rma_location_id" ) + rma_operation_id = fields.Many2one( + comodel_name="rma.operation", + string="Requested operation", + ) # Expand domain for RMAs location_id = fields.Many2one( domain="create_rma and [('id', 'child_of', rma_location_ids)]" diff --git a/rma/wizard/stock_picking_return_views.xml b/rma/wizard/stock_picking_return_views.xml index 983815eb..167519d9 100644 --- a/rma/wizard/stock_picking_return_views.xml +++ b/rma/wizard/stock_picking_return_views.xml @@ -8,12 +8,20 @@ stock.return.picking - + + + + +