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
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
|
@@ -317,18 +318,8 @@ class Rma(models.Model):
|
|
317
318
|
)
|
318
319
|
|
319
320
|
def _compute_delivery_picking_count(self):
|
320
|
-
|
321
|
-
|
322
|
-
# same picking and the same rma.
|
323
|
-
rma_data = self.env["stock.move"].read_group(
|
324
|
-
[("rma_id", "in", self.ids)],
|
325
|
-
["rma_id", "picking_id"],
|
326
|
-
["rma_id", "picking_id"],
|
327
|
-
lazy=False,
|
328
|
-
)
|
329
|
-
mapped_data = Counter(map(lambda r: r["rma_id"][0], rma_data))
|
330
|
-
for record in self:
|
331
|
-
record.delivery_picking_count = mapped_data.get(record.id, 0)
|
321
|
+
for rma in self:
|
322
|
+
rma.delivery_picking_count = len(rma.delivery_move_ids.picking_id)
|
332
323
|
|
333
324
|
@api.depends(
|
334
325
|
"delivery_move_ids",
|
@@ -670,21 +661,85 @@ class Rma(models.Model):
|
|
670
661
|
}
|
671
662
|
|
672
663
|
def _add_message_subscribe_partner(self):
|
664
|
+
self.ensure_one()
|
673
665
|
if self.partner_id and self.partner_id not in self.message_partner_ids:
|
674
666
|
self.message_subscribe([self.partner_id.id])
|
675
667
|
|
668
|
+
def _product_is_storable(self, product=None):
|
669
|
+
product = product or self.product_id
|
670
|
+
return product.type in ["product", "consu"]
|
671
|
+
|
672
|
+
def _prepare_procurement_group_vals(self):
|
673
|
+
return {
|
674
|
+
"move_type": "direct",
|
675
|
+
"partner_id": self and self.partner_shipping_id.id or False,
|
676
|
+
"name": self and ", ".join(self.mapped("name")) or False,
|
677
|
+
}
|
678
|
+
|
679
|
+
def _prepare_common_procurement_vals(
|
680
|
+
self, warehouse=None, scheduled_date=None, group=None
|
681
|
+
):
|
682
|
+
self.ensure_one()
|
683
|
+
group = group or self.procurement_group_id
|
684
|
+
if not group:
|
685
|
+
group = self.env["procurement.group"].create(
|
686
|
+
self._prepare_procurement_group_vals()
|
687
|
+
)
|
688
|
+
return {
|
689
|
+
"company_id": self.company_id,
|
690
|
+
"group_id": group,
|
691
|
+
"date_planned": scheduled_date or fields.Datetime.now(),
|
692
|
+
"warehouse_id": warehouse or self.warehouse_id,
|
693
|
+
"partner_id": group.partner_id.id,
|
694
|
+
"priority": self.priority,
|
695
|
+
}
|
696
|
+
|
697
|
+
def _prepare_reception_procurement_vals(self, group=None):
|
698
|
+
"""This method is used only for reception and a specific RMA IN route."""
|
699
|
+
vals = self._prepare_common_procurement_vals(group=group)
|
700
|
+
vals["route_ids"] = self.warehouse_id.rma_in_route_id
|
701
|
+
vals["rma_receiver_ids"] = [(6, 0, self.ids)]
|
702
|
+
if self.move_id:
|
703
|
+
vals["origin_returned_move_id"] = self.move_id.id
|
704
|
+
return vals
|
705
|
+
|
706
|
+
def _prepare_reception_procurements(self):
|
707
|
+
procurements = []
|
708
|
+
group_model = self.env["procurement.group"]
|
709
|
+
for rma in self:
|
710
|
+
if not rma._product_is_storable():
|
711
|
+
continue
|
712
|
+
group = rma.procurement_group_id
|
713
|
+
if not group:
|
714
|
+
group = group_model.create(rma._prepare_procurement_group_vals())
|
715
|
+
procurements.append(
|
716
|
+
group_model.Procurement(
|
717
|
+
rma.product_id,
|
718
|
+
rma.product_uom_qty,
|
719
|
+
rma.product_uom,
|
720
|
+
rma.location_id,
|
721
|
+
rma.product_id.display_name,
|
722
|
+
group.name,
|
723
|
+
rma.company_id,
|
724
|
+
rma._prepare_reception_procurement_vals(group),
|
725
|
+
)
|
726
|
+
)
|
727
|
+
return procurements
|
728
|
+
|
676
729
|
def action_confirm(self):
|
677
730
|
"""Invoked when 'Confirm' button in rma form view is clicked."""
|
678
|
-
self.ensure_one()
|
679
731
|
self._ensure_required_fields()
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
self.
|
686
|
-
|
687
|
-
|
732
|
+
self = self.filtered(lambda rma: rma.state == "draft")
|
733
|
+
if not self:
|
734
|
+
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
|
+
self.write({"state": "confirmed"})
|
740
|
+
for rma in self:
|
741
|
+
rma._add_message_subscribe_partner()
|
742
|
+
self._send_confirmation_email()
|
688
743
|
|
689
744
|
def action_refund(self):
|
690
745
|
"""Invoked when 'Refund' button in rma form view is clicked
|
@@ -723,11 +778,8 @@ class Rma(models.Model):
|
|
723
778
|
self._ensure_can_be_replaced()
|
724
779
|
# Force active_id to avoid issues when coming from smart buttons
|
725
780
|
# in other models
|
726
|
-
action = (
|
727
|
-
|
728
|
-
.sudo()
|
729
|
-
.with_context(active_id=self.id)
|
730
|
-
.read()[0]
|
781
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
782
|
+
"rma.rma_delivery_wizard_action"
|
731
783
|
)
|
732
784
|
action["name"] = "Replace product(s)"
|
733
785
|
action["context"] = dict(self.env.context)
|
@@ -746,11 +798,8 @@ class Rma(models.Model):
|
|
746
798
|
self._ensure_can_be_returned()
|
747
799
|
# Force active_id to avoid issues when coming from smart buttons
|
748
800
|
# in other models
|
749
|
-
action = (
|
750
|
-
|
751
|
-
.sudo()
|
752
|
-
.with_context(active_id=self.id)
|
753
|
-
.read()[0]
|
801
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
802
|
+
"rma.rma_delivery_wizard_action"
|
754
803
|
)
|
755
804
|
action["context"] = dict(self.env.context)
|
756
805
|
action["context"].update(
|
@@ -766,11 +815,8 @@ class Rma(models.Model):
|
|
766
815
|
self._ensure_can_be_split()
|
767
816
|
# Force active_id to avoid issues when coming from smart buttons
|
768
817
|
# in other models
|
769
|
-
action = (
|
770
|
-
|
771
|
-
.sudo()
|
772
|
-
.with_context(active_id=self.id)
|
773
|
-
.read()[0]
|
818
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
819
|
+
"rma.rma_split_wizard_action"
|
774
820
|
)
|
775
821
|
action["context"] = dict(self.env.context)
|
776
822
|
action["context"].update(active_id=self.id, active_ids=self.ids)
|
@@ -782,11 +828,8 @@ class Rma(models.Model):
|
|
782
828
|
self._ensure_can_be_returned()
|
783
829
|
# Force active_id to avoid issues when coming from smart buttons
|
784
830
|
# in other models
|
785
|
-
action = (
|
786
|
-
|
787
|
-
.sudo()
|
788
|
-
.with_context(active_id=self.id)
|
789
|
-
.read()[0]
|
831
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
832
|
+
"rma.rma_finalization_wizard_action"
|
790
833
|
)
|
791
834
|
action["context"] = dict(self.env.context)
|
792
835
|
action["context"].update(active_id=self.id, active_ids=self.ids)
|
@@ -794,7 +837,7 @@ class Rma(models.Model):
|
|
794
837
|
|
795
838
|
def action_cancel(self):
|
796
839
|
"""Invoked when 'Cancel' button in rma form view is clicked."""
|
797
|
-
self.
|
840
|
+
self.reception_move_id._action_cancel()
|
798
841
|
self.write({"state": "cancelled"})
|
799
842
|
|
800
843
|
def action_draft(self):
|
@@ -819,25 +862,28 @@ class Rma(models.Model):
|
|
819
862
|
"url": self.get_portal_url(),
|
820
863
|
}
|
821
864
|
|
822
|
-
def
|
823
|
-
"""Invoked when 'Receipt' smart button in rma form view is clicked."""
|
865
|
+
def _action_view_pickings(self, pickings):
|
824
866
|
self.ensure_one()
|
825
867
|
# Force active_id to avoid issues when coming from smart buttons
|
826
868
|
# in other models
|
827
|
-
action = (
|
828
|
-
|
829
|
-
.sudo()
|
830
|
-
.with_context(active_id=self.id)
|
831
|
-
.read()[0]
|
832
|
-
)
|
833
|
-
action.update(
|
834
|
-
res_id=self.reception_move_id.picking_id.id,
|
835
|
-
view_mode="form",
|
836
|
-
view_id=False,
|
837
|
-
views=False,
|
869
|
+
action = self.env["ir.actions.act_window"]._for_xml_id(
|
870
|
+
"stock.action_picking_tree_all"
|
838
871
|
)
|
872
|
+
if len(pickings) > 1:
|
873
|
+
action["domain"] = [("id", "in", pickings.ids)]
|
874
|
+
elif pickings:
|
875
|
+
action.update(
|
876
|
+
res_id=pickings.id,
|
877
|
+
view_mode="form",
|
878
|
+
view_id=False,
|
879
|
+
views=False,
|
880
|
+
)
|
839
881
|
return action
|
840
882
|
|
883
|
+
def action_view_receipt(self):
|
884
|
+
"""Invoked when 'Receipt' smart button in rma form view is clicked."""
|
885
|
+
return self._action_view_pickings(self.mapped("reception_move_id.picking_id"))
|
886
|
+
|
841
887
|
def action_view_refund(self):
|
842
888
|
"""Invoked when 'Refund' smart button in rma form view is clicked."""
|
843
889
|
self.ensure_one()
|
@@ -853,23 +899,7 @@ class Rma(models.Model):
|
|
853
899
|
|
854
900
|
def action_view_delivery(self):
|
855
901
|
"""Invoked when 'Delivery' smart button in rma form view is clicked."""
|
856
|
-
|
857
|
-
self.env.ref("stock.action_picking_tree_all")
|
858
|
-
.sudo()
|
859
|
-
.with_context(active_id=self.id)
|
860
|
-
.read()[0]
|
861
|
-
)
|
862
|
-
picking = self.delivery_move_ids.mapped("picking_id")
|
863
|
-
if len(picking) > 1:
|
864
|
-
action["domain"] = [("id", "in", picking.ids)]
|
865
|
-
elif picking:
|
866
|
-
action.update(
|
867
|
-
res_id=picking.id,
|
868
|
-
view_mode="form",
|
869
|
-
view_id=False,
|
870
|
-
views=False,
|
871
|
-
)
|
872
|
-
return action
|
902
|
+
return self._action_view_pickings(self.mapped("delivery_move_ids.picking_id"))
|
873
903
|
|
874
904
|
# Validation business methods
|
875
905
|
def _ensure_required_fields(self):
|
@@ -985,81 +1015,6 @@ class Rma(models.Model):
|
|
985
1015
|
)
|
986
1016
|
)
|
987
1017
|
|
988
|
-
# Reception business methods
|
989
|
-
def _create_receptions_from_picking(self):
|
990
|
-
self.ensure_one()
|
991
|
-
stock_return_picking_form = Form(
|
992
|
-
self.env["stock.return.picking"].with_context(
|
993
|
-
active_ids=self.picking_id.ids,
|
994
|
-
active_id=self.picking_id.id,
|
995
|
-
active_model="stock.picking",
|
996
|
-
)
|
997
|
-
)
|
998
|
-
return_wizard = stock_return_picking_form.save()
|
999
|
-
if self.location_id:
|
1000
|
-
return_wizard.location_id = self.location_id
|
1001
|
-
return_wizard.product_return_moves.filtered(
|
1002
|
-
lambda r: r.move_id != self.move_id
|
1003
|
-
).unlink()
|
1004
|
-
return_line = return_wizard.product_return_moves
|
1005
|
-
return_line.update(
|
1006
|
-
{
|
1007
|
-
"quantity": self.product_uom_qty,
|
1008
|
-
# The to_refund field is now True by default, which isn't right in the
|
1009
|
-
# RMA creation context
|
1010
|
-
"to_refund": False,
|
1011
|
-
}
|
1012
|
-
)
|
1013
|
-
# set_rma_picking_type is to override the copy() method of stock
|
1014
|
-
# picking and change the default picking type to rma picking type.
|
1015
|
-
picking_action = return_wizard.with_context(
|
1016
|
-
set_rma_picking_type=True
|
1017
|
-
).create_returns()
|
1018
|
-
picking_id = picking_action["res_id"]
|
1019
|
-
picking = self.env["stock.picking"].browse(picking_id)
|
1020
|
-
picking.origin = "{} ({})".format(self.name, picking.origin)
|
1021
|
-
move = picking.move_ids
|
1022
|
-
move.priority = self.priority
|
1023
|
-
return move
|
1024
|
-
|
1025
|
-
def _create_receptions_from_product(self):
|
1026
|
-
self.ensure_one()
|
1027
|
-
picking = self.env["stock.picking"].create(self._prepare_picking_vals())
|
1028
|
-
picking.action_confirm()
|
1029
|
-
picking.action_assign()
|
1030
|
-
picking.message_post_with_view(
|
1031
|
-
"mail.message_origin_link",
|
1032
|
-
values={"self": picking, "origin": self},
|
1033
|
-
subtype_id=self.env.ref("mail.mt_note").id,
|
1034
|
-
)
|
1035
|
-
return picking.move_ids
|
1036
|
-
|
1037
|
-
def _prepare_picking_vals(self):
|
1038
|
-
return {
|
1039
|
-
"picking_type_id": self.warehouse_id.rma_in_type_id.id,
|
1040
|
-
"origin": self.name,
|
1041
|
-
"partner_id": self.partner_shipping_id.id,
|
1042
|
-
"location_id": self.partner_shipping_id.property_stock_customer.id,
|
1043
|
-
"location_dest_id": self.location_id.id,
|
1044
|
-
"move_ids": [
|
1045
|
-
(
|
1046
|
-
0,
|
1047
|
-
0,
|
1048
|
-
{
|
1049
|
-
"product_id": self.product_id.id,
|
1050
|
-
# same text as origin move or product text in partner lang
|
1051
|
-
"name": self.move_id.name
|
1052
|
-
or self.product_id.with_context(
|
1053
|
-
lang=self.partner_id.lang or "en_US"
|
1054
|
-
).display_name,
|
1055
|
-
"location_id": self.partner_shipping_id.property_stock_customer.id,
|
1056
|
-
"location_dest_id": self.location_id.id,
|
1057
|
-
"product_uom_qty": self.product_uom_qty,
|
1058
|
-
},
|
1059
|
-
)
|
1060
|
-
],
|
1061
|
-
}
|
1062
|
-
|
1063
1018
|
# Extract business methods
|
1064
1019
|
def extract_quantity(self, qty, uom):
|
1065
1020
|
self.ensure_one()
|
@@ -1133,44 +1088,100 @@ class Rma(models.Model):
|
|
1133
1088
|
"rma_id": self.id,
|
1134
1089
|
}
|
1135
1090
|
|
1136
|
-
|
1137
|
-
|
1138
|
-
"""Intended to be invoked by the delivery wizard"""
|
1091
|
+
def _delivery_should_be_grouped(self):
|
1092
|
+
"""Checks if the rmas should be grouped for the delivery process"""
|
1139
1093
|
group_returns = self.env.company.rma_return_grouping
|
1140
1094
|
if "rma_return_grouping" in self.env.context:
|
1141
1095
|
group_returns = self.env.context.get("rma_return_grouping")
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1096
|
+
return group_returns
|
1097
|
+
|
1098
|
+
def _delivery_group_key(self):
|
1099
|
+
"""Returns a key by which the rmas should be grouped for the delivery process"""
|
1100
|
+
self.ensure_one()
|
1101
|
+
return (self.partner_shipping_id.id, self.company_id.id, self.warehouse_id.id)
|
1102
|
+
|
1103
|
+
def _group_delivery_if_needed(self):
|
1104
|
+
"""Groups the given rmas by the returned key from _delivery_group_key
|
1105
|
+
by setting the procurement_group_id on the each rma if there is not yet on set"""
|
1106
|
+
if not self._delivery_should_be_grouped():
|
1107
|
+
return
|
1108
|
+
grouped_rmas = groupby(
|
1109
|
+
sorted(self, key=lambda rma: rma._delivery_group_key()),
|
1110
|
+
key=lambda rma: [rma._delivery_group_key()],
|
1111
|
+
)
|
1112
|
+
for _group, rmas in grouped_rmas:
|
1113
|
+
rmas = (
|
1114
|
+
self.browse()
|
1115
|
+
.concat(*list(rmas))
|
1116
|
+
.filtered(lambda rma: not rma.procurement_group_id)
|
1151
1117
|
)
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1118
|
+
if not rmas:
|
1119
|
+
continue
|
1120
|
+
proc_group = self.env["procurement.group"].create(
|
1121
|
+
rmas._prepare_procurement_group_vals()
|
1122
|
+
)
|
1123
|
+
rmas.write({"procurement_group_id": proc_group.id})
|
1124
|
+
|
1125
|
+
def _prepare_delivery_procurement_vals(self, scheduled_date=None):
|
1126
|
+
"""This method is used only for Delivery (not replace). It is important to set
|
1127
|
+
RMA Out route."""
|
1128
|
+
vals = self._prepare_common_procurement_vals(scheduled_date=scheduled_date)
|
1129
|
+
vals["rma_id"] = self.id
|
1130
|
+
vals["route_ids"] = self.warehouse_id.rma_out_route_id
|
1131
|
+
vals["move_orig_ids"] = [(6, 0, self.reception_move_id.ids)]
|
1132
|
+
return vals
|
1133
|
+
|
1134
|
+
def _prepare_delivery_procurements(self, scheduled_date=None, qty=None, uom=None):
|
1135
|
+
self._group_delivery_if_needed()
|
1136
|
+
procurements = []
|
1137
|
+
group_model = self.env["procurement.group"]
|
1138
|
+
for rma in self:
|
1139
|
+
if not rma.procurement_group_id:
|
1140
|
+
rma.procurement_group_id = group_model.create(
|
1141
|
+
rma._prepare_procurement_group_vals()
|
1164
1142
|
)
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1143
|
+
|
1144
|
+
vals = rma._prepare_delivery_procurement_vals(scheduled_date)
|
1145
|
+
group = vals.get("group_id")
|
1146
|
+
procurements.append(
|
1147
|
+
group_model.Procurement(
|
1148
|
+
rma.product_id,
|
1149
|
+
qty or rma.product_uom_qty,
|
1150
|
+
uom or rma.product_uom,
|
1151
|
+
rma.partner_shipping_id.property_stock_customer,
|
1152
|
+
rma.product_id.display_name,
|
1153
|
+
group.name,
|
1154
|
+
rma.company_id,
|
1155
|
+
vals,
|
1173
1156
|
)
|
1157
|
+
)
|
1158
|
+
return procurements
|
1159
|
+
|
1160
|
+
# Returning business methods
|
1161
|
+
def create_return(self, scheduled_date, qty=None, uom=None):
|
1162
|
+
"""Intended to be invoked by the delivery wizard"""
|
1163
|
+
self._ensure_can_be_returned()
|
1164
|
+
self._ensure_qty_to_return(qty, uom)
|
1165
|
+
rmas_to_return = self.filtered(
|
1166
|
+
lambda rma: rma.can_be_returned and rma._product_is_storable()
|
1167
|
+
)
|
1168
|
+
procurements = rmas_to_return._prepare_delivery_procurements(
|
1169
|
+
scheduled_date, qty, uom
|
1170
|
+
)
|
1171
|
+
if procurements:
|
1172
|
+
self.env["procurement.group"].run(procurements)
|
1173
|
+
pickings = defaultdict(lambda: self.browse())
|
1174
|
+
for rma in rmas_to_return:
|
1175
|
+
picking = rma.delivery_move_ids.picking_id.sorted("id", reverse=True)[0]
|
1176
|
+
pickings[picking] |= rma
|
1177
|
+
rma.message_post(
|
1178
|
+
body=_(
|
1179
|
+
'Return: <a href="#" data-oe-model="stock.picking" '
|
1180
|
+
'data-oe-id="%(id)d">%(name)s</a> has been created.'
|
1181
|
+
)
|
1182
|
+
% ({"id": picking.id, "name": picking.name})
|
1183
|
+
)
|
1184
|
+
for picking, rmas in pickings.items():
|
1174
1185
|
picking.action_confirm()
|
1175
1186
|
picking.action_assign()
|
1176
1187
|
picking.message_post_with_view(
|
@@ -1180,42 +1191,53 @@ class Rma(models.Model):
|
|
1180
1191
|
)
|
1181
1192
|
rmas_to_return.write({"state": "waiting_return"})
|
1182
1193
|
|
1183
|
-
def
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
"origin": origin or self.name,
|
1190
|
-
"partner_id": self.partner_shipping_id.id,
|
1191
|
-
"company_id": self.company_id.id,
|
1192
|
-
"move_ids": [],
|
1193
|
-
}
|
1194
|
+
def _prepare_replace_procurement_vals(self, warehouse=None, scheduled_date=None):
|
1195
|
+
"""This method is used only for Replace (not Delivery). We do not use any
|
1196
|
+
specific route here."""
|
1197
|
+
vals = self._prepare_common_procurement_vals(warehouse, scheduled_date)
|
1198
|
+
vals["rma_id"] = self.id
|
1199
|
+
return vals
|
1194
1200
|
|
1195
|
-
def
|
1196
|
-
self
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
)
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1201
|
+
def _prepare_replace_procurements(
|
1202
|
+
self, warehouse, scheduled_date, product, qty, uom
|
1203
|
+
):
|
1204
|
+
procurements = []
|
1205
|
+
group_model = self.env["procurement.group"]
|
1206
|
+
for rma in self:
|
1207
|
+
if not rma._product_is_storable(product):
|
1208
|
+
continue
|
1209
|
+
|
1210
|
+
if not rma.procurement_group_id:
|
1211
|
+
rma.procurement_group_id = group_model.create(
|
1212
|
+
rma._prepare_procurement_group_vals()
|
1213
|
+
)
|
1214
|
+
|
1215
|
+
vals = rma._prepare_replace_procurement_vals(warehouse, scheduled_date)
|
1216
|
+
group = vals.get("group_id")
|
1217
|
+
procurements.append(
|
1218
|
+
group_model.Procurement(
|
1219
|
+
product,
|
1220
|
+
qty,
|
1221
|
+
uom,
|
1222
|
+
rma.partner_shipping_id.property_stock_customer,
|
1223
|
+
product.display_name,
|
1224
|
+
group.name,
|
1225
|
+
rma.company_id,
|
1226
|
+
vals,
|
1227
|
+
)
|
1228
|
+
)
|
1229
|
+
return procurements
|
1211
1230
|
|
1212
1231
|
# Replacing business methods
|
1213
1232
|
def create_replace(self, scheduled_date, warehouse, product, qty, uom):
|
1214
1233
|
"""Intended to be invoked by the delivery wizard"""
|
1215
|
-
self.ensure_one()
|
1216
1234
|
self._ensure_can_be_replaced()
|
1217
1235
|
moves_before = self.delivery_move_ids
|
1218
|
-
self.
|
1236
|
+
procurements = self._prepare_replace_procurements(
|
1237
|
+
warehouse, scheduled_date, product, qty, uom
|
1238
|
+
)
|
1239
|
+
if procurements:
|
1240
|
+
self.env["procurement.group"].run(procurements)
|
1219
1241
|
new_moves = self.delivery_move_ids - moves_before
|
1220
1242
|
body = ""
|
1221
1243
|
# The product replacement could explode into several moves like in the case of
|
@@ -1239,6 +1261,12 @@ class Rma(models.Model):
|
|
1239
1261
|
)
|
1240
1262
|
+ "\n"
|
1241
1263
|
)
|
1264
|
+
for rma in self:
|
1265
|
+
rma._add_replace_message(body, qty, uom)
|
1266
|
+
self.write({"state": "waiting_replacement"})
|
1267
|
+
|
1268
|
+
def _add_replace_message(self, body, qty, uom):
|
1269
|
+
self.ensure_one()
|
1242
1270
|
self.message_post(
|
1243
1271
|
body=body
|
1244
1272
|
or _(
|
@@ -1251,74 +1279,13 @@ class Rma(models.Model):
|
|
1251
1279
|
)
|
1252
1280
|
% (
|
1253
1281
|
{
|
1254
|
-
"id":
|
1255
|
-
"name":
|
1282
|
+
"id": self.id,
|
1283
|
+
"name": self.display_name,
|
1256
1284
|
"qty": qty,
|
1257
1285
|
"uom": uom.name,
|
1258
1286
|
}
|
1259
1287
|
)
|
1260
1288
|
)
|
1261
|
-
if self.state != "waiting_replacement":
|
1262
|
-
self.state = "waiting_replacement"
|
1263
|
-
|
1264
|
-
def _action_launch_stock_rule(
|
1265
|
-
self,
|
1266
|
-
scheduled_date,
|
1267
|
-
warehouse,
|
1268
|
-
product,
|
1269
|
-
qty,
|
1270
|
-
uom,
|
1271
|
-
):
|
1272
|
-
"""Creates a delivery picking and launch stock rule. It is invoked by:
|
1273
|
-
rma.create_replace
|
1274
|
-
"""
|
1275
|
-
self.ensure_one()
|
1276
|
-
if self.product_id.type not in ("consu", "product"):
|
1277
|
-
return
|
1278
|
-
if not self.procurement_group_id:
|
1279
|
-
self.procurement_group_id = (
|
1280
|
-
self.env["procurement.group"]
|
1281
|
-
.create(
|
1282
|
-
{
|
1283
|
-
"name": self.name,
|
1284
|
-
"move_type": "direct",
|
1285
|
-
"partner_id": self.partner_shipping_id.id,
|
1286
|
-
}
|
1287
|
-
)
|
1288
|
-
.id
|
1289
|
-
)
|
1290
|
-
values = self._prepare_procurement_values(
|
1291
|
-
self.procurement_group_id, scheduled_date, warehouse
|
1292
|
-
)
|
1293
|
-
procurement = self.env["procurement.group"].Procurement(
|
1294
|
-
product,
|
1295
|
-
qty,
|
1296
|
-
uom,
|
1297
|
-
self.partner_shipping_id.property_stock_customer,
|
1298
|
-
self.product_id.display_name,
|
1299
|
-
self.procurement_group_id.name,
|
1300
|
-
self.company_id,
|
1301
|
-
values,
|
1302
|
-
)
|
1303
|
-
self.env["procurement.group"].run([procurement])
|
1304
|
-
return True
|
1305
|
-
|
1306
|
-
def _prepare_procurement_values(
|
1307
|
-
self,
|
1308
|
-
group_id,
|
1309
|
-
scheduled_date,
|
1310
|
-
warehouse,
|
1311
|
-
):
|
1312
|
-
self.ensure_one()
|
1313
|
-
return {
|
1314
|
-
"company_id": self.company_id,
|
1315
|
-
"group_id": group_id,
|
1316
|
-
"date_planned": scheduled_date,
|
1317
|
-
"warehouse_id": warehouse,
|
1318
|
-
"partner_id": self.partner_shipping_id.id,
|
1319
|
-
"rma_id": self.id,
|
1320
|
-
"priority": self.priority,
|
1321
|
-
}
|
1322
1289
|
|
1323
1290
|
# Mail business methods
|
1324
1291
|
def _creation_subtype(self):
|