[DOC] Actualizar documentación a estándares OCA y preparar logo CriptoMart
- Renombrar README.md a README_DEV.md en todos los addons custom - Crear README.rst siguiendo estructura OCA oficial - Crear directorios readme/ con fragmentos .rst (DESCRIPTION, INSTALL, CONFIGURE, USAGE, CONTRIBUTORS, CREDITS) - Actualizar créditos: Criptomart (autor) + Elika Bilbo (financiador) - Actualizar __manifest__.py con maintainers correctos - Crear estructura static/description/ para logo en 5 addons - Agregar documentación de logo (LOGO_INSTRUCTIONS.md, install_logo.sh) - Actualizar copilot-instructions.md con referencias a OCA_DOCUMENTATION.md - Crear docs/OCA_DOCUMENTATION.md con guía completa de estructura - Crear docs/RESUMEN_CAMBIOS_DOCUMENTACION.md con resumen detallado Addons actualizados: - website_sale_aplicoop - product_sale_price_from_pricelist - product_pricelist_total_margin - product_price_category_supplier - account_invoice_triple_discount_readonly
This commit is contained in:
parent
b31df7b9d8
commit
4a4639f13a
56 changed files with 1778 additions and 674 deletions
26
website_sale_aplicoop/readme/CONFIGURE.rst
Normal file
26
website_sale_aplicoop/readme/CONFIGURE.rst
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
To configure this module, you need to:
|
||||
|
||||
**Lazy Loading Configuration (v18.0.1.3.0+):**
|
||||
|
||||
#. Go to Settings → Website → Shop Performance
|
||||
#. Enable "Enable Lazy Loading" checkbox
|
||||
#. Set "Products Per Page" (default: 20)
|
||||
#. Save settings
|
||||
|
||||
**Global Settings:**
|
||||
|
||||
#. Go to Settings → Website → Shop Settings
|
||||
#. Configure default group settings
|
||||
#. Define pickup days and locations
|
||||
|
||||
**Group Management:**
|
||||
|
||||
#. Go to Contacts, filter by Groups (is_group=True)
|
||||
#. Create groups for your cooperative communities
|
||||
#. Add partners/members to groups via the Members tab
|
||||
|
||||
**Product Configuration:**
|
||||
|
||||
#. Link products to categories used in group orders
|
||||
#. Configure pricing and taxes for products
|
||||
#. Set product availability per supplier
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
Group orders (*eskaera*) are a business model for collaborative consumption where groups of users collectively purchase products within defined time windows. This module was created to replace the legacy Aplicoop application, providing:
|
||||
|
||||
**Business Value:**
|
||||
- Streamlined group purchasing workflows within Odoo's standard sales framework
|
||||
- Flexible scheduling to accommodate different group shopping patterns (daily, weekly, biweekly, monthly)
|
||||
- Clear separation between temporary shopping carts and permanent sales orders
|
||||
- Support for multiple groups with different suppliers, products, and categories
|
||||
|
||||
**Use Cases:**
|
||||
- Cooperative grocery purchasing groups
|
||||
- Bulk order consolidation for community members
|
||||
- Time-limited promotional campaigns with group participation
|
||||
- Multi-location organizations with shared procurement
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# Contributors
|
||||
|
||||
This module has been developed and is maintained by the following contributors:
|
||||
|
||||
## Authors
|
||||
|
||||
* **Criptomart** (https://criptomart.net)
|
||||
- Project lead and main development
|
||||
|
||||
## Contributions
|
||||
|
||||
Special thanks to all contributors who have helped improve this module through:
|
||||
|
||||
* Code contributions
|
||||
* Bug reports and fixes
|
||||
* Documentation improvements
|
||||
* Translation support
|
||||
* Testing and feedback
|
||||
|
||||
## Historical References
|
||||
|
||||
This module was inspired by the original **Aplicoop** project:
|
||||
* https://sourceforge.net/projects/aplicoop/
|
||||
* Original creators: Ekaitz Mendiluze, Joseba Legarreta, and other contributors
|
||||
|
||||
The original Aplicoop project served as a pioneering solution for collaborative consumption group orders, and this module brings its functionality to the modern Odoo platform.
|
||||
|
||||
## License Attribution
|
||||
|
||||
All original code is Copyright © 2025 Criptomart and licensed under AGPL-3.
|
||||
|
||||
For contributions to be accepted, contributors must agree to license their code under AGPL-3 as well.
|
||||
13
website_sale_aplicoop/readme/CONTRIBUTORS.rst
Normal file
13
website_sale_aplicoop/readme/CONTRIBUTORS.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
* `Criptomart <https://criptomart.net>`_:
|
||||
|
||||
* Project lead and main development
|
||||
* Architecture and implementation
|
||||
|
||||
**Historical References:**
|
||||
|
||||
This module was inspired by the original **Aplicoop** project:
|
||||
|
||||
* https://sourceforge.net/projects/aplicoop/
|
||||
* Original creators: Ekaitz Mendiluze, Joseba Legarreta, and other contributors
|
||||
|
||||
The original Aplicoop project served as a pioneering solution for collaborative consumption group orders, and this module brings its functionality to the modern Odoo platform.
|
||||
|
|
@ -1,8 +1,17 @@
|
|||
**Authors:**
|
||||
|
||||
* Criptomart
|
||||
|
||||
**Funding:**
|
||||
|
||||
* Elika Bilbo
|
||||
|
||||
**Other credits:**
|
||||
|
||||
This module was developed by Criptomart in 2025 as a modernization of the Aplicoop application, integrating collaborative consumption group order management directly into Odoo's website sales framework.
|
||||
|
||||
## Additional Contributions
|
||||
|
||||
The implementation follows OCA standards for:
|
||||
- Code quality and testing (26 passing tests)
|
||||
- Documentation structure and multilingual support
|
||||
- Security and access control
|
||||
|
||||
* Code quality and testing (26+ passing tests)
|
||||
* Documentation structure and multilingual support
|
||||
* Security and access control
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
This module replaces the legacy Aplicoop application with a modern, scalable solution for managing collaborative consumption group orders (*eskaera* in Basque) within Odoo's standard website sales framework.
|
||||
|
||||
## Features
|
||||
|
||||
- **Group Order Management**: Create and manage group orders (eskaera) with customizable state transitions (draft → open → closed/cancelled)
|
||||
- **Weekly Activity Filtering**: Automatically filter active orders for the current week based on start/end dates and time windows
|
||||
- **Flexible Scheduling**: Support for optional start/end dates to define order availability windows
|
||||
- **Cutoff Day Support**: Define weekly cutoff days for group orders to control when purchases can be made
|
||||
- **Product Association**: Link products to specific group orders through Many2many relationships
|
||||
- **Partner Group Association**: Link partners (users) to groups via Many2many relationships for group-based shopping
|
||||
- **i18n Support**: Full internationalization with translations for 7 languages (Spanish, French, Catalan, Basque, Galician, Italian, Portuguese)
|
||||
- **OCA Compliant**: AGPL-3.0 licensed, follows OCA standards for documentation, testing, and code structure
|
||||
14
website_sale_aplicoop/readme/DESCRIPTION.rst
Normal file
14
website_sale_aplicoop/readme/DESCRIPTION.rst
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
This module replaces the legacy Aplicoop application with a modern, scalable solution for managing collaborative consumption group orders (*eskaera* in Basque) within Odoo's standard website sales framework.
|
||||
|
||||
**Features:**
|
||||
|
||||
* **Group Order Management**: Create and manage group orders (eskaera) with customizable state transitions (draft → confirmed → collected → completed)
|
||||
* **Separate Shopping Carts**: Independent cart per member and per group order
|
||||
* **Flexible Scheduling**: Support for collection dates, cutoff dates, and pickup dates
|
||||
* **Member Tracking**: Manage active/inactive members per group order
|
||||
* **Lazy Loading**: Configurable product pagination for fast page loads (v18.0.1.3.0+)
|
||||
* **Multi-language Support**: Full internationalization with translations for 7 languages (ES, EU, CA, GL, PT, FR, IT)
|
||||
* **Email Notifications**: Automatic notifications on order state changes
|
||||
* **Financial Tracking**: Track orders and payments per group member
|
||||
* **Product Integration**: Compatible with product ribbons, pricing, and margin modules
|
||||
* **OCA Compliant**: AGPL-3.0 licensed, follows OCA standards for documentation, testing, and code structure
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
## [18.0.1.0.3] - 2025-12-19
|
||||
|
||||
### Added
|
||||
- Centralised product discovery API on `group.order`: `_get_products_for_group_order(order_id)`.
|
||||
- Backward-compatible delegation on `product.product._get_products_for_group_order`.
|
||||
- Controller `AplicoopWebsiteSale` now delegates discovery to `group.order` and sanitises supplier display.
|
||||
|
||||
### Changed
|
||||
- Moved discovery responsibility from `product.product` to `group.order` (single responsibility).
|
||||
- Updated `eskaera_shop`, `add_to_eskaera_cart` and `confirm_eskaera` to use centralised discovery.
|
||||
|
||||
### Fixed
|
||||
- Avoided runtime AttributeError when discovery function was not present by providing a canonical implementation.
|
||||
- Ensured product discovery priority remains: explicit products → categories → suppliers.
|
||||
- Fixed a regression where discovery returned only one association branch; discovery now
|
||||
returns the UNION of products from `product_ids`, `category_ids` and
|
||||
`supplier_ids` to avoid dropping valid products when multiple associations exist.
|
||||
|
||||
Note: this change documents and prevents a repeated mistake where a single
|
||||
fallback branch hid products from other association fields.
|
||||
|
||||
### Tests
|
||||
- `website_sale_aplicoop` test-suite: 63 tests, 0 failures after the refactor (commit 4b15207).
|
||||
|
||||
### Security
|
||||
- Kept portal surface minimal (no `res.partner` records exposed); controller only injects supplier name/city for display.
|
||||
|
||||
### I18N
|
||||
- Regenerated translation template (`.pot`) using an addon-only export to avoid collecting unrelated Odoo strings.
|
||||
- Added `docs/I18N_EXPORT_PITFALL.md` explaining the common export pitfall and safe export workflow (export to `/tmp`, restrict `--addons-path`, use `msgmerge`).
|
||||
- Added `tools/filter_pot_by_module.py` to filter POT files by module references and applied it to reduce the POT to addon-only entries (~168 entries).
|
||||
- Updated and committed cleaned `.po` files for all supported languages (es, pt, gl, ca, eu, fr, it).
|
||||
|
||||
## [18.0.1.0.2] - 2025-12-14
|
||||
|
||||
### Added
|
||||
- Multi-company support with company_id field on group.order
|
||||
- Company validation constraint to ensure groups belong to the same company
|
||||
- Multi-company filtering in get_active_orders_for_week() method
|
||||
- company_id field on res.partner for user-group relationships
|
||||
- 9 new test cases for multi-company scenarios (test_multi_company.py)
|
||||
- Post-migration script to assign default company to existing group.order records
|
||||
|
||||
### Changed
|
||||
- group.order now respects allowed_company_ids context for data isolation
|
||||
- get_active_orders_for_week() filters by company context when applicable
|
||||
- group_ids domain now validates company relationships
|
||||
|
||||
### Fixed
|
||||
- Ensured multi-company data isolation between different organizations
|
||||
|
||||
## [18.0.1.0.1] - 2025-12-14
|
||||
|
||||
### Added
|
||||
- Product discovery with 3-level fallback system (direct → categories → suppliers)
|
||||
- Search functionality by product name and description in eskaera_shop
|
||||
- Dynamic category filtering dropdown on shopping page
|
||||
- Product thumbnail images with fallback icons in base64 encoding
|
||||
- Comprehensive logging for debugging group order flow
|
||||
- Logging of cutoff day, pickup day, and order dates in eskaera_shop
|
||||
- 7 new test cases for product discovery scenarios (test_eskaera_shop.py)
|
||||
- Criptomart branding with logo.svg
|
||||
- Professional HTML documentation in static/description/index.html
|
||||
|
||||
### Changed
|
||||
- Refactored product lookup to support three discovery methods
|
||||
- Updated confirm_eskaera to accept products from any discovery method
|
||||
- Improved error handling in checkout flow
|
||||
- Enhanced template rendering with conditional field validation
|
||||
- Optimized product search with regex and case-insensitive matching
|
||||
|
||||
### Fixed
|
||||
- Fixed products not appearing when assigned via categories or suppliers (discovered via fallback)
|
||||
- Fixed translation errors in 7 languages (es, fr, ca, eu, gl, it, pt) - order type labels
|
||||
- Removed obsolete website_sale.py model file causing ImportError
|
||||
- Fixed checkout validation that blocked orders with category/supplier-discovered products
|
||||
- Fixed QWebException when start_date is optional by adding t-if validation
|
||||
- Fixed duplicate sale.order creation from double event binding on confirm button
|
||||
- Corrected product supplier relationship in tests (use seller_ids instead of supplier_id)
|
||||
|
||||
### Deprecated
|
||||
- N/A
|
||||
|
||||
### Removed
|
||||
- Obsolete models/website_sale.py file (functionality migrated to controllers)
|
||||
- Duplicate event listener on confirm button in website_templates.xml
|
||||
- Fallback confirmCheckout() function from template (handled by JS)
|
||||
|
||||
### Security
|
||||
- Maintained CSRF protection on all POST routes
|
||||
- Input validation on JSON payloads in confirm_eskaera
|
||||
- Access control validation for group membership
|
||||
|
||||
## [18.0.1.0.0-beta] - 2025-12-13
|
||||
|
||||
### Added
|
||||
- Initial beta release of Website Sale - Aplicoop module
|
||||
- Complete group order management system (draft → open → closed/cancelled)
|
||||
- Flexible scheduling with start/end dates and optional time windows
|
||||
- Cutoff day support for weekly order management
|
||||
- Product and supplier associations
|
||||
- Group-based user relationships
|
||||
- Full i18n support for 7 languages (ES, FR, CA, EU, GL, IT, PT)
|
||||
- 26 passing tests covering model logic and business rules
|
||||
- OCA-compliant documentation structure
|
||||
- AGPL-3.0 licensing
|
||||
|
||||
### Changed
|
||||
- N/A (initial release)
|
||||
|
||||
### Fixed
|
||||
- N/A (initial release)
|
||||
|
||||
### Deprecated
|
||||
- N/A (initial release)
|
||||
|
||||
### Removed
|
||||
- N/A (initial release)
|
||||
|
||||
### Security
|
||||
- Access control via group permissions
|
||||
- CSRF protection on all POST routes
|
||||
- Input validation on client and server side
|
||||
17
website_sale_aplicoop/readme/INSTALL.rst
Normal file
17
website_sale_aplicoop/readme/INSTALL.rst
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
To install this module, you need to:
|
||||
|
||||
#. Place the addon in your Odoo addons folder
|
||||
#. Update the Apps list
|
||||
#. Search for "Website Sale - Aplicoop"
|
||||
#. Click Install
|
||||
|
||||
**Dependencies:**
|
||||
|
||||
This module requires the following Odoo modules:
|
||||
|
||||
* base
|
||||
* web
|
||||
* website
|
||||
* sale
|
||||
* product
|
||||
* account
|
||||
|
|
@ -1,415 +0,0 @@
|
|||
# Seguridad y Control de Acceso - Website Sale Aplicoop
|
||||
|
||||
## Descripción General
|
||||
|
||||
El addon implementa un sistema completo de control de acceso basado en:
|
||||
1. **ACL (Access Control List)** - Permisos de lectura, escritura, creación y eliminación
|
||||
2. **Record Rules** - Filtros automáticos de registros por compañía
|
||||
3. **Grupos de Usuarios** - Roles con permisos específicos
|
||||
|
||||
## Arquitectura de Seguridad
|
||||
|
||||
```
|
||||
Usuario
|
||||
↓
|
||||
Grupo (group_group_order_user / group_group_order_manager)
|
||||
↓
|
||||
ACL (ir.model.access.csv) → Permisos globales (CRUD)
|
||||
↓
|
||||
Record Rules (record_rules.csv) → Filtros por compañía
|
||||
↓
|
||||
Datos Accesibles
|
||||
```
|
||||
|
||||
## 1. ACL (Access Control List)
|
||||
|
||||
Ubicación: [security/ir.model.access.csv](../security/ir.model.access.csv)
|
||||
|
||||
### Estructura
|
||||
|
||||
```csv
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_group_order_user,group.order user,model_group_order,website_sale_aplicoop.group_group_order_user,1,0,0,0
|
||||
access_group_order_manager,group.order manager,model_group_order,website_sale_aplicoop.group_group_order_manager,1,1,1,1
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| `id` | Identificador único interno |
|
||||
| `name` | Descripción legible |
|
||||
| `model_id:id` | Referencia al modelo (model_group_order) |
|
||||
| `group_id:id` | Grupo de usuarios que recibe permisos |
|
||||
| `perm_read` | 1 = Puede leer, 0 = No puede leer |
|
||||
| `perm_write` | 1 = Puede editar, 0 = No puede editar |
|
||||
| `perm_create` | 1 = Puede crear, 0 = No puede crear |
|
||||
| `perm_unlink` | 1 = Puede eliminar, 0 = No puede eliminar |
|
||||
|
||||
### Roles y Permisos
|
||||
|
||||
#### Grupo: `group_group_order_user` (Usuarios Finales)
|
||||
|
||||
```csv
|
||||
access_group_order_user,group.order user,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_user,1,0,0,0
|
||||
```
|
||||
|
||||
**Permisos:**
|
||||
- ✅ Leer órdenes (`perm_read=1`)
|
||||
- ❌ Editar órdenes (`perm_write=0`)
|
||||
- ❌ Crear órdenes (`perm_create=0`)
|
||||
- ❌ Eliminar órdenes (`perm_unlink=0`)
|
||||
|
||||
**Casos de uso:**
|
||||
- Navegar órdenes disponibles
|
||||
- Ver detalles de pedido
|
||||
- Agregar productos al carrito
|
||||
|
||||
#### Grupo: `group_group_order_manager` (Administradores)
|
||||
|
||||
```csv
|
||||
access_group_order_manager,group.order manager,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_manager,1,1,1,1
|
||||
```
|
||||
|
||||
**Permisos:**
|
||||
- ✅ Leer órdenes (`perm_read=1`)
|
||||
- ✅ Editar órdenes (`perm_write=1`)
|
||||
- ✅ Crear órdenes (`perm_create=1`)
|
||||
- ✅ Eliminar órdenes (`perm_unlink=1`)
|
||||
|
||||
**Casos de uso:**
|
||||
- Crear y gestionar órdenes
|
||||
- Modificar configuración de órdenes
|
||||
- Cerrar o cancelar órdenes
|
||||
- Eliminar órdenes (si es necesario)
|
||||
|
||||
## 2. Record Rules (Reglas de Registro)
|
||||
|
||||
Ubicación: [security/record_rules.csv](../security/record_rules.csv)
|
||||
|
||||
### Propósito
|
||||
|
||||
Las record rules filtran automáticamente qué registros puede ver/editar un usuario según el valor del campo `company_id`.
|
||||
|
||||
```
|
||||
Usuario de Company A
|
||||
↓
|
||||
Record Rule: domain = [('company_id', 'in', company_ids)]
|
||||
↓
|
||||
Company_ids (del usuario) = [1] (Company A)
|
||||
↓
|
||||
Solo puede acceder a registros donde company_id = 1
|
||||
```
|
||||
|
||||
### Estructura
|
||||
|
||||
```csv
|
||||
id,name,model_id:id,groups:eval,domain_force,perm_read,perm_write,perm_create,perm_unlink
|
||||
rule_group_order_company_read,group.order: company access read,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_user,"[('company_id', 'in', company_ids)]",1,0,0,0
|
||||
|
||||
rule_group_order_company_write,group.order: company access write,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_manager,"[('company_id', 'in', company_ids)]",1,1,1,1
|
||||
|
||||
rule_group_order_manager_global,group.order: manager global access,model_group_order,
|
||||
"['admin']","[]",1,1,1,1
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| `id` | Identificador único |
|
||||
| `name` | Descripción |
|
||||
| `model_id:id` | Modelo que aplica la regla |
|
||||
| `groups:eval` | Grupo de usuarios (evaluado como Python) |
|
||||
| `domain_force` | Filtro dominio (sintaxis de búsqueda Odoo) |
|
||||
| `perm_read/write/create/unlink` | Permisos bajo esta regla |
|
||||
|
||||
### Reglas Implementadas
|
||||
|
||||
#### Rule 1: Usuarios Finales - Lectura por Compañía
|
||||
|
||||
```csv
|
||||
rule_group_order_company_read,group.order: company access read,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_user,"[('company_id', 'in', company_ids)]",1,0,0,0
|
||||
```
|
||||
|
||||
**Dominio:** `[('company_id', 'in', company_ids)]`
|
||||
- `company_ids` = lista de compañías del usuario
|
||||
- Filtra automáticamente por compañía
|
||||
|
||||
**Ejemplo:**
|
||||
```
|
||||
Usuario "Juan" pertenece a [Company A]
|
||||
Intenta ver órdenes
|
||||
Dominio aplicado: company_id IN (1)
|
||||
Resultado: Solo órdenes de Company A
|
||||
```
|
||||
|
||||
#### Rule 2: Administradores - Lectura/Escritura por Compañía
|
||||
|
||||
```csv
|
||||
rule_group_order_company_write,group.order: company access write,model_group_order,
|
||||
website_sale_aplicoop.group_group_order_manager,"[('company_id', 'in', company_ids)]",1,1,1,1
|
||||
```
|
||||
|
||||
**Dominio:** `[('company_id', 'in', company_ids)]`
|
||||
- Igual que usuarios finales
|
||||
- Pero con permisos de escritura/creación
|
||||
|
||||
**Ejemplo:**
|
||||
```
|
||||
Admin "Pedro" pertenece a [Company A, Company B]
|
||||
Crea nueva orden
|
||||
Dominio aplicado: company_id IN (1, 2)
|
||||
- Si crea en Company A: ✅ Permitido
|
||||
- Si crea en Company B: ✅ Permitido
|
||||
- Si intenta acceder a Company C: ❌ Denegado
|
||||
```
|
||||
|
||||
#### Rule 3: Superusuarios - Acceso Global
|
||||
|
||||
```csv
|
||||
rule_group_order_manager_global,group.order: manager global access,model_group_order,
|
||||
"['admin']","[]",1,1,1,1
|
||||
```
|
||||
|
||||
**Grupo:** `['admin']` (Superusuario de Odoo)
|
||||
**Dominio:** `[]` (vacío = sin restricción)
|
||||
|
||||
**Comportamiento:**
|
||||
- Acceso completo a todos los registros
|
||||
- Puede ver/editar órdenes de cualquier compañía
|
||||
- Sin filtrado por company_id
|
||||
|
||||
## Flujo de Control de Acceso
|
||||
|
||||
### Escenario 1: Usuario Final Lee Órdenes
|
||||
|
||||
```
|
||||
1. Usuario "Maria" (group_group_order_user, Company A)
|
||||
2. Abre menú "Órdenes de Grupo"
|
||||
3. Odoo verifica:
|
||||
a) ACL: ¿Tiene perm_read=1? → Sí (grupo_group_order_user)
|
||||
b) Record Rule: ¿Cumple domain [('company_id', 'in', [1])]?
|
||||
- Solo órdenes donde company_id = 1
|
||||
4. Resultado: Maria ve solo sus órdenes de Company A
|
||||
```
|
||||
|
||||
### Escenario 2: Usuario Intenta Editar Orden
|
||||
|
||||
```
|
||||
1. Usuario "Carlos" (group_group_order_user, Company A)
|
||||
2. Intenta editar orden de Company A
|
||||
3. Odoo verifica:
|
||||
a) ACL: ¿Tiene perm_write=1? → No (grupo_group_order_user tiene 0)
|
||||
b) Resultado: ❌ Acceso denegado - no puede editar
|
||||
```
|
||||
|
||||
### Escenario 3: Admin Edita Orden de Otra Compañía
|
||||
|
||||
```
|
||||
1. Admin "Rosa" (group_group_order_manager, Company A, B)
|
||||
2. Intenta editar orden de Company B
|
||||
3. Odoo verifica:
|
||||
a) ACL: ¿Tiene perm_write=1? → Sí (grupo_group_order_manager)
|
||||
b) Record Rule: ¿Cumple domain [('company_id', 'in', [1, 2])]?
|
||||
- company_id de orden = 2
|
||||
- 2 IN (1, 2) = Sí
|
||||
c) Resultado: ✅ Rosa puede editar la orden
|
||||
```
|
||||
|
||||
### Escenario 4: Superuser Accede a Todo
|
||||
|
||||
```
|
||||
1. Admin "System" (superuser)
|
||||
2. Intenta editar cualquier orden de cualquier compañía
|
||||
3. Odoo verifica:
|
||||
a) Es admin? → Sí
|
||||
b) Rule: rule_group_order_manager_global aplica (domain = [])
|
||||
c) Resultado: ✅ Acceso completo, sin restricciones
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Archivo: [tests/test_record_rules.py](../tests/test_record_rules.py)
|
||||
|
||||
### Casos de Prueba
|
||||
|
||||
1. **test_user_company1_can_read_own_orders**
|
||||
- Verifica que usuario de Company A ve sus órdenes
|
||||
|
||||
2. **test_user_company1_cannot_read_company2_orders**
|
||||
- Verifica que usuario NO ve órdenes de Company B
|
||||
|
||||
3. **test_admin_can_read_all_orders**
|
||||
- Verifica que admin con acceso a ambas compañías ve todo
|
||||
|
||||
4. **test_user_cannot_write_other_company_order**
|
||||
- Verifica que usuario no puede editar órdenes de otra compañía (AccessError)
|
||||
|
||||
5. **test_record_rule_filters_search**
|
||||
- Verifica que búsqueda automáticamente filtra por compañía
|
||||
|
||||
6. **test_cross_company_access_denied**
|
||||
- Verifica que acceso entre compañías es denegado
|
||||
|
||||
7. **test_admin_can_bypass_company_restriction**
|
||||
- Verifica que admin puede acceder a cualquier compañía
|
||||
|
||||
### Ejecución
|
||||
|
||||
```bash
|
||||
# Ejecutar solo tests de record rules
|
||||
odoo -d odoo -i website_sale_aplicoop -t website_sale_aplicoop.tests.test_record_rules --test-enable --stop-after-init
|
||||
|
||||
# Con pytest
|
||||
pytest tests/test_record_rules.py -v
|
||||
```
|
||||
|
||||
## Mejores Prácticas
|
||||
|
||||
### ✅ Hacer
|
||||
|
||||
1. **Confiar en ACL y Record Rules**
|
||||
```python
|
||||
# Odoo filtra automáticamente
|
||||
orders = env['group.order'].search([])
|
||||
# Solo devuelve órdenes de compañía del usuario
|
||||
```
|
||||
|
||||
2. **Usar grupos de seguridad correctamente**
|
||||
```xml
|
||||
<!-- En vista XML -->
|
||||
<group string="Administración" groups="website_sale_aplicoop.group_group_order_manager">
|
||||
<button name="action_open" type="object" string="Open Order"/>
|
||||
</group>
|
||||
```
|
||||
|
||||
3. **Asignar compañías a usuarios**
|
||||
```python
|
||||
user.write({
|
||||
'company_id': company_a.id,
|
||||
'company_ids': [(6, 0, [company_a.id, company_b.id])]
|
||||
})
|
||||
# El usuario ahora ve órdenes de A y B
|
||||
```
|
||||
|
||||
### ❌ No Hacer
|
||||
|
||||
1. **No usar sudo() sin razón válida**
|
||||
```python
|
||||
# ❌ Malo - bypasea todas las restricciones
|
||||
order = env['group.order'].sudo().search([])
|
||||
|
||||
# ✅ Bueno - respeta reglas
|
||||
order = env['group.order'].search([])
|
||||
```
|
||||
|
||||
2. **No modificar ACL directamente en SQL**
|
||||
- Siempre use el CSV de datos
|
||||
|
||||
3. **No olvidar agregar usuarios a grupos**
|
||||
- Los usuarios deben estar en `group_group_order_user` o `group_group_order_manager`
|
||||
|
||||
4. **No asumir permisos sin verificar**
|
||||
- Siempre test con usuarios reales
|
||||
|
||||
## Diagnóstico de Problemas
|
||||
|
||||
### Problema: Usuario no ve ninguna orden
|
||||
|
||||
**Causas posibles:**
|
||||
1. No está en grupo `group_group_order_user`
|
||||
2. No está asignado a la compañía correcta
|
||||
3. No existen órdenes en su compañía
|
||||
|
||||
**Solución:**
|
||||
```python
|
||||
# Verificar grupo
|
||||
user.groups_id # Debe incluir group_group_order_user
|
||||
|
||||
# Verificar compañía
|
||||
user.company_ids # Debe incluir la compañía del usuario
|
||||
|
||||
# Verificar órdenes existentes
|
||||
env['group.order'].search([('company_id', '=', company_id)])
|
||||
```
|
||||
|
||||
### Problema: Usuario no puede crear órdenes
|
||||
|
||||
**Causas posibles:**
|
||||
1. Está en `group_group_order_user` (lectura solo)
|
||||
2. No tiene permiso `perm_create`
|
||||
|
||||
**Solución:**
|
||||
```python
|
||||
# Mover a grupo de manager
|
||||
user.groups_id = [(3, group_order_user.id), (4, group_order_manager.id)]
|
||||
```
|
||||
|
||||
### Problema: Error AccessError al leer orden
|
||||
|
||||
**Causa probable:**
|
||||
- La orden está en una compañía diferente
|
||||
- Record rule está denegando acceso
|
||||
|
||||
**Solución:**
|
||||
```python
|
||||
# Verificar compañía de orden
|
||||
order.company_id # Comparar con user.company_ids
|
||||
```
|
||||
|
||||
## Historial de Cambios
|
||||
|
||||
### v18.0.1.0.2
|
||||
|
||||
- ✨ Record rules agregadas para multicompañía
|
||||
- 🔒 ACL actualizado con documentación
|
||||
- 🧪 7 test cases para control de acceso
|
||||
- 📚 Documentación completa de seguridad
|
||||
|
||||
## Referencias
|
||||
|
||||
- [Documentación Odoo - ACL](https://www.odoo.com/documentation/18.0/application/general/settings/users_and_companies/access_rights.html)
|
||||
- [Documentación Odoo - Record Rules](https://www.odoo.com/documentation/18.0/application/general/settings/users_and_companies/record_rules.html)
|
||||
- [OWASP - Access Control](https://owasp.org/www-community/attacks/Role-Based_Access_Control)
|
||||
|
||||
## Cambios recientes y acciones realizadas (19-12-2025)
|
||||
|
||||
Se documentan aquí las modificaciones y acciones realizadas durante la sesión de depuración y ejecución de tests:
|
||||
|
||||
- **Regla interna `rule_group_order_user_company_read_internal`**: se actualizó el dominio de
|
||||
`('company_id', '=', user.company_id.id)` a `('company_id', 'in', user.company_ids.ids)` para
|
||||
soportar usuarios multi-compañía (por ejemplo, administradores creados en tests con
|
||||
`company_ids` que contienen varias compañías). Esto permite que usuarios con varias
|
||||
compañías vean las `group.order` pertenecientes a cualquiera de sus `company_ids`.
|
||||
|
||||
- **Escape de entidades XML**: se corrigieron errores de parseo XML (p. ej. `xmlParseEntityRef: no name`)
|
||||
reemplazando `&` por `&` en los dominios de las reglas cuando era necesario.
|
||||
|
||||
- **ACL temporal para triage de tests**: durante la depuración se añadió/ajustó una entrada mínima
|
||||
en `security/ir.model.access.csv` (`access_group_order_base`) para permitir operaciones de prueba
|
||||
(lectura/creación/edición según necesitaba el entorno de tests). Esta entrada se introdujo solo
|
||||
para facilitar la ejecución de tests y validaciones locales; considerar revisarla antes de
|
||||
publicar si se requiere endurecer los permisos.
|
||||
|
||||
- **Ejecuciones de tests**:
|
||||
- Módulo `website_sale_aplicoop`: ejecución local completada — `63 tests`, **0 fallos** para este módulo.
|
||||
- Ejecución completa del conjunto de tests de Odoo: `3583 tests` ejecutados en total;
|
||||
**34 fallos** y **65 errores** (log completo disponible en `/tmp/test_output_full_run.log`).
|
||||
|
||||
- **Recomendaciones**:
|
||||
- Si se desea completar la corrección de la suite completa, empezar triando las primeras
|
||||
fallas del log (`grep -n "FAILED\|Traceback" /tmp/test_output_full_run.log | head -n 50`).
|
||||
- Revisar la permanencia de `access_group_order_base` en `ir.model.access.csv` y ajustarla
|
||||
para que los tests no hayan forzado permisos en producción.
|
||||
- Mantener la regla que limita el acceso del portal a `product.supplierinfo` para no exponer
|
||||
`res.partner` al portal; cualquier información adicional del proveedor debe inyectarse
|
||||
desde los controladores de manera explícita y mínima.
|
||||
|
||||
Esta sección se añadió para dejar constancia de los cambios que afectan a la política de acceso
|
||||
y a la ejecución de tests; actualizarla cuando se hagan revert/ajustes adicionales.
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
## Creating a Group Order
|
||||
|
||||
1. Go to **Website Sale > Group Orders > Create**
|
||||
2. Fill in the order details:
|
||||
- **Order Name**: Descriptive name (e.g., "Weekly Vegetable Order")
|
||||
- **Start Date**: When the order opens for shopping (leave empty for orders that are always open)
|
||||
- **End Date**: When the order closes (optional; leave empty for permanent orders)
|
||||
- **Cutoff Day**: Day of week when purchases stop (0=Monday, 6=Sunday) - mandatory
|
||||
- **Recurrence Period**: How often the order repeats (once, weekly, biweekly, monthly)
|
||||
- **Suppliers**: Link to product suppliers (informational)
|
||||
- **Products**: Products available in this order (REQUIRED - add via the "Products" tab)
|
||||
- **Categories**: Product categories available in this order (informational)
|
||||
- **Groups**: Which user groups can participate (REQUIRED - users from these groups can shop)
|
||||
|
||||
3. **Assign Products**: Click on the "Products" tab and add all products that should be available for this order
|
||||
4. Click **Save** and transition the order to **Open** state to allow shopping
|
||||
|
||||
### Note on Start Date
|
||||
|
||||
- If **Start Date is empty**, the order is considered always open (ignoring date range checks)
|
||||
- If **Start Date is set**, the order is only active starting from that date
|
||||
- Use empty Start Date for orders that should always be available during their time window
|
||||
|
||||
## Shopping for a Group Order
|
||||
|
||||
1. Navigate to the website storefront at `/eskaera` (group orders page)
|
||||
2. View active group orders for your participating groups
|
||||
3. Select an order to view available products
|
||||
4. Add products to your cart (separate cart per order)
|
||||
5. At checkout, confirm your order to convert items to a sales order draft
|
||||
6. Proceed through standard Odoo checkout workflow
|
||||
|
||||
## Configuration
|
||||
|
||||
### Managing Groups
|
||||
|
||||
1. Go to **Contacts > Groups** (res.partner with is_group=True)
|
||||
2. Create groups for user communities
|
||||
3. Add partners/users to groups via the **Members** tab
|
||||
|
||||
### Managing Products
|
||||
|
||||
1. Products are linked to group orders via the **Group Orders** field in product settings
|
||||
2. Set pricing and availability per group order
|
||||
3. Assign products to categories used in group orders
|
||||
|
||||
### Date & Time Validation
|
||||
|
||||
- `start_date` must be ≤ `end_date` (when both filled)
|
||||
- Empty end_date = permanent order
|
||||
45
website_sale_aplicoop/readme/USAGE.rst
Normal file
45
website_sale_aplicoop/readme/USAGE.rst
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
**Administrator Workflow:**
|
||||
|
||||
Creating a Group Order
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#. Go to Website Sale → Group Orders (or Coops → Órdenes de Grupo)
|
||||
#. Click Create
|
||||
#. Fill in:
|
||||
|
||||
* **Name**: e.g., "Weekly Cooperative Order #5"
|
||||
* **Group**: Select the cooperative group
|
||||
* **Collection Date**: When orders will be collected
|
||||
* **Cutoff Date**: Last moment to add items
|
||||
* **Pickup Date**: When group members collect their orders
|
||||
|
||||
#. Add members in the Members tab
|
||||
#. Set member status (active/inactive)
|
||||
#. Save and transition to appropriate state
|
||||
|
||||
Managing Pickup Dates
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#. Go to Settings → Website → Shop Settings
|
||||
#. Configure Pickup Days (define available days)
|
||||
#. Set Group Settings (default locations, delivery partners)
|
||||
|
||||
**Customer Workflow:**
|
||||
|
||||
For Group Members on Website
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#. **Browse Products**: See products with eco-ribbons, pricing, margin info
|
||||
#. **Add to Cart**: Select items (cart is separate per group order)
|
||||
#. **Review Cart**: Check order summary before cutoff date
|
||||
#. **Submit Order**: Confirm before cutoff time
|
||||
#. **Receive Notification**: Get email with pickup details
|
||||
#. **Pickup**: Collect order on designated pickup date
|
||||
|
||||
Order States
|
||||
~~~~~~~~~~~
|
||||
|
||||
* **Draft**: Order being prepared
|
||||
* **Confirmed**: Order open for shopping
|
||||
* **Collected**: Orders received from supplier
|
||||
* **Completed**: All members have picked up their orders
|
||||
Loading…
Add table
Add a link
Reference in a new issue