From 6f0e59775904f20c2690854fe8646ef7b3bc22c3 Mon Sep 17 00:00:00 2001 From: David Beal Date: Thu, 11 Jul 2024 12:42:19 +0200 Subject: [PATCH] ADD account_stock_situation --- account_stock_situation/README.rst | 66 +++ account_stock_situation/__init__.py | 1 + account_stock_situation/__manifest__.py | 19 + account_stock_situation/models/__init__.py | 2 + account_stock_situation/models/company.py | 116 +++++ .../models/config_settings.py | 50 ++ .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 1 + account_stock_situation/readme/USAGE.rst | 1 + .../static/description/index.html | 427 ++++++++++++++++++ account_stock_situation/views/action.xml | 21 + .../views/config_settings.xml | 76 ++++ requirements.txt | 1 + .../odoo/addons/account_stock_situation | 1 + setup/account_stock_situation/setup.py | 6 + 15 files changed, 790 insertions(+) create mode 100644 account_stock_situation/README.rst create mode 100644 account_stock_situation/__init__.py create mode 100644 account_stock_situation/__manifest__.py create mode 100644 account_stock_situation/models/__init__.py create mode 100644 account_stock_situation/models/company.py create mode 100644 account_stock_situation/models/config_settings.py create mode 100644 account_stock_situation/readme/CONTRIBUTORS.rst create mode 100644 account_stock_situation/readme/DESCRIPTION.rst create mode 100644 account_stock_situation/readme/USAGE.rst create mode 100644 account_stock_situation/static/description/index.html create mode 100644 account_stock_situation/views/action.xml create mode 100644 account_stock_situation/views/config_settings.xml create mode 120000 setup/account_stock_situation/odoo/addons/account_stock_situation create mode 100644 setup/account_stock_situation/setup.py diff --git a/account_stock_situation/README.rst b/account_stock_situation/README.rst new file mode 100644 index 000000000..a97ccd388 --- /dev/null +++ b/account_stock_situation/README.rst @@ -0,0 +1,66 @@ +======================= +Account Stock Situation +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:17a4d0785da8b351798bf3c7d2b0463b8a22bf996209b21ecc9043ea00b9bfce + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fak--odoo--incubator-lightgray.png?logo=github + :target: https://github.com/akretion/ak-odoo-incubator/tree/16.0/account_stock_situation + :alt: akretion/ak-odoo-incubator + +|badge1| |badge2| |badge3| + +Generate Periodically a miscellaneous account move for stock valuation with an xlsx report attachement + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Consider to check your report before validate your account move and reverse the previous one. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +* Akretion + * David BEAL + +Maintainers +~~~~~~~~~~~ + +This module is part of the `akretion/ak-odoo-incubator `_ project on GitHub. + +You are welcome to contribute. diff --git a/account_stock_situation/__init__.py b/account_stock_situation/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/account_stock_situation/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_stock_situation/__manifest__.py b/account_stock_situation/__manifest__.py new file mode 100644 index 000000000..1c058e25b --- /dev/null +++ b/account_stock_situation/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2024 David BEAL @ akretion +{ + "name": "Account Stock Situation", + "version": "16.0.1.0.0", + "author": "Akretion", + "website": "https://github.com/akretion/ak-odoo-incubator", + "license": "AGPL-3", + "category": "Accounting", + "depends": [ + "account", + "stock", + ], + "data": [ + "views/config_settings.xml", + "views/action.xml", + ], + "external_dependencies": {"python": ["polars"]}, + "installable": True, +} diff --git a/account_stock_situation/models/__init__.py b/account_stock_situation/models/__init__.py new file mode 100644 index 000000000..ff33dd7a1 --- /dev/null +++ b/account_stock_situation/models/__init__.py @@ -0,0 +1,2 @@ +from . import company +from . import config_settings diff --git a/account_stock_situation/models/company.py b/account_stock_situation/models/company.py new file mode 100644 index 000000000..1f98fcc03 --- /dev/null +++ b/account_stock_situation/models/company.py @@ -0,0 +1,116 @@ +import base64 +import io +from collections import defaultdict + +import polars as pl + +from odoo import fields, models, tools +from odoo.exceptions import UserError + + +class ResCompany(models.Model): + _inherit = "res.company" + + valued_warehouse_ids = fields.Many2many( + comodel_name="stock.warehouse", + domain=lambda self: [("company_id", "=", self.env.company.id)], + ) + stock_journal_id = fields.Many2one(comodel_name="account.journal") + cost_vs_purchase_threshold = fields.Integer(string="Seuil en %") + account_purchase_stock_id = fields.Many2one(comodel_name="account.account") + account_stock_id = fields.Many2one(comodel_name="account.account") + + def _set_account_stock_valuation(self, company_string_id): + self = self.env.ref(company_string_id) + value, attach = self._get_stock_valuation_another() + for mfield in ( + "account_stock_id", + "account_purchase_stock_id", + "stock_journal_id", + ): + if not self[mfield]: + raise UserError( + f"Le champ '{mfield}' n'est pas défini: vérifiez les " + "paramètres intitulés 'Valorisation de stock'" + ) + move = self.env["account.move"].create( + { + "journal_id": self.stock_journal_id.id, + "company_id": self.id, + "to_check": True, + "move_type": "entry", + "line_ids": [ + ( + 0, + 0, + { + "account_id": self.account_stock_id.id, + "name": "stock", + "debit": 0, + "credit": value, + }, + ), + ( + 0, + 0, + { + "account_id": self.account_purchase_stock_id.id, + "name": "stock", + "debit": value, + "credit": 0, + }, + ), + ], + } + ) + attach.res_id = move.id + + def _get_stock_valuation_another(self): + self.ensure_one() + coef = self.cost_vs_purchase_threshold + base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url") + if tools.config.get("running_env") == "dev": + base_url = "http://anothercorp.localhost/" + location_ids = [x.lot_stock_id.id for x in self.valued_warehouse_ids] + product_qties = self.env["stock.quant"].read_group( + [("location_id", "child_of", location_ids)], + ["product_id", "quantity"], + ["product_id"], + ) + product_ids = [x["product_id"][0] for x in product_qties] + products = self.env["product.product"].browse(product_ids) + prices = { + x: x.variant_seller_ids and x.variant_seller_ids[0] or 0 for x in products + } + vals = defaultdict(list) + for prd_q in product_qties: + product = products.filtered(lambda s: s.id == prd_q["product_id"][0]) + vals["code"].append(product.default_code) + vals["designation"].append(product.name) + vals["qté"].append(round(prd_q["quantity"])) + vals["valeur"].append( + round( + max( + product.standard_price, + prices[product] and prices[product].price or 0 * coef / 100, + ) + * prd_q["quantity"] + ) + ) + vals["lien"].append( + f"{base_url}/web#id={prd_q['product_id'][0]}&cids={self.id}&action=" + f"{self.env.ref('product.product_normal_action_sell').id}&model=" + "product.product&view_type=form" + ) + df = pl.from_dict(vals) + mfile = io.BytesIO() + df.write_excel(workbook=mfile) + attach = self.env["ir.attachment"].create( + { + "name": "Valorisation_stock_jourdain", + "type": "binary", + "res_model": "account.move", + "datas": base64.b64encode(mfile.getvalue()), + } + ) + return sum(vals["valeur"]), attach diff --git a/account_stock_situation/models/config_settings.py b/account_stock_situation/models/config_settings.py new file mode 100644 index 000000000..e55efb2be --- /dev/null +++ b/account_stock_situation/models/config_settings.py @@ -0,0 +1,50 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + def __default_account_stock_domain(self): + return self._account_stock_domain() + + def __default_account_purchase_stock_domain(self): + return self._account_stock_domain(kind="purchase") + + valued_warehouse_ids = fields.Many2many( + related="company_id.valued_warehouse_ids", readonly=False + ) + cost_vs_purchase_threshold = fields.Integer( + related="company_id.cost_vs_purchase_threshold", readonly=False, default=120 + ) + stock_journal_id = fields.Many2one( + comodel_name="account.journal", + readonly=False, + related="company_id.stock_journal_id", + domain=[("type", "=", "general")], + ) + account_purchase_stock_id = fields.Many2one( + comodel_name="account.account", + readonly=False, + related="company_id.account_purchase_stock_id", + domain=[("code", "ilike", lambda s: s.account_purchase_stock_domain)], + ) + account_stock_id = fields.Many2one( + comodel_name="account.account", + readonly=False, + related="company_id.account_stock_id", + domain=[("code", "ilike", lambda s: s.account_stock_domain)], + ) + account_stock_domain = fields.Char(default=__default_account_stock_domain) + account_purchase_stock_domain = fields.Char( + default=__default_account_purchase_stock_domain + ) + + def _account_stock_domain(self, kind=None): + "Other localisations maybe completed here" + if "l10n_fr" in self.env.registry: + if not kind: + return "355%00" + elif kind == "purchase": + return "603%" + else: + return "%" diff --git a/account_stock_situation/readme/CONTRIBUTORS.rst b/account_stock_situation/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..3237802ef --- /dev/null +++ b/account_stock_situation/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Akretion + * David BEAL diff --git a/account_stock_situation/readme/DESCRIPTION.rst b/account_stock_situation/readme/DESCRIPTION.rst new file mode 100644 index 000000000..7ddde3d3b --- /dev/null +++ b/account_stock_situation/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Generate Periodically a miscellaneous account move for stock valuation with an xlsx report attachement diff --git a/account_stock_situation/readme/USAGE.rst b/account_stock_situation/readme/USAGE.rst new file mode 100644 index 000000000..a90351f54 --- /dev/null +++ b/account_stock_situation/readme/USAGE.rst @@ -0,0 +1 @@ +Consider to check your report before validate your account move and reverse the previous one. diff --git a/account_stock_situation/static/description/index.html b/account_stock_situation/static/description/index.html new file mode 100644 index 000000000..fb34b1c69 --- /dev/null +++ b/account_stock_situation/static/description/index.html @@ -0,0 +1,427 @@ + + + + + +Account Stock Situation + + + +
+

