-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #513 from ForgeFlow/17_nc_mig_rma_account
[17.0] [MIG] rma_account
- Loading branch information
Showing
30 changed files
with
2,901 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg | ||
:alt: License LGPL-3 | ||
|
||
=========== | ||
RMA Account | ||
=========== | ||
|
||
This module integrates Return Merchandise Authorizations (RMA) with invoices, | ||
allowing to: | ||
|
||
#. Create complete RMA's using existing invoices as a reference. | ||
#. Create refunds from a RMA. | ||
|
||
Usage | ||
===== | ||
|
||
RMA are accessible though Inventory menu. There's four menus, divided by type. | ||
Users can access to the list of RMA or RMA lines. | ||
|
||
Create an RMA: | ||
|
||
#. Select a partner. Fill the rma lines by selecting an invoice. | ||
#. Request approval and approve. | ||
#. Click on RMA Lines button. | ||
#. Click on more and select an option: "Receive products", "Create Delivery | ||
Order, Create Refund". | ||
#. Go back to the RMA. Set the RMA to done if not further action is required. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/ForgeFlow/stock-rma/issues>`_. In case of trouble, please | ||
check there if your issue has already been reported. If you spotted it first, | ||
help us smashing it by providing a detailed and welcomed feedback. | ||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
* Jordi Ballester Alomar <[email protected]> | ||
* Aaron Henriquez <[email protected]> | ||
* Lois Rilo <[email protected]> | ||
* Bhavesh Odedra <[email protected]> | ||
* Akim Juillerat <[email protected]> | ||
|
||
Maintainer | ||
---------- | ||
|
||
This module is maintained by ForgeFlow. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Copyright 2017 ForgeFlow S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) | ||
|
||
from . import models | ||
from . import wizards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright 2017 ForgeFlow S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) | ||
|
||
{ | ||
"name": "RMA Account", | ||
"version": "17.0.1.0.0", | ||
"license": "LGPL-3", | ||
"category": "RMA", | ||
"summary": "Integrates RMA with Invoice Processing", | ||
"author": "ForgeFlow", | ||
"website": "https://github.com/ForgeFlow", | ||
"depends": ["stock_account", "rma"], | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"data/rma_operation.xml", | ||
"views/rma_order_view.xml", | ||
"views/rma_operation_view.xml", | ||
"views/rma_order_line_view.xml", | ||
"views/account_move_view.xml", | ||
"views/rma_account_menu.xml", | ||
"wizards/rma_add_account_move.xml", | ||
"wizards/rma_refund.xml", | ||
], | ||
"installable": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?xml version="1.0" ?> | ||
<odoo noupdate="1"> | ||
|
||
<record id="rma.rma_operation_customer_replace" model="rma.operation"> | ||
<field name="refund_policy">no</field> | ||
</record> | ||
|
||
<record id="rma.rma_operation_supplier_replace" model="rma.operation"> | ||
<field name="refund_policy">no</field> | ||
</record> | ||
|
||
<record id="rma_operation_customer_refund" model="rma.operation"> | ||
<field name="name">Refund after receive</field> | ||
<field name="code">RF-C</field> | ||
<field name="refund_policy">received</field> | ||
<field name="receipt_policy">ordered</field> | ||
<field name="delivery_policy">no</field> | ||
<field name="type">customer</field> | ||
<field name="in_route_id" ref="rma.route_rma_customer" /> | ||
<field name="out_route_id" ref="rma.route_rma_customer" /> | ||
</record> | ||
|
||
<record id="rma_operation_supplier_refund" model="rma.operation"> | ||
<field name="name">Refund after deliver</field> | ||
<field name="code">RF-S</field> | ||
<field name="refund_policy">ordered</field> | ||
<field name="receipt_policy">no</field> | ||
<field name="delivery_policy">ordered</field> | ||
<field name="type">supplier</field> | ||
<field name="in_route_id" ref="rma.route_rma_supplier" /> | ||
<field name="out_route_id" ref="rma.route_rma_supplier" /> | ||
</record> | ||
|
||
<record id="rma.rma_operation_ds_replace" model="rma.operation"> | ||
<field name="refund_policy">no</field> | ||
</record> | ||
|
||
<record id="rma.rma_operation_ds_replace_supplier" model="rma.operation"> | ||
<field name="refund_policy">no</field> | ||
</record> | ||
|
||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from . import rma_order | ||
from . import rma_order_line | ||
from . import rma_operation | ||
from . import account_move | ||
from . import account_move_line | ||
from . import procurement | ||
from . import stock_move | ||
from . import stock_valuation_layer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# Copyright 2017-22 ForgeFlow S.L. | ||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) | ||
|
||
from odoo import api, fields, models | ||
from odoo.tools.float_utils import float_compare | ||
|
||
|
||
class AccountMove(models.Model): | ||
_inherit = "account.move" | ||
|
||
@api.depends("line_ids.rma_line_ids") | ||
def _compute_used_in_rma_count(self): | ||
for inv in self: | ||
rmas = inv.mapped("line_ids.rma_line_ids") | ||
inv.used_in_rma_count = len(rmas) | ||
|
||
@api.depends("line_ids.rma_line_id") | ||
def _compute_rma_count(self): | ||
for inv in self: | ||
rmas = inv.mapped("line_ids.rma_line_id") | ||
inv.rma_count = len(rmas) | ||
|
||
def _prepare_invoice_line_from_rma_line(self, rma_line): | ||
sequence = max(self.line_ids.mapped("sequence")) + 1 if self.line_ids else 10 | ||
qty = rma_line.qty_to_refund | ||
if float_compare(qty, 0.0, precision_rounding=rma_line.uom_id.rounding) <= 0: | ||
qty = 0.0 | ||
data = { | ||
"move_id": self.id, | ||
"product_uom_id": rma_line.uom_id.id, | ||
"product_id": rma_line.product_id.id, | ||
"price_unit": rma_line.company_id.currency_id._convert( | ||
rma_line._get_price_unit(), | ||
self.currency_id, | ||
self.company_id, | ||
self.date, | ||
round=False, | ||
), | ||
"quantity": qty, | ||
"discount": 0.0, | ||
"rma_line_id": rma_line.id, | ||
"sequence": sequence + 1, | ||
} | ||
return data | ||
|
||
def _post_process_invoice_line_from_rma_line(self, new_line, rma_line): | ||
new_line.rma_line_id = rma_line | ||
new_line.name = f"{self.add_rma_line_id.name}: {new_line.name}" | ||
new_line.account_id = new_line.account_id | ||
return True | ||
|
||
@api.onchange("add_rma_line_id") | ||
def onchange_add_rma_line_id(self): | ||
if not self.add_rma_line_id: | ||
return {} | ||
if not self.partner_id: | ||
self.partner_id = self.add_rma_line_id.partner_id.id | ||
|
||
new_line = self.env["account.move.line"] | ||
if self.add_rma_line_id not in (self.line_ids.mapped("rma_line_id")): | ||
data = self._prepare_invoice_line_from_rma_line(self.add_rma_line_id) | ||
new_line = new_line.new(data) | ||
self._post_process_invoice_line_from_rma_line( | ||
new_line, self.add_rma_line_id | ||
) | ||
# Compute invoice_origin. | ||
origins = set(self.line_ids.mapped("rma_line_id.name")) | ||
self.invoice_origin = ",".join(list(origins)) | ||
self.add_rma_line_id = False | ||
|
||
rma_count = fields.Integer(compute="_compute_rma_count", string="# of RMA") | ||
used_in_rma_count = fields.Integer( | ||
compute="_compute_used_in_rma_count", string="# of Used in RMA" | ||
) | ||
|
||
add_rma_line_id = fields.Many2one( | ||
comodel_name="rma.order.line", | ||
string="Add from RMA line", | ||
ondelete="set null", | ||
help="Create a refund in based on an existing rma_line", | ||
) | ||
|
||
def action_view_used_in_rma(self): | ||
rmas = self.mapped("line_ids.rma_line_ids") | ||
return self._prepare_action_view_rma(rmas) | ||
|
||
def action_view_rma(self): | ||
rmas = self.mapped("line_ids.rma_line_id") | ||
return self._prepare_action_view_rma(rmas) | ||
|
||
def _prepare_action_view_rma(self, rmas): | ||
if self.move_type in ["in_invoice", "in_refund"]: | ||
action = self.env.ref("rma.action_rma_supplier_lines") | ||
form_view = self.env.ref("rma.view_rma_line_supplier_form", False) | ||
else: | ||
action = self.env.ref("rma.action_rma_customer_lines") | ||
form_view = self.env.ref("rma.view_rma_line_form", False) | ||
result = action.sudo().read()[0] | ||
rma_ids = rmas.ids | ||
# choose the view_mode accordingly | ||
if not rma_ids: | ||
result["domain"] = [("id", "in", [])] | ||
elif len(rma_ids) > 1: | ||
result["domain"] = [("id", "in", rma_ids)] | ||
else: | ||
res = form_view | ||
result["views"] = [(res and res.id or False, "form")] | ||
result["res_id"] = rma_ids and rma_ids[0] or False | ||
return result | ||
|
||
def _stock_account_prepare_anglo_saxon_out_lines_vals(self): | ||
product_model = self.env["product.product"] | ||
res = super()._stock_account_prepare_anglo_saxon_out_lines_vals() | ||
for line in res: | ||
if line.get("product_id", False): | ||
product = product_model.browse(line.get("product_id", False)) | ||
if ( | ||
line.get("account_id") | ||
!= product.categ_id.property_stock_valuation_account_id.id | ||
): | ||
current_move = self.browse(line.get("move_id", False)) | ||
current_rma = current_move.invoice_line_ids.filtered( | ||
lambda x, product=product: x.rma_line_id | ||
and x.product_id.id == product.id | ||
).mapped("rma_line_id") | ||
if len(current_rma) == 1: | ||
line.update({"rma_line_id": current_rma.id}) | ||
elif len(current_rma) > 1: | ||
find_with_label_rma = current_rma.filtered( | ||
lambda x, line=line: x.name == line.get("name") | ||
) | ||
if len(find_with_label_rma) == 1: | ||
line.update({"rma_line_id": find_with_label_rma.id}) | ||
return res | ||
|
||
def _stock_account_get_last_step_stock_moves(self): | ||
rslt = super()._stock_account_get_last_step_stock_moves() | ||
for invoice in self.filtered(lambda x: x.move_type == "out_invoice"): | ||
rslt += invoice.mapped("line_ids.rma_line_id.move_ids").filtered( | ||
lambda x: x.state == "done" and x.location_dest_id.usage == "customer" | ||
) | ||
for invoice in self.filtered(lambda x: x.move_type == "out_refund"): | ||
# Add refunds generated from the RMA | ||
rslt += invoice.mapped("line_ids.rma_line_id.move_ids").filtered( | ||
lambda x: x.state == "done" and x.location_id.usage == "customer" | ||
) | ||
return rslt |
Oops, something went wrong.