Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] rma: configurable workflow #417

Open
wants to merge 7 commits into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
172 changes: 157 additions & 15 deletions rma/models/rma.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,63 @@ def _domain_location_id(self):
copy=False,
)

sbejaoui marked this conversation as resolved.
Show resolved Hide resolved
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"
)
return_product_id = fields.Many2one(
"product.product",
help="Product to be returned if it's different from the originally delivered "
"item.",
)
different_return_product = fields.Boolean(
related="operation_id.different_return_product"
)

@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 +451,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 +471,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 +494,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 @@ -699,8 +782,11 @@ def _prepare_reception_procurement_vals(self, group=None):
vals = self._prepare_common_procurement_vals(group=group)
vals["route_ids"] = self.warehouse_id.rma_in_route_id
vals["rma_receiver_ids"] = [(6, 0, self.ids)]
vals["to_refund"] = self.operation_id.action_create_refund == "update_quantity"
if self.move_id:
vals["origin_returned_move_id"] = self.move_id.id
if not self.operation_id.different_return_product:
vals["move_orig_ids"] = [(6, 0, self.move_id.ids)]
return vals

def _prepare_reception_procurements(self):
Expand All @@ -712,34 +798,76 @@ def _prepare_reception_procurements(self):
group = rma.procurement_group_id
if not group:
group = group_model.create(rma._prepare_procurement_group_vals())
product = self.product_id
if self.different_return_product:
if not self.return_product_id:
raise ValidationError(
_(
"The selected operation requires a return product different"
" from the originally delivered item. Please select the "
"product to return."
)
)
product = self.return_product_id
procurements.append(
group_model.Procurement(
rma.product_id,
product,
rma.product_uom_qty,
rma.product_uom,
rma.location_id,
rma.product_id.display_name,
product.display_name,
group.name,
rma.company_id,
rma._prepare_reception_procurement_vals(group),
)
)
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 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.with_context(
rma_return_grouping=rec.env.company.rma_return_grouping
).create_replace(
fields.Datetime.now(),
rec.warehouse_id,
rec.product_id,
rec.product_uom_qty,
rec.product_uom,
)
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 +1504,20 @@ 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.with_context(
rma_return_grouping=rec.env.company.rma_return_grouping
).create_replace(
fields.Datetime.now(),
rec.warehouse_id,
rec.product_id,
rec.product_uom_qty,
rec.product_uom,
)

if rec.operation_id.action_create_refund == "automatic_after_receipt":
rec.action_refund()

def update_received_state(self):
"""Invoked by:
Expand Down
36 changes: 36 additions & 0 deletions rma/models/rma_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,42 @@ 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.",
)
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_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",
)
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"),
("update_quantity", "Update Quantities"),
],
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 !"),
Expand Down
11 changes: 4 additions & 7 deletions rma/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.

See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -275,7 +274,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: gray; } /* line numbers */
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -301,7 +300,7 @@
span.pre {
white-space: pre }

span.problematic, pre.problematic {
span.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -530,9 +529,7 @@ <h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
Expand Down
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
Loading