odoo-addon-rma 16.0.3.6.0.2__py3-none-any.whl → 16.0.5.0.0__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 +1 -1
- odoo/addons/rma/__manifest__.py +3 -1
- odoo/addons/rma/i18n/de.po +85 -0
- odoo/addons/rma/i18n/de_AT.po +85 -0
- odoo/addons/rma/i18n/es.po +85 -0
- odoo/addons/rma/i18n/fr.po +85 -0
- odoo/addons/rma/i18n/it.po +85 -0
- odoo/addons/rma/i18n/nl.po +85 -0
- odoo/addons/rma/i18n/pt.po +85 -0
- odoo/addons/rma/i18n/pt_BR.po +85 -0
- odoo/addons/rma/i18n/rma.pot +225 -0
- odoo/addons/rma/i18n/ro.po +85 -0
- odoo/addons/rma/i18n/zh_CN.po +85 -0
- odoo/addons/rma/models/rma.py +160 -15
- odoo/addons/rma/models/rma_operation.py +148 -1
- odoo/addons/rma/static/description/index.html +1 -1
- odoo/addons/rma/tests/__init__.py +2 -0
- odoo/addons/rma/tests/test_rma_dashboard.py +73 -0
- odoo/addons/rma/tests/test_rma_operation.py +317 -0
- odoo/addons/rma/views/dashboard.xml +188 -0
- odoo/addons/rma/views/rma_operation.xml +85 -0
- odoo/addons/rma/views/rma_views.xml +32 -6
- odoo/addons/rma/wizard/stock_picking_return.py +9 -0
- odoo/addons/rma/wizard/stock_picking_return_views.xml +5 -0
- {odoo_addon_rma-16.0.3.6.0.2.dist-info → odoo_addon_rma-16.0.5.0.0.dist-info}/METADATA +2 -2
- {odoo_addon_rma-16.0.3.6.0.2.dist-info → odoo_addon_rma-16.0.5.0.0.dist-info}/RECORD +28 -24
- {odoo_addon_rma-16.0.3.6.0.2.dist-info → odoo_addon_rma-16.0.5.0.0.dist-info}/WHEEL +0 -0
- {odoo_addon_rma-16.0.3.6.0.2.dist-info → odoo_addon_rma-16.0.5.0.0.dist-info}/top_level.txt +0 -0
odoo/addons/rma/i18n/zh_CN.po
CHANGED
@@ -125,6 +125,13 @@ msgid ""
|
|
125
125
|
"title=\"Download\"/>"
|
126
126
|
msgstr ""
|
127
127
|
|
128
|
+
#. module: rma
|
129
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
130
|
+
msgid ""
|
131
|
+
"<i class=\"fa fa-ellipsis-v\" role=\"img\" aria-label=\"Manage\" "
|
132
|
+
"title=\"Manage\"/>"
|
133
|
+
msgstr ""
|
134
|
+
|
128
135
|
#. module: rma
|
129
136
|
#: model_terms:ir.ui.view,arch_db:rma.portal_rma_page
|
130
137
|
msgid ""
|
@@ -236,6 +243,26 @@ msgid ""
|
|
236
243
|
"specific.\" groups=\"base.group_multi_company\"/>"
|
237
244
|
msgstr ""
|
238
245
|
|
246
|
+
#. module: rma
|
247
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
248
|
+
msgid "<span>Awaiting action</span>"
|
249
|
+
msgstr ""
|
250
|
+
|
251
|
+
#. module: rma
|
252
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
253
|
+
msgid "<span>Draft</span>"
|
254
|
+
msgstr ""
|
255
|
+
|
256
|
+
#. module: rma
|
257
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
258
|
+
msgid "<span>New</span>"
|
259
|
+
msgstr ""
|
260
|
+
|
261
|
+
#. module: rma
|
262
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
263
|
+
msgid "<span>Processed</span>"
|
264
|
+
msgstr ""
|
265
|
+
|
239
266
|
#. module: rma
|
240
267
|
#: model_terms:ir.ui.view,arch_db:rma.portal_rma_page
|
241
268
|
msgid "<strong class=\"d-block mb-1\">Delivery</strong>"
|
@@ -444,7 +471,10 @@ msgid "Avatar"
|
|
444
471
|
msgstr ""
|
445
472
|
|
446
473
|
#. module: rma
|
474
|
+
#. odoo-python
|
475
|
+
#: code:addons/rma/models/rma_operation.py:0
|
447
476
|
#: model_terms:ir.ui.view,arch_db:rma.rma_view_search
|
477
|
+
#, python-format
|
448
478
|
msgid "Awaiting Action"
|
449
479
|
msgstr ""
|
450
480
|
|
@@ -512,6 +542,11 @@ msgstr ""
|
|
512
542
|
msgid "Closed"
|
513
543
|
msgstr ""
|
514
544
|
|
545
|
+
#. module: rma
|
546
|
+
#: model:ir.model.fields,field_description:rma.field_rma_operation__color
|
547
|
+
msgid "Color"
|
548
|
+
msgstr ""
|
549
|
+
|
515
550
|
#. module: rma
|
516
551
|
#: model:ir.model.fields,field_description:rma.field_rma_tag__color
|
517
552
|
msgid "Color Index"
|
@@ -546,6 +581,7 @@ msgstr ""
|
|
546
581
|
|
547
582
|
#. module: rma
|
548
583
|
#: model:ir.ui.menu,name:rma.rma_configuration_menu
|
584
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
549
585
|
msgid "Configuration"
|
550
586
|
msgstr ""
|
551
587
|
|
@@ -574,6 +610,21 @@ msgid ""
|
|
574
610
|
"same category. The conversion will be made based on the ratios."
|
575
611
|
msgstr ""
|
576
612
|
|
613
|
+
#. module: rma
|
614
|
+
#: model:ir.model.fields,field_description:rma.field_rma_operation__count_rma_awaiting_action
|
615
|
+
msgid "Count Rma Awaiting Action"
|
616
|
+
msgstr ""
|
617
|
+
|
618
|
+
#. module: rma
|
619
|
+
#: model:ir.model.fields,field_description:rma.field_rma_operation__count_rma_draft
|
620
|
+
msgid "Count Rma Draft"
|
621
|
+
msgstr ""
|
622
|
+
|
623
|
+
#. module: rma
|
624
|
+
#: model:ir.model.fields,field_description:rma.field_rma_operation__count_rma_processed
|
625
|
+
msgid "Count Rma Processed"
|
626
|
+
msgstr ""
|
627
|
+
|
577
628
|
#. module: rma
|
578
629
|
#: model:ir.model.fields,field_description:rma.field_stock_return_picking__create_rma
|
579
630
|
msgid "Create RMAs"
|
@@ -584,6 +635,11 @@ msgstr ""
|
|
584
635
|
msgid "Create a new RMA finalization"
|
585
636
|
msgstr ""
|
586
637
|
|
638
|
+
#. module: rma
|
639
|
+
#: model_terms:ir.actions.act_window,help:rma.rma_dashboard_action
|
640
|
+
msgid "Create a new RMA operation"
|
641
|
+
msgstr ""
|
642
|
+
|
587
643
|
#. module: rma
|
588
644
|
#: model_terms:ir.actions.act_window,help:rma.action_rma_tag
|
589
645
|
msgid "Create a new RMA tag"
|
@@ -711,8 +767,11 @@ msgid "Display Name"
|
|
711
767
|
msgstr ""
|
712
768
|
|
713
769
|
#. module: rma
|
770
|
+
#. odoo-python
|
771
|
+
#: code:addons/rma/models/rma_operation.py:0
|
714
772
|
#: model:ir.model.fields.selection,name:rma.selection__rma__state__draft
|
715
773
|
#: model_terms:ir.ui.view,arch_db:rma.rma_view_search
|
774
|
+
#, python-format
|
716
775
|
msgid "Draft"
|
717
776
|
msgstr ""
|
718
777
|
|
@@ -1077,6 +1136,11 @@ msgstr ""
|
|
1077
1136
|
msgid "New"
|
1078
1137
|
msgstr ""
|
1079
1138
|
|
1139
|
+
#. module: rma
|
1140
|
+
#: model:ir.actions.act_window,name:rma.action_rma_form
|
1141
|
+
msgid "New RMA"
|
1142
|
+
msgstr ""
|
1143
|
+
|
1080
1144
|
#. module: rma
|
1081
1145
|
#: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline
|
1082
1146
|
msgid "Next Activity Deadline"
|
@@ -1173,6 +1237,11 @@ msgstr ""
|
|
1173
1237
|
msgid "Other Information"
|
1174
1238
|
msgstr ""
|
1175
1239
|
|
1240
|
+
#. module: rma
|
1241
|
+
#: model:ir.ui.menu,name:rma.rma_dashboard_menu
|
1242
|
+
msgid "Overview"
|
1243
|
+
msgstr ""
|
1244
|
+
|
1176
1245
|
#. module: rma
|
1177
1246
|
#: model:ir.model.fields,field_description:rma.field_rma_team__alias_user_id
|
1178
1247
|
msgid "Owner"
|
@@ -1227,7 +1296,10 @@ msgid "Priority"
|
|
1227
1296
|
msgstr ""
|
1228
1297
|
|
1229
1298
|
#. module: rma
|
1299
|
+
#. odoo-python
|
1300
|
+
#: code:addons/rma/models/rma_operation.py:0
|
1230
1301
|
#: model_terms:ir.ui.view,arch_db:rma.rma_view_search
|
1302
|
+
#, python-format
|
1231
1303
|
msgid "Processed"
|
1232
1304
|
msgstr ""
|
1233
1305
|
|
@@ -1296,6 +1368,7 @@ msgstr ""
|
|
1296
1368
|
#: model:ir.module.category,name:rma.rma_module_category
|
1297
1369
|
#: model:ir.ui.menu,name:rma.rma_menu
|
1298
1370
|
#: model_terms:ir.ui.view,arch_db:rma.res_config_settings_view_form
|
1371
|
+
#: model_terms:ir.ui.view,arch_db:rma.rma_operation_kanban
|
1299
1372
|
#: model_terms:ir.ui.view,arch_db:rma.view_partner_form
|
1300
1373
|
#: model_terms:ir.ui.view,arch_db:rma.view_picking_form
|
1301
1374
|
msgid "RMA"
|
@@ -1407,6 +1480,11 @@ msgstr ""
|
|
1407
1480
|
msgid "RMA Out Type"
|
1408
1481
|
msgstr ""
|
1409
1482
|
|
1483
|
+
#. module: rma
|
1484
|
+
#: model:ir.actions.act_window,name:rma.rma_dashboard_action
|
1485
|
+
msgid "RMA Overview"
|
1486
|
+
msgstr ""
|
1487
|
+
|
1410
1488
|
#. module: rma
|
1411
1489
|
#: model_terms:ir.ui.view,arch_db:rma.res_config_settings_view_form
|
1412
1490
|
msgid "RMA Receipt Confirmation Email"
|
@@ -1945,6 +2023,13 @@ msgstr ""
|
|
1945
2023
|
msgid "That operation name already exists !"
|
1946
2024
|
msgstr ""
|
1947
2025
|
|
2026
|
+
#. module: rma
|
2027
|
+
#: model_terms:ir.actions.act_window,help:rma.rma_dashboard_action
|
2028
|
+
msgid ""
|
2029
|
+
"The RMA operation system allows you to configure each return operation\n"
|
2030
|
+
" with specific settings that will adjust its behavior."
|
2031
|
+
msgstr ""
|
2032
|
+
|
1948
2033
|
#. module: rma
|
1949
2034
|
#: model:ir.model.fields,help:rma.field_rma_tag__active
|
1950
2035
|
msgid "The active field allows you to hide the category without removing it."
|
odoo/addons/rma/models/rma.py
CHANGED
@@ -317,6 +317,63 @@ class Rma(models.Model):
|
|
317
317
|
copy=False,
|
318
318
|
)
|
319
319
|
|
320
|
+
show_create_receipt = fields.Boolean(
|
321
|
+
string="Show Create Receipt Button", compute="_compute_show_create_receipt"
|
322
|
+
)
|
323
|
+
show_create_return = fields.Boolean(
|
324
|
+
string="Show Create Return Button", compute="_compute_show_create_return"
|
325
|
+
)
|
326
|
+
show_create_replace = fields.Boolean(
|
327
|
+
string="Show Create replace Button", compute="_compute_show_create_replace"
|
328
|
+
)
|
329
|
+
show_create_refund = fields.Boolean(
|
330
|
+
string="Show Create refund Button", compute="_compute_show_refund_replace"
|
331
|
+
)
|
332
|
+
return_product_id = fields.Many2one(
|
333
|
+
"product.product",
|
334
|
+
help="Product to be returned if it's different from the originally delivered "
|
335
|
+
"item.",
|
336
|
+
)
|
337
|
+
different_return_product = fields.Boolean(
|
338
|
+
related="operation_id.different_return_product"
|
339
|
+
)
|
340
|
+
|
341
|
+
@api.depends("operation_id.action_create_receipt", "state", "reception_move_id")
|
342
|
+
def _compute_show_create_receipt(self):
|
343
|
+
for rec in self:
|
344
|
+
rec.show_create_receipt = (
|
345
|
+
not rec.reception_move_id
|
346
|
+
and rec.operation_id.action_create_receipt == "manual_on_confirm"
|
347
|
+
and rec.state == "confirmed"
|
348
|
+
)
|
349
|
+
|
350
|
+
@api.depends("operation_id.action_create_delivery", "can_be_returned")
|
351
|
+
def _compute_show_create_return(self):
|
352
|
+
for rec in self:
|
353
|
+
rec.show_create_return = (
|
354
|
+
rec.operation_id.action_create_delivery
|
355
|
+
in ("manual_on_confirm", "manual_after_receipt")
|
356
|
+
and rec.can_be_returned
|
357
|
+
)
|
358
|
+
|
359
|
+
@api.depends("operation_id.action_create_delivery", "can_be_replaced")
|
360
|
+
def _compute_show_create_replace(self):
|
361
|
+
for rec in self:
|
362
|
+
rec.show_create_replace = (
|
363
|
+
rec.operation_id.action_create_delivery
|
364
|
+
in ("manual_on_confirm", "manual_after_receipt")
|
365
|
+
and rec.can_be_replaced
|
366
|
+
)
|
367
|
+
|
368
|
+
@api.depends("operation_id.action_create_refund", "can_be_refunded")
|
369
|
+
def _compute_show_refund_replace(self):
|
370
|
+
for rec in self:
|
371
|
+
rec.show_create_refund = (
|
372
|
+
rec.operation_id.action_create_refund
|
373
|
+
in ("manual_on_confirm", "manual_after_receipt")
|
374
|
+
and rec.can_be_refunded
|
375
|
+
)
|
376
|
+
|
320
377
|
def _compute_delivery_picking_count(self):
|
321
378
|
for rma in self:
|
322
379
|
rma.delivery_picking_count = len(rma.delivery_move_ids.picking_id)
|
@@ -394,9 +451,17 @@ class Rma(models.Model):
|
|
394
451
|
an rma can be refunded. It is used in rma.action_refund method.
|
395
452
|
"""
|
396
453
|
for record in self:
|
397
|
-
record.can_be_refunded =
|
454
|
+
record.can_be_refunded = (
|
455
|
+
record.operation_id.action_create_refund
|
456
|
+
in ("manual_after_receipt", "automatic_after_receipt")
|
457
|
+
and record.state == "received"
|
458
|
+
) or (
|
459
|
+
record.operation_id.action_create_refund
|
460
|
+
in ("manual_on_confirm", "automatic_on_confirm")
|
461
|
+
and record.state == "confirmed"
|
462
|
+
)
|
398
463
|
|
399
|
-
@api.depends("remaining_qty", "state")
|
464
|
+
@api.depends("remaining_qty", "state", "operation_id.action_create_delivery")
|
400
465
|
def _compute_can_be_returned(self):
|
401
466
|
"""Compute 'can_be_returned'. This field controls the visibility
|
402
467
|
of the 'Return to customer' button in the rma form
|
@@ -406,8 +471,17 @@ class Rma(models.Model):
|
|
406
471
|
rma._ensure_can_be_returned.
|
407
472
|
"""
|
408
473
|
for r in self:
|
409
|
-
r.can_be_returned = (
|
410
|
-
|
474
|
+
r.can_be_returned = r.remaining_qty > 0 and (
|
475
|
+
(
|
476
|
+
r.operation_id.action_create_delivery
|
477
|
+
in ("manual_after_receipt", "automatic_after_receipt")
|
478
|
+
and r.state in ["received", "waiting_return"]
|
479
|
+
)
|
480
|
+
or (
|
481
|
+
r.operation_id.action_create_delivery
|
482
|
+
in ("manual_on_confirm", "automatic_on_confirm")
|
483
|
+
and r.state == "confirmed"
|
484
|
+
)
|
411
485
|
)
|
412
486
|
|
413
487
|
@api.depends("state")
|
@@ -420,11 +494,20 @@ class Rma(models.Model):
|
|
420
494
|
rma._ensure_can_be_replaced.
|
421
495
|
"""
|
422
496
|
for r in self:
|
423
|
-
r.can_be_replaced =
|
424
|
-
|
425
|
-
"
|
426
|
-
|
427
|
-
|
497
|
+
r.can_be_replaced = (
|
498
|
+
r.operation_id.action_create_delivery
|
499
|
+
in ("manual_after_receipt", "automatic_after_receipt")
|
500
|
+
and r.state
|
501
|
+
in [
|
502
|
+
"received",
|
503
|
+
"waiting_replacement",
|
504
|
+
"replaced",
|
505
|
+
]
|
506
|
+
) or (
|
507
|
+
r.operation_id.action_create_delivery
|
508
|
+
in ("manual_on_confirm", "automatic_on_confirm")
|
509
|
+
and r.state == "confirmed"
|
510
|
+
)
|
428
511
|
|
429
512
|
@api.depends("state", "remaining_qty")
|
430
513
|
def _compute_can_be_finished(self):
|
@@ -699,8 +782,11 @@ class Rma(models.Model):
|
|
699
782
|
vals = self._prepare_common_procurement_vals(group=group)
|
700
783
|
vals["route_ids"] = self.warehouse_id.rma_in_route_id
|
701
784
|
vals["rma_receiver_ids"] = [(6, 0, self.ids)]
|
785
|
+
vals["to_refund"] = self.operation_id.action_create_refund == "update_quantity"
|
702
786
|
if self.move_id:
|
703
787
|
vals["origin_returned_move_id"] = self.move_id.id
|
788
|
+
if not self.operation_id.different_return_product:
|
789
|
+
vals["move_orig_ids"] = [(6, 0, self.move_id.ids)]
|
704
790
|
return vals
|
705
791
|
|
706
792
|
def _prepare_reception_procurements(self):
|
@@ -712,13 +798,24 @@ class Rma(models.Model):
|
|
712
798
|
group = rma.procurement_group_id
|
713
799
|
if not group:
|
714
800
|
group = group_model.create(rma._prepare_procurement_group_vals())
|
801
|
+
product = self.product_id
|
802
|
+
if self.different_return_product:
|
803
|
+
if not self.return_product_id:
|
804
|
+
raise ValidationError(
|
805
|
+
_(
|
806
|
+
"The selected operation requires a return product different"
|
807
|
+
" from the originally delivered item. Please select the "
|
808
|
+
"product to return."
|
809
|
+
)
|
810
|
+
)
|
811
|
+
product = self.return_product_id
|
715
812
|
procurements.append(
|
716
813
|
group_model.Procurement(
|
717
|
-
|
814
|
+
product,
|
718
815
|
rma.product_uom_qty,
|
719
816
|
rma.product_uom,
|
720
817
|
rma.location_id,
|
721
|
-
|
818
|
+
product.display_name,
|
722
819
|
group.name,
|
723
820
|
rma.company_id,
|
724
821
|
rma._prepare_reception_procurement_vals(group),
|
@@ -726,20 +823,54 @@ class Rma(models.Model):
|
|
726
823
|
)
|
727
824
|
return procurements
|
728
825
|
|
826
|
+
def _create_receipt(self):
|
827
|
+
procurements = self._prepare_reception_procurements()
|
828
|
+
if procurements:
|
829
|
+
self.env["procurement.group"].run(procurements)
|
830
|
+
self.reception_move_id.picking_id.action_assign()
|
831
|
+
if self.operation_id.auto_confirm_reception:
|
832
|
+
self.reception_move_id._set_quantities_to_reservation()
|
833
|
+
self.reception_move_id._action_done()
|
834
|
+
|
835
|
+
def action_create_receipt(self):
|
836
|
+
self.ensure_one()
|
837
|
+
self._create_receipt()
|
838
|
+
self.ensure_one()
|
839
|
+
return {
|
840
|
+
"name": _("Receipt"),
|
841
|
+
"type": "ir.actions.act_window",
|
842
|
+
"view_type": "form",
|
843
|
+
"view_mode": "form",
|
844
|
+
"res_model": "stock.picking",
|
845
|
+
"views": [[False, "form"]],
|
846
|
+
"res_id": self.reception_move_id.picking_id.id,
|
847
|
+
}
|
848
|
+
|
729
849
|
def action_confirm(self):
|
730
850
|
"""Invoked when 'Confirm' button in rma form view is clicked."""
|
731
851
|
self._ensure_required_fields()
|
732
852
|
self = self.filtered(lambda rma: rma.state == "draft")
|
733
853
|
if not self:
|
734
854
|
return
|
735
|
-
procurements = self._prepare_reception_procurements()
|
736
|
-
if procurements:
|
737
|
-
self.env["procurement.group"].run(procurements)
|
738
|
-
self.reception_move_id.picking_id.action_assign()
|
739
855
|
self.write({"state": "confirmed"})
|
740
856
|
for rma in self:
|
741
857
|
rma._add_message_subscribe_partner()
|
742
858
|
self._send_confirmation_email()
|
859
|
+
for rec in self:
|
860
|
+
if rec.operation_id.action_create_receipt == "automatic_on_confirm":
|
861
|
+
rec._create_receipt()
|
862
|
+
if rec.operation_id.action_create_delivery == "automatic_on_confirm":
|
863
|
+
rec.with_context(
|
864
|
+
rma_return_grouping=rec.env.company.rma_return_grouping
|
865
|
+
).create_replace(
|
866
|
+
fields.Datetime.now(),
|
867
|
+
rec.warehouse_id,
|
868
|
+
rec.product_id,
|
869
|
+
rec.product_uom_qty,
|
870
|
+
rec.product_uom,
|
871
|
+
)
|
872
|
+
if rec.operation_id.action_create_refund == "automatic_on_confirm":
|
873
|
+
rec.action_refund()
|
743
874
|
|
744
875
|
def action_refund(self):
|
745
876
|
"""Invoked when 'Refund' button in rma form view is clicked
|
@@ -1377,6 +1508,20 @@ class Rma(models.Model):
|
|
1377
1508
|
"""
|
1378
1509
|
self.write({"state": "received"})
|
1379
1510
|
self._send_receipt_confirmation_email()
|
1511
|
+
for rec in self:
|
1512
|
+
if rec.operation_id.action_create_delivery == "automatic_after_receipt":
|
1513
|
+
rec.with_context(
|
1514
|
+
rma_return_grouping=rec.env.company.rma_return_grouping
|
1515
|
+
).create_replace(
|
1516
|
+
fields.Datetime.now(),
|
1517
|
+
rec.warehouse_id,
|
1518
|
+
rec.product_id,
|
1519
|
+
rec.product_uom_qty,
|
1520
|
+
rec.product_uom,
|
1521
|
+
)
|
1522
|
+
|
1523
|
+
if rec.operation_id.action_create_refund == "automatic_after_receipt":
|
1524
|
+
rec.action_refund()
|
1380
1525
|
|
1381
1526
|
def update_received_state(self):
|
1382
1527
|
"""Invoked by:
|
@@ -1,7 +1,14 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
2
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
3
|
|
4
|
-
from
|
4
|
+
from ast import literal_eval
|
5
|
+
from collections import defaultdict
|
6
|
+
|
7
|
+
from odoo import _, api, fields, models
|
8
|
+
from odoo.osv.expression import AND
|
9
|
+
|
10
|
+
PROCESSED_STATES = ["received", "refunded", "replaced", "finished"]
|
11
|
+
AWAITING_ACTION_STATES = ["waiting_return", "waiting_replacement", "confirmed"]
|
5
12
|
|
6
13
|
|
7
14
|
class RmaOperation(models.Model):
|
@@ -10,7 +17,147 @@ class RmaOperation(models.Model):
|
|
10
17
|
|
11
18
|
active = fields.Boolean(default=True)
|
12
19
|
name = fields.Char(required=True, translate=True)
|
20
|
+
color = fields.Integer()
|
21
|
+
count_rma_draft = fields.Integer(compute="_compute_count_rma")
|
22
|
+
count_rma_awaiting_action = fields.Integer(compute="_compute_count_rma")
|
23
|
+
count_rma_processed = fields.Integer(compute="_compute_count_rma")
|
24
|
+
action_create_receipt = fields.Selection(
|
25
|
+
[
|
26
|
+
("manual_on_confirm", "Manually on Confirm"),
|
27
|
+
("automatic_on_confirm", "Automatically on Confirm"),
|
28
|
+
],
|
29
|
+
string="Create Receipt",
|
30
|
+
default="automatic_on_confirm",
|
31
|
+
help="Define how the receipt action should be handled.",
|
32
|
+
)
|
33
|
+
different_return_product = fields.Boolean(
|
34
|
+
help="If checked, allows the return of a product different from the one "
|
35
|
+
"originally ordered. Used if the delivery is created automatically",
|
36
|
+
)
|
37
|
+
auto_confirm_reception = fields.Boolean(
|
38
|
+
help="Enable this option to automatically confirm the reception when the RMA is"
|
39
|
+
" confirmed."
|
40
|
+
)
|
41
|
+
action_create_delivery = fields.Selection(
|
42
|
+
[
|
43
|
+
("manual_on_confirm", "Manually on Confirm"),
|
44
|
+
("automatic_on_confirm", "Automatically on Confirm"),
|
45
|
+
("manual_after_receipt", "Manually After Receipt"),
|
46
|
+
("automatic_after_receipt", "Automatically After Receipt"),
|
47
|
+
],
|
48
|
+
string="Delivery Action",
|
49
|
+
help="Define how the delivery action should be handled.",
|
50
|
+
default="manual_after_receipt",
|
51
|
+
)
|
52
|
+
action_create_refund = fields.Selection(
|
53
|
+
[
|
54
|
+
("manual_on_confirm", "Manually on Confirm"),
|
55
|
+
("automatic_on_confirm", "Automatically on Confirm"),
|
56
|
+
("manual_after_receipt", "Manually After Receipt"),
|
57
|
+
("automatic_after_receipt", "Automatically After Receipt"),
|
58
|
+
("update_quantity", "Update Quantities"),
|
59
|
+
],
|
60
|
+
string="Refund Action",
|
61
|
+
default="manual_after_receipt",
|
62
|
+
help="Define how the refund action should be handled.",
|
63
|
+
)
|
13
64
|
|
14
65
|
_sql_constraints = [
|
15
66
|
("name_uniq", "unique (name)", "That operation name already exists !"),
|
16
67
|
]
|
68
|
+
|
69
|
+
@api.model
|
70
|
+
def _get_rma_draft_domain(self):
|
71
|
+
return [("state", "=", "draft")]
|
72
|
+
|
73
|
+
@api.model
|
74
|
+
def _get_rma_awaiting_action_domain(self):
|
75
|
+
return [("state", "in", AWAITING_ACTION_STATES)]
|
76
|
+
|
77
|
+
@api.model
|
78
|
+
def _get_rma_processed_domain(self):
|
79
|
+
return [("state", "in", PROCESSED_STATES)]
|
80
|
+
|
81
|
+
def _compute_count_rma(self):
|
82
|
+
self.update(
|
83
|
+
{
|
84
|
+
"count_rma_draft": 0,
|
85
|
+
"count_rma_processed": 0,
|
86
|
+
"count_rma_awaiting_action": 0,
|
87
|
+
}
|
88
|
+
)
|
89
|
+
state_by_op = defaultdict(int)
|
90
|
+
for group in self.env["rma"].read_group(
|
91
|
+
AND([[("operation_id", "!=", False)]]),
|
92
|
+
groupby=["operation_id", "state"],
|
93
|
+
fields=["id"],
|
94
|
+
lazy=False,
|
95
|
+
):
|
96
|
+
operation_id = group.get("operation_id")[0]
|
97
|
+
state = group.get("state")
|
98
|
+
count = group.get("__count")
|
99
|
+
if state == "draft":
|
100
|
+
state_by_op[(operation_id, "count_rma_draft")] += count
|
101
|
+
if state in PROCESSED_STATES:
|
102
|
+
state_by_op[(operation_id, "count_rma_processed")] += count
|
103
|
+
if state in AWAITING_ACTION_STATES:
|
104
|
+
state_by_op[(operation_id, "count_rma_awaiting_action")] += count
|
105
|
+
for (operation_id, field), count in state_by_op.items():
|
106
|
+
self.browse(operation_id).update({field: count})
|
107
|
+
|
108
|
+
def _get_action(self, name, domain):
|
109
|
+
action = self.env["ir.actions.actions"]._for_xml_id("rma.rma_action")
|
110
|
+
action["display_name"] = name
|
111
|
+
context = {
|
112
|
+
"search_default_operation_id": [self.id],
|
113
|
+
"default_operation_id": self.id,
|
114
|
+
}
|
115
|
+
action_context = literal_eval(action["context"])
|
116
|
+
context = {**action_context, **context}
|
117
|
+
action["context"] = context
|
118
|
+
action["domain"] = domain
|
119
|
+
return action
|
120
|
+
|
121
|
+
def get_action_rma_tree_draft(self):
|
122
|
+
self.ensure_one()
|
123
|
+
name = self.display_name + ": " + _("Draft")
|
124
|
+
return self._get_action(
|
125
|
+
name,
|
126
|
+
domain=AND(
|
127
|
+
[
|
128
|
+
[("operation_id", "=", self.id)],
|
129
|
+
self._get_rma_draft_domain(),
|
130
|
+
]
|
131
|
+
),
|
132
|
+
)
|
133
|
+
|
134
|
+
def get_action_rma_tree_awaiting_action(self):
|
135
|
+
self.ensure_one()
|
136
|
+
name = self.display_name + ": " + _("Awaiting Action")
|
137
|
+
return self._get_action(
|
138
|
+
name,
|
139
|
+
domain=AND(
|
140
|
+
[
|
141
|
+
[("operation_id", "=", self.id)],
|
142
|
+
self._get_rma_awaiting_action_domain(),
|
143
|
+
]
|
144
|
+
),
|
145
|
+
)
|
146
|
+
|
147
|
+
def get_action_rma_tree_processed(self):
|
148
|
+
self.ensure_one()
|
149
|
+
name = self.display_name + ": " + _("Processed")
|
150
|
+
return self._get_action(
|
151
|
+
name,
|
152
|
+
domain=AND(
|
153
|
+
[
|
154
|
+
[("operation_id", "=", self.id)],
|
155
|
+
self._get_rma_processed_domain(),
|
156
|
+
]
|
157
|
+
),
|
158
|
+
)
|
159
|
+
|
160
|
+
def get_action_all_rma(self):
|
161
|
+
self.ensure_one()
|
162
|
+
name = self.display_name
|
163
|
+
return self._get_action(name, domain=[("operation_id", "=", self.id)])
|
@@ -367,7 +367,7 @@ ul.auto-toc {
|
|
367
367
|
!! This file is generated by oca-gen-addon-readme !!
|
368
368
|
!! changes will be overwritten. !!
|
369
369
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
370
|
-
!! source digest: sha256:
|
370
|
+
!! source digest: sha256:db1b39424a93fe4f3c6ffccfa616d7a490b2bed08da3749b27dc85edbeee3da6
|
371
371
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
372
372
|
<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>
|
373
373
|
<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>.
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Copyright 2024 ACSONE SA/NV
|
2
|
+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
3
|
+
|
4
|
+
from .test_rma import TestRma
|
5
|
+
|
6
|
+
PROCESSED_STATES = ["received", "refunded", "replaced", "finished"]
|
7
|
+
AWAITING_ACTION_STATES = ["waiting_return", "waiting_replacement", "confirmed"]
|
8
|
+
|
9
|
+
|
10
|
+
class TestRmaDashboard(TestRma):
|
11
|
+
def test_0(self):
|
12
|
+
operation_replace = self.env.ref("rma.rma_operation_replace")
|
13
|
+
operation_return = self.env.ref("rma.rma_operation_return")
|
14
|
+
operation_refund = self.env.ref("rma.rma_operation_refund")
|
15
|
+
replace_draft_1 = self._create_rma(
|
16
|
+
self.partner, self.product, 1, self.rma_loc, operation=operation_replace
|
17
|
+
)
|
18
|
+
self._create_rma(
|
19
|
+
self.partner, self.product, 1, self.rma_loc, operation=operation_replace
|
20
|
+
) # replace_draft_2
|
21
|
+
replace_draft_1.copy({"state": "confirmed"}) # replace_confirmed
|
22
|
+
replace_draft_1.copy({"state": "received"}) # replace_received
|
23
|
+
replace_draft_1.copy({"state": "waiting_return"}) # replace_waiting_return
|
24
|
+
replace_draft_1.copy( # replace_waiting_replacement
|
25
|
+
{"state": "waiting_replacement"}
|
26
|
+
)
|
27
|
+
return_draft = self._create_rma(
|
28
|
+
self.partner, self.product, 1, self.rma_loc, operation=operation_return
|
29
|
+
)
|
30
|
+
return_draft.copy({"state": "confirmed"}) # return_confirmed
|
31
|
+
return_draft.copy({"state": "waiting_return"}) # return_waiting_return
|
32
|
+
return_draft.copy({"state": "returned"}) # return_returned
|
33
|
+
return_draft.copy({"state": "finished"}) # return_finished
|
34
|
+
refund_draft = self._create_rma(
|
35
|
+
self.partner, self.product, 1, self.rma_loc, operation=operation_refund
|
36
|
+
)
|
37
|
+
refund_draft.copy({"state": "finished"}) # refund_refunded
|
38
|
+
|
39
|
+
self.assertEqual(operation_replace.count_rma_draft, 2)
|
40
|
+
self.assertEqual(operation_replace.count_rma_awaiting_action, 3)
|
41
|
+
self.assertEqual(operation_replace.count_rma_processed, 1)
|
42
|
+
|
43
|
+
self.assertEqual(operation_return.count_rma_draft, 1)
|
44
|
+
self.assertEqual(operation_return.count_rma_awaiting_action, 2)
|
45
|
+
self.assertEqual(operation_return.count_rma_processed, 1)
|
46
|
+
|
47
|
+
self.assertEqual(operation_refund.count_rma_draft, 1)
|
48
|
+
self.assertEqual(operation_refund.count_rma_awaiting_action, 0)
|
49
|
+
self.assertEqual(operation_refund.count_rma_processed, 1)
|
50
|
+
|
51
|
+
action = operation_replace.get_action_rma_tree_draft()
|
52
|
+
self.assertListEqual(
|
53
|
+
["&", ("operation_id", "=", operation_replace.id), ("state", "=", "draft")],
|
54
|
+
action.get("domain"),
|
55
|
+
)
|
56
|
+
action = operation_replace.get_action_rma_tree_awaiting_action()
|
57
|
+
self.assertListEqual(
|
58
|
+
[
|
59
|
+
"&",
|
60
|
+
("operation_id", "=", operation_replace.id),
|
61
|
+
("state", "in", AWAITING_ACTION_STATES),
|
62
|
+
],
|
63
|
+
action.get("domain"),
|
64
|
+
)
|
65
|
+
action = operation_replace.get_action_rma_tree_processed()
|
66
|
+
self.assertListEqual(
|
67
|
+
[
|
68
|
+
"&",
|
69
|
+
("operation_id", "=", operation_replace.id),
|
70
|
+
("state", "in", PROCESSED_STATES),
|
71
|
+
],
|
72
|
+
action.get("domain"),
|
73
|
+
)
|