Compare commits
2 commits
2c52a9f36e
...
91641c7c88
| Author | SHA1 | Date | |
|---|---|---|---|
| 91641c7c88 | |||
| 54e7755197 |
11 changed files with 325 additions and 8 deletions
|
|
@ -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": [],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ""
|
||||||
|
|
|
||||||
|
|
@ -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 ""
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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" />
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "Criptomart",
|
"author": "Criptomart",
|
||||||
"depends": ["stock_inventory"],
|
"depends": ["stock_inventory"],
|
||||||
"data": [],
|
"data": [
|
||||||
|
"views/stock_quant_view.xml",
|
||||||
|
],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
stock_inventory_category_concurrency/i18n/es.po
Normal file
18
stock_inventory_category_concurrency/i18n/es.po
Normal 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"
|
||||||
|
|
@ -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 ""
|
||||||
|
|
@ -1,18 +1,23 @@
|
||||||
from odoo import _, models
|
from odoo import _, models, fields
|
||||||
from odoo.exceptions import ValidationError
|
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):
|
class InventoryAdjustmentsGroup(models.Model):
|
||||||
_inherit = "stock.inventory"
|
_inherit = "stock.inventory"
|
||||||
|
|
||||||
def action_state_to_in_progress(self):
|
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()
|
self.ensure_one()
|
||||||
# Reusar la lógica original, pero parchear el caso de category
|
|
||||||
search_filter = [
|
search_filter = [
|
||||||
(
|
(
|
||||||
"location_id",
|
"location_id",
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue