1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/stock_account_enterprise/report/stock_report.py
2024-12-10 09:04:09 +07:00

110 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
from odoo import api, fields, models
from odoo.exceptions import UserError
from odoo.osv.expression import expression
class StockReport(models.Model):
_inherit = 'stock.report'
valuation = fields.Float("Valuation of Inventory using a Domain", readonly=True, store=False,
help="Note that you can only access this value in the read_group, only the sum operator is supported")
stock_value = fields.Float("Total Valuation of Inventory", readonly=True, store=False,
help="Note that you can only access this value in the read_group, only the sum operator is supported and only date_done is used from the domain")
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
"""
This is a hack made in order to improve performance as adding
inventory valuation on the report itself would be too costly.
Basically when asked to return the valuation, it will run a smaller
SQL query that will calculate the inventory valuation on the given
domain.
Only the SUM operator is supported for valuation.
We can also get the stock_value of the inventory at a specific date
(default is today).
The same applies to this stock_value field, it only supports the sum operator
and does not support the group by.
NB: This should probably be implemented in a read instead of read_group since
we don't support grouping
NB: We might be able to avoid doing this hack by optimizing the query used to
generate the report (= TODO: see nse)
"""
stock_value = next((field for field in fields if re.search(r'\bstock_value\b', field)), False)
valuation = next((field for field in fields if re.search(r'\bvaluation\b', field)), False)
if stock_value:
fields.remove(stock_value)
if valuation:
fields.remove(valuation)
if stock_value or valuation:
if groupby:
raise UserError("valuation and stock_value don't support grouping")
if any(field.split(':')[1].split('(')[0] != 'sum' for field in [stock_value, valuation] if field):
raise UserError("read_group only support operator sum for valuation and stock_value")
res = []
if fields:
res = super(StockReport, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
if not res and (stock_value or valuation):
res = [{}]
if stock_value:
products = self.env['product.product'].with_context(active_test=False)
# Split the recordset for faster computing.
value = sum(
product.value_svl
for products_split in self.env.cr.split_for_in_conditions(
products.search([("product_tmpl_id.type", "=", "product")]).ids
)
for product in products.browse(products_split)
)
res[0].update({
'__count': 1,
stock_value.split(':')[0]: value,
})
if valuation:
query = """
SELECT
SUM(move_valuation.valuation) as valuation
FROM (
SELECT
sum(svl.value) AS valuation
FROM
stock_move move
INNER JOIN stock_valuation_layer AS svl ON svl.stock_move_id = move.id
WHERE
move.id IN (
SELECT "stock_report".id FROM %s WHERE %s)
GROUP BY
move.id
) as move_valuation
"""
subdomain = domain + [('company_id', '=', self.env.company.id)]
subtables, subwhere, subparams = expression(subdomain, self).query.get_sql()
self.env.cr.execute(query % (subtables, subwhere), subparams)
res[0].update({
'__count': 1,
valuation.split(':')[0]: self.env.cr.fetchall()[0][0],
})
return res