Skip to content

Commit

Permalink
[IMP] rma: configurable workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
sbejaoui committed Aug 16, 2024
1 parent 4ff83e0 commit 31588af
Show file tree
Hide file tree
Showing 7 changed files with 611 additions and 19 deletions.
1 change: 1 addition & 0 deletions rma/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"views/stock_picking_views.xml",
"views/stock_warehouse_views.xml",
"views/res_config_settings_views.xml",
"views/rma_operation.xml",
],
"post_init_hook": "post_init_hook",
"application": True,
Expand Down
213 changes: 200 additions & 13 deletions rma/models/rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,101 @@ def _domain_location_id(self):
copy=False,
)

show_create_receipt = fields.Boolean(
string="Show Create Receipt Button", compute="_compute_show_create_receipt"
)
show_create_return = fields.Boolean(
string="Show Create Return Button", compute="_compute_show_create_return"
)
show_create_replace = fields.Boolean(
string="Show Create replace Button", compute="_compute_show_create_replace"
)
show_create_refund = fields.Boolean(
string="Show Create refund Button", compute="_compute_show_refund_replace"
)

# Replace fields, used when the delivery is created automatically
replace_warehouse_id = fields.Many2one(
"stock.warehouse",
help="Warehouse from which the replacement product will be shipped.",
compute="_compute_replace_warehouse_id",
store=True,
readonly=False,
)

replace_product_id = fields.Many2one(
"product.product",
help="Product to be used as the replacement for the returned item.",
)

replace_product_uom_qty = fields.Float(
string="Replacement Quantity",
help="Quantity of the replacement product to be delivered.",
)

replace_product_uom = fields.Many2one(
"uom.uom",
string="Replacement UOM",
help="Unit of Measure for the replacement product.",
default=lambda self: self.env.ref("uom.product_uom_unit").id,
compute="_compute_replace_product_uom",
store=True,
readonly=False,
)
show_replacement_fields = fields.Boolean(compute="_compute_show_replacement_fields")

@api.depends("company_id")
def _compute_replace_warehouse_id(self):
warehouse_model = self.env["stock.warehouse"]
for rec in self:
rec.replace_warehouse_id = warehouse_model.search(
[("company_id", "=", rec.company_id.id)], limit=1
)

@api.depends("operation_id.action_create_delivery")
def _compute_show_replacement_fields(self):
for rec in self:
rec.show_replacement_fields = rec.operation_id.action_create_delivery in (
"automatic_on_confirm",
"automatic_after_receipt",
)

@api.depends("operation_id.action_create_receipt", "state", "reception_move_id")
def _compute_show_create_receipt(self):
for rec in self:
rec.show_create_receipt = (
not rec.reception_move_id
and rec.operation_id.action_create_receipt == "manual_on_confirm"
and rec.state == "confirmed"
)

@api.depends("operation_id.action_create_delivery", "can_be_returned")
def _compute_show_create_return(self):
for rec in self:
rec.show_create_return = (
rec.operation_id.action_create_delivery
in ("manual_on_confirm", "manual_after_receipt")
and rec.can_be_returned
)

@api.depends("operation_id.action_create_delivery", "can_be_replaced")
def _compute_show_create_replace(self):
for rec in self:
rec.show_create_replace = (
rec.operation_id.action_create_delivery
in ("manual_on_confirm", "manual_after_receipt")
and rec.can_be_replaced
)

@api.depends("operation_id.action_create_refund", "can_be_refunded")
def _compute_show_refund_replace(self):
for rec in self:
rec.show_create_refund = (
rec.operation_id.action_create_refund
in ("manual_on_confirm", "manual_after_receipt")
and rec.can_be_refunded
)

def _compute_delivery_picking_count(self):
for rma in self:
rma.delivery_picking_count = len(rma.delivery_move_ids.picking_id)
Expand Down Expand Up @@ -394,9 +489,17 @@ def _compute_can_be_refunded(self):
an rma can be refunded. It is used in rma.action_refund method.
"""
for record in self:
record.can_be_refunded = record.state == "received"
record.can_be_refunded = (
record.operation_id.action_create_refund
in ("manual_after_receipt", "automatic_after_receipt")
and record.state == "received"
) or (
record.operation_id.action_create_refund
in ("manual_on_confirm", "automatic_on_confirm")
and record.state == "confirmed"
)

@api.depends("remaining_qty", "state")
@api.depends("remaining_qty", "state", "operation_id.action_create_delivery")
def _compute_can_be_returned(self):
"""Compute 'can_be_returned'. This field controls the visibility
of the 'Return to customer' button in the rma form
Expand All @@ -406,8 +509,17 @@ def _compute_can_be_returned(self):
rma._ensure_can_be_returned.
"""
for r in self:
r.can_be_returned = (
r.state in ["received", "waiting_return"] and r.remaining_qty > 0
r.can_be_returned = r.remaining_qty > 0 and (
(
r.operation_id.action_create_delivery
in ("manual_after_receipt", "automatic_after_receipt")
and r.state in ["received", "waiting_return"]
)
or (
r.operation_id.action_create_delivery
in ("manual_on_confirm", "automatic_on_confirm")
and r.state == "confirmed"
)
)

@api.depends("state")
Expand All @@ -420,11 +532,20 @@ def _compute_can_be_replaced(self):
rma._ensure_can_be_replaced.
"""
for r in self:
r.can_be_replaced = r.state in [
"received",
"waiting_replacement",
"replaced",
]
r.can_be_replaced = (
r.operation_id.action_create_delivery
in ("manual_after_receipt", "automatic_after_receipt")
and r.state
in [
"received",
"waiting_replacement",
"replaced",
]
) or (
r.operation_id.action_create_delivery
in ("manual_on_confirm", "automatic_on_confirm")
and r.state == "confirmed"
)

