[FIX] website_sale_aplicoop: Correct XPath for block element

- Changed xpath from div[@id='website_info_settings'] to block[@id='website_info_settings']
- Fixes RPC error when loading res.config.settings view

[FIX] product_price_category_supplier: Convert README to reStructuredText

- Converted README.md to README.rst for proper Odoo documentation
- Fixed docutils warnings and formatting issues
- Updated reStructuredText syntax for code blocks and literals
This commit is contained in:
snt 2026-02-16 15:16:56 +01:00
parent 0d5f0be88c
commit 5ba8ddda92
3 changed files with 410 additions and 44 deletions

View file

@ -49,39 +49,39 @@ Este repositorio contiene addons personalizados y modificados de Odoo 18.0. El p
1. **Estructura de carpeta i18n/**:
```
addon_name/
├── i18n/
│ ├── es.po # Español (obligatorio)
│ ├── eu.po # Euskera (obligatorio)
│ └── addon_name.pot # Template (generado)
```
```
addon_name/
├── i18n/
│ ├── es.po # Español (obligatorio)
│ ├── eu.po # Euskera (obligatorio)
│ └── addon_name.pot # Template (generado)
```
2. **NO usar `_()` en definiciones de campos a nivel de módulo**:
```python
# ❌ INCORRECTO - causa warnings
from odoo import _
name = fields.Char(string=_("Name"))
```python
# ❌ INCORRECTO - causa warnings
from odoo import _
name = fields.Char(string=_("Name"))
# ✅ CORRECTO - traducción se maneja por .po files
name = fields.Char(string="Name")
```
# ✅ CORRECTO - traducción se maneja por .po files
name = fields.Char(string="Name")
```
3. **Usar `_()` solo en métodos y código ejecutable**:
```python
def action_confirm(self):
message = _("Confirmed successfully")
return {'warning': {'message': message}}
```
```python
def action_confirm(self):
message = _("Confirmed successfully")
return {'warning': {'message': message}}
```
4. **Generar/actualizar traducciones**:
```bash
# Exportar términos a traducir
Pedir al usuario generar a través de UI, no sabemos el método correcto para exportar SÓLO las cadenas del addon sin incluir todo el sistema.
```
```bash
# Exportar términos a traducir
Pedir al usuario generar a través de UI, no sabemos el método correcto para exportar SÓLO las cadenas del addon sin incluir todo el sistema.
```
Usar sólo polib y apend cadenas en los archivos .po, msmerge corrompe los archivos.
@ -147,7 +147,7 @@ addons-cm/
### Local Development
```bash
# Iniciar entorno
# Iniciar entorno (puertos: 8070=web, 8073=longpolling)
docker-compose up -d
# Actualizar addon
@ -158,20 +158,37 @@ docker-compose logs -f odoo
# Ejecutar tests
docker-compose exec odoo odoo -d odoo --test-enable --stop-after-init -u addon_name
# Acceder a shell de Odoo
docker-compose exec odoo bash
# Acceder a PostgreSQL
docker-compose exec db psql -U odoo -d odoo
````
### Quality Checks
```bash
# Ejecutar todos los checks
# Ejecutar todos los checks (usa .pre-commit-config.yaml)
pre-commit run --all-files
# O usar Makefile
make lint # Solo linting
make format # Formatear código
make check-addon # Verificar addon específico
# O usar Makefile (ver `make help` para todos los comandos)
make lint # Solo linting (pre-commit)
make format # Formatear código (black + isort)
make check-format # Verificar formateo sin modificar
make flake8 # Ejecutar flake8
make pylint # Ejecutar pylint (todos)
make pylint-required # Solo verificaciones mandatorias
make clean # Limpiar archivos temporales
```
### Tools Configuration
- **black**: Line length 88, target Python 3.10+ (ver `pyproject.toml`)
- **isort**: Profile black, sections: STDLIB > THIRDPARTY > ODOO > ODOO_ADDONS > FIRSTPARTY > LOCALFOLDER
- **flake8**: Ver `.flake8` para reglas específicas
- **pylint**: Configurado para Odoo con `pylint-odoo` plugin
### Testing
- Tests en `tests/` de cada addon
@ -179,6 +196,37 @@ make check-addon # Verificar addon específico
- Herencia: `odoo.tests.common.TransactionCase`
- Ejecutar: `--test-enable` flag
## Critical Architecture Patterns
### Product Variants Architecture
**IMPORTANTE**: Los campos de lógica de negocio SIEMPRE van en `product.product` (variantes), no en `product.template`:
```python
# ✅ CORRECTO - Lógica en product.product
class ProductProduct(models.Model):
_inherit = 'product.product'
last_purchase_price_updated = fields.Boolean(default=False)
list_price_theoritical = fields.Float(default=0.0)
def _compute_theoritical_price(self):
for product in self:
# Cálculo real por variante
pass
# ✅ CORRECTO - Template solo tiene campos related
class ProductTemplate(models.Model):
_inherit = 'product.template'
last_purchase_price_updated = fields.Boolean(
related='product_variant_ids.last_purchase_price_updated',
readonly=False
)
```
**Por qué**: Evita problemas con pricelists y reportes que operan a nivel de variante. Ver `product_sale_price_from_pricelist` como ejemplo.
## Common Patterns
### Extending Models
@ -233,6 +281,35 @@ return {
}
```
### Logging Pattern
```python
import logging
_logger = logging.getLogger(__name__)
# En métodos de cálculo de precios, usar logging detallado:
_logger.info(
"[PRICE DEBUG] Product %s [%s]: base_price=%.2f, tax_amount=%.2f",
product.default_code or product.name,
product.id,
base_price,
tax_amount,
)
```
### Price Calculation Pattern
```python
# Usar product_get_price_helper para cálculos consistentes
partial_price = product._get_price(qty=1, pricelist=pricelist)
base_price = partial_price.get('value', 0.0) or 0.0
# Siempre validar taxes
if not product.taxes_id:
raise UserError(_("No taxes defined for product %s") % product.name)
```
## Dependencies Management
### OCA Dependencies (`oca_dependencies.txt`)
@ -287,7 +364,22 @@ access_model_user,model.name.user,model_model_name,base.group_user,1,1,1,0
### Price Calculation
**Problem**: Prices not updating from pricelist
**Solution**: Use `product_sale_price_from_pricelist` with proper configuration
**Solution**:
1. Use `product_sale_price_from_pricelist` with proper configuration
2. Set pricelist in Settings > Sales > Automatic Price Configuration
3. Ensure `last_purchase_price_compute_type` is NOT set to `manual_update`
4. Verify product has taxes configured (required for price calculation)
### Product Variant Issues
**Problem**: Computed fields not working in pricelists/reports
**Solution**: Move business logic from `product.template` to `product.product` and use `related` fields in template
### Manifest Dependencies
**Problem**: Module not loading, dependency errors
**Solution**: Check both `__manifest__.py` depends AND `oca_dependencies.txt` for OCA repos
## Testing Guidelines
@ -307,18 +399,18 @@ access_model_user,model.name.user,model_model_name,base.group_user,1,1,1,0
```javascript
odoo.define("module.tour", function (require) {
"use strict";
var tour = require("web_tour.tour");
tour.register(
"tour_name",
{
test: true,
url: "/web",
},
[
// Tour steps
],
);
"use strict";
var tour = require("web_tour.tour");
tour.register(
"tour_name",
{
test: true,
url: "/web",
},
[
// Tour steps
],
);
});
```
@ -364,11 +456,41 @@ Cada addon debe tener un README.md con:
7. **Technical Details**: Modelos, campos, métodos
8. **Translations**: Estado de traducciones (si aplica)
### **manifest**.py Structure
Todos los addons custom deben seguir esta estructura:
```python
# Copyright YEAR - Today AUTHOR
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ # noqa: B018
"name": "Addon Name",
"version": "18.0.X.Y.Z", # X=major, Y=minor, Z=patch
"category": "category_name",
"summary": "Short description",
"author": "Odoo Community Association (OCA), Your Company",
"maintainers": ["maintainer_github"],
"website": "https://github.com/OCA/repo",
"license": "AGPL-3",
"depends": [
"base",
# Lista ordenada alfabéticamente
],
"data": [
"security/ir.model.access.csv",
"views/actions.xml",
"views/menu.xml",
"views/model_views.xml",
],
}
```
### Code Comments
- Docstrings en clases y métodos públicos
- Comentarios inline para lógica compleja
- TODOs con contexto completo
- Logging detallado en operaciones de precios/descuentos
## Version Control
@ -397,6 +519,61 @@ Tags: `[ADD]`, `[FIX]`, `[IMP]`, `[REF]`, `[REM]`, `[I18N]`, `[DOC]`
- Indexes en campos frecuentemente buscados
- Avoid N+1 queries con `prefetch`
## Key Business Features
### Eskaera System (website_sale_aplicoop)
Sistema completo de compras colaborativas para cooperativas de consumo:
- **Group Orders**: Pedidos grupales con estados (draft → confirmed → collected → completed)
- **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
- **Multi-language**: ES, EU, CA, GL, PT, FR, IT
- **Member Tracking**: Gestión de miembros activos/inactivos por grupo
**Flujo típico**:
1. Administrador crea grupo order con fechas (collection, cutoff, pickup)
2. Miembros añaden productos a su carrito individual
3. Sistema valida cutoff date antes de confirmar
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.
### Triple Discount System
Todos los documentos de compra/venta soportan 3 descuentos consecutivos:
```python
# Ejemplo: Precio = 600.00
# Desc. 1 = 50% → 300.00
# Desc. 2 = 50% → 150.00
# Desc. 3 = 50% → 75.00
```
**IMPORTANTE**: Usar `account_invoice_triple_discount_readonly` para evitar bug de acumulación de descuentos.
### Automatic Pricing System
`product_sale_price_from_pricelist` calcula automáticamente precio de venta basado en:
- Último precio de compra (`last_purchase_price_received`)
- Tipo de cálculo de descuentos (`last_purchase_price_compute_type`)
- Pricelist configurado en Settings
- Impuestos del producto
**Configuración crítica**:
```python
# En Settings > Sales > Automatic Price Configuration
product_pricelist_automatic = [ID_pricelist]
# En producto
last_purchase_price_compute_type != "manual_update" # Para auto-cálculo
```
## Resources
- **OCA Guidelines**: https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst
@ -406,6 +583,6 @@ Tags: `[ADD]`, `[FIX]`, `[IMP]`, `[REF]`, `[REM]`, `[I18N]`, `[DOC]`
---
**Last Updated**: 2026-02-12
**Last Updated**: 2026-02-16
**Odoo Version**: 18.0
**Python Version**: 3.10+