diff --git a/stock_valuation_layer_category_groupby/README.md b/stock_valuation_layer_category_groupby/README.md
index 786397b..505fcc3 100644
--- a/stock_valuation_layer_category_groupby/README.md
+++ b/stock_valuation_layer_category_groupby/README.md
@@ -2,40 +2,60 @@
## Description
-This module allows grouping by product category in the stock valuation layer reports.
+This module allows grouping by product category at different hierarchy levels in the stock valuation layer reports.
### Problem
By default, the `categ_id` field in `stock.valuation.layer` is a related field without storage (`store=False`). This means it cannot be used for grouping in reports and pivot views, even though it can be used for filtering and searching.
+Additionally, when dealing with hierarchical category structures (e.g., Food > Dairy > Cheese > Cheddar), it's often useful to group by different levels of the hierarchy.
+
### Solution
-This module makes the `categ_id` field stored (`store=True`) and indexed, which enables:
-- Grouping by product category in list views
-- Grouping by product category in pivot views
-- Grouping by product category in graph views
+This module makes the `categ_id` field stored (`store=True`) and indexed, and adds computed fields for each category hierarchy level (up to 4 levels), enabling:
+- Grouping by product category (full path) in list, pivot, and graph views
+- Grouping by category level 1 (top-level category)
+- Grouping by category level 2 (second-level category)
+- Grouping by category level 3 (third-level category)
+- Grouping by category level 4 (fourth-level category)
- Better performance when filtering by category
## Installation
1. Install the module from the Apps menu
-2. The field will be automatically populated for existing records
+2. The fields will be automatically populated for existing records
## Usage
After installation:
1. Go to Inventory > Reporting > Inventory Valuation
2. Switch to Pivot or Graph view
-3. Click on "Measures" or group options
-4. You will now see "Product Category" available for grouping
+3. Click on "Group By" options
+4. You will now see multiple category grouping options:
+ - **Product Category**: Groups by the full category (leaf node)
+ - **Category Level 1**: Groups by top-level category
+ - **Category Level 2**: Groups by second-level category
+ - **Category Level 3**: Groups by third-level category
+ - **Category Level 4**: Groups by fourth-level category
+
+### Example
+
+If you have a category structure like:
+- Food (Level 1)
+ - Dairy (Level 2)
+ - Cheese (Level 3)
+ - Cheddar (Level 4)
+
+You can now group your inventory valuation by "Food" (Level 1), "Dairy" (Level 2), "Cheese" (Level 3), or "Cheddar" (Level 4) as needed.
## Technical Details
-The module extends `stock.valuation.layer` model and modifies the `categ_id` field to:
-- `store=True`: Store the value in the database
-- `index=True`: Add database index for better performance
+The module extends `stock.valuation.layer` model and:
+- Modifies the `categ_id` field to: `store=True` and `index=True`
+- Adds computed stored fields: `categ_level_1_id`, `categ_level_2_id`, `categ_level_3_id`, `categ_level_4_id`
+- Uses the `parent_path` field from `product.category` to determine hierarchy levels
-The field remains a related field, so it will automatically update when the product category changes.
+All fields are indexed for better performance and are automatically updated when product categories change.
## Bug Tracker
diff --git a/stock_valuation_layer_category_groupby/i18n/es.po b/stock_valuation_layer_category_groupby/i18n/es.po
index ed1f2fd..052e6e8 100644
--- a/stock_valuation_layer_category_groupby/i18n/es.po
+++ b/stock_valuation_layer_category_groupby/i18n/es.po
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-12-04 17:24+0000\n"
-"PO-Revision-Date: 2025-12-04 17:24+0000\n"
+"POT-Creation-Date: 2025-12-10 17:24+0000\n"
+"PO-Revision-Date: 2025-12-10 17:24+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -21,6 +21,30 @@ msgstr ""
msgid "Product Category"
msgstr "Categoría de producto"
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_1_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 1"
+msgstr "Categoría Nivel 1"
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_2_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 2"
+msgstr "Categoría Nivel 2"
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_3_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 3"
+msgstr "Categoría Nivel 3"
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_4_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 4"
+msgstr "Categoría Nivel 4"
+
#. module: stock_valuation_layer_category_groupby
#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__smart_search
msgid "Smart Search"
diff --git a/stock_valuation_layer_category_groupby/i18n/stock_valuation_layer_category_groupby.pot b/stock_valuation_layer_category_groupby/i18n/stock_valuation_layer_category_groupby.pot
index 3cb8e99..c057852 100644
--- a/stock_valuation_layer_category_groupby/i18n/stock_valuation_layer_category_groupby.pot
+++ b/stock_valuation_layer_category_groupby/i18n/stock_valuation_layer_category_groupby.pot
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-12-04 17:24+0000\n"
-"PO-Revision-Date: 2025-12-04 17:24+0000\n"
+"POT-Creation-Date: 2025-12-10 17:24+0000\n"
+"PO-Revision-Date: 2025-12-10 17:24+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -21,6 +21,30 @@ msgstr ""
msgid "Product Category"
msgstr ""
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_1_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 1"
+msgstr ""
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_2_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 2"
+msgstr ""
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_3_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 3"
+msgstr ""
+
+#. module: stock_valuation_layer_category_groupby
+#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__categ_level_4_id
+#: model_terms:ir.ui.view,arch_db:stock_valuation_layer_category_groupby.view_inventory_valuation_search_category
+msgid "Category Level 4"
+msgstr ""
+
#. module: stock_valuation_layer_category_groupby
#: model:ir.model.fields,field_description:stock_valuation_layer_category_groupby.field_stock_valuation_layer__smart_search
msgid "Smart Search"
diff --git a/stock_valuation_layer_category_groupby/models/stock_valuation_layer.py b/stock_valuation_layer_category_groupby/models/stock_valuation_layer.py
index bba7017..d7c4aec 100644
--- a/stock_valuation_layer_category_groupby/models/stock_valuation_layer.py
+++ b/stock_valuation_layer_category_groupby/models/stock_valuation_layer.py
@@ -1,7 +1,7 @@
# Copyright 2025 Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from odoo import fields, models
+from odoo import api, fields, models
class StockValuationLayer(models.Model):
@@ -9,3 +9,55 @@ class StockValuationLayer(models.Model):
# Make categ_id stored to allow grouping in reports
categ_id = fields.Many2one(store=True, index=True)
+
+ # Category hierarchy levels for grouping
+ categ_level_1_id = fields.Many2one(
+ comodel_name="product.category",
+ string="Category Level 1",
+ compute="_compute_category_levels",
+ store=True,
+ index=True,
+ )
+ categ_level_2_id = fields.Many2one(
+ comodel_name="product.category",
+ string="Category Level 2",
+ compute="_compute_category_levels",
+ store=True,
+ index=True,
+ )
+ categ_level_3_id = fields.Many2one(
+ comodel_name="product.category",
+ string="Category Level 3",
+ compute="_compute_category_levels",
+ store=True,
+ index=True,
+ )
+ categ_level_4_id = fields.Many2one(
+ comodel_name="product.category",
+ string="Category Level 4",
+ compute="_compute_category_levels",
+ store=True,
+ index=True,
+ )
+
+ @api.depends("categ_id", "categ_id.parent_path")
+ def _compute_category_levels(self):
+ """Compute category hierarchy levels for better grouping options."""
+ for layer in self:
+ if not layer.categ_id or not layer.categ_id.parent_path:
+ layer.categ_level_1_id = False
+ layer.categ_level_2_id = False
+ layer.categ_level_3_id = False
+ layer.categ_level_4_id = False
+ continue
+
+ # parent_path format: "1/2/3/" where each number is a category ID
+ path_ids = [
+ int(x) for x in layer.categ_id.parent_path.split("/") if x.isdigit()
+ ]
+
+ # Assign levels based on hierarchy
+ layer.categ_level_1_id = path_ids[0] if len(path_ids) >= 1 else False
+ layer.categ_level_2_id = path_ids[1] if len(path_ids) >= 2 else False
+ layer.categ_level_3_id = path_ids[2] if len(path_ids) >= 3 else False
+ layer.categ_level_4_id = path_ids[3] if len(path_ids) >= 4 else False
diff --git a/stock_valuation_layer_category_groupby/views/stock_valuation_layer_views.xml b/stock_valuation_layer_category_groupby/views/stock_valuation_layer_views.xml
index c202e4b..680c5b6 100644
--- a/stock_valuation_layer_category_groupby/views/stock_valuation_layer_views.xml
+++ b/stock_valuation_layer_category_groupby/views/stock_valuation_layer_views.xml
@@ -13,6 +13,26 @@
name="group_by_categ_id"
context="{'group_by': 'categ_id'}"
/>
+
+
+
+