Account Stock Situation

+ + +

Beta License: AGPL-3 akretion/ak-odoo-incubator

+

Generate Periodically a miscellaneous account move for stock valuation with an xlsx report attachement

+

Table of contents

+ +
+

Usage

+

Consider to check your report before validate your account move and reverse the previous one.

+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the akretion/ak-odoo-incubator project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/account_stock_situation/views/action.xml b/account_stock_situation/views/action.xml new file mode 100644 index 000000000..2b7494d52 --- /dev/null +++ b/account_stock_situation/views/action.xml @@ -0,0 +1,21 @@ + + + + + Stock Valorisation + + code + model._set_account_stock_valuation('base.main_company') + 1 + months + -1 + + False + + + diff --git a/account_stock_situation/views/config_settings.xml b/account_stock_situation/views/config_settings.xml new file mode 100644 index 000000000..16a0de8b4 --- /dev/null +++ b/account_stock_situation/views/config_settings.xml @@ -0,0 +1,76 @@ + + + + res.config.settings + + + + +

Valorisation de Stock Valuation

+
+
+
+ Warehouses +
+ Warehouses where stock is valued periodically +
+
+ +
+
+
+
+
+ Cost vs. purchase price % threshold +
+ Below this threshold, the cost value is substitued by purchase price. +
+
+ +
+
+
+
+
+ Journal +
+ Journal used for stock valuation. +
+
+ +
+
+
+
+
+ Stock account +
+ Stock account +
+
+ +
+
+
+
+
+ Purchase stock account +
+ Stock account +
+
+ +
+
+
+
+
+
+
+ +
diff --git a/requirements.txt b/requirements.txt index 2ea583741..d98ad5c69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ # generated from manifests external_dependencies +polars simplejson diff --git a/setup/account_stock_situation/odoo/addons/account_stock_situation b/setup/account_stock_situation/odoo/addons/account_stock_situation new file mode 120000 index 000000000..4b6c7e3f8 --- /dev/null +++ b/setup/account_stock_situation/odoo/addons/account_stock_situation @@ -0,0 +1 @@ +../../../../account_stock_situation \ No newline at end of file diff --git a/setup/account_stock_situation/setup.py b/setup/account_stock_situation/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/account_stock_situation/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)