Skip to content

Commit e9a1f45

Browse files
committed
ADD account_stock_situation
1 parent d104027 commit e9a1f45

File tree

15 files changed

+784
-0
lines changed

15 files changed

+784
-0
lines changed

account_stock_situation/README.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
=======================
2+
Account Stock Situation
3+
=======================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:17a4d0785da8b351798bf3c7d2b0463b8a22bf996209b21ecc9043ea00b9bfce
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fak--odoo--incubator-lightgray.png?logo=github
20+
:target: https://github.com/akretion/ak-odoo-incubator/tree/16.0/account_stock_situation
21+
:alt: akretion/ak-odoo-incubator
22+
23+
|badge1| |badge2| |badge3|
24+
25+
Generate Periodically a miscellaneous account move for stock valuation with an xlsx report attachement
26+
27+
**Table of contents**
28+
29+
.. contents::
30+
:local:
31+
32+
Usage
33+
=====
34+
35+
Consider to check your report before validate your account move and reverse the previous one.
36+
37+
Bug Tracker
38+
===========
39+
40+
Bugs are tracked on `GitHub Issues <https://github.com/akretion/ak-odoo-incubator/issues>`_.
41+
In case of trouble, please check there if your issue has already been reported.
42+
If you spotted it first, help us to smash it by providing a detailed and welcomed
43+
`feedback <https://github.com/akretion/ak-odoo-incubator/issues/new?body=module:%20account_stock_situation%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
44+
45+
Do not contact contributors directly about support or help with technical issues.
46+
47+
Credits
48+
=======
49+
50+
Authors
51+
~~~~~~~
52+
53+
* Akretion
54+
55+
Contributors
56+
~~~~~~~~~~~~
57+
58+
* Akretion
59+
* David BEAL <david.beal@akretion.com>
60+
61+
Maintainers
62+
~~~~~~~~~~~
63+
64+
This module is part of the `akretion/ak-odoo-incubator <https://github.com/akretion/ak-odoo-incubator/tree/16.0/account_stock_situation>`_ project on GitHub.
65+
66+
You are welcome to contribute.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2024 David BEAL @ akretion
2+
{
3+
"name": "Account Stock Situation",
4+
"version": "16.0.1.0.0",
5+
"author": "Akretion",
6+
"website": "https://github.com/akretion/ak-odoo-incubator",
7+
"license": "AGPL-3",
8+
"category": "Accounting",
9+
"depends": [
10+
"account",
11+
"stock",
12+
],
13+
"data": [
14+
"views/config_settings.xml",
15+
"views/action.xml",
16+
],
17+
"external_dependencies": {"python": ["polars"]},
18+
"installable": True,
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import company
2+
from . import config_settings
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import base64
2+
import io
3+
from collections import defaultdict
4+
5+
import polars as pl
6+
7+
from odoo import fields, models, tools
8+
from odoo.exceptions import UserError
9+
10+
11+
class ResCompany(models.Model):
12+
_inherit = "res.company"
13+
14+
valued_warehouse_ids = fields.Many2many(
15+
comodel_name="stock.warehouse",
16+
domain=lambda self: [("company_id", "=", self.env.company.id)],
17+
)
18+
stock_journal_id = fields.Many2one(comodel_name="account.journal")
19+
cost_vs_purchase_threshold = fields.Integer(string="Seuil en %")
20+
account_purchase_stock_id = fields.Many2one(comodel_name="account.account")
21+
account_stock_id = fields.Many2one(comodel_name="account.account")
22+
23+
def _set_account_stock_valuation(self, company_string_id):
24+
self = self.env.ref(company_string_id)
25+
value, attach = self._get_stock_valuation_another()
26+
for mfield in (
27+
"account_stock_id",
28+
"account_purchase_stock_id",
29+
"stock_journal_id",
30+
):
31+
if not self[mfield]:
32+
raise UserError(
33+
f"Le champ '{mfield}' n'est pas défini: vérifiez les "
34+
"paramètres intitulés 'Valorisation de stock'"
35+
)
36+
move = self.env["account.move"].create(
37+
{
38+
"journal_id": self.stock_journal_id.id,
39+
"company_id": self.id,
40+
"to_check": True,
41+
"move_type": "entry",
42+
"line_ids": [
43+
(
44+
0,
45+
0,
46+
{
47+
"account_id": self.account_stock_id.id,
48+
"name": "stock",
49+
"debit": 0,
50+
"credit": value,
51+
},
52+
),
53+
(
54+
0,
55+
0,
56+
{
57+
"account_id": self.account_purchase_stock_id.id,
58+
"name": "stock",
59+
"debit": value,
60+
"credit": 0,
61+
},
62+
),
63+
],
64+
}
65+
)
66+
attach.res_id = move.id
67+
68+
def _get_stock_valuation_another(self):
69+
self.ensure_one()
70+
coef = self.cost_vs_purchase_threshold
71+
base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url")
72+
if tools.config.get("running_env") == "dev":
73+
base_url = "http://anothercorp.localhost/"
74+
location_ids = [x.lot_stock_id.id for x in self.valued_warehouse_ids]
75+
# TODO conserver un group par emplacement : donc autant de colonnes
76+
# de nombres de produits que d'entrepots dans l'excel
77+
product_qties = self.env["stock.quant"].read_group(
78+
[("location_id", "child_of", location_ids)],
79+
["product_id", "quantity"],
80+
["product_id"],
81+
)
82+
product_ids = [x["product_id"][0] for x in product_qties]
83+
products = self.env["product.product"].browse(product_ids)
84+
prices = {
85+
x: x.variant_seller_ids and x.variant_seller_ids[0] or 0 for x in products
86+
}
87+
vals = defaultdict(list)
88+
for prd_q in product_qties:
89+
product = products.filtered(lambda s: s.id == prd_q["product_id"][0])
90+
vals["code"].append(product.default_code)
91+
vals["designation"].append(product.name)
92+
# TODO mettre une colonne qté par entrepot (x colonnes)
93+
vals["qté"].append(round(prd_q["quantity"]))
94+
# TODO quand la valeur est < cost_vs_purchase_threshold % de ce seuil
95+
# mettre une colonne 'check' à la valeur 1
96+
vals["valeur"].append(
97+
round(
98+
max(
99+
product.standard_price,
100+
prices[product] and prices[product].price or 0 * coef / 100,
101+
)
102+
* prd_q["quantity"]
103+
)
104+
)
105+
# TODO mettre l'url en first column
106+
vals["lien"].append(
107+
f"{base_url}/web#id={prd_q['product_id'][0]}&cids={self.id}&action="
108+
f"{self.env.ref('product.product_normal_action_sell').id}&model="
109+
"product.product&view_type=form"
110+
)
111+
df = pl.from_dict(vals)
112+
mfile = io.BytesIO()
113+
df.write_excel(workbook=mfile)
114+
attach = self.env["ir.attachment"].create(
115+
{
116+
"name": "Valorisation_stock_jourdain",
117+
"type": "binary",
118+
"res_model": "account.move",
119+
"datas": base64.b64encode(mfile.getvalue()),
120+
}
121+
)
122+
return sum(vals["valeur"]), attach
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from odoo import fields, models
2+
3+
4+
class ResConfigSettings(models.TransientModel):
5+
_inherit = "res.config.settings"
6+
7+
valued_warehouse_ids = fields.Many2many(
8+
related="company_id.valued_warehouse_ids", readonly=False
9+
)
10+
cost_vs_purchase_threshold = fields.Integer(
11+
related="company_id.cost_vs_purchase_threshold", readonly=False, default=120
12+
)
13+
stock_journal_id = fields.Many2one(
14+
comodel_name="account.journal",
15+
readonly=False,
16+
related="company_id.stock_journal_id",
17+
domain=[("type", "=", "general")],
18+
)
19+
account_purchase_stock_id = fields.Many2one(
20+
comodel_name="account.account",
21+
readonly=False,
22+
related="company_id.account_purchase_stock_id",
23+
)
24+
account_stock_id = fields.Many2one(
25+
comodel_name="account.account",
26+
readonly=False,
27+
related="company_id.account_stock_id",
28+
)
29+
account_stock_help = fields.Text(compute="_compute_account_stock_help")
30+
31+
def _compute_account_stock_help(self):
32+
for rec in self:
33+
name = ""
34+
if "l10n_fr" in self.env.registry._init_modules:
35+
name = "Compte de stock: '355...'"
36+
name += "Compte de stock d'achat: '603...'"
37+
rec.account_stock_help = name
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* Akretion
2+
* David BEAL <david.beal@akretion.com>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Generate Periodically a miscellaneous account move for stock valuation with an xlsx report attachement
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Consider to check your report before validate your account move and reverse the previous one.

0 commit comments

Comments
 (0)