CriptoMart/red-supermercados-coop#1 purchase_order_product_recommendation_supermarket: sticky header. Add menu option for product.stock.out.period

This commit is contained in:
Luis 2025-10-07 11:22:19 +02:00
parent 2c52a9f36e
commit 54e7755197
6 changed files with 261 additions and 0 deletions

View file

@ -13,7 +13,14 @@
"security/ir.model.access.csv", "security/ir.model.access.csv",
"wizards/purchase_order_recommendation.xml", "wizards/purchase_order_recommendation.xml",
"views/product_template_view.xml", "views/product_template_view.xml",
"views/product_stock_out_period_menu.xml",
"data/stock_out_cron.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": [], "demo": [],
} }

View file

@ -165,6 +165,48 @@ msgstr ""
"Cantidad de productos en stock + Cantidad de producto por venir (pedidos " "Cantidad de productos en stock + Cantidad de producto por venir (pedidos "
"confirmados)" "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 #. module: purchase_order_product_recommendation_supermarket
#: model:ir.model.fields,help:purchase_order_product_recommendation_supermarket.field_purchase_order_recommendation__ignore_zero_stock_days #: model:ir.model.fields,help:purchase_order_product_recommendation_supermarket.field_purchase_order_recommendation__ignore_zero_stock_days
msgid "" 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 #: model:ir.model.fields,field_description:purchase_order_product_recommendation_supermarket.field_purchase_order_recommendation_line__units_virtual_available
msgid "Units Virtual Available" msgid "Units Virtual Available"
msgstr "" 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}"/> context="{'no_return_action': True}"/>
</header> </header>
</xpath> </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="line_amount" position="replace">
<field name="order_days" widget="numeric_step" /> <field name="order_days" widget="numeric_step" />