@api.depends("state", "remaining_qty")
def _compute_can_be_finished(self):
Expand Down Expand Up @@ -531,6 +652,14 @@ def _compute_product_uom(self):
else:
record.product_uom = False

@api.depends("replace_product_id")
def _compute_replace_product_uom(self):
for record in self:
if record.product_id:
record.replace_product_uom = record.replace_product_id.uom_id
else:
record.replace_product_uom = False

@api.depends("picking_id", "product_id", "company_id")
def _compute_location_id(self):
for record in self:
Expand Down Expand Up @@ -726,20 +855,73 @@ def _prepare_reception_procurements(self):
)
return procurements

def _create_receipt(self):
procurements = self._prepare_reception_procurements()
if procurements:
self.env["procurement.group"].run(procurements)
self.reception_move_id.picking_id.action_assign()

def action_create_receipt(self):
self.ensure_one()
self._create_receipt()
self.ensure_one()
return {
"name": _("Receipt"),
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "stock.picking",
"views": [[False, "form"]],
"res_id": self.reception_move_id.picking_id.id,
}

def _create_replace_or_return(self):
"""create a replace or return order based on the operation seetings"""
self.ensure_one()
if self.operation_id.different_return_product:
if (
not self.replace_product_id
or not self.replace_product_uom_qty
or not self.replace_warehouse_id
):
raise ValidationError(
_(
"The selected operation provides for the replacement with a "
"different product. Please complete the replacement "
"information."
)
)
self.create_replace(
fields.Datetime.now(),
self.replace_warehouse_id,
self.replace_product_id,
self.replace_product_uom_qty,
self.replace_product_uom,
)
else:
self.with_context(
rma_return_grouping=self.env.company.rma_return_grouping
).create_return(
fields.Datetime.now(), self.product_uom_qty, self.product_uom
)

def action_confirm(self):
"""Invoked when 'Confirm' button in rma form view is clicked."""
self._ensure_required_fields()
self = self.filtered(lambda rma: rma.state == "draft")
if not self:
return
procurements = self._prepare_reception_procurements()
if procurements:
self.env["procurement.group"].run(procurements)
self.reception_move_id.picking_id.action_assign()
self.write({"state": "confirmed"})
for rma in self:
rma._add_message_subscribe_partner()
self._send_confirmation_email()
for rec in self:
if rec.operation_id.action_create_receipt == "automatic_on_confirm":
rec._create_receipt()
if rec.operation_id.action_create_delivery == "automatic_on_confirm":
rec._create_replace_or_return()
if rec.operation_id.action_create_refund == "automatic_on_confirm":
rec.action_refund()

def action_refund(self):
"""Invoked when 'Refund' button in rma form view is clicked
Expand Down Expand Up @@ -1376,6 +1558,11 @@ def update_received_state_on_reception(self):
"""
self.write({"state": "received"})
self._send_receipt_confirmation_email()
for rec in self:
if rec.operation_id.action_create_delivery == "automatic_after_receipt":
rec._create_replace_or_return()
if rec.operation_id.action_create_refund == "automatic_after_receipt":
rec.action_refund()

def update_received_state(self):
"""Invoked by:
Expand Down
38 changes: 38 additions & 0 deletions rma/models/rma_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,44 @@ class RmaOperation(models.Model):
active = fields.Boolean(default=True)
name = fields.Char(required=True, translate=True)

action_create_receipt = fields.Selection(
[
("manual_on_confirm", "Manually on Confirm"),
("automatic_on_confirm", "Automatically on Confirm"),
],
string="Create Receipt",
default="automatic_on_confirm",
help="Define how the receipt action should be handled.",
)
action_create_delivery = fields.Selection(
[
("manual_on_confirm", "Manually on Confirm"),
("automatic_on_confirm", "Automatically on Confirm"),
("manual_after_receipt", "Manually After Receipt"),
("automatic_after_receipt", "Automatically After Receipt"),
],
string="Delivery Action",
help="Define how the delivery action should be handled.",
default="manual_after_receipt",
)

different_return_product = fields.Boolean(
help="If checked, allows the return of a product different from the one "
"originally ordered. Used if the delivery is created automatically",
)

action_create_refund = fields.Selection(
[
("manual_on_confirm", "Manually on Confirm"),
("automatic_on_confirm", "Automatically on Confirm"),
("manual_after_receipt", "Manually After Receipt"),
("automatic_after_receipt", "Automatically After Receipt"),
],
string="Refund Action",
default="manual_after_receipt",
help="Define how the refund action should be handled.",
)

_sql_constraints = [
("name_uniq", "unique (name)", "That operation name already exists !"),
]
1 change: 1 addition & 0 deletions rma/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import test_rma
from . import test_rma_operation
Loading

0 comments on commit 31588af

Please sign in to comment.