odoo-addon-rma 17.0.1.1.1__py3-none-any.whl → 17.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 +6 -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 +22 -0
- odoo/addons/rma/i18n/it.po +22 -0
- 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/17.0.1.2.0/post-migration.py +17 -0
- odoo/addons/rma/models/res_partner.py +1 -1
- odoo/addons/rma/models/rma.py +241 -276
- odoo/addons/rma/models/stock_move.py +17 -32
- odoo/addons/rma/models/stock_warehouse.py +100 -25
- odoo/addons/rma/readme/CONTRIBUTORS.md +1 -0
- odoo/addons/rma/readme/ROADMAP.md +3 -0
- odoo/addons/rma/static/description/index.html +5 -1
- odoo/addons/rma/tests/test_rma.py +78 -21
- odoo/addons/rma/wizard/stock_picking_return.py +90 -13
- odoo/addons/rma/wizard/stock_picking_return_views.xml +1 -0
- {odoo_addon_rma-17.0.1.1.1.dist-info → odoo_addon_rma-17.0.2.0.0.1.dist-info}/METADATA +7 -2
- {odoo_addon_rma-17.0.1.1.1.dist-info → odoo_addon_rma-17.0.2.0.0.1.dist-info}/RECORD +29 -28
- {odoo_addon_rma-17.0.1.1.1.dist-info → odoo_addon_rma-17.0.2.0.0.1.dist-info}/WHEEL +0 -0
- {odoo_addon_rma-17.0.1.1.1.dist-info → odoo_addon_rma-17.0.2.0.0.1.dist-info}/top_level.txt +0 -0
odoo/addons/rma/models/rma.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
# Copyright 2020 Tecnativa - Ernesto Tejeda
|
2
2
|
# Copyright 2023 Tecnativa - Pedro M. Baeza
|
3
|
+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
|
3
4
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
4
5
|
import logging
|
5
|
-
from collections import
|
6
|
+
from collections import defaultdict
|
7
|
+
from itertools import groupby
|
6
8
|
|
7
9
|
from odoo import _, api, fields, models
|
8
10
|
from odoo.exceptions import AccessError, ValidationError
|
9
|
-
from odoo.tests import Form
|
10
11
|
from odoo.tools import html2plaintext
|
11
12
|
|
12
13
|
from odoo.addons.stock.models.stock_move import PROCUREMENT_PRIORITIES
|
@@ -259,18 +260,8 @@ class Rma(models.Model):
|
|
259
260
|
)
|
260
261
|
|
261
262
|
def _compute_delivery_picking_count(self):
|
262
|
-
|
263
|
-
|
264
|
-
# same picking and the same rma.
|
265
|
-
rma_data = self.env["stock.move"].read_group(
|
266
|
-
[("rma_id", "in", self.ids)],
|
267
|
-
["rma_id", "picking_id"],
|
268
|
-
["rma_id", "picking_id"],
|
269
|
-
lazy=False,
|
270
|
-
)
|
271
|
-
mapped_data = Counter(map(lambda r: r["rma_id"][0], rma_data))
|
272
|
-
for record in self:
|
273
|
-
record.delivery_picking_count = mapped_data.get(record.id, 0)
|
263
|
+
for rma in self:
|
264
|
+
rma.delivery_picking_count = len(rma.delivery_move_ids.picking_id)
|
274
265
|
|
275
266
|
@api.depends(
|
276
267
|
"delivery_move_ids",
|
@@ -609,22 +600,85 @@ class Rma(models.Model):
|
|
609
600
|
}
|
610
601
|
|
611
602
|
def _add_message_subscribe_partner(self):
|
603
|
+
self.ensure_one()
|
612
604
|
if self.partner_id and self.partner_id not in self.message_partner_ids:
|
613
605
|
self.message_subscribe([self.partner_id.id])
|
614
606
|
|
607
|
+
def _product_is_storable(self, product=None):
|
608
|
+
product = product or self.product_id
|
609
|
+
return product.type in ["product", "consu"]
|
610
|
+
|
611
|
+
def _prepare_procurement_group_vals(self):
|
612
|
+
return {
|
613
|
+
"move_type": "direct",
|
614
|
+
"partner_id": self and self.partner_shipping_id.id or False,
|
615
|
+
"name": self and ", ".join(self.mapped("name")) or False,
|
616
|
+
}
|
617
|
+
|
618
|
+
def _prepare_common_procurement_vals(
|
619
|
+
self, warehouse=None, scheduled_date=None, group=None
|
620
|
+
):
|
621
|
+
self.ensure_one()
|
622
|
+
group = group or self.procurement_group_id
|
623
|
+
if not group:
|
624
|
+
group = self.env["procurement.group"].create(
|
625
|
+
self._prepare_procurement_group_vals()
|
626
|
+
)
|
627
|
+
return {
|
628
|
+
"company_id": self.company_id,
|
629
|
+
"group_id": group,
|
630
|
+
"date_planned": scheduled_date or fields.Datetime.now(),
|
631
|
+
"warehouse_id": warehouse or self.warehouse_id,
|
632
|
+
"partner_id": group.partner_id.id,
|
633
|
+
"priority": self.priority,
|
634
|
+
}
|
635
|
+
|
636
|
+
def _prepare_reception_procurement_vals(self, group=None):
|
637
|
+
"""This method is used only for reception and a specific RMA IN route."""
|
638
|
+
vals = self._prepare_common_procurement_vals(group=group)
|
639
|
+
vals["route_ids"] = self.warehouse_id.rma_in_route_id
|
640
|
+
vals["rma_receiver_ids"] = [(6, 0, self.ids)]
|
641
|
+
if self.move_id:
|
642
|
+
vals["origin_returned_move_id"] = self.move_id.id
|
643
|
+
return vals
|
644
|
+
|
645
|
+
def _prepare_reception_procurements(self):
|
646
|
+
procurements = []
|
647
|
+
group_model = self.env["procurement.group"]
|
648
|
+
for rma in self:
|
649
|
+
if not rma._product_is_storable():
|
650
|
+
continue
|
651
|
+
group = rma.procurement_group_id
|
652
|
+
if not group:
|
653
|
+
group = group_model.create(rma._prepare_procurement_group_vals())
|
654
|
+
procurements.append(
|
655
|
+
group_model.Procurement(
|
656
|
+
rma.product_id,
|
657
|
+
rma.product_uom_qty,
|
658
|
+
rma.product_uom,
|
659
|
+
rma.location_id,
|
660
|
+
rma.product_id.display_name,
|
661
|
+
group.name,
|
662
|
+
rma.company_id,
|
663
|
+
rma._prepare_reception_procurement_vals(group),
|
664
|
+
)
|
665
|
+
)
|
666
|
+
return procurements
|
667
|
+
|
615
668
|
def action_confirm(self):
|
616
669
|
"""Invoked when 'Confirm' button in rma form view is clicked."""
|
617
|
-
self.ensure_one()
|
618
670
|
self._ensure_required_fields()
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
671
|
+
self = self.filtered(lambda rma: rma.state == "draft")
|
672
|
+
if not self:
|
673
|
+
return
|
674
|
+
procurements = self._prepare_reception_procurements()
|
675
|
+
if procurements:
|
676
|
+
self.env["procurement.group"].run(procurements)
|
677
|
+
self.reception_move_id.picking_id.action_assign()
|
678
|
+
self.write({"state": "confirmed"})
|
679
|
+
for rma in self:
|
680
|
+
rma._add_message_subscribe_partner()
|
681
|
+
self._send_confirmation_email()
|
628
682
|
|
629
683
|
def action_refund(self):
|
630
684
|
"""Invoked when 'Refund' button in rma form view is clicked
|
@@ -663,11 +717,8 @@ class Rma(models.Model):
|
|
663
717
|
self._ensure_can_be_replaced()
|
664
718
|
# Force active_id to avoid issues when coming from smart buttons
|
665
719
|
# in other models
|
666
|
-
action = (
|
667
|
-
|
668
|
-
.sudo()
|
669
|
-
.with_context(active_id=self.id)
|
670
|
-
.read()[0]
|
720
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
721
|
+
"rma.rma_delivery_wizard_action"
|
671
722
|
)
|
672
723
|
action["name"] = "Replace product(s)"
|
673
724
|
action["context"] = dict(self.env.context)
|
@@ -686,11 +737,8 @@ class Rma(models.Model):
|
|
686
737
|
self._ensure_can_be_returned()
|
687
738
|
# Force active_id to avoid issues when coming from smart buttons
|
688
739
|
# in other models
|
689
|
-
action = (
|
690
|
-
|
691
|
-
.sudo()
|
692
|
-
.with_context(active_id=self.id)
|
693
|
-
.read()[0]
|
740
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
741
|
+
"rma.rma_delivery_wizard_action"
|
694
742
|
)
|
695
743
|
action["context"] = dict(self.env.context)
|
696
744
|
action["context"].update(
|
@@ -706,11 +754,8 @@ class Rma(models.Model):
|
|
706
754
|
self._ensure_can_be_split()
|
707
755
|
# Force active_id to avoid issues when coming from smart buttons
|
708
756
|
# in other models
|
709
|
-
action = (
|
710
|
-
|
711
|
-
.sudo()
|
712
|
-
.with_context(active_id=self.id)
|
713
|
-
.read()[0]
|
757
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
758
|
+
"rma.rma_split_wizard_action"
|
714
759
|
)
|
715
760
|
action["context"] = dict(self.env.context)
|
716
761
|
action["context"].update(active_id=self.id, active_ids=self.ids)
|
@@ -722,11 +767,8 @@ class Rma(models.Model):
|
|
722
767
|
self._ensure_can_be_returned()
|
723
768
|
# Force active_id to avoid issues when coming from smart buttons
|
724
769
|
# in other models
|
725
|
-
action = (
|
726
|
-
|
727
|
-
.sudo()
|
728
|
-
.with_context(active_id=self.id)
|
729
|
-
.read()[0]
|
770
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
771
|
+
"rma.rma_finalization_wizard_action"
|
730
772
|
)
|
731
773
|
action["context"] = dict(self.env.context)
|
732
774
|
action["context"].update(active_id=self.id, active_ids=self.ids)
|
@@ -734,7 +776,7 @@ class Rma(models.Model):
|
|
734
776
|
|
735
777
|
def action_cancel(self):
|
736
778
|
"""Invoked when 'Cancel' button in rma form view is clicked."""
|
737
|
-
self.
|
779
|
+
self.reception_move_id._action_cancel()
|
738
780
|
self.write({"state": "cancelled"})
|
739
781
|
|
740
782
|
def action_draft(self):
|
@@ -759,25 +801,28 @@ class Rma(models.Model):
|
|
759
801
|
"url": self.get_portal_url(),
|
760
802
|
}
|
761
803
|
|
762
|
-
def
|
763
|
-
"""Invoked when 'Receipt' smart button in rma form view is clicked."""
|
804
|
+
def _action_view_pickings(self, pickings):
|
764
805
|
self.ensure_one()
|
765
806
|
# Force active_id to avoid issues when coming from smart buttons
|
766
807
|
# in other models
|
767
|
-
action = (
|
768
|
-
|
769
|
-
.sudo()
|
770
|
-
.with_context(active_id=self.id)
|
771
|
-
.read()[0]
|
772
|
-
)
|
773
|
-
action.update(
|
774
|
-
res_id=self.reception_move_id.picking_id.id,
|
775
|
-
view_mode="form",
|
776
|
-
view_id=False,
|
777
|
-
views=False,
|
808
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
809
|
+
"stock.action_picking_tree_all"
|
778
810
|
)
|
811
|
+
if len(pickings) > 1:
|
812
|
+
action["domain"] = [("id", "in", pickings.ids)]
|
813
|
+
elif pickings:
|
814
|
+
action.update(
|
815
|
+
res_id=pickings.id,
|
816
|
+
view_mode="form",
|
817
|
+
view_id=False,
|
818
|
+
views=False,
|
819
|
+
)
|
779
820
|
return action
|
780
821
|
|
822
|
+
def action_view_receipt(self):
|
823
|
+
"""Invoked when 'Receipt' smart button in rma form view is clicked."""
|
824
|
+
return self._action_view_pickings(self.mapped("reception_move_id.picking_id"))
|
825
|
+
|
781
826
|
def action_view_refund(self):
|
782
827
|
"""Invoked when 'Refund' smart button in rma form view is clicked."""
|
783
828
|
self.ensure_one()
|
@@ -793,23 +838,7 @@ class Rma(models.Model):
|
|
793
838
|
|
794
839
|
def action_view_delivery(self):
|
795
840
|
"""Invoked when 'Delivery' smart button in rma form view is clicked."""
|
796
|
-
|
797
|
-
self.env.ref("stock.action_picking_tree_all")
|
798
|
-
.sudo()
|
799
|
-
.with_context(active_id=self.id)
|
800
|
-
.read()[0]
|
801
|
-
)
|
802
|
-
picking = self.delivery_move_ids.mapped("picking_id")
|
803
|
-
if len(picking) > 1:
|
804
|
-
action["domain"] = [("id", "in", picking.ids)]
|
805
|
-
elif picking:
|
806
|
-
action.update(
|
807
|
-
res_id=picking.id,
|
808
|
-
view_mode="form",
|
809
|
-
view_id=False,
|
810
|
-
views=False,
|
811
|
-
)
|
812
|
-
return action
|
841
|
+
return self._action_view_pickings(self.mapped("delivery_move_ids.picking_id"))
|
813
842
|
|
814
843
|
# Validation business methods
|
815
844
|
def _ensure_required_fields(self):
|
@@ -925,83 +954,6 @@ class Rma(models.Model):
|
|
925
954
|
)
|
926
955
|
)
|
927
956
|
|
928
|
-
# Reception business methods
|
929
|
-
def _create_receptions_from_picking(self):
|
930
|
-
self.ensure_one()
|
931
|
-
stock_return_picking_form = Form(
|
932
|
-
self.env["stock.return.picking"].with_context(
|
933
|
-
active_ids=self.picking_id.ids,
|
934
|
-
active_id=self.picking_id.id,
|
935
|
-
active_model="stock.picking",
|
936
|
-
)
|
937
|
-
)
|
938
|
-
return_wizard = stock_return_picking_form.save()
|
939
|
-
if self.location_id:
|
940
|
-
return_wizard.location_id = self.location_id
|
941
|
-
return_wizard.product_return_moves.filtered(
|
942
|
-
lambda r: r.move_id != self.move_id
|
943
|
-
).unlink()
|
944
|
-
return_line = return_wizard.product_return_moves
|
945
|
-
return_line.update(
|
946
|
-
{
|
947
|
-
"quantity": self.product_uom_qty,
|
948
|
-
# The to_refund field is now True by default, which isn't right in the
|
949
|
-
# RMA creation context
|
950
|
-
"to_refund": False,
|
951
|
-
}
|
952
|
-
)
|
953
|
-
# set_rma_picking_type is to override the copy() method of stock
|
954
|
-
# picking and change the default picking type to rma picking type.
|
955
|
-
picking_action = return_wizard.with_context(
|
956
|
-
set_rma_picking_type=True
|
957
|
-
).create_returns()
|
958
|
-
picking_id = picking_action["res_id"]
|
959
|
-
picking = self.env["stock.picking"].browse(picking_id)
|
960
|
-
picking.origin = f"{self.name} ({picking.origin})"
|
961
|
-
move = picking.move_ids
|
962
|
-
move.priority = self.priority
|
963
|
-
return move
|
964
|
-
|
965
|
-
def _create_receptions_from_product(self):
|
966
|
-
self.ensure_one()
|
967
|
-
picking = self.env["stock.picking"].create(self._prepare_picking_vals())
|
968
|
-
picking.action_confirm()
|
969
|
-
picking.action_assign()
|
970
|
-
picking.message_post_with_source(
|
971
|
-
"mail.message_origin_link",
|
972
|
-
render_values={"self": picking, "origin": self},
|
973
|
-
subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
|
974
|
-
)
|
975
|
-
return picking.move_ids
|
976
|
-
|
977
|
-
def _prepare_picking_vals(self):
|
978
|
-
return {
|
979
|
-
"picking_type_id": self.warehouse_id.rma_in_type_id.id,
|
980
|
-
"origin": self.name,
|
981
|
-
"partner_id": self.partner_shipping_id.id,
|
982
|
-
"location_id": self.partner_shipping_id.property_stock_customer.id,
|
983
|
-
"location_dest_id": self.location_id.id,
|
984
|
-
"move_ids": [
|
985
|
-
(
|
986
|
-
0,
|
987
|
-
0,
|
988
|
-
{
|
989
|
-
"product_id": self.product_id.id,
|
990
|
-
# same text as origin move or product text in partner lang
|
991
|
-
"name": self.move_id.name
|
992
|
-
or self.product_id.with_context(
|
993
|
-
lang=self.partner_id.lang or "en_US"
|
994
|
-
).display_name,
|
995
|
-
"location_id": (
|
996
|
-
self.partner_shipping_id.property_stock_customer.id
|
997
|
-
),
|
998
|
-
"location_dest_id": self.location_id.id,
|
999
|
-
"product_uom_qty": self.product_uom_qty,
|
1000
|
-
},
|
1001
|
-
)
|
1002
|
-
],
|
1003
|
-
}
|
1004
|
-
|
1005
957
|
# Extract business methods
|
1006
958
|
def extract_quantity(self, qty, uom):
|
1007
959
|
self.ensure_one()
|
@@ -1075,44 +1027,101 @@ class Rma(models.Model):
|
|
1075
1027
|
"rma_id": self.id,
|
1076
1028
|
}
|
1077
1029
|
|
1078
|
-
|
1079
|
-
|
1080
|
-
"""Intended to be invoked by the delivery wizard"""
|
1030
|
+
def _delivery_should_be_grouped(self):
|
1031
|
+
"""Checks if the rmas should be grouped for the delivery process"""
|
1081
1032
|
group_returns = self.env.company.rma_return_grouping
|
1082
1033
|
if "rma_return_grouping" in self.env.context:
|
1083
1034
|
group_returns = self.env.context.get("rma_return_grouping")
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1035
|
+
return group_returns
|
1036
|
+
|
1037
|
+
def _delivery_group_key(self):
|
1038
|
+
"""Returns a key by which the rmas should be grouped for the delivery process"""
|
1039
|
+
self.ensure_one()
|
1040
|
+
return (self.partner_shipping_id.id, self.company_id.id, self.warehouse_id.id)
|
1041
|
+
|
1042
|
+
def _group_delivery_if_needed(self):
|
1043
|
+
"""Groups the given rmas by the returned key from _delivery_group_key
|
1044
|
+
by setting the procurement_group_id on the each rma if there is not yet on
|
1045
|
+
set"""
|
1046
|
+
if not self._delivery_should_be_grouped():
|
1047
|
+
return
|
1048
|
+
grouped_rmas = groupby(
|
1049
|
+
sorted(self, key=lambda rma: rma._delivery_group_key()),
|
1050
|
+
key=lambda rma: [rma._delivery_group_key()],
|
1051
|
+
)
|
1052
|
+
for _group, rmas in grouped_rmas:
|
1053
|
+
rmas = (
|
1054
|
+
self.browse()
|
1055
|
+
.concat(*list(rmas))
|
1056
|
+
.filtered(lambda rma: not rma.procurement_group_id)
|
1093
1057
|
)
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1058
|
+
if not rmas:
|
1059
|
+
continue
|
1060
|
+
proc_group = self.env["procurement.group"].create(
|
1061
|
+
rmas._prepare_procurement_group_vals()
|
1062
|
+
)
|
1063
|
+
rmas.write({"procurement_group_id": proc_group.id})
|
1064
|
+
|
1065
|
+
def _prepare_delivery_procurement_vals(self, scheduled_date=None):
|
1066
|
+
"""This method is used only for Delivery (not replace). It is important to set
|
1067
|
+
RMA Out route."""
|
1068
|
+
vals = self._prepare_common_procurement_vals(scheduled_date=scheduled_date)
|
1069
|
+
vals["rma_id"] = self.id
|
1070
|
+
vals["route_ids"] = self.warehouse_id.rma_out_route_id
|
1071
|
+
vals["move_orig_ids"] = [(6, 0, self.reception_move_id.ids)]
|
1072
|
+
return vals
|
1073
|
+
|
1074
|
+
def _prepare_delivery_procurements(self, scheduled_date=None, qty=None, uom=None):
|
1075
|
+
self._group_delivery_if_needed()
|
1076
|
+
procurements = []
|
1077
|
+
group_model = self.env["procurement.group"]
|
1078
|
+
for rma in self:
|
1079
|
+
if not rma.procurement_group_id:
|
1080
|
+
rma.procurement_group_id = group_model.create(
|
1081
|
+
rma._prepare_procurement_group_vals()
|
1106
1082
|
)
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1083
|
+
|
1084
|
+
vals = rma._prepare_delivery_procurement_vals(scheduled_date)
|
1085
|
+
group = vals.get("group_id")
|
1086
|
+
procurements.append(
|
1087
|
+
group_model.Procurement(
|
1088
|
+
rma.product_id,
|
1089
|
+
qty or rma.product_uom_qty,
|
1090
|
+
uom or rma.product_uom,
|
1091
|
+
rma.partner_shipping_id.property_stock_customer,
|
1092
|
+
rma.product_id.display_name,
|
1093
|
+
group.name,
|
1094
|
+
rma.company_id,
|
1095
|
+
vals,
|
1115
1096
|
)
|
1097
|
+
)
|
1098
|
+
return procurements
|
1099
|
+
|
1100
|
+
# Returning business methods
|
1101
|
+
def create_return(self, scheduled_date, qty=None, uom=None):
|
1102
|
+
"""Intended to be invoked by the delivery wizard"""
|
1103
|
+
self._ensure_can_be_returned()
|
1104
|
+
self._ensure_qty_to_return(qty, uom)
|
1105
|
+
rmas_to_return = self.filtered(
|
1106
|
+
lambda rma: rma.can_be_returned and rma._product_is_storable()
|
1107
|
+
)
|
1108
|
+
procurements = rmas_to_return._prepare_delivery_procurements(
|
1109
|
+
scheduled_date, qty, uom
|
1110
|
+
)
|
1111
|
+
if procurements:
|
1112
|
+
self.env["procurement.group"].run(procurements)
|
1113
|
+
pickings = defaultdict(lambda: self.browse())
|
1114
|
+
for rma in rmas_to_return:
|
1115
|
+
picking = rma.delivery_move_ids.picking_id.sorted("id", reverse=True)[0]
|
1116
|
+
pickings[picking] |= rma
|
1117
|
+
rma.message_post(
|
1118
|
+
body=_(
|
1119
|
+
'Return: <a href="#" data-oe-model="stock.picking" '
|
1120
|
+
'data-oe-id="%(id)d">%(name)s</a> has been created.'
|
1121
|
+
)
|
1122
|
+
% ({"id": picking.id, "name": picking.name})
|
1123
|
+
)
|
1124
|
+
for picking, rmas in pickings.items():
|
1116
1125
|
picking.action_confirm()
|
1117
1126
|
picking.action_assign()
|
1118
1127
|
picking.message_post_with_source(
|
@@ -1122,42 +1131,53 @@ class Rma(models.Model):
|
|
1122
1131
|
)
|
1123
1132
|
rmas_to_return.write({"state": "waiting_return"})
|
1124
1133
|
|
1125
|
-
def
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
"origin": origin or self.name,
|
1132
|
-
"partner_id": self.partner_shipping_id.id,
|
1133
|
-
"company_id": self.company_id.id,
|
1134
|
-
"move_ids": [],
|
1135
|
-
}
|
1134
|
+
def _prepare_replace_procurement_vals(self, warehouse=None, scheduled_date=None):
|
1135
|
+
"""This method is used only for Replace (not Delivery). We do not use any
|
1136
|
+
specific route here."""
|
1137
|
+
vals = self._prepare_common_procurement_vals(warehouse, scheduled_date)
|
1138
|
+
vals["rma_id"] = self.id
|
1139
|
+
return vals
|
1136
1140
|
|
1137
|
-
def
|
1138
|
-
self
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
)
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1141
|
+
def _prepare_replace_procurements(
|
1142
|
+
self, warehouse, scheduled_date, product, qty, uom
|
1143
|
+
):
|
1144
|
+
procurements = []
|
1145
|
+
group_model = self.env["procurement.group"]
|
1146
|
+
for rma in self:
|
1147
|
+
if not rma._product_is_storable(product):
|
1148
|
+
continue
|
1149
|
+
|
1150
|
+
if not rma.procurement_group_id:
|
1151
|
+
rma.procurement_group_id = group_model.create(
|
1152
|
+
rma._prepare_procurement_group_vals()
|
1153
|
+
)
|
1154
|
+
|
1155
|
+
vals = rma._prepare_replace_procurement_vals(warehouse, scheduled_date)
|
1156
|
+
group = vals.get("group_id")
|
1157
|
+
procurements.append(
|
1158
|
+
group_model.Procurement(
|
1159
|
+
product,
|
1160
|
+
qty,
|
1161
|
+
uom,
|
1162
|
+
rma.partner_shipping_id.property_stock_customer,
|
1163
|
+
product.display_name,
|
1164
|
+
group.name,
|
1165
|
+
rma.company_id,
|
1166
|
+
vals,
|
1167
|
+
)
|
1168
|
+
)
|
1169
|
+
return procurements
|
1153
1170
|
|
1154
1171
|
# Replacing business methods
|
1155
1172
|
def create_replace(self, scheduled_date, warehouse, product, qty, uom):
|
1156
1173
|
"""Intended to be invoked by the delivery wizard"""
|
1157
|
-
self.ensure_one()
|
1158
1174
|
self._ensure_can_be_replaced()
|
1159
1175
|
moves_before = self.delivery_move_ids
|
1160
|
-
self.
|
1176
|
+
procurements = self._prepare_replace_procurements(
|
1177
|
+
warehouse, scheduled_date, product, qty, uom
|
1178
|
+
)
|
1179
|
+
if procurements:
|
1180
|
+
self.env["procurement.group"].run(procurements)
|
1161
1181
|
new_moves = self.delivery_move_ids - moves_before
|
1162
1182
|
body = ""
|
1163
1183
|
# The product replacement could explode into several moves like in the case of
|
@@ -1181,6 +1201,12 @@ class Rma(models.Model):
|
|
1181
1201
|
)
|
1182
1202
|
+ "\n"
|
1183
1203
|
)
|
1204
|
+
for rma in self:
|
1205
|
+
rma._add_replace_message(body, qty, uom)
|
1206
|
+
self.write({"state": "waiting_replacement"})
|
1207
|
+
|
1208
|
+
def _add_replace_message(self, body, qty, uom):
|
1209
|
+
self.ensure_one()
|
1184
1210
|
self.message_post(
|
1185
1211
|
body=body
|
1186
1212
|
or _(
|
@@ -1193,74 +1219,13 @@ class Rma(models.Model):
|
|
1193
1219
|
)
|
1194
1220
|
% (
|
1195
1221
|
{
|
1196
|
-
"id":
|
1197
|
-
"name":
|
1222
|
+
"id": self.id,
|
1223
|
+
"name": self.display_name,
|
1198
1224
|
"qty": qty,
|
1199
1225
|
"uom": uom.name,
|
1200
1226
|
}
|
1201
1227
|
)
|
1202
1228
|
)
|
1203
|
-
if self.state != "waiting_replacement":
|
1204
|
-
self.state = "waiting_replacement"
|
1205
|
-
|
1206
|
-
def _action_launch_stock_rule(
|
1207
|
-
self,
|
1208
|
-
scheduled_date,
|
1209
|
-
warehouse,
|
1210
|
-
product,
|
1211
|
-
qty,
|
1212
|
-
uom,
|
1213
|
-
):
|
1214
|
-
"""Creates a delivery picking and launch stock rule. It is invoked by:
|
1215
|
-
rma.create_replace
|
1216
|
-
"""
|
1217
|
-
self.ensure_one()
|
1218
|
-
if self.product_id.type not in ("consu", "product"):
|
1219
|
-
return
|
1220
|
-
if not self.procurement_group_id:
|
1221
|
-
self.procurement_group_id = (
|
1222
|
-
self.env["procurement.group"]
|
1223
|
-
.create(
|
1224
|
-
{
|
1225
|
-
"name": self.name,
|
1226
|
-
"move_type": "direct",
|
1227
|
-
"partner_id": self.partner_shipping_id.id,
|
1228
|
-
}
|
1229
|
-
)
|
1230
|
-
.id
|
1231
|
-
)
|
1232
|
-
values = self._prepare_procurement_values(
|
1233
|
-
self.procurement_group_id, scheduled_date, warehouse
|
1234
|
-
)
|
1235
|
-
procurement = self.env["procurement.group"].Procurement(
|
1236
|
-
product,
|
1237
|
-
qty,
|
1238
|
-
uom,
|
1239
|
-
self.partner_shipping_id.property_stock_customer,
|
1240
|
-
self.product_id.display_name,
|
1241
|
-
self.procurement_group_id.name,
|
1242
|
-
self.company_id,
|
1243
|
-
values,
|
1244
|
-
)
|
1245
|
-
self.env["procurement.group"].run([procurement])
|
1246
|
-
return True
|
1247
|
-
|
1248
|
-
def _prepare_procurement_values(
|
1249
|
-
self,
|
1250
|
-
group_id,
|
1251
|
-
scheduled_date,
|
1252
|
-
warehouse,
|
1253
|
-
):
|
1254
|
-
self.ensure_one()
|
1255
|
-
return {
|
1256
|
-
"company_id": self.company_id,
|
1257
|
-
"group_id": group_id,
|
1258
|
-
"date_planned": scheduled_date,
|
1259
|
-
"warehouse_id": warehouse,
|
1260
|
-
"partner_id": self.partner_shipping_id.id,
|
1261
|
-
"rma_id": self.id,
|
1262
|
-
"priority": self.priority,
|
1263
|
-
}
|
1264
1229
|
|
1265
1230
|
# Mail business methods
|
1266
1231
|
def _creation_subtype(self):
|