diff --git a/account_move_line_rma_order_line/tests/test_account_move_line_rma_order_line.py b/account_move_line_rma_order_line/tests/test_account_move_line_rma_order_line.py new file mode 100644 index 00000000..5b38e5fd --- /dev/null +++ b/account_move_line_rma_order_line/tests/test_account_move_line_rma_order_line.py @@ -0,0 +1,294 @@ +# © 2017-2022 ForgeFlow S.L. (www.forgeflow.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.tests import common + + +class TestAccountMoveLineRmaOrderLine(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(TestAccountMoveLineRmaOrderLine, cls).setUpClass() + cls.rma_model = cls.env["rma.order"] + cls.rma_line_model = cls.env["rma.order.line"] + cls.rma_refund_wiz = cls.env["rma.refund"] + cls.rma_add_stock_move = cls.env["rma_add_stock_move"] + cls.rma_make_picking = cls.env["rma_make_picking.wizard"] + cls.invoice_model = cls.env["account.move"] + cls.stock_picking_model = cls.env["stock.picking"] + cls.invoice_line_model = cls.env["account.move.line"] + cls.product_model = cls.env["product.product"] + cls.product_ctg_model = cls.env["product.category"] + cls.acc_type_model = cls.env["account.account.type"] + cls.account_model = cls.env["account.account"] + cls.aml_model = cls.env["account.move.line"] + cls.res_users_model = cls.env["res.users"] + + cls.partner1 = cls.env.ref("base.res_partner_1") + cls.location_stock = cls.env.ref("stock.stock_location_stock") + cls.company = cls.env.ref("base.main_company") + cls.group_rma_user = cls.env.ref("rma.group_rma_customer_user") + cls.group_account_invoice = cls.env.ref("account.group_account_invoice") + cls.group_account_manager = cls.env.ref("account.group_account_manager") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + wh = cls.env.ref("stock.warehouse0") + cls.stock_rma_location = wh.lot_rma_id + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + # Create account for Goods Received Not Invoiced + acc_type = cls._create_account_type("equity", "other", "equity") + name = "Goods Received Not Invoiced" + code = "grni" + cls.account_grni = cls._create_account(acc_type, name, code, cls.company) + + # Create account for Cost of Goods Sold + acc_type = cls._create_account_type("expense", "other", "expense") + name = "Cost of Goods Sold" + code = "cogs" + cls.account_cogs = cls._create_account(acc_type, name, code, cls.company) + # Create account for Inventory + acc_type = cls._create_account_type("asset", "other", "asset") + name = "Inventory" + code = "inventory" + cls.account_inventory = cls._create_account(acc_type, name, code, cls.company) + # Create Product + cls.product = cls._create_product() + cls.product_uom_id = cls.env.ref("uom.product_uom_unit") + # Create users + cls.rma_user = cls._create_user( + "rma_user", [cls.group_rma_user, cls.group_account_invoice], cls.company + ) + cls.account_invoice = cls._create_user( + "account_invoice", [cls.group_account_invoice], cls.company + ) + cls.account_manager = cls._create_user( + "account_manager", [cls.group_account_manager], cls.company + ) + + @classmethod + def _create_user(cls, login, groups, company): + """ Create a user.""" + group_ids = [group.id for group in groups] + user = cls.res_users_model.with_context({"no_reset_password": True}).create( + { + "name": "Test User", + "login": login, + "password": "demo", + "email": "test@yourcompany.com", + "company_id": company.id, + "company_ids": [(4, company.id)], + "groups_id": [(6, 0, group_ids)], + } + ) + return user.id + + @classmethod + def _create_account_type(cls, name, type, internal_group): + acc_type = cls.acc_type_model.create( + {"name": name, "type": type, "internal_group": internal_group} + ) + return acc_type + + @classmethod + def _create_account(cls, acc_type, name, code, company): + """Create an account.""" + account = cls.account_model.create( + { + "name": name, + "code": code, + "user_type_id": acc_type.id, + "company_id": company.id, + } + ) + return account + + @classmethod + def _create_product(cls): + """Create a Product.""" + # group_ids = [group.id for group in groups] + product_ctg = cls.product_ctg_model.create( + { + "name": "test_product_ctg", + "property_stock_valuation_account_id": cls.account_inventory.id, + "property_valuation": "real_time", + "property_stock_account_input_categ_id": cls.account_grni.id, + "property_stock_account_output_categ_id": cls.account_cogs.id, + } + ) + product = cls.product_model.create( + { + "name": "test_product", + "categ_id": product_ctg.id, + "type": "product", + "standard_price": 1.0, + "list_price": 1.0, + } + ) + return product + + @classmethod + def _create_picking(cls, partner): + return cls.stock_picking_model.create( + { + "partner_id": partner.id, + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.supplier_location.id, + } + ) + + @classmethod + def _prepare_move(cls, product, qty, src, dest, picking_in): + res = { + "partner_id": cls.partner1.id, + "product_id": product.id, + "name": product.partner_ref, + "state": "confirmed", + "product_uom": cls.product_uom_id.id or product.uom_id.id, + "product_uom_qty": qty, + "origin": "Test RMA", + "location_id": src.id, + "location_dest_id": dest.id, + "picking_id": picking_in.id, + } + return res + + @classmethod + def _create_rma(cls, products2move, partner): + picking_in = cls._create_picking(partner) + moves = [] + for item in products2move: + move_values = cls._prepare_move( + item[0], item[1], cls.stock_location, cls.customer_location, picking_in + ) + moves.append(cls.env["stock.move"].create(move_values)) + + rma_id = cls.rma_model.create( + { + "reference": "0001", + "type": "customer", + "partner_id": partner.id, + "company_id": cls.env.ref("base.main_company").id, + } + ) + for move in moves: + wizard = cls.rma_add_stock_move.new( + { + "move_ids": [(6, 0, move.ids)], + "rma_id": rma_id.id, + "partner_id": move.partner_id.id, + } + ) + # data = wizard._prepare_rma_line_from_stock_move(move) + wizard.add_lines() + + # CHECK ME: this code duplicate rma lines, what is the porpourse? + # if move.product_id.rma_customer_operation_id: + # move.product_id.rma_customer_operation_id.in_route_id = False + # move.product_id.categ_id.rma_customer_operation_id = False + # move.product_id.rma_customer_operation_id = False + # wizard._prepare_rma_line_from_stock_move(move) + # cls.line = cls.rma_line_model.create(data) + return rma_id + + def _get_balance(self, domain): + """ + Call read_group method and return the balance of particular account. + """ + aml_rec = self.aml_model.read_group( + domain, ["debit", "credit", "account_id"], ["account_id"] + ) + if aml_rec: + return aml_rec[0].get("debit", 0) - aml_rec[0].get("credit", 0) + else: + return 0.0 + + def _check_account_balance(self, account_id, rma_line=None, expected_balance=0.0): + """ + Check the balance of the account + """ + domain = [("account_id", "=", account_id)] + if rma_line: + domain.extend([("rma_line_id", "=", rma_line.id)]) + + balance = self._get_balance(domain) + if rma_line: + self.assertEqual( + balance, + expected_balance, + "Balance is not %s for rma Line %s." + % (str(expected_balance), rma_line.name), + ) + + def test_rma_invoice(self): + """Test that the rma line moves from the rma order to the + account move line and to the invoice line. + """ + products2move = [ + (self.product, 1), + ] + rma = self._create_rma(products2move, self.partner1) + rma_line = rma.rma_line_ids + for rma in rma_line: + if rma.price_unit == 0: + rma.price_unit = 1.0 + rma_line.action_rma_approve() + wizard = self.rma_make_picking.with_context( + { + "active_id": 1, + "active_ids": rma_line.ids, + "active_model": "rma.order.line", + "picking_type": "incoming", + } + ).create({}) + operation = self.env["rma.operation"].search( + [("type", "=", "customer"), ("refund_policy", "=", "received")], limit=1 + ) + rma_line.write({"operation_id": operation.id}) + rma_line.write({"refund_policy": "received"}) + + wizard._create_picking() + res = rma_line.action_view_in_shipments() + if "res_id" in res: + picking = self.env["stock.picking"].browse(res["res_id"]) + else: + picking_ids = self.env["stock.picking"].search(res["domain"]) + picking = self.env["stock.picking"].browse(picking_ids) + picking.move_lines.write({"quantity_done": 1.0}) + picking.button_validate() + # decreasing cogs + expected_balance = -1.0 + for record in rma_line: + self._check_account_balance( + self.account_cogs.id, rma_line=record, expected_balance=expected_balance + ) + make_refund = self.rma_refund_wiz.with_context( + { + "customer": True, + "active_ids": rma_line.ids, + "active_model": "rma.order.line", + } + ).create( + { + "description": "Test refund", + } + ) + for item in make_refund.item_ids: + item.write( + { + "qty_to_refund": 1.0, + } + ) + make_refund.invoice_refund() + rma_line.move_line_ids.move_id.filtered( + lambda x: x.state != "posted" + ).action_post() + for aml in rma_line.move_line_ids.move_id.filtered( + lambda x: x.move_type in ("out_refund", "in_refund") + ).invoice_line_ids: + if aml.product_id == rma_line.product_id and aml.move_id: + self.assertEqual( + aml.rma_line_id, + rma_line, + "Rma Order line has not been copied from the invoice to " + "the account move line.", + ) diff --git a/rma/models/stock_rule.py b/rma/models/stock_rule.py index bf1340da..a3da529f 100644 --- a/rma/models/stock_rule.py +++ b/rma/models/stock_rule.py @@ -35,7 +35,8 @@ class StockRule(models.Model): res["partner_id"] = line.delivery_address_id.id else: res["partner_id"] = line.rma_id.partner_id.id - dest_loc = self.env["stock.location"].browse([res["location_dest_id"]])[0] - if dest_loc.usage == "internal": - res["price_unit"] = line.price_unit + company_id = res["company_id"] + company = self.env["res.company"].browse(company_id) + cost = product_id.with_company(company).standard_price + res["price_unit"] = cost return res diff --git a/rma_account/models/__init__.py b/rma_account/models/__init__.py index 09afbe77..a5c03656 100644 --- a/rma_account/models/__init__.py +++ b/rma_account/models/__init__.py @@ -1,7 +1,5 @@ -# Copyright 2017 ForgeFlow S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - from . import rma_order from . import rma_order_line from . import rma_operation from . import account_move +from . import procurement diff --git a/rma_account/models/account_move.py b/rma_account/models/account_move.py index 4afe1ac9..d4f5deac 100644 --- a/rma_account/models/account_move.py +++ b/rma_account/models/account_move.py @@ -168,7 +168,7 @@ class AccountMoveLine(models.Model): rma_line_id = fields.Many2one( comodel_name="rma.order.line", - string="RMA line refund", + string="RMA line", ondelete="set null", - help="This will contain the rma line that originated the refund line", + help="This will contain the rma line that originated this line", ) diff --git a/rma_account/models/procurement.py b/rma_account/models/procurement.py new file mode 100644 index 00000000..9404d1c2 --- /dev/null +++ b/rma_account/models/procurement.py @@ -0,0 +1,48 @@ +# Copyright 2017-2022 ForgeFlow S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import fields, models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _get_stock_move_values( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ): + res = super(StockRule, self)._get_stock_move_values( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ) + if "rma_line_id" in values: + line = values.get("rma_line_id") + move = line.reference_move_id + if move and move.stock_valuation_layer_ids: + cost = move.stock_valuation_layer_ids[-1].unit_cost + res["price_unit"] = cost + return res + + +class ProcurementGroup(models.Model): + _inherit = "procurement.group" + + rma_id = fields.Many2one( + comodel_name="rma.order", string="RMA", ondelete="set null" + ) + rma_line_id = fields.Many2one( + comodel_name="rma.order.line", string="RMA line", ondelete="set null" + ) diff --git a/rma_account/models/rma_order.py b/rma_account/models/rma_order.py index 747316c2..370630d2 100644 --- a/rma_account/models/rma_order.py +++ b/rma_account/models/rma_order.py @@ -9,7 +9,9 @@ class RmaOrder(models.Model): def _compute_invoice_refund_count(self): for rec in self: - invoices = rec.mapped("rma_line_ids.refund_line_ids.move_id") + invoices = rec.mapped("rma_line_ids.move_line_ids.move_id").filtered( + lambda m: m.move_type in ["in_refund", "out_refund"] + ) rec.invoice_refund_count = len(invoices) def _compute_invoice_count(self): diff --git a/rma_account/models/rma_order_line.py b/rma_account/models/rma_order_line.py index 0e0a78b1..02ee3157 100644 --- a/rma_account/models/rma_order_line.py +++ b/rma_account/models/rma_order_line.py @@ -16,19 +16,20 @@ class RmaOrderLine(models.Model): return self.env["res.partner"] @api.depends( - "refund_line_ids", "refund_line_ids.move_id.state", "refund_policy", "type" + "move_line_ids", "move_line_ids.move_id.state", "refund_policy", "type" ) def _compute_qty_refunded(self): for rec in self: rec.qty_refunded = sum( - rec.refund_line_ids.filtered( + rec.move_line_ids.filtered( lambda i: i.move_id.state in ("posted") + and i.move_id.move_type in ["out_refund", "in_refund"] ).mapped("quantity") ) @api.depends( - "refund_line_ids", - "refund_line_ids.move_id.state", + "move_line_ids", + "move_line_ids.move_id.state", "refund_policy", "move_ids", "move_ids.state", @@ -47,7 +48,11 @@ class RmaOrderLine(models.Model): def _compute_refund_count(self): for rec in self: - rec.refund_count = len(rec.refund_line_ids.mapped("move_id")) + rec.refund_count = len( + rec.move_line_ids.mapped("move_id").filtered( + lambda m: m.move_type in ["out_refund", "in_refund"] + ) + ) invoice_address_id = fields.Many2one( "res.partner", @@ -68,7 +73,7 @@ class RmaOrderLine(models.Model): readonly=True, states={"draft": [("readonly", False)]}, ) - refund_line_ids = fields.One2many( + move_line_ids = fields.One2many( comodel_name="account.move.line", inverse_name="rma_line_id", string="Refund Lines", @@ -269,12 +274,14 @@ class RmaOrderLine(models.Model): } def action_view_refunds(self): - move_ids = self.mapped("refund_line_ids.move_id").ids + moves = self.mapped("move_line_ids.move_id").filtered( + lambda m: m.move_type in ["out_refund", "in_refund"] + ) form_view_ref = self.env.ref("account.view_move_form", False) tree_view_ref = self.env.ref("account.view_move_tree", False) return { - "domain": [("id", "in", move_ids)], + "domain": [("id", "in", moves.ids)], "name": "Refunds", "res_model": "account.move", "type": "ir.actions.act_window", diff --git a/rma_account/tests/test_rma_account.py b/rma_account/tests/test_rma_account.py index 6d07bf3a..7f169e7a 100644 --- a/rma_account/tests/test_rma_account.py +++ b/rma_account/tests/test_rma_account.py @@ -224,7 +224,7 @@ class TestRmaAccount(common.SingleTransactionCase): } ).create({"description": "Test refund"}) make_refund.invoice_refund() - rma.refund_line_ids.move_id.action_post() + rma.move_line_ids.move_id.action_post() rma._compute_refund_count() self.assertEqual(rma.refund_count, 1) self.assertEqual(rma.qty_to_refund, 0.0) @@ -266,8 +266,8 @@ class TestRmaAccount(common.SingleTransactionCase): } ).create({"description": "Test refund"}) make_refund.invoice_refund() - rma.refund_line_ids.move_id.action_post() + rma.move_line_ids.move_id.action_post() rma._compute_refund_count() self.assertEqual( - self.operation_1.refund_journal_id, rma.refund_line_ids.journal_id + self.operation_1.refund_journal_id, rma.move_line_ids.journal_id ) diff --git a/rma_account/wizards/rma_refund.py b/rma_account/wizards/rma_refund.py index 264ddb60..7c2b878b 100644 --- a/rma_account/wizards/rma_refund.py +++ b/rma_account/wizards/rma_refund.py @@ -80,7 +80,13 @@ class RmaRefund(models.TransientModel): for wizard in self: first = self.item_ids[0] values = self._prepare_refund(wizard, first.line_id) - new_refund = self.env["account.move"].create(values) + default_move_type = ( + "in_refund" if first.line_id.type == "supplier" else "out_refund", + ) + account_move_model = self.env["account.move"].with_context( + default_move_type=default_move_type + ) + new_refund = account_move_model.create(values) return new_refund def invoice_refund(self): @@ -106,17 +112,8 @@ class RmaRefund(models.TransientModel): @api.model def prepare_refund_line(self, item): - accounts = item.product.product_tmpl_id._get_product_accounts() - if item.line_id.type == "customer": - account = accounts["income"] - else: - account = accounts["expense"] - if not account: - raise ValidationError(_("Accounts are not configured for this product.")) - values = { "name": item.line_id.name or item.rma_id.name, - "account_id": account.id, "price_unit": item.line_id.price_unit, "product_uom_id": item.line_id.uom_id.id, "product_id": item.product.id, diff --git a/rma_purchase/__init__.py b/rma_purchase/__init__.py index f3284a96..aee8895e 100644 --- a/rma_purchase/__init__.py +++ b/rma_purchase/__init__.py @@ -1,5 +1,2 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - from . import models from . import wizards diff --git a/rma_purchase/__manifest__.py b/rma_purchase/__manifest__.py index fcda2e51..153e14d6 100644 --- a/rma_purchase/__manifest__.py +++ b/rma_purchase/__manifest__.py @@ -1,13 +1,12 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - { "name": "RMA Purchase", "version": "15.0.1.0.0", "category": "RMA", "summary": "RMA from PO", "license": "LGPL-3", - "author": "Eficent, Odoo Community Association (OCA)", + "author": "ForgeFlow, Odoo Community Association (OCA)", "website": "https://github.com/ForgeFlow/stock-rma", "depends": ["rma_account", "purchase"], "data": [ @@ -19,4 +18,5 @@ "wizards/rma_add_purchase.xml", ], "installable": True, + "auto_install": True, } diff --git a/rma_purchase/models/__init__.py b/rma_purchase/models/__init__.py index d41e378c..5edaa9af 100644 --- a/rma_purchase/models/__init__.py +++ b/rma_purchase/models/__init__.py @@ -1,7 +1,6 @@ -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - from . import rma_order from . import rma_order_line from . import purchase_order from . import purchase_order_line from . import rma_operation +from . import procurement diff --git a/rma_purchase/models/procurement.py b/rma_purchase/models/procurement.py new file mode 100644 index 00000000..854181f5 --- /dev/null +++ b/rma_purchase/models/procurement.py @@ -0,0 +1,61 @@ +# Copyright 2017-2022 ForgeFlow S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import fields, models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _get_stock_move_values( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ): + res = super(StockRule, self)._get_stock_move_values( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ) + if "rma_line_id" in values: + line = values.get("rma_line_id") + if line.reference_move_id: + return res + if line.purchase_order_line_id: + moves = line.purchase_order_line_id.move_ids + if moves: + # TODO: Should we be smart in the choice of the move? + layers = moves.mapped("stock_valuation_layer_ids") + cost = layers[-1].unit_cost + res["price_unit"] = cost + elif line.account_move_line_id.purchase_line_id: + purchase_lines = line.account_move_line_id.purchase_line_id + moves = purchase_lines.mapped("move_ids") + if moves: + layers = moves.mapped("stock_valuation_layer_ids") + cost = layers[-1].unit_cost + # TODO: Should we be smart in the choice of the move? + res["price_unit"] = cost + return res + + +class ProcurementGroup(models.Model): + _inherit = "procurement.group" + + rma_id = fields.Many2one( + comodel_name="rma.order", string="RMA", ondelete="set null" + ) + rma_line_id = fields.Many2one( + comodel_name="rma.order.line", string="RMA line", ondelete="set null" + ) diff --git a/rma_purchase/models/purchase_order.py b/rma_purchase/models/purchase_order.py index 37d9f784..4d81bc04 100644 --- a/rma_purchase/models/purchase_order.py +++ b/rma_purchase/models/purchase_order.py @@ -1,4 +1,4 @@ -# Copyright 2017-18 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, models diff --git a/rma_purchase/models/purchase_order_line.py b/rma_purchase/models/purchase_order_line.py index 70444eee..4962d861 100644 --- a/rma_purchase/models/purchase_order_line.py +++ b/rma_purchase/models/purchase_order_line.py @@ -1,4 +1,4 @@ -# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models diff --git a/rma_purchase/models/rma_operation.py b/rma_purchase/models/rma_operation.py index 5ee52512..6f03753c 100644 --- a/rma_purchase/models/rma_operation.py +++ b/rma_purchase/models/rma_operation.py @@ -1,4 +1,4 @@ -# Copyright 2018 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import _, api, fields, models diff --git a/rma_purchase/models/rma_order.py b/rma_purchase/models/rma_order.py index 286276f6..503fdd5a 100644 --- a/rma_purchase/models/rma_order.py +++ b/rma_purchase/models/rma_order.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models diff --git a/rma_purchase/models/rma_order_line.py b/rma_purchase/models/rma_order_line.py index 2015d4d9..319ac080 100644 --- a/rma_purchase/models/rma_order_line.py +++ b/rma_purchase/models/rma_order_line.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import _, api, fields, models diff --git a/rma_purchase/tests/__init__.py b/rma_purchase/tests/__init__.py index 061a9ecc..c7f1b5f2 100644 --- a/rma_purchase/tests/__init__.py +++ b/rma_purchase/tests/__init__.py @@ -1,4 +1 @@ -# 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 test_rma_purchase diff --git a/rma_purchase/tests/test_rma_purchase.py b/rma_purchase/tests/test_rma_purchase.py index c9cd65f6..558d2389 100644 --- a/rma_purchase/tests/test_rma_purchase.py +++ b/rma_purchase/tests/test_rma_purchase.py @@ -1,4 +1,4 @@ -# Copyright 2017-18 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo.fields import Datetime diff --git a/rma_purchase/wizards/__init__.py b/rma_purchase/wizards/__init__.py index 73c6279c..632e2e5b 100644 --- a/rma_purchase/wizards/__init__.py +++ b/rma_purchase/wizards/__init__.py @@ -1,6 +1,3 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - from . import rma_make_picking from . import rma_add_purchase from . import rma_order_line_make_purchase_order diff --git a/rma_purchase/wizards/rma_add_purchase.py b/rma_purchase/wizards/rma_add_purchase.py index 143ea44e..4ba17d1c 100644 --- a/rma_purchase/wizards/rma_add_purchase.py +++ b/rma_purchase/wizards/rma_add_purchase.py @@ -1,6 +1,5 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) - from odoo import _, api, fields, models from odoo.exceptions import ValidationError diff --git a/rma_purchase/wizards/rma_make_picking.py b/rma_purchase/wizards/rma_make_picking.py index f1694bf3..36f16ba6 100644 --- a/rma_purchase/wizards/rma_make_picking.py +++ b/rma_purchase/wizards/rma_make_picking.py @@ -1,4 +1,4 @@ -# © 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from odoo import api, fields, models diff --git a/rma_purchase/wizards/rma_order_line_make_purchase_order.py b/rma_purchase/wizards/rma_order_line_make_purchase_order.py index 5bda01fe..ce702041 100644 --- a/rma_purchase/wizards/rma_order_line_make_purchase_order.py +++ b/rma_purchase/wizards/rma_order_line_make_purchase_order.py @@ -1,5 +1,5 @@ -# Copyright 2018 Eficent Business and IT Consulting Services S.L. -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0). +# Copyright 2017-2022 ForgeFlow S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from datetime import datetime diff --git a/rma_sale/models/__init__.py b/rma_sale/models/__init__.py index 162f1ebd..bcab3a0d 100644 --- a/rma_sale/models/__init__.py +++ b/rma_sale/models/__init__.py @@ -1,7 +1,8 @@ -# Copyright 2020 ForgeFlow S.L. +# Copyright 2020-2022 ForgeFlow S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) from . import sale_order_line from . import sale_order from . import rma_order_line from . import rma_order from . import rma_operation +from . import procurement diff --git a/rma_sale/models/procurement.py b/rma_sale/models/procurement.py new file mode 100644 index 00000000..07b291e6 --- /dev/null +++ b/rma_sale/models/procurement.py @@ -0,0 +1,50 @@ +# Copyright 2022 ForgeFlow S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + +from odoo import models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _get_stock_move_values( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ): + res = super(StockRule, self)._get_stock_move_values( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ) + if "rma_line_id" in values: + line = values.get("rma_line_id") + if line.reference_move_id: + return res + if line.sale_line_id: + moves = line.sale_line_id.move_ids + if moves: + # TODO: Should we be smart in the choice of the move? + layers = moves.mapped("stock_valuation_layer_ids") + cost = layers[-1].unit_cost + res["price_unit"] = cost + elif line.account_move_line_id: + sale_lines = line.account_move_line_id.sale_line_ids + moves = sale_lines.mapped("move_ids") + if moves: + layers = moves.mapped("stock_valuation_layer_ids") + cost = layers[-1].unit_cost + # TODO: Should we be smart in the choice of the move? + res["price_unit"] = cost + return res