Compare commits

..

2 commits

11 changed files with 325 additions and 8 deletions

View file

@ -13,7 +13,14 @@
"security/ir.model.access.csv",
"wizards/purchase_order_recommendation.xml",
"views/product_template_view.xml",
"views/product_stock_out_period_menu.xml",
"data/stock_out_cron.xml",
],
"assets": {
"web.assets_backend": [
"purchase_order_product_recommendation_supermarket/static/src/scss/sticky_recommendation.scss",
# "purchase_order_product_recommendation_supermarket/static/src/js/sticky_recommendation.js",
],
},
"demo": [],
}

View file

@ -165,6 +165,48 @@ msgstr ""
"Cantidad de productos en stock + Cantidad de producto por venir (pedidos "
"confirmados)"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_form
msgid "Stock-out Period"
msgstr "Periodo sin stock"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_tree
#: model:ir.actions.act_window,name:purchase_order_product_recommendation_supermarket.action_product_stock_out_period
#: model:ir.ui.menu,name:purchase_order_product_recommendation_supermarket.menu_product_stock_out_period
msgid "Stock-out Periods"
msgstr "Periodos sin stock"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Open"
msgstr "Abierto"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Closed"
msgstr "Cerrado"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Search Stock-out Periods"
msgstr "Buscar periodos sin stock"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Open State"
msgstr "Estado (abierto)"
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Product"
msgstr "Producto"
#. module: purchase_order_product_recommendation_supermarket
#: model:ir.actions.act_window,help:purchase_order_product_recommendation_supermarket.action_product_stock_out_period
msgid "List of computed periods where a product template had zero stock. Open periods are still ongoing."
msgstr "Listado de periodos calculados en los que una plantilla de producto estuvo sin stock. Los periodos abiertos siguen en curso."
#. module: purchase_order_product_recommendation_supermarket
#: model:ir.model.fields,help:purchase_order_product_recommendation_supermarket.field_purchase_order_recommendation__ignore_zero_stock_days
msgid ""

View file

@ -468,3 +468,40 @@ msgstr ""
#: model:ir.model.fields,field_description:purchase_order_product_recommendation_supermarket.field_purchase_order_recommendation_line__units_virtual_available
msgid "Units Virtual Available"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_form
msgid "Stock-out Period"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_tree
#: model:ir.actions.act_window,name:purchase_order_product_recommendation_supermarket.action_product_stock_out_period
#: model:ir.ui.menu,name:purchase_order_product_recommendation_supermarket.menu_product_stock_out_period
msgid "Stock-out Periods"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Open"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Closed"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Search Stock-out Periods"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model_terms:ir.ui.view,arch_db:purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search
msgid "Open State"
msgstr ""
#. module: purchase_order_product_recommendation_supermarket
#: model:ir.actions.act_window,help:purchase_order_product_recommendation_supermarket.action_product_stock_out_period
msgid "List of computed periods where a product template had zero stock. Open periods are still ongoing."
msgstr ""

View file

@ -0,0 +1,104 @@
/* Sticky header for purchase recommendation lines tree view */
/* Make the tree container scrollable so position:sticky works inside */
.o_purchase_recommendation_tree.o_list_view, /* defensive if Odoo adds class */
.o_purchase_recommendation_tree {
max-height: 85vh; /* adjustable */
overflow-y: auto;
position: relative;
}
/* Target Odoo list table header cells */
.o_purchase_recommendation_tree table thead th,
.o_purchase_recommendation_tree .o_list_table thead th,
.o_purchase_recommendation_tree table thead th > div,
.o_purchase_recommendation_tree .o_list_table thead th > div {
position: sticky !important;
top: 0 !important;
z-index: 7 !important; /* above possible indicators */
background: var(--o-view-background-color, #f8f9fa) !important;
line-height: 1.2rem;
box-sizing: border-box;
}
/* Extra background for nested inner elements */
.o_purchase_recommendation_tree table thead th > div {
background: inherit;
}
/* Subtle bottom border / shadow */
.o_purchase_recommendation_tree table thead th::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 1px;
background: rgba(0,0,0,0.15);
pointer-events: none;
}
/* Prevent collapse issues that sometimes break sticky in Firefox */
.o_purchase_recommendation_tree table {
border-collapse: separate !important;
border-spacing: 0;
width: 100%;
}
/* Row separators (avoid double borders) */
.o_purchase_recommendation_tree table tbody tr {
border-bottom: 1px solid #8f8d8d;
}
// .o_purchase_recommendation_tree table tbody tr:last-child {
// border-bottom: 0;
// }
// /* Remove previous cell-level borders */
// .o_purchase_recommendation_tree table td,
// .o_purchase_recommendation_tree table th {
// border-bottom: none;
// }
/* Zebra striping: only apply to rows without state-driven bg (avoid overriding decoration-* classes) */
.o_purchase_recommendation_tree table tbody tr:nth-child(odd):not([class*='o_data_row_selected']):not(.o_list_view_group_header) td {
background-color: #ebe6e6;
border-bottom: 1px solid #8f8d8d;
}
.o_purchase_recommendation_tree table tbody tr:nth-child(even):not([class*='o_data_row_selected']):not(.o_list_view_group_header) td {
background-color: #ffffff;
border-bottom: 1px solid #8f8d8d;
}
/* Keep Odoo decoration colors dominant (info/success/danger/muted) */
.o_purchase_recommendation_tree table tbody tr[decoration-info] td,
.o_purchase_recommendation_tree table tbody tr[decoration-success] td,
.o_purchase_recommendation_tree table tbody tr[decoration-danger] td,
.o_purchase_recommendation_tree table tbody tr[decoration-muted] td {
background-color: inherit;
}
/* Hover highlight (soft) */
.o_purchase_recommendation_tree table tbody tr:hover td {
background-color: #eef6ff;
}
.o_purchase_recommendation_tree table tbody tr.o_data_row_selected td {
background-color: #d9ecff !important;
}
/* Stronger text color for better contrast over zebra backgrounds */
/* Force stronger text color (override potential nested span styles) */
.o_purchase_recommendation_tree table tbody tr td,
.o_purchase_recommendation_tree table tbody tr td span,
.o_purchase_recommendation_tree table tbody tr td div {
color: #1b1b1b !important;
}
/* Optional: indicate scroll with gradient at top when not at start */
.o_purchase_recommendation_tree.is-scrolled::before {
content: '';
position: sticky;
top: 0;
height: 0.35rem;
display: block;
background: linear-gradient(var(--o-view-background-color, #f8f9fa), rgba(248,249,250,0));
z-index: 6;
pointer-events: none;
}

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- Tree view: order by start_date desc -->
<record id="view_product_stock_out_period_tree" model="ir.ui.view">
<field name="name">product.stock.out.period.tree</field>
<field name="model">product.stock.out.period</field>
<field name="arch" type="xml">
<tree string="Stock-out Periods" default_order="start_date desc" create="0" edit="0">
<field name="product_tmpl_id"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="days_out"/>
<field name="is_open"/>
</tree>
</field>
</record>
<!-- Form view (read-only) -->
<record id="view_product_stock_out_period_form" model="ir.ui.view">
<field name="name">product.stock.out.period.form</field>
<field name="model">product.stock.out.period</field>
<field name="arch" type="xml">
<form string="Stock-out Period" create="0" edit="0">
<group>
<field name="product_tmpl_id"/>
<field name="is_open"/>
</group>
<group>
<field name="start_date"/>
<field name="end_date"/>
<field name="days_out"/>
</group>
</form>
</field>
</record>
<!-- Search view with default filter open -->
<record id="view_product_stock_out_period_search" model="ir.ui.view">
<field name="name">product.stock.out.period.search</field>
<field name="model">product.stock.out.period</field>
<field name="arch" type="xml">
<search string="Search Stock-out Periods">
<field name="product_tmpl_id"/>
<filter name="filter_open" string="Open" domain="[('is_open','=',True)]" help="Show only currently open stock-out periods"/>
<filter name="filter_closed" string="Closed" domain="[('is_open','=',False)]" help="Show closed stock-out periods"/>
<group expand="0" string="Group By">
<filter name="group_product" string="Product" context="{'group_by':'product_tmpl_id'}"/>
<filter name="group_open" string="Open State" context="{'group_by':'is_open'}"/>
</group>
</search>
</field>
</record>
<!-- Action -->
<record id="action_product_stock_out_period" model="ir.actions.act_window">
<field name="name">Stock-out Periods</field>
<field name="res_model">product.stock.out.period</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="purchase_order_product_recommendation_supermarket.view_product_stock_out_period_search"/>
<field name="context">{"search_default_filter_open": 1}</field>
<field name="help" type="html">
<p>List of computed periods where a product template had zero stock. Open periods are still ongoing.</p>
</field>
</record>
<!-- Menu under Inventory -> Reporting -->
<menuitem id="menu_product_stock_out_period" name="Stock-out Periods" parent="stock.menu_warehouse_report" action="purchase_order_product_recommendation_supermarket.action_product_stock_out_period" sequence="50"/>
</odoo>

View file

@ -15,6 +15,9 @@
context="{'no_return_action': True}"/>
</header>
</xpath>
<xpath expr="//field[@name='line_ids']/tree" position="attributes">
<attribute name="class">o_purchase_recommendation_tree</attribute>
</xpath>
<field name="line_amount" position="replace">
<field name="order_days" widget="numeric_step" />

View file

@ -7,6 +7,8 @@
"license": "AGPL-3",
"author": "Criptomart",
"depends": ["stock_inventory"],
"data": [],
"data": [
"views/stock_quant_view.xml",
],
"installable": True,
}

View file

@ -0,0 +1,18 @@
# Traducciones para stock_inventory_category_concurrency
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-07 00:00+0000\n"
"PO-Revision-Date: 2025-10-07 00:00+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: stock_inventory_category_concurrency
#: model_terms:ir.ui.view,arch_db:stock_inventory_category_concurrency.stock_quant_search_category_filter
msgid "Product Category"
msgstr "Categoría de producto"

View file

@ -0,0 +1,18 @@
# Translation template for stock_inventory_category_concurrency
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-07 00:00+0000\n"
"PO-Revision-Date: 2025-10-07 00:00+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: stock_inventory_category_concurrency
#: model_terms:ir.ui.view,arch_db:stock_inventory_category_concurrency.stock_quant_search_category_filter
msgid "Product Category"
msgstr ""

View file

@ -1,18 +1,23 @@
from odoo import _, models
from odoo import _, models, fields
from odoo.exceptions import ValidationError
class StockQuant(models.Model):
_inherit = "stock.quant"
product_categ_id = fields.Many2one(
related="product_tmpl_id.categ_id",
store=True,
index=True,
string="Product Category",
)
class InventoryAdjustmentsGroup(models.Model):
_inherit = "stock.inventory"
def action_state_to_in_progress(self):
"""
Relaja el bloqueo por categoría: si el ajuste actual es por categoría,
solo bloquea otros ajustes en progreso que afecten a la MISMA categoría exacta,
no a categorías hermanas distintas ni a todas sus hijas.
"""
self.ensure_one()
# Reusar la lógica original, pero parchear el caso de category
search_filter = [
(
"location_id",

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="stock_quant_search_category_filter" model="ir.ui.view">
<field name="name">stock.quant.search.category.filter</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.quant_search_view"/>
<field name="arch" type="xml">
<xpath expr="//search/group[filter[@name='productgroup']]" position="inside">
<filter name="product_categ_group" string="Product Category" context="{'group_by':'product_categ_id'}"/>
</xpath>
</field>
</record>
</odoo>