odoo-addon-rma 16.0.1.3.0.1__py3-none-any.whl → 16.0.2.0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/rma/README.rst +5 -1
- odoo/addons/rma/__manifest__.py +1 -1
- odoo/addons/rma/hooks.py +12 -1
- odoo/addons/rma/i18n/de.po +22 -0
- odoo/addons/rma/i18n/de_AT.po +22 -0
- odoo/addons/rma/i18n/es.po +22 -0
- odoo/addons/rma/i18n/fr.po +30 -7
- odoo/addons/rma/i18n/it.po +40 -18
- odoo/addons/rma/i18n/nl.po +22 -0
- odoo/addons/rma/i18n/pt.po +22 -0
- odoo/addons/rma/i18n/pt_BR.po +22 -0
- odoo/addons/rma/i18n/rma.pot +22 -0
- odoo/addons/rma/i18n/ro.po +22 -0
- odoo/addons/rma/i18n/zh_CN.po +22 -0
- odoo/addons/rma/migrations/16.0.1.4.0/post-migration.py +14 -0
- odoo/addons/rma/models/rma.py +240 -273
- odoo/addons/rma/models/stock_move.py +17 -32
- odoo/addons/rma/models/stock_picking.py +2 -2
- odoo/addons/rma/models/stock_warehouse.py +93 -19
- odoo/addons/rma/readme/CONTRIBUTORS.rst +1 -0
- odoo/addons/rma/readme/ROADMAP.rst +3 -0
- odoo/addons/rma/static/description/index.html +5 -1
- odoo/addons/rma/tests/test_rma.py +63 -4
- odoo/addons/rma/wizard/stock_picking_return.py +90 -13
- {odoo_addon_rma-16.0.1.3.0.1.dist-info → odoo_addon_rma-16.0.2.0.0.1.dist-info}/METADATA +6 -2
- {odoo_addon_rma-16.0.1.3.0.1.dist-info → odoo_addon_rma-16.0.2.0.0.1.dist-info}/RECORD +28 -27
- {odoo_addon_rma-16.0.1.3.0.1.dist-info → odoo_addon_rma-16.0.2.0.0.1.dist-info}/WHEEL +0 -0
- {odoo_addon_rma-16.0.1.3.0.1.dist-info → odoo_addon_rma-16.0.2.0.0.1.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
|
+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
|
2
3
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
4
|
|
4
5
|
from odoo import _, api, fields, models
|
@@ -22,7 +23,7 @@ class StockMove(models.Model):
|
|
22
23
|
string="RMA receivers",
|
23
24
|
copy=False,
|
24
25
|
)
|
25
|
-
# RMA that
|
26
|
+
# RMA that creates the out move
|
26
27
|
rma_id = fields.Many2one(
|
27
28
|
comodel_name="rma",
|
28
29
|
string="RMA return",
|
@@ -32,8 +33,8 @@ class StockMove(models.Model):
|
|
32
33
|
def unlink(self):
|
33
34
|
# A stock user could have no RMA permissions, so the ids wouldn't
|
34
35
|
# be accessible due to record rules.
|
35
|
-
rma_receiver = self.sudo().
|
36
|
-
rma = self.sudo().
|
36
|
+
rma_receiver = self.sudo().rma_receiver_ids
|
37
|
+
rma = self.sudo().rma_id
|
37
38
|
res = super().unlink()
|
38
39
|
rma_receiver.filtered(lambda x: x.state != "cancelled").write(
|
39
40
|
{"state": "draft"}
|
@@ -103,38 +104,22 @@ class StockMove(models.Model):
|
|
103
104
|
res["rma_id"] = self.sudo().rma_id.id
|
104
105
|
return res
|
105
106
|
|
106
|
-
def
|
107
|
-
|
108
|
-
self.
|
109
|
-
|
110
|
-
|
111
|
-
partner_invoice_id = original_picking.sale_id.partner_invoice_id.id
|
112
|
-
partner_shipping_id = original_picking.sale_id.partner_shipping_id.id
|
113
|
-
else:
|
114
|
-
partner_invoice_id = partner.address_get(["invoice"]).get("invoice", False)
|
115
|
-
partner_shipping_id = partner.address_get(["delivery"]).get(
|
116
|
-
"delivery", False
|
117
|
-
)
|
118
|
-
return {
|
119
|
-
"user_id": self.env.user.id,
|
120
|
-
"partner_id": partner.id,
|
121
|
-
"partner_shipping_id": partner_shipping_id,
|
122
|
-
"partner_invoice_id": partner_invoice_id,
|
123
|
-
"origin": original_picking.name,
|
124
|
-
"picking_id": original_picking.id,
|
125
|
-
"move_id": self.origin_returned_move_id.id,
|
126
|
-
"product_id": self.origin_returned_move_id.product_id.id,
|
127
|
-
"product_uom_qty": self.product_uom_qty,
|
128
|
-
"product_uom": self.product_uom.id,
|
129
|
-
"reception_move_id": self.id,
|
130
|
-
"company_id": self.company_id.id,
|
131
|
-
"location_id": self.location_dest_id.id,
|
132
|
-
"state": "confirmed",
|
133
|
-
}
|
107
|
+
def _prepare_procurement_values(self):
|
108
|
+
res = super()._prepare_procurement_values()
|
109
|
+
if self.rma_id:
|
110
|
+
res["rma_id"] = self.rma_id.id
|
111
|
+
return res
|
134
112
|
|
135
113
|
|
136
114
|
class StockRule(models.Model):
|
137
115
|
_inherit = "stock.rule"
|
138
116
|
|
139
117
|
def _get_custom_move_fields(self):
|
140
|
-
|
118
|
+
move_fields = super()._get_custom_move_fields()
|
119
|
+
move_fields += [
|
120
|
+
"rma_id",
|
121
|
+
"origin_returned_move_id",
|
122
|
+
"move_orig_ids",
|
123
|
+
"rma_receiver_ids",
|
124
|
+
]
|
125
|
+
return move_fields
|
@@ -30,8 +30,8 @@ class StockPicking(models.Model):
|
|
30
30
|
|
31
31
|
def action_view_rma(self):
|
32
32
|
self.ensure_one()
|
33
|
-
action = self.
|
34
|
-
rma = self.
|
33
|
+
action = self.env["ir.actions.act_window"]._for_xml_id("rma.rma_action")
|
34
|
+
rma = self.move_lines.mapped("rma_ids")
|
35
35
|
if len(rma) == 1:
|
36
36
|
action.update(
|
37
37
|
res_id=rma.id,
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
|
+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
|
2
3
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
4
|
|
4
|
-
from odoo import _,
|
5
|
+
from odoo import _, fields, models
|
5
6
|
|
6
7
|
|
7
8
|
class StockWarehouse(models.Model):
|
@@ -27,35 +28,39 @@ class StockWarehouse(models.Model):
|
|
27
28
|
comodel_name="stock.location",
|
28
29
|
string="RMA Location",
|
29
30
|
)
|
31
|
+
rma_in_route_id = fields.Many2one("stock.route", "RMA in Route")
|
32
|
+
rma_out_route_id = fields.Many2one("stock.route", "RMA out Route")
|
30
33
|
|
31
|
-
|
32
|
-
def create(self, vals_list):
|
33
|
-
"""To create an RMA location and link it with a new warehouse,
|
34
|
-
this method is overridden instead of '_get_locations_values'
|
35
|
-
method because the locations that are created with the
|
36
|
-
values returned by that method are forced to be children
|
37
|
-
of view_location_id, and we don't want that.
|
38
|
-
"""
|
39
|
-
res = super().create(vals_list)
|
40
|
-
stock_location = self.env["stock.location"]
|
41
|
-
for record in res:
|
42
|
-
rma_location_vals = record._get_rma_location_values()
|
43
|
-
record.rma_loc_id = stock_location.create(rma_location_vals).id
|
44
|
-
return res
|
45
|
-
|
46
|
-
def _get_rma_location_values(self):
|
34
|
+
def _get_rma_location_values(self, vals, code=False):
|
47
35
|
"""this method is intended to be used by 'create' method
|
48
36
|
to create a new RMA location to be linked to a new warehouse.
|
49
37
|
"""
|
38
|
+
company_id = vals.get(
|
39
|
+
"company_id", self.default_get(["company_id"])["company_id"]
|
40
|
+
)
|
41
|
+
code = vals.get("code") or code or ""
|
42
|
+
code = code.replace(" ", "").upper()
|
43
|
+
view_location_id = vals.get("view_location_id")
|
44
|
+
view_location = (
|
45
|
+
view_location_id
|
46
|
+
and self.view_location_id.browse(view_location_id)
|
47
|
+
or self.view_location_id
|
48
|
+
)
|
50
49
|
return {
|
51
|
-
"name":
|
50
|
+
"name": view_location.name,
|
52
51
|
"active": True,
|
53
52
|
"return_location": True,
|
54
53
|
"usage": "internal",
|
55
|
-
"company_id":
|
54
|
+
"company_id": company_id,
|
56
55
|
"location_id": self.env.ref("rma.stock_location_rma").id,
|
56
|
+
"barcode": self._valid_barcode(code + "-RMA", company_id),
|
57
57
|
}
|
58
58
|
|
59
|
+
def _get_locations_values(self, vals, code=False):
|
60
|
+
res = super()._get_locations_values(vals, code)
|
61
|
+
res["rma_loc_id"] = self._get_rma_location_values(vals, code)
|
62
|
+
return res
|
63
|
+
|
59
64
|
def _get_sequence_values(self, name=False, code=False):
|
60
65
|
values = super()._get_sequence_values(name=name, code=code)
|
61
66
|
values.update(
|
@@ -77,12 +82,14 @@ class StockWarehouse(models.Model):
|
|
77
82
|
return values
|
78
83
|
|
79
84
|
def _update_name_and_code(self, new_name=False, new_code=False):
|
85
|
+
res = super()._update_name_and_code(new_name, new_code)
|
80
86
|
for warehouse in self:
|
81
87
|
sequence_data = warehouse._get_sequence_values()
|
82
88
|
warehouse.rma_in_type_id.sequence_id.write(sequence_data["rma_in_type_id"])
|
83
89
|
warehouse.rma_out_type_id.sequence_id.write(
|
84
90
|
sequence_data["rma_out_type_id"]
|
85
91
|
)
|
92
|
+
return res
|
86
93
|
|
87
94
|
def _get_picking_type_create_values(self, max_sequence):
|
88
95
|
data, next_sequence = super()._get_picking_type_create_values(max_sequence)
|
@@ -138,3 +145,70 @@ class StockWarehouse(models.Model):
|
|
138
145
|
{"return_picking_type_id": data.get("rma_out_type_id", False)}
|
139
146
|
)
|
140
147
|
return data
|
148
|
+
|
149
|
+
def _get_routes_values(self):
|
150
|
+
res = super()._get_routes_values()
|
151
|
+
rma_routes = {
|
152
|
+
"rma_in_route_id": {
|
153
|
+
"routing_key": "rma_in",
|
154
|
+
"depends": ["active"],
|
155
|
+
"route_update_values": {
|
156
|
+
"name": self._format_routename("RMA In"),
|
157
|
+
"active": self.active,
|
158
|
+
},
|
159
|
+
"route_create_values": {
|
160
|
+
"warehouse_selectable": True,
|
161
|
+
"company_id": self.company_id.id,
|
162
|
+
"sequence": 100,
|
163
|
+
},
|
164
|
+
"rules_values": {
|
165
|
+
"active": True,
|
166
|
+
},
|
167
|
+
},
|
168
|
+
"rma_out_route_id": {
|
169
|
+
"routing_key": "rma_out",
|
170
|
+
"depends": ["active"],
|
171
|
+
"route_update_values": {
|
172
|
+
"name": self._format_routename("RMA Out"),
|
173
|
+
"active": self.active,
|
174
|
+
},
|
175
|
+
"route_create_values": {
|
176
|
+
"warehouse_selectable": True,
|
177
|
+
"company_id": self.company_id.id,
|
178
|
+
"sequence": 110,
|
179
|
+
},
|
180
|
+
"rules_values": {
|
181
|
+
"active": True,
|
182
|
+
},
|
183
|
+
},
|
184
|
+
}
|
185
|
+
if self.env.context.get("rma_post_init_hook"):
|
186
|
+
return rma_routes
|
187
|
+
res.update(rma_routes)
|
188
|
+
return res
|
189
|
+
|
190
|
+
def get_rules_dict(self):
|
191
|
+
res = super().get_rules_dict()
|
192
|
+
customer_loc, supplier_loc = self._get_partner_locations()
|
193
|
+
for warehouse in self:
|
194
|
+
res[warehouse.id].update(
|
195
|
+
{
|
196
|
+
"rma_in": [
|
197
|
+
self.Routing(
|
198
|
+
customer_loc,
|
199
|
+
warehouse.rma_loc_id,
|
200
|
+
warehouse.rma_in_type_id,
|
201
|
+
"pull",
|
202
|
+
)
|
203
|
+
],
|
204
|
+
"rma_out": [
|
205
|
+
self.Routing(
|
206
|
+
warehouse.rma_loc_id,
|
207
|
+
customer_loc,
|
208
|
+
warehouse.rma_out_type_id,
|
209
|
+
"pull",
|
210
|
+
)
|
211
|
+
],
|
212
|
+
}
|
213
|
+
)
|
214
|
+
return res
|
@@ -1,3 +1,6 @@
|
|
1
1
|
* As soon as the picking is selected, the user should select the move,
|
2
2
|
but perhaps stock.move _rec_name could be improved to better show what
|
3
3
|
the product of that move is.
|
4
|
+
* Add RMA reception and/or RMA delivery on several steps - 2 or 3 - like
|
5
|
+
normal receptions/deliveries. It should be a separate option inside the
|
6
|
+
warehouse definition.
|
@@ -366,7 +366,7 @@ ul.auto-toc {
|
|
366
366
|
!! This file is generated by oca-gen-addon-readme !!
|
367
367
|
!! changes will be overwritten. !!
|
368
368
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
369
|
-
!! source digest: sha256:
|
369
|
+
!! source digest: sha256:62d0c2b19f67175025b621f74656297363fe9b028799723026166ed8d24b7b8b
|
370
370
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
371
371
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/rma/tree/16.0/rma"><img alt="OCA/rma" src="https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/rma-16-0/rma-16-0-rma"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/rma&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
372
372
|
<p>This module allows you to manage <a class="reference external" href="https://en.wikipedia.org/wiki/Return_merchandise_authorization">Return Merchandise Authorization (RMA)</a>.
|
@@ -488,6 +488,9 @@ will be the default one if no team is set.</li>
|
|
488
488
|
<li>As soon as the picking is selected, the user should select the move,
|
489
489
|
but perhaps stock.move _rec_name could be improved to better show what
|
490
490
|
the product of that move is.</li>
|
491
|
+
<li>Add RMA reception and/or RMA delivery on several steps - 2 or 3 - like
|
492
|
+
normal receptions/deliveries. It should be a separate option inside the
|
493
|
+
warehouse definition.</li>
|
491
494
|
</ul>
|
492
495
|
</div>
|
493
496
|
<div class="section" id="bug-tracker">
|
@@ -518,6 +521,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|
518
521
|
</li>
|
519
522
|
<li>Chafique Delli <<a class="reference external" href="mailto:chafique.delli@akretion.com">chafique.delli@akretion.com</a>></li>
|
520
523
|
<li>Giovanni Serra - Ooops <<a class="reference external" href="mailto:giovanni@ooops404.com">giovanni@ooops404.com</a>></li>
|
524
|
+
<li>Michael Tietz (MT Software) <<a class="reference external" href="mailto:mtietz@mt-software.de">mtietz@mt-software.de</a>></li>
|
521
525
|
</ul>
|
522
526
|
</div>
|
523
527
|
<div class="section" id="maintainers">
|
@@ -1,9 +1,12 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
|
+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
|
2
3
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
4
|
|
4
5
|
from odoo.exceptions import UserError, ValidationError
|
5
6
|
from odoo.tests import Form, TransactionCase, new_test_user, users
|
6
7
|
|
8
|
+
from .. import hooks
|
9
|
+
|
7
10
|
|
8
11
|
class TestRma(TransactionCase):
|
9
12
|
@classmethod
|
@@ -72,6 +75,8 @@ class TestRma(TransactionCase):
|
|
72
75
|
{"name": "[Test] It's out of warranty. To be scrapped"}
|
73
76
|
)
|
74
77
|
cls.env.ref("rma.group_rma_manual_finalization").users |= cls.env.user
|
78
|
+
cls.env.ref("stock.group_stock_multi_locations").users |= cls.env.user
|
79
|
+
cls.warehouse = cls.env.ref("stock.warehouse0")
|
75
80
|
# Ensure grouping
|
76
81
|
cls.env.company.rma_return_grouping = True
|
77
82
|
|
@@ -130,6 +135,49 @@ class TestRma(TransactionCase):
|
|
130
135
|
|
131
136
|
|
132
137
|
class TestRmaCase(TestRma):
|
138
|
+
def test_post_init_hook(self):
|
139
|
+
warehouse = self.env["stock.warehouse"].create(
|
140
|
+
{
|
141
|
+
"name": "Test warehouse",
|
142
|
+
"code": "code",
|
143
|
+
"company_id": self.env.company.id,
|
144
|
+
}
|
145
|
+
)
|
146
|
+
hooks.post_init_hook(self.env.cr, self.registry)
|
147
|
+
self.assertTrue(warehouse.rma_in_type_id)
|
148
|
+
self.assertEqual(
|
149
|
+
warehouse.rma_in_type_id.default_location_dest_id, warehouse.rma_loc_id
|
150
|
+
)
|
151
|
+
self.assertEqual(
|
152
|
+
warehouse.rma_out_type_id.default_location_src_id, warehouse.rma_loc_id
|
153
|
+
)
|
154
|
+
self.assertTrue(warehouse.rma_loc_id)
|
155
|
+
self.assertTrue(warehouse.rma_in_route_id)
|
156
|
+
self.assertTrue(warehouse.rma_out_route_id)
|
157
|
+
|
158
|
+
def test_rma_replace_pick_ship(self):
|
159
|
+
self.warehouse.write({"delivery_steps": "pick_ship"})
|
160
|
+
rma = self._create_rma(self.partner, self.product, 1, self.rma_loc)
|
161
|
+
rma.action_confirm()
|
162
|
+
rma.reception_move_id.quantity_done = 1
|
163
|
+
rma.reception_move_id.picking_id._action_done()
|
164
|
+
self.assertEqual(rma.reception_move_id.picking_id.state, "done")
|
165
|
+
self.assertEqual(rma.state, "received")
|
166
|
+
res = rma.action_replace()
|
167
|
+
wizard_form = Form(self.env[res["res_model"]].with_context(**res["context"]))
|
168
|
+
wizard_form.product_id = self.product
|
169
|
+
wizard_form.product_uom_qty = rma.product_uom_qty
|
170
|
+
wizard = wizard_form.save()
|
171
|
+
wizard.action_deliver()
|
172
|
+
self.assertEqual(rma.delivery_picking_count, 2)
|
173
|
+
out_pickings = rma.mapped("delivery_move_ids.picking_id")
|
174
|
+
self.assertIn(
|
175
|
+
self.warehouse.pick_type_id, out_pickings.mapped("picking_type_id")
|
176
|
+
)
|
177
|
+
self.assertIn(
|
178
|
+
self.warehouse.out_type_id, out_pickings.mapped("picking_type_id")
|
179
|
+
)
|
180
|
+
|
133
181
|
def test_computed(self):
|
134
182
|
# If partner changes, the invoice address is set
|
135
183
|
rma = self.env["rma"].new()
|
@@ -331,7 +379,7 @@ class TestRmaCase(TestRma):
|
|
331
379
|
# line of refund_1
|
332
380
|
self.assertEqual(len(refund_1.invoice_line_ids), 3)
|
333
381
|
self.assertEqual(
|
334
|
-
refund_1.invoice_line_ids.
|
382
|
+
refund_1.invoice_line_ids.rma_id,
|
335
383
|
(rma_1 | rma_2 | rma_3),
|
336
384
|
)
|
337
385
|
self.assertEqual(
|
@@ -538,6 +586,13 @@ class TestRmaCase(TestRma):
|
|
538
586
|
all_rmas = rma_1 | rma_2 | rma_3 | rma_4
|
539
587
|
self.assertEqual(all_rmas.mapped("state"), ["received"] * 4)
|
540
588
|
self.assertEqual(all_rmas.mapped("can_be_returned"), [True] * 4)
|
589
|
+
all_in_pickings = all_rmas.mapped("reception_move_id.picking_id")
|
590
|
+
self.assertEqual(
|
591
|
+
all_in_pickings.mapped("picking_type_id"), self.warehouse.rma_in_type_id
|
592
|
+
)
|
593
|
+
self.assertEqual(
|
594
|
+
all_in_pickings.mapped("location_dest_id"), self.warehouse.rma_loc_id
|
595
|
+
)
|
541
596
|
# Mass return of those four RMAs
|
542
597
|
delivery_wizard = (
|
543
598
|
self.env["rma.delivery.wizard"]
|
@@ -548,6 +603,10 @@ class TestRmaCase(TestRma):
|
|
548
603
|
# Two pickings were created
|
549
604
|
pick_1 = (rma_1 | rma_2 | rma_3).mapped("delivery_move_ids.picking_id")
|
550
605
|
pick_2 = rma_4.delivery_move_ids.picking_id
|
606
|
+
self.assertEqual(pick_1.picking_type_id, self.warehouse.rma_out_type_id)
|
607
|
+
self.assertEqual(pick_1.location_id, self.warehouse.rma_loc_id)
|
608
|
+
self.assertEqual(pick_2.picking_type_id, self.warehouse.rma_out_type_id)
|
609
|
+
self.assertEqual(pick_2.location_id, self.warehouse.rma_loc_id)
|
551
610
|
self.assertEqual(len(pick_1), 1)
|
552
611
|
self.assertEqual(len(pick_2), 1)
|
553
612
|
self.assertNotEqual(pick_1, pick_2)
|
@@ -563,7 +622,7 @@ class TestRmaCase(TestRma):
|
|
563
622
|
# line of picking_1
|
564
623
|
self.assertEqual(len(pick_1.move_ids), 3)
|
565
624
|
self.assertEqual(
|
566
|
-
pick_1.move_ids.
|
625
|
+
pick_1.move_ids.rma_id,
|
567
626
|
(rma_1 | rma_2 | rma_3),
|
568
627
|
)
|
569
628
|
self.assertEqual(
|
@@ -634,14 +693,14 @@ class TestRmaCase(TestRma):
|
|
634
693
|
origin_moves = origin_delivery.move_ids
|
635
694
|
self.assertTrue(origin_moves[0].rma_ids)
|
636
695
|
self.assertTrue(origin_moves[1].rma_ids)
|
637
|
-
rmas = origin_moves.
|
696
|
+
rmas = origin_moves.rma_ids
|
638
697
|
self.assertEqual(rmas.mapped("state"), ["confirmed"] * 2)
|
639
698
|
# Each reception move is linked one of the generated RMAs
|
640
699
|
reception = self.env["stock.picking"].browse(picking_action["res_id"])
|
641
700
|
reception_moves = reception.move_ids
|
642
701
|
self.assertTrue(reception_moves[0].rma_receiver_ids)
|
643
702
|
self.assertTrue(reception_moves[1].rma_receiver_ids)
|
644
|
-
self.assertEqual(reception_moves.
|
703
|
+
self.assertEqual(reception_moves.rma_receiver_ids, rmas)
|
645
704
|
# Validate the reception picking to set rmas to 'received' state
|
646
705
|
reception_moves[0].quantity_done = reception_moves[0].product_uom_qty
|
647
706
|
reception_moves[1].quantity_done = reception_moves[1].product_uom_qty
|
@@ -1,8 +1,25 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
|
+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
|
2
3
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
4
|
+
from copy import deepcopy
|
3
5
|
|
4
6
|
from odoo import _, api, fields, models
|
5
7
|
from odoo.exceptions import ValidationError
|
8
|
+
from odoo.tools import float_compare
|
9
|
+
|
10
|
+
|
11
|
+
class ReturnPickingLine(models.TransientModel):
|
12
|
+
_inherit = "stock.return.picking.line"
|
13
|
+
|
14
|
+
def _prepare_rma_vals(self):
|
15
|
+
self.ensure_one()
|
16
|
+
return {
|
17
|
+
"move_id": self.move_id.id,
|
18
|
+
"product_id": self.move_id.product_id.id,
|
19
|
+
"product_uom_qty": self.quantity,
|
20
|
+
"product_uom": self.product_id.uom_id.id,
|
21
|
+
"location_id": self.wizard_id.location_id.id or self.move_id.location_id.id,
|
22
|
+
}
|
6
23
|
|
7
24
|
|
8
25
|
class ReturnPicking(models.TransientModel):
|
@@ -48,6 +65,52 @@ class ReturnPicking(models.TransientModel):
|
|
48
65
|
location_id = return_picking_type.default_location_dest_id.id
|
49
66
|
self.location_id = location_id
|
50
67
|
|
68
|
+
def _prepare_rma_partner_values(self):
|
69
|
+
self.ensure_one()
|
70
|
+
partner = self.picking_id.partner_id
|
71
|
+
partner_address = partner.address_get(["invoice", "delivery"])
|
72
|
+
partner_invoice_id = partner_address.get("invoice", False)
|
73
|
+
partner_shipping_id = partner_address.get("delivery", False)
|
74
|
+
return (
|
75
|
+
partner,
|
76
|
+
partner_invoice_id and partner.browse(partner_invoice_id) or partner,
|
77
|
+
partner_shipping_id and partner.browse(partner_shipping_id) or partner,
|
78
|
+
)
|
79
|
+
|
80
|
+
def _prepare_rma_vals(self):
|
81
|
+
partner, partner_invoice, partner_shipping = self._prepare_rma_partner_values()
|
82
|
+
origin = self.picking_id.name
|
83
|
+
vals = self.env["rma"]._prepare_procurement_group_vals()
|
84
|
+
vals["partner_id"] = partner_shipping.id
|
85
|
+
vals["name"] = origin
|
86
|
+
group = self.env["procurement.group"].create(vals)
|
87
|
+
return {
|
88
|
+
"user_id": self.env.user.id,
|
89
|
+
"partner_id": partner.id,
|
90
|
+
"partner_shipping_id": partner_shipping.id,
|
91
|
+
"partner_invoice_id": partner_invoice.id,
|
92
|
+
"origin": origin,
|
93
|
+
"picking_id": self.picking_id.id,
|
94
|
+
"company_id": self.company_id.id,
|
95
|
+
"procurement_group_id": group.id,
|
96
|
+
}
|
97
|
+
|
98
|
+
def _prepare_rma_vals_list(self):
|
99
|
+
vals_list = []
|
100
|
+
for return_picking in self:
|
101
|
+
global_vals = return_picking._prepare_rma_vals()
|
102
|
+
for line in return_picking.product_return_moves:
|
103
|
+
if (
|
104
|
+
not line.move_id
|
105
|
+
or float_compare(line.quantity, 0, line.product_id.uom_id.rounding)
|
106
|
+
<= 0
|
107
|
+
):
|
108
|
+
continue
|
109
|
+
vals = deepcopy(global_vals)
|
110
|
+
vals.update(line._prepare_rma_vals())
|
111
|
+
vals_list.append(vals)
|
112
|
+
return vals_list
|
113
|
+
|
51
114
|
def create_returns(self):
|
52
115
|
"""Override create_returns method for creating one or more
|
53
116
|
'confirmed' RMAs after return a delivery picking in case
|
@@ -57,10 +120,6 @@ class ReturnPicking(models.TransientModel):
|
|
57
120
|
as the 'Receipt'.
|
58
121
|
"""
|
59
122
|
if self.create_rma:
|
60
|
-
# set_rma_picking_type is to override the copy() method of stock
|
61
|
-
# picking and change the default picking type to rma picking type
|
62
|
-
self_with_context = self.with_context(set_rma_picking_type=True)
|
63
|
-
res = super(ReturnPicking, self_with_context).create_returns()
|
64
123
|
if not self.picking_id.partner_id:
|
65
124
|
raise ValidationError(
|
66
125
|
_(
|
@@ -68,12 +127,30 @@ class ReturnPicking(models.TransientModel):
|
|
68
127
|
"'Stock Picking' from which RMAs will be created"
|
69
128
|
)
|
70
129
|
)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
]
|
76
|
-
self.env
|
77
|
-
|
78
|
-
|
79
|
-
|
130
|
+
vals_list = self._prepare_rma_vals_list()
|
131
|
+
rmas = self.env["rma"].create(vals_list)
|
132
|
+
rmas.action_confirm()
|
133
|
+
picking = rmas.reception_move_id.picking_id
|
134
|
+
picking = picking and picking[0] or picking
|
135
|
+
ctx = dict(self.env.context)
|
136
|
+
ctx.update(
|
137
|
+
{
|
138
|
+
"default_partner_id": picking.partner_id.id,
|
139
|
+
"search_default_picking_type_id": picking.picking_type_id.id,
|
140
|
+
"search_default_draft": False,
|
141
|
+
"search_default_assigned": False,
|
142
|
+
"search_default_confirmed": False,
|
143
|
+
"search_default_ready": False,
|
144
|
+
"search_default_planning_issues": False,
|
145
|
+
"search_default_available": False,
|
146
|
+
}
|
147
|
+
)
|
148
|
+
return {
|
149
|
+
"name": _("Returned Picking"),
|
150
|
+
"view_mode": "form,tree,calendar",
|
151
|
+
"res_model": "stock.picking",
|
152
|
+
"res_id": picking.id,
|
153
|
+
"type": "ir.actions.act_window",
|
154
|
+
"context": ctx,
|
155
|
+
}
|
156
|
+
return super().create_returns()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: odoo-addon-rma
|
3
|
-
Version: 16.0.
|
3
|
+
Version: 16.0.2.0.0.1
|
4
4
|
Summary: Return Merchandise Authorization (RMA)
|
5
5
|
Home-page: https://github.com/OCA/rma
|
6
6
|
Author: Tecnativa, Odoo Community Association (OCA)
|
@@ -24,7 +24,7 @@ Return Merchandise Authorization Management
|
|
24
24
|
!! This file is generated by oca-gen-addon-readme !!
|
25
25
|
!! changes will be overwritten. !!
|
26
26
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
27
|
-
!! source digest: sha256:
|
27
|
+
!! source digest: sha256:62d0c2b19f67175025b621f74656297363fe9b028799723026166ed8d24b7b8b
|
28
28
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
29
29
|
|
30
30
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
|
@@ -151,6 +151,9 @@ Known issues / Roadmap
|
|
151
151
|
* As soon as the picking is selected, the user should select the move,
|
152
152
|
but perhaps stock.move _rec_name could be improved to better show what
|
153
153
|
the product of that move is.
|
154
|
+
* Add RMA reception and/or RMA delivery on several steps - 2 or 3 - like
|
155
|
+
normal receptions/deliveries. It should be a separate option inside the
|
156
|
+
warehouse definition.
|
154
157
|
|
155
158
|
Bug Tracker
|
156
159
|
===========
|
@@ -182,6 +185,7 @@ Contributors
|
|
182
185
|
|
183
186
|
* Chafique Delli <chafique.delli@akretion.com>
|
184
187
|
* Giovanni Serra - Ooops <giovanni@ooops404.com>
|
188
|
+
* Michael Tietz (MT Software) <mtietz@mt-software.de>
|
185
189
|
|
186
190
|
Maintainers
|
187
191
|
~~~~~~~~~~~
|