diff --git a/rma_analytic/README.rst b/rma_analytic/README.rst new file mode 100644 index 00000000..4f6f749a --- /dev/null +++ b/rma_analytic/README.rst @@ -0,0 +1,35 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: https://www.gnu.org/licenses/lgpl + :alt: License: LGPL-3 + +========================== +RMA with Analytic Accounts +========================== + +This module introduces the following features: + +* Adds the analytic account to the RMA order lines. + +* Propagates the analytic account to the procurements created + +* Introduce rules to ensure consistency + + +Usage +===== + +* Add the analytic information in the rma line or let the system fill it + from origin + + +Contributors +------------ + +* Aaron Henriquez +* Serpent Consulting Services Pvt. Ltd. + + +Maintainer +---------- + +This module is maintained by Eficent. diff --git a/rma_analytic/__init__.py b/rma_analytic/__init__.py new file mode 100644 index 00000000..aee8895e --- /dev/null +++ b/rma_analytic/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/rma_analytic/__manifest__.py b/rma_analytic/__manifest__.py new file mode 100644 index 00000000..72c45266 --- /dev/null +++ b/rma_analytic/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Analytic Account in RMA", + "version": "12.0.1.0.0", + "author": "Eficent," "Odoo Community Association (OCA)", + "license": "LGPL-3", + "website": "http://www.eficent.com", + "category": "Analytic", + "depends": [ + "rma_account", + "stock_analytic", + "procurement_mto_analytic", + ], + "data": ["views/rma_order_line_view.xml"], + "installable": True, +} diff --git a/rma_analytic/models/__init__.py b/rma_analytic/models/__init__.py new file mode 100644 index 00000000..12c8922c --- /dev/null +++ b/rma_analytic/models/__init__.py @@ -0,0 +1,2 @@ +from . import stock_move +from . import rma_order_line diff --git a/rma_analytic/models/rma_order_line.py b/rma_analytic/models/rma_order_line.py new file mode 100644 index 00000000..4ac13c87 --- /dev/null +++ b/rma_analytic/models/rma_order_line.py @@ -0,0 +1,25 @@ +# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class RmaOrderLine(models.Model): + + _inherit = "rma.order.line" + + analytic_account_id = fields.Many2one( + comodel_name="account.analytic.account", + string="Analytic Account", + ) + + @api.multi + def _prepare_rma_line_from_inv_line(self, line): + res = super( + RmaOrderLine, self + )._prepare_rma_line_from_inv_line(line) + if line.account_analytic_id: + res.update( + analytic_account_id=line.account_analytic_id.id + ) + return res diff --git a/rma_analytic/models/stock_move.py b/rma_analytic/models/stock_move.py new file mode 100644 index 00000000..d0932dc5 --- /dev/null +++ b/rma_analytic/models/stock_move.py @@ -0,0 +1,17 @@ +# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class StockMove(models.Model): + _inherit = "stock.move" + + def _prepare_procurement_values(self): + res = super(StockMove, self)._prepare_procurement_values() + res.update( + { + "account_analytic_id": self.rma_line_id.analytic_account_id.id + } + ) + return res diff --git a/rma_analytic/tests/__init__.py b/rma_analytic/tests/__init__.py new file mode 100644 index 00000000..6e6f6965 --- /dev/null +++ b/rma_analytic/tests/__init__.py @@ -0,0 +1 @@ +from . import test_rma_analytic diff --git a/rma_analytic/tests/test_rma_analytic.py b/rma_analytic/tests/test_rma_analytic.py new file mode 100644 index 00000000..6ae294be --- /dev/null +++ b/rma_analytic/tests/test_rma_analytic.py @@ -0,0 +1,204 @@ +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo.addons.rma.tests import test_rma + + +class TestRmaAnalytic(test_rma.TestRma): + + @classmethod + def setUpClass(cls): + super(TestRmaAnalytic, cls).setUpClass() + cls.rma_add_invoice_wiz = cls.env["rma_add_invoice"] + cls.rma_refund_wiz = cls.env["rma.refund"] + products2move = [ + (cls.product_1, 3), + (cls.product_2, 5), + (cls.product_3, 2), + ] + cls.rma_add_invoice_wiz = cls.env["rma_add_invoice"] + cls.rma_ana_id = cls._create_rma_from_move( + products2move, + "supplier", + cls.env.ref("base.res_partner_2"), + dropship=False, + ) + receivable_type = cls.env.ref( + "account.data_account_type_receivable" + ) + # Create Invoices: + customer_account = ( + cls.env["account.account"] + .search( + [("user_type_id", "=", receivable_type.id)], limit=1 + ) + .id + ) + cls.inv_customer = cls.env["account.invoice"].create( + { + "partner_id": cls.partner_id.id, + "account_id": customer_account, + "type": "out_invoice", + } + ) + cls.anal = cls.env["account.analytic.account"].create( + {"name": "Name"} + ) + cls.inv_line_1 = cls.env["account.invoice.line"].create( + { + "name": cls.partner_id.name, + "product_id": cls.product_1.id, + "quantity": 12.0, + "price_unit": 100.0, + "account_analytic_id": cls.anal.id, + "invoice_id": cls.inv_customer.id, + "uom_id": cls.product_1.uom_id.id, + "account_id": customer_account, + } + ) + + @classmethod + def _prepare_move(cls, product, qty, src, dest, picking_in): + res = super(TestRmaAnalytic, cls)._prepare_move( + product, qty, src, dest, picking_in + ) + analytic_1 = cls.env["account.analytic.account"].create( + {"name": "Test account #1"} + ) + res.update({"analytic_account_id": analytic_1.id}) + return res + + def test_analytic(self): + for line in self.rma_ana_id.rma_line_ids: + for move in line.move_ids: + self.assertEqual( + line.analytic_account_id, + move.analytic_account_id, + "the analytic account is not propagated", + ) + + def test_invoice_analytic(self): + """Test wizard to create RMA from a customer invoice.""" + rma_line = ( + self.env["rma.order.line"] + .with_context(customer=True) + .new( + { + "partner_id": self.partner_id.id, + "product_id": self.product_1.id, + "operation_id": self.env.ref( + "rma.rma_operation_customer_replace" + ).id, + "in_route_id": self.env.ref( + "rma.route_rma_customer" + ), + "out_route_id": self.env.ref( + "rma.route_rma_customer" + ), + "in_warehouse_id": self.env.ref( + "stock.warehouse0" + ), + "out_warehouse_id": self.env.ref( + "stock.warehouse0" + ), + "location_id": self.env.ref( + "stock.stock_location_stock" + ), + "type": "customer", + "invoice_line_id": self.inv_line_1.id, + "uom_id": self.product_1.uom_id.id, + } + ) + ) + rma_line._onchange_invoice_line_id() + self.assertEqual( + rma_line.analytic_account_id, + self.inv_line_1.account_analytic_id, + ) + + def test_invoice_analytic02(self): + self.product_1.rma_customer_operation_id = self.env.ref( + "rma.rma_operation_customer_replace" + ).id + rma_order = ( + self.env["rma.order"] + .with_context(customer=True) + .create( + { + "name": "RMA", + "partner_id": self.partner_id.id, + "type": "customer", + "rma_line_ids": [], + } + ) + ) + add_inv = self.rma_add_invoice_wiz.with_context( + { + "customer": True, + "active_ids": [rma_order.id], + "active_model": "rma.order", + } + ).create( + { + "invoice_line_ids": [ + (6, 0, self.inv_customer.invoice_line_ids.ids) + ] + } + ) + add_inv.add_lines() + + self.assertEqual( + rma_order.mapped("rma_line_ids.analytic_account_id"), + self.inv_line_1.account_analytic_id, + ) + + def test_refund_analytic(self): + self.product_1.rma_customer_operation_id = self.env.ref( + "rma_account.rma_operation_customer_refund" + ).id + rma_line = ( + self.env["rma.order.line"] + .with_context(customer=True) + .create( + { + "partner_id": self.partner_id.id, + "product_id": self.product_1.id, + "operation_id": self.env.ref( + "rma_account.rma_operation_customer_refund" + ).id, + "in_route_id": self.env.ref( + "rma.route_rma_customer" + ).id, + "out_route_id": self.env.ref( + "rma.route_rma_customer" + ).id, + "in_warehouse_id": self.env.ref( + "stock.warehouse0" + ).id, + "out_warehouse_id": self.env.ref( + "stock.warehouse0" + ).id, + "location_id": self.env.ref( + "stock.stock_location_stock" + ).id, + "type": "customer", + "invoice_line_id": self.inv_line_1.id, + "uom_id": self.product_1.uom_id.id, + } + ) + ) + rma_line._onchange_invoice_line_id() + rma_line.action_rma_to_approve() + rma_line.action_rma_approve() + make_refund = self.rma_refund_wiz.with_context( + { + "customer": True, + "active_ids": rma_line.ids, + "active_model": "rma.order.line", + } + ).create({"description": "Test refund"}) + make_refund.invoice_refund() + self.assertEqual( + rma_line.mapped("analytic_account_id"), + rma_line.mapped("refund_line_ids.account_analytic_id"), + ) diff --git a/rma_analytic/views/rma_order_line_view.xml b/rma_analytic/views/rma_order_line_view.xml new file mode 100644 index 00000000..b37b181f --- /dev/null +++ b/rma_analytic/views/rma_order_line_view.xml @@ -0,0 +1,48 @@ + + + + + rma.order.line.tree + rma.order.line + + + + + + + + + + rma.order.line.supplier.tree + rma.order.line + + + + + + + + + + rma.order.line.supplier.form + rma.order.line + + + + + + + + + + rma.order.line.form + rma.order.line + + + + + + + + diff --git a/rma_analytic/wizards/__init__.py b/rma_analytic/wizards/__init__.py new file mode 100644 index 00000000..31333467 --- /dev/null +++ b/rma_analytic/wizards/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from . import rma_add_stock_move +from . import rma_make_picking +from . import rma_add_invoice +from . import rma_refund diff --git a/rma_analytic/wizards/rma_add_invoice.py b/rma_analytic/wizards/rma_add_invoice.py new file mode 100644 index 00000000..54e86dc4 --- /dev/null +++ b/rma_analytic/wizards/rma_add_invoice.py @@ -0,0 +1,18 @@ +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import models + + +class RmaAddInvoice(models.TransientModel): + _inherit = "rma_add_invoice" + + def _prepare_rma_line_from_inv_line(self, line): + res = super( + RmaAddInvoice, self + )._prepare_rma_line_from_inv_line(line) + if line.account_analytic_id: + res.update( + analytic_account_id=line.account_analytic_id.id + ) + return res diff --git a/rma_analytic/wizards/rma_add_stock_move.py b/rma_analytic/wizards/rma_add_stock_move.py new file mode 100644 index 00000000..fb50ab3b --- /dev/null +++ b/rma_analytic/wizards/rma_add_stock_move.py @@ -0,0 +1,16 @@ +# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import api, models + + +class RmaAddStockMove(models.TransientModel): + _inherit = "rma_add_stock_move" + + @api.model + def _prepare_rma_line_from_stock_move(self, sm, lot=False): + data = super( + RmaAddStockMove, self + )._prepare_rma_line_from_stock_move(sm, lot) + data.update(analytic_account_id=sm.analytic_account_id.id) + return data diff --git a/rma_analytic/wizards/rma_make_picking.py b/rma_analytic/wizards/rma_make_picking.py new file mode 100644 index 00000000..a45dd9e9 --- /dev/null +++ b/rma_analytic/wizards/rma_make_picking.py @@ -0,0 +1,18 @@ +# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import models, api + + +class RmaMakePicking(models.TransientModel): + _inherit = "rma_make_picking.wizard" + + @api.model + def _get_procurement_data(self, item, group, qty, picking_type): + procurement_data = super( + RmaMakePicking, self + )._get_procurement_data(item, group, qty, picking_type) + procurement_data.update( + analytic_account_id=item.line_id.analytic_account_id.id + ) + return procurement_data diff --git a/rma_analytic/wizards/rma_refund.py b/rma_analytic/wizards/rma_refund.py new file mode 100644 index 00000000..41c3c5ea --- /dev/null +++ b/rma_analytic/wizards/rma_refund.py @@ -0,0 +1,17 @@ +# © 2017 Eficent Business and IT Consulting Services S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import api, models + + +class RmaRefund(models.TransientModel): + _inherit = "rma.refund" + + @api.model + def prepare_refund_line(self, item, refund): + res = super(RmaRefund, self).prepare_refund_line(item, refund) + if item.line_id.analytic_account_id: + res.update( + account_analytic_id=item.line_id.analytic_account_id.id + ) + return res