diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 418e309..a62dd49 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -227,6 +227,30 @@ class ProductTemplate(models.Model):
**Por qué**: Evita problemas con pricelists y reportes que operan a nivel de variante. Ver `product_sale_price_from_pricelist` como ejemplo.
+### QWeb Template Best Practices
+
+**CRÍTICO**: QWeb tiene limitaciones estrictas con lógica compleja. **Siempre mover lógica al controller**:
+
+```python
+# ❌ MAL - QWeb no puede parsear esto
+#
+
+# ✅ CORRECTO - Preparar datos en controller
+class WebsiteController:
+ def _prepare_product_display_info(self, product, price_info):
+ """Pre-procesar todos los valores para QWeb."""
+ price = price_info.get(product.id, {}).get('price') or product.list_price or 0.0
+ return {
+ 'display_price': float(price),
+ 'safe_uom_category': product.uom_id.category_id.name or '',
+ }
+
+# En template: acceso simple, sin lógica
+#
+```
+
+Ver [docs/QWEB_BEST_PRACTICES.md](../docs/QWEB_BEST_PRACTICES.md) para más detalles.
+
## Common Patterns
### Extending Models
@@ -381,6 +405,30 @@ access_model_user,model.name.user,model_model_name,base.group_user,1,1,1,0
**Problem**: Module not loading, dependency errors
**Solution**: Check both `__manifest__.py` depends AND `oca_dependencies.txt` for OCA repos
+### QWeb Template Errors
+
+**Problem**: `TypeError: 'NoneType' object is not callable` in templates
+**Solution**:
+
+1. Move complex logic from template to controller
+2. Use simple attribute access in templates (no conditionals)
+3. Pre-process all display values in Python
+4. See [docs/QWEB_BEST_PRACTICES.md](../docs/QWEB_BEST_PRACTICES.md) for patterns
+
+**Example Pattern**:
+
+```python
+# Controller: prepare clean data
+def _prepare_display_info(self, product):
+ return {
+ 'price': product.price or 0.0,
+ 'uom': product.uom_id.name or '',
+ }
+
+# Template: use simple access
+
+```
+
## Testing Guidelines
### Unit Tests
@@ -529,6 +577,7 @@ Sistema completo de compras colaborativas para cooperativas de consumo:
- **Separate Carts**: Carrito independiente por miembro y por grupo
- **Cutoff Dates**: Validación de fechas límite para pedidos
- **Pickup Management**: Gestión de días de recogida
+- **Lazy Loading**: Carga configurable de productos (v18.0.1.3.0+)
- **Multi-language**: ES, EU, CA, GL, PT, FR, IT
- **Member Tracking**: Gestión de miembros activos/inactivos por grupo
@@ -540,7 +589,21 @@ Sistema completo de compras colaborativas para cooperativas de consumo:
4. Notificaciones automáticas al cambiar estados
5. Tracking de fulfillment por miembro
-Ver [website_sale_aplicoop/README.md](../website_sale_aplicoop/README.md) para detalles.
+**Configuración Lazy Loading** (v18.0.1.3.0+):
+
+```
+Settings > Website > Shop Performance
+ [✓] Enable Lazy Loading
+ [20] Products Per Page
+```
+
+**Mejoras Recientes**:
+
+- v18.0.1.3.1: Fixes críticos de cálculo de fechas
+- v18.0.1.3.0: Lazy loading, mejora de rendimiento de 10-20s → 500-800ms
+- Refactor de template rendering: Mover lógica QWeb al controller
+
+Ver [website_sale_aplicoop/README.md](../website_sale_aplicoop/README.md) y [docs/LAZY_LOADING.md](../docs/LAZY_LOADING.md) para detalles.
### Triple Discount System
@@ -583,6 +646,13 @@ last_purchase_price_compute_type != "manual_update" # Para auto-cálculo
---
-**Last Updated**: 2026-02-16
+**Last Updated**: 2026-02-18
**Odoo Version**: 18.0
**Python Version**: 3.10+
+
+## Recent Changes Summary
+
+- **2026-02-18**: Refactor `product_main_seller` - Remover alias innecesario `default_supplier_id`
+- **2026-02-16**: v18.0.1.3.1 fixes críticos de cálculo de fechas en Eskaera
+- **2026-02-12**: v18.0.1.3.0 Lazy loading y fixes de template rendering QWeb
+- **2026-02-02**: UI improvements y date calculation fixes
diff --git a/README.md b/README.md
index d927e66..dd547b3 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,13 @@ Este repositorio contiene los addons personalizados para Kidekoop, un sistema co
| [account_invoice_triple_discount_readonly](account_invoice_triple_discount_readonly/) | Fix para bug de descuentos acumulados | ✅ Estable |
| [product_price_category_supplier](product_price_category_supplier/) | Gestión de categorías por proveedor | ✅ Estable |
| [product_sale_price_from_pricelist](product_sale_price_from_pricelist/) | Auto-cálculo precio venta desde compra | ✅ Estable |
-| [website_sale_aplicoop](website_sale_aplicoop/) | Sistema completo de eskaera web con **lazy loading** 🚀 | ✅ Estable |
+| [website_sale_aplicoop](website_sale_aplicoop/) | Sistema completo de eskaera web | ✅ **v18.0.1.3.1** - Estable |
-**✨ Nueva Feature v18.0.1.3.0**: `website_sale_aplicoop` incluye **lazy loading configurable** para mejorar el rendimiento de carga de productos. Reduce el tiempo de carga inicial de 10-20s a 500-800ms. Ver [docs/LAZY_LOADING.md](docs/LAZY_LOADING.md) para detalles.
+**✨ Feature v18.0.1.3.0**: `website_sale_aplicoop` incluye **lazy loading configurable** para mejorar el rendimiento de carga de productos (10-20s → 500-800ms).
+
+**🔧 Fixes v18.0.1.3.1**: Correcciones críticas en cálculo de fechas y refactor de template rendering para evitar errores QWeb.
+
+Ver [docs/LAZY_LOADING.md](docs/LAZY_LOADING.md) y [docs/FINAL_SOLUTION_SUMMARY.md](docs/FINAL_SOLUTION_SUMMARY.md) para detalles.
## 🚀 Quick Start
diff --git a/docs/README.md b/docs/README.md
index 9c751cf..9faa4dc 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -4,7 +4,11 @@ Esta carpeta contiene documentación técnica y de referencia del proyecto.
## Contenido
-### 🚀 Performance & Features (Nuevas)
+### � Cambios Recientes
+
+- **[RECENT_CHANGES.md](RECENT_CHANGES.md)** - 🆕 Resumen de todos los cambios recientes (Feb 2026)
+
+### �🚀 Performance & Features (Nuevas)
- **[LAZY_LOADING_QUICK_START.md](LAZY_LOADING_QUICK_START.md)** - ⚡ Guía rápida (5 min) si solo necesitas lo esencial
- **[LAZY_LOADING_DOCS_INDEX.md](LAZY_LOADING_DOCS_INDEX.md)** - Índice centralizado de documentación de lazy loading (v18.0.1.3.0)
@@ -20,6 +24,10 @@ Esta carpeta contiene documentación técnica y de referencia del proyecto.
### Resolución de Problemas
+- **[FINAL_SOLUTION_SUMMARY.md](FINAL_SOLUTION_SUMMARY.md)** - Solución definitiva para errores de templates QWeb en website_sale_aplicoop
+- **[FIX_TEMPLATE_ERROR_SUMMARY.md](FIX_TEMPLATE_ERROR_SUMMARY.md)** - Resumen de correcciones de templates
+- **[QWEB_BEST_PRACTICES.md](QWEB_BEST_PRACTICES.md)** - Mejores prácticas para templates QWeb (CRÍTICO)
+- **[TEMPLATE_FIX_INDEX.md](TEMPLATE_FIX_INDEX.md)** - Índice de documentación de fixes de templates
- **[CORRECCION_PRECIOS_IVA.md](CORRECCION_PRECIOS_IVA.md)** - Correcciones relacionadas con precios e IVA
- **[TEST_MANUAL.md](TEST_MANUAL.md)** - Guía de tests manuales
diff --git a/docs/RECENT_CHANGES.md b/docs/RECENT_CHANGES.md
new file mode 100644
index 0000000..50ad4ee
--- /dev/null
+++ b/docs/RECENT_CHANGES.md
@@ -0,0 +1,278 @@
+# Cambios Recientes del Proyecto
+
+**Última actualización**: 18 de febrero de 2026
+
+## Resumen Ejecutivo
+
+El proyecto ha recibido importantes mejoras en rendimiento, arquitectura y estabilidad durante febrero de 2026:
+
+1. **Refactoring de `product_main_seller`** - Eliminación de campo alias innecesario
+2. **Lazy Loading v18.0.1.3.0** - Mejora de rendimiento de 10-20s → 500-800ms
+3. **Template Rendering Fixes v18.0.1.3.1** - Solución definitiva para errores QWeb
+4. **Date Calculation Fixes v18.0.1.3.1** - Correcciones críticas en validación de fechas
+
+---
+
+## 📅 Timeline de Cambios
+
+### 18 de Febrero (Hoy)
+
+#### `[REF] product_main_seller: Remover campo alias default_supplier_id`
+
+**Commit**: `ed048c8`
+
+**Cambio**: Se eliminó el campo `default_supplier_id` que era un alias innecesario
+
+**Razón**:
+- Campo redundante que duplicaba `main_seller_id`
+- Los addons custom ya usan `main_seller_id` directamente
+- Evitar crear extensiones innecesarias en addons OCA
+
+**Impacto**:
+- ✅ Código más limpio
+- ✅ Menos confusión en arquitectura
+- ⚠️ Revisar cualquier código personalizado que use `default_supplier_id`
+
+**Archivos Afectados**:
+- `product_main_seller/models/product_template.py` - Se removió campo alias
+
+**Acción Requerida**:
+```bash
+# Actualizar addon en instancia Odoo
+docker-compose exec odoo odoo -d odoo -u product_main_seller --stop-after-init
+```
+
+**Para Developers**:
+```python
+# ❌ ANTES
+product.default_supplier_id # Alias innecesario
+
+# ✅ AHORA (preferido)
+product.main_seller_id # Campo original
+```
+
+---
+
+### 16 de Febrero (v18.0.1.3.1)
+
+#### `[FIX] website_sale_aplicoop: Critical date calculation fixes`
+
+**Versión**: 18.0.1.3.1
+
+**Cambios Principales**:
+
+1. **Date Calculation Logic**:
+ - Corregido cálculo de `cutoff_date`: Changed `days_ahead <= 0` to `days_ahead < 0`
+ - Permite que cutoff_date sea el mismo día que hoy
+ - Agregado `store=True` en `delivery_date` para persistencia
+
+2. **Constraints & Validations**:
+ - Nueva constraint `_check_cutoff_before_pickup`
+ - Valida que pickup_day >= cutoff_day en órdenes semanales
+ - Previene configuraciones inválidas
+
+3. **Cron Job Automático**:
+ - Nuevo `_cron_update_dates` que recalcula fechas diariamente
+ - Asegura que las fechas computadas permanezcan actuales
+
+4. **UI Improvements**:
+ - Nueva sección "Calculated Dates" en formulario
+ - Muestra readonly cutoff_date, pickup_date, delivery_date
+ - Mejor visibilidad de fechas automáticas
+
+**Testing**:
+- 6 nuevos tests de regresión con tag `post_install` y `date_calculations`
+- Validación de todas las combinaciones de días (49 combinaciones)
+- Asegura que cutoff puede ser hoy sin errores
+
+**Para Developers**:
+```python
+# Ahora es seguro establecer cutoff_date al mismo día
+if today == cutoff_day: # ✅ Funciona correctamente
+ # La validación permite esto
+ pass
+```
+
+---
+
+### 12 de Febrero (v18.0.1.3.0)
+
+#### `[ADD] website_sale_aplicoop: Lazy Loading Implementation`
+
+**Versión**: 18.0.1.3.0
+
+**Cambio Mayor**: Implementación de lazy loading configurable para productos
+
+**Resultados de Rendimiento**:
+- **Antes**: Carga de página = 10-20 segundos (todos los productos)
+- **Después**:
+ - Página 1: 500-800ms (20 productos)
+ - Páginas subsecuentes: 200-400ms vía AJAX
+ - **Mejora**: 95% más rápido
+
+**Configuración**:
+```
+Settings > Website > Shop Performance
+ [✓] Enable Lazy Loading
+ [20] Products Per Page
+```
+
+**Características**:
+- Botón "Load More" configurable
+- Spinner durante carga
+- Event listeners re-attached en nuevos productos
+- Botón se oculta automáticamente cuando no hay más productos
+
+**Archivos Modificados**:
+- `website_sale_aplicoop/models/group_order.py` - Método `_get_products_paginated()`
+- `website_sale_aplicoop/views/website_templates.xml` - Nuevo template `eskaera_shop_products`
+- `website_sale_aplicoop/static/js/` - JavaScript para AJAX y event handling
+
+**Documentación**:
+- [LAZY_LOADING.md](LAZY_LOADING.md) - Documentación técnica completa
+- [LAZY_LOADING_QUICK_START.md](LAZY_LOADING_QUICK_START.md) - Guía rápida
+- [UPGRADE_INSTRUCTIONS_v18.0.1.3.0.md](UPGRADE_INSTRUCTIONS_v18.0.1.3.0.md) - Pasos de actualización
+
+---
+
+### Febrero 2-16 (v18.0.1.2.0 - v18.0.1.3.0)
+
+#### `[FIX] website_sale_aplicoop: Move template logic to controller`
+
+**Commit**: `5721687` - FINAL SOLUTION
+
+**Problema**:
+```
+TypeError: 'NoneType' object is not callable
+Template: website_sale_aplicoop.eskaera_shop_products
+```
+
+**Causa Raíz**: QWeb no puede parsear:
+- Conditionals complejos en `t-set`
+- Operadores 'or' encadenados en `t-attf-*`
+- Cadenas profundas de atributos con lógica
+
+**Solución**: Mover TODA la lógica al controller
+
+```python
+# Controller prepara datos limpios
+def _prepare_product_display_info(self, product, price_info):
+ price = price_info.get(product.id, {}).get('price') or 0.0
+ uom = product.uom_id.category_id.name if product.uom_id and product.uom_id.category_id else ''
+ return {
+ 'display_price': float(price),
+ 'safe_uom_category': uom,
+ }
+
+# Template usa acceso simple
+#
+```
+
+**Documentación**:
+- [FINAL_SOLUTION_SUMMARY.md](FINAL_SOLUTION_SUMMARY.md) - Análisis completo
+- [QWEB_BEST_PRACTICES.md](QWEB_BEST_PRACTICES.md) - Mejores prácticas
+
+**Para Developers**:
+Este es el patrón recomendado para todos los templates complejos:
+1. Preparar datos en el controller
+2. Pasar dict simple al template
+3. Template solo accede atributos, sin lógica
+
+---
+
+## 🎯 Cambios Transversales
+
+### Mejoras de Código
+
+| Commit | Descripción |
+|--------|-------------|
+| 6fbc7b9 | Remover atributos string= redundantes en website_sale_aplicoop |
+| 5c89795 | Corregir errores de traducción obligatorios (linting) |
+| 40ce973 | Infinite scroll + search filter integration |
+| dc44ace | Agregar configuración ESLint |
+| b15e9bc | Aumentar threshold de complejidad ciclomática en flake8 |
+
+### Pruebas
+
+- Tests de regresión para date calculations (v18.0.1.3.1)
+- Tests de lazy loading (v18.0.1.3.0)
+- Validación de constraints de fechas
+
+---
+
+## 📚 Documentación Actualizada
+
+- **`.github/copilot-instructions.md`** - Actualizado con nuevos patrones y fixes
+- **`README.md`** - Información sobre v18.0.1.3.1 y lazy loading
+- **`product_main_seller/README.md`** - Actualizado sin `default_supplier_id`
+- **`docs/README.md`** - Nuevo índice de documentación de fixes
+- **`website_sale_aplicoop/README.md`** - Changelog actualizado
+
+---
+
+## ⚠️ Cosas Importantes para Developers
+
+### 1. Patrón de Templates QWeb
+**Cambio Crítico**: Nunca poner lógica en templates, siempre en controller
+
+```python
+# ✅ CORRECTO
+def _prepare_data(self):
+ return {'price': 100.0, 'name': 'Product'}
+
+# ❌ INCORRECTO (No hagas esto)
+#
+```
+
+### 2. Field Names en product_main_seller
+**Cambio**: Use `main_seller_id` en lugar de `default_supplier_id`
+
+```python
+# ✅ CORRECTO
+product.main_seller_id
+
+# ❌ OBSOLETO
+product.default_supplier_id # Ya no existe
+```
+
+### 3. Lazy Loading Configuration
+Si trabajas con website_sale_aplicoop, la configuración está en:
+
+```
+Settings > Website > Shop Performance
+```
+
+No es necesario modificar código, es configurable.
+
+### 4. Date Calculations en Eskaera
+Ahora puedes usar cutoff_date = hoy sin problemas:
+
+```python
+# ✅ Ahora funciona
+order.cutoff_date = today # Antes fallaba
+```
+
+---
+
+## 🔍 Cambios Detectados pero No Documentados
+
+Verifica si necesitas cambios en:
+
+1. Código que usa `default_supplier_id` de `product_main_seller`
+2. Lógica en templates (especialmente en website_sale_aplicoop)
+3. Configuración de lazy loading si tienes instancia personalizada
+
+---
+
+## 📞 Para Más Detalles
+
+- Refactoring product_main_seller: Ver commit `ed048c8`
+- Lazy loading: Ver [docs/LAZY_LOADING.md](LAZY_LOADING.md)
+- Template fixes: Ver [docs/FINAL_SOLUTION_SUMMARY.md](FINAL_SOLUTION_SUMMARY.md)
+- Date calculations: Ver [website_sale_aplicoop/README.md](../website_sale_aplicoop/README.md)
+
+---
+
+**Última actualización**: 2026-02-18
+**Versión Actual**: 18.0.1.3.1
+**Status**: ✅ Production Ready
diff --git a/product_main_seller/README.md b/product_main_seller/README.md
index d9da2eb..b58dfea 100644
--- a/product_main_seller/README.md
+++ b/product_main_seller/README.md
@@ -21,29 +21,19 @@ Adds a "Main Vendor" field to products that automatically tracks the primary sup
### Fields Added
-- `default_supplier_id` (Many2one → res.partner, computed, stored)
+- `main_seller_id` (Many2one → res.partner, computed, stored)
- The main vendor for this product
- Computed from `seller_ids` with lowest sequence
- Stored for performance
- - Searchable
-
-- `default_supplier_ref` (Char, related to `default_supplier_id.ref`)
- - The supplier's reference code
- - Readonly
+ - Searchable and filterable
### Computation Logic
The main vendor is determined by:
1. Looking at all supplierinfo records (`seller_ids`)
-2. Filtering for valid suppliers (not companies)
+2. Filtering for valid suppliers (active partners)
3. Selecting the one with the **lowest sequence** number
-4. If no sequence, uses the first one
-
-### Migration Hook
-
-Includes `pre_init_hook` that:
-- Populates `default_supplier_id` on existing products during installation
-- Ensures data consistency from the start
+4. If no suppliers, returns empty
## Dependencies
@@ -57,6 +47,8 @@ docker-compose exec odoo odoo -d odoo -u product_main_seller --stop-after-init
## Usage
+## Usage
+
### Viewing Main Vendor
1. Open a product form (Products > Products > [Product])
@@ -76,28 +68,17 @@ To change the main vendor:
```python
# Find all products from a specific vendor
products = self.env['product.template'].search([
- ('default_supplier_id', '=', vendor_id)
+ ('main_seller_id', '=', vendor_id)
])
```
-## OCA Source
-
-- **Repository**: [purchase-workflow](https://github.com/OCA/purchase-workflow)
-- **Original Author**: GRAP
-- **Maintainers**: legalsylvain, quentinDupont
-- **License**: AGPL-3
-
-## Modifications for Kidekoop
-
-None - Used as-is from OCA.
-
## Use Cases in Kidekoop
This module is critical for:
-- `product_price_category_supplier`: Bulk updating products by main vendor
-- Purchase order management
- Vendor performance analysis
+- Purchase order management
- Inventory planning by supplier
+- Default supplier selection in purchase workflows
## Views Modified