diff --git a/setup/stock_landed_costs_analytic/.eggs/README.txt b/setup/stock_landed_costs_analytic/.eggs/README.txt new file mode 100644 index 0000000000..5d01668824 --- /dev/null +++ b/setup/stock_landed_costs_analytic/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/setup/stock_landed_costs_analytic/odoo/addons/stock_landed_costs_analytic b/setup/stock_landed_costs_analytic/odoo/addons/stock_landed_costs_analytic new file mode 120000 index 0000000000..b378889d93 --- /dev/null +++ b/setup/stock_landed_costs_analytic/odoo/addons/stock_landed_costs_analytic @@ -0,0 +1 @@ +../../../../stock_landed_costs_analytic \ No newline at end of file diff --git a/setup/stock_landed_costs_analytic/setup.py b/setup/stock_landed_costs_analytic/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/stock_landed_costs_analytic/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_landed_costs_analytic/README.rst b/stock_landed_costs_analytic/README.rst new file mode 100644 index 0000000000..979d68ccbc --- /dev/null +++ b/stock_landed_costs_analytic/README.rst @@ -0,0 +1,64 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +=========================== +Stock Landed Costs Analytic +=========================== + +This module adds an analytic account and analytic tags on landed costs lines +so that on landed costs validation account moves get analytic account and +analytic tags values from landed costs lines. + +Usage +===== + +To use this module, you need to: + +#. Create a Landed Cost +#. Set Analytic Account and Analytic Tags on your Additional Costs +#. Validate your Landed Cost +#. Each journal items created from your Landed Cost should have Analytic Account and Analytic Costs from Additional Cost if Account on journal item and on Additional Cost is the same. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/87/13.0 + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Benoit Aimont + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/stock_landed_costs_analytic/__init__.py b/stock_landed_costs_analytic/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/stock_landed_costs_analytic/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_landed_costs_analytic/__manifest__.py b/stock_landed_costs_analytic/__manifest__.py new file mode 100644 index 0000000000..c4563dc3b9 --- /dev/null +++ b/stock_landed_costs_analytic/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Stock Landed Costs Analytic", + "summary": """ + This module adds an analytic account and analytic tags on landed costs + lines so that on landed costs validation account moves get analytic + account and analytic tags values from landed costs lines.""", + "version": "13.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-analytic", + "depends": ["stock_landed_costs"], + "data": ["views/stock_landed_cost_lines.xml"], + "demo": [], +} diff --git a/stock_landed_costs_analytic/models/__init__.py b/stock_landed_costs_analytic/models/__init__.py new file mode 100644 index 0000000000..6bc349a804 --- /dev/null +++ b/stock_landed_costs_analytic/models/__init__.py @@ -0,0 +1,2 @@ +from . import stock_landed_cost_lines +from . import stock_valuation_adjustment_lines diff --git a/stock_landed_costs_analytic/models/stock_landed_cost_lines.py b/stock_landed_costs_analytic/models/stock_landed_cost_lines.py new file mode 100644 index 0000000000..135d8c3a83 --- /dev/null +++ b/stock_landed_costs_analytic/models/stock_landed_cost_lines.py @@ -0,0 +1,14 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class StockLandedCostLines(models.Model): + + _inherit = "stock.landed.cost.lines" + + analytic_account_id = fields.Many2one( + string="Analytic Account", comodel_name="account.analytic.account", + ) + analytic_tag_ids = fields.Many2many("account.analytic.tag", string="Analytic Tags") diff --git a/stock_landed_costs_analytic/models/stock_valuation_adjustment_lines.py b/stock_landed_costs_analytic/models/stock_valuation_adjustment_lines.py new file mode 100644 index 0000000000..9ce1f48082 --- /dev/null +++ b/stock_landed_costs_analytic/models/stock_valuation_adjustment_lines.py @@ -0,0 +1,28 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class StockValuationAdjustmentLines(models.Model): + + _inherit = "stock.valuation.adjustment.lines" + + def _create_account_move_line( + self, move, credit_account_id, debit_account_id, qty_out, already_out_account_id + ): + res = super(StockValuationAdjustmentLines, self)._create_account_move_line( + move, credit_account_id, debit_account_id, qty_out, already_out_account_id + ) + cost_line = self.cost_line_id + for line in res: + if line[2]["account_id"] == cost_line.account_id.id: + if cost_line.analytic_account_id: + line[2].update( + {"analytic_account_id": cost_line.analytic_account_id.id} + ) + if cost_line.analytic_tag_ids: + line[2].update( + {"analytic_tag_ids": [(6, 0, cost_line.analytic_tag_ids.ids)]} + ) + return res diff --git a/stock_landed_costs_analytic/static/description/icon.png b/stock_landed_costs_analytic/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/stock_landed_costs_analytic/static/description/icon.png differ diff --git a/stock_landed_costs_analytic/tests/__init__.py b/stock_landed_costs_analytic/tests/__init__.py new file mode 100644 index 0000000000..a8e9090117 --- /dev/null +++ b/stock_landed_costs_analytic/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_landed_costs_analytic diff --git a/stock_landed_costs_analytic/tests/test_stock_landed_costs_analytic.py b/stock_landed_costs_analytic/tests/test_stock_landed_costs_analytic.py new file mode 100644 index 0000000000..529e684543 --- /dev/null +++ b/stock_landed_costs_analytic/tests/test_stock_landed_costs_analytic.py @@ -0,0 +1,114 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestStockLandedCostsAnalytic(TransactionCase): + def setUp(self): + super(TestStockLandedCostsAnalytic, self).setUp() + self.Product = self.env["product.product"] + self.Picking = self.env["stock.picking"] + self.LandedCost = self.env["stock.landed.cost"] + self.ProductCategory = self.env["product.category"] + self.AnalyticTag = self.env["account.analytic.tag"] + self.Account = self.env["account.account"] + + self.analytic_tag_1 = self.AnalyticTag.create({"name": "analytic tag test 1"}) + self.analytic_tag_2 = self.AnalyticTag.create({"name": "analytic tag test 2"}) + self.analytic_account_1 = self.env.ref("analytic.analytic_agrolait") + self.analytic_account_2 = self.env.ref("analytic.analytic_asustek") + self.account_1 = self.Account.create( + { + "name": "Account 1 test", + "code": "Account1", + "user_type_id": self.env["account.account.type"].search([], limit=1).id, + "reconcile": True, + } + ) + self.account_2 = self.Account.create( + { + "name": "Account 2 test", + "code": "Account2", + "user_type_id": self.env["account.account.type"].search([], limit=1).id, + "reconcile": True, + } + ) + self.category = self.ProductCategory.create( + { + "name": "Product Category Test", + "property_cost_method": "fifo", + "property_valuation": "real_time", + } + ) + self.product = self.Product.create( + { + "name": "Product Test", + "type": "product", + "standard_price": 1.0, + "categ_id": self.category.id, + } + ) + self.landed_cost_product = self.Product.create( + {"name": "Landed Cost Product Test", "type": "service"} + ) + picking_vals = { + "name": "Landed Cost Picking Test", + "picking_type_id": self.ref("stock.picking_type_out"), + "location_id": self.ref("stock.stock_location_stock"), + "location_dest_id": self.ref("stock.stock_location_customers"), + "move_lines": [ + ( + 0, + 0, + { + "name": "Move Test", + "product_id": self.product.id, + "product_uom_qty": 5, + "product_uom": self.ref("uom.product_uom_unit"), + }, + ) + ], + } + picking_landed_cost = self.Picking.create(picking_vals) + landed_cost_vals = { + "picking_ids": [picking_landed_cost.id], + "cost_lines": [ + ( + 0, + 0, + { + "product_id": self.landed_cost_product.id, + "price_unit": 2.0, + "split_method": "equal", + "account_id": self.account_1.id, + "analytic_account_id": self.analytic_account_1.id, + "analytic_tag_ids": [(6, 0, self.analytic_tag_1.ids)], + }, + ), + ( + 0, + 0, + { + "product_id": self.landed_cost_product.id, + "price_unit": 4.0, + "split_method": "equal", + "account_id": self.account_2.id, + "analytic_account_id": self.analytic_account_2.id, + "analytic_tag_ids": [(6, 0, self.analytic_tag_2.ids)], + }, + ), + ], + } + self.landed_cost = self.LandedCost.create(landed_cost_vals) + + def test_stock_landed_costs_analytic(self): + self.landed_cost.button_validate() + self.assertTrue(self.landed_cost.account_move_id) + for line in self.landed_cost.account_move_id.line_ids: + if line.account_id == self.account_1: + self.assertEqual(line.analytic_tag_ids.ids, self.analytic_tag_1.ids) + self.assertEqual(line.analytic_account_id, self.analytic_account_1) + if line.account_id == self.account_2: + self.assertEqual(line.analytic_tag_ids.ids, self.analytic_tag_2.ids) + self.assertEqual(line.analytic_account_id, self.analytic_account_2) diff --git a/stock_landed_costs_analytic/views/stock_landed_cost_lines.xml b/stock_landed_costs_analytic/views/stock_landed_cost_lines.xml new file mode 100644 index 0000000000..5ecbcbe1df --- /dev/null +++ b/stock_landed_costs_analytic/views/stock_landed_cost_lines.xml @@ -0,0 +1,21 @@ + + + + + stock.landed.cost.form (in stock_landed_costs_analytic) + stock.landed.cost + + + + + + + + +