|
| 1 | +# OpenSPP Development Guidelines |
| 2 | + |
| 3 | +Social protection platform built on Odoo 19. ~90 modules (`spp_*`). |
| 4 | + |
| 5 | +## Principles (MUST read before changes) |
| 6 | + |
| 7 | +All principles are in `docs/principles/`: |
| 8 | + |
| 9 | +- [naming-conventions.md](docs/principles/naming-conventions.md) - Module, model, field, security group naming |
| 10 | +- [access-rights.md](docs/principles/access-rights.md) - Three-tier security architecture |
| 11 | +- [module-architecture.md](docs/principles/module-architecture.md) - Module organization and extension patterns |
| 12 | +- [module-visibility.md](docs/principles/module-visibility.md) - application, auto_install, and category settings |
| 13 | +- [api-design.md](docs/principles/api-design.md) - External identifiers, never expose DB IDs |
| 14 | +- [performance-scalability.md](docs/principles/performance-scalability.md) - Batch processing with queue_job |
| 15 | +- [testing.md](docs/principles/testing.md) - Coverage targets (85%+ for core) |
| 16 | +- [approval-workflows.md](docs/principles/approval-workflows.md) - State machines and mixins |
| 17 | +- [error-handling.md](docs/principles/error-handling.md) - Exceptions, logging, no PII in logs |
| 18 | +- [audit-compliance.md](docs/principles/audit-compliance.md) - Audit trails, data integrity |
| 19 | +- [ui-design.md](docs/principles/ui-design.md) - Form layouts, tabs, multi-column patterns |
| 20 | +- [pretty-urls.md](docs/principles/pretty-urls.md) - User-friendly URL paths for actions |
| 21 | +- [odoo19-compatibility.md](docs/principles/odoo19-compatibility.md) - Odoo 19 gotchas (constraints, views, Command API) |
| 22 | +- [consent-data-sharing.md](docs/principles/consent-data-sharing.md) - Consent management, notice boundaries, data |
| 23 | + sharing |
| 24 | +- [module-descriptions.md](docs/principles/module-descriptions.md) - Writing readme/DESCRIPTION.md files for modules |
| 25 | + |
| 26 | +## Architecture |
| 27 | + |
| 28 | +- [ADRs](docs/architecture/decisions/) - Architecture Decision Records |
| 29 | + |
| 30 | +### Layered Architecture (Dependencies flow downward) |
| 31 | + |
| 32 | +``` |
| 33 | +Layer 3: COUNTRY/DOMAIN EXTENSIONS (spp_4ps_*, spp_farmer_*) |
| 34 | + ↓ |
| 35 | +Layer 2: CAPABILITIES (spp_programs, spp_entitlement_*, spp_change_request_v2) |
| 36 | + ↓ |
| 37 | +Layer 1: FOUNDATION (spp_registry, spp_security, spp_area) |
| 38 | +``` |
| 39 | + |
| 40 | +### Extension Patterns |
| 41 | + |
| 42 | +- **Inherit and Extend**: `_inherit = "res.partner"` + add fields |
| 43 | +- **Hook Methods**: `_pre_enrollment_hook()`, `_post_enrollment_hook()` |
| 44 | +- **Never expose DB IDs** in APIs - use `spp.reg.id` external identifiers |
| 45 | + |
| 46 | +## Quick Checklist |
| 47 | + |
| 48 | +When auditing or modifying a module: |
| 49 | + |
| 50 | +- [ ] Naming follows `spp_*` / `spp.*` conventions |
| 51 | +- [ ] `application` and `auto_install` set correctly per [module-visibility](docs/principles/module-visibility.md) |
| 52 | +- [ ] `ir.model.access.csv` exists and complete |
| 53 | +- [ ] No `print()` - use `_logger` |
| 54 | +- [ ] No bare `except:` clauses |
| 55 | +- [ ] No `cr.commit()` in loops - use `queue_job` |
| 56 | +- [ ] No PII in log messages |
| 57 | +- [ ] Tests exist for core functionality |
| 58 | + |
| 59 | +## Bug Fixing Approach |
| 60 | + |
| 61 | +When fixing issues: first write a failing test that reproduces the bug, then fix it. Fix problems at the source (e.g., |
| 62 | +correct XML/ACL definitions) rather than working around them in tests or code. If a root fix isn't possible, document |
| 63 | +why and propose alternatives. |
| 64 | + |
| 65 | +## Known Pitfalls (from recurring issues) |
| 66 | + |
| 67 | +### Access Rights (Most Common Error) |
| 68 | + |
| 69 | +- **Always check `ir.model.access.csv`** before declaring a module complete |
| 70 | +- When tests fail with `AccessError`, fix the ACL, don't bypass with `sudo()` |
| 71 | +- Tests must run with appropriate user context (officer, manager), not just admin |
| 72 | +- After security changes, **always re-run affected tests** - they often break |
| 73 | +- Related models need ACLs too (e.g., if `spp.program` has ACL, `spp.program.membership` likely needs one) |
| 74 | + |
| 75 | +### Demo Data |
| 76 | + |
| 77 | +- Demo data must create **complete, consistent records** - check all required relations |
| 78 | +- Approval states must match approval records (e.g., `approval_state='pending'` requires pending review records) |
| 79 | +- Use `with_context(tracking_disable=True)` when creating demo data to avoid sending notifications |
| 80 | +- Test demo data generation with dedicated tests that verify all expected records exist |
| 81 | + |
| 82 | +### Views and XML |
| 83 | + |
| 84 | +- XPath must use `hasclass('classname')` not `@class='classname'` (Odoo 19) |
| 85 | +- Always use `Command.create()` not `(0, 0, {...})` tuples for relational writes |
| 86 | +- When updating views, verify the correct view is being displayed (not cached old version) |
| 87 | +- Search views: check `<filter>` and `<group>` syntax against Odoo 19 docs |
| 88 | + |
| 89 | +### Tests |
| 90 | + |
| 91 | +- **NEVER remove or weaken existing tests** without explicit approval |
| 92 | +- After subagent implementations, verify: "Can you confirm no tests were removed or weakened?" |
| 93 | +- When fixing security, tests often need user context updates - fix tests, don't skip them |
| 94 | +- If tests cannot run due to install issues, fix the install, don't mark tests as skipped |
| 95 | + |
| 96 | +### State Machines and Approvals |
| 97 | + |
| 98 | +- `spp.approval.mixin` records must have consistent state: |
| 99 | + - `approval_state='pending'` → must have pending `spp.approval.review` records |
| 100 | + - `approval_state='approved'` → all reviews must be approved |
| 101 | +- When creating test data for approval flows, create the full approval chain |
| 102 | + |
| 103 | +### Self-Improvement |
| 104 | + |
| 105 | +- After every correction or mistake, propose an update to this Known Pitfalls section |
| 106 | +- After every PR, consider whether patterns or pitfalls were discovered that should be documented here |
| 107 | + |
| 108 | +## Running OpenSPP Locally |
| 109 | + |
| 110 | +**Quick Start** (Docker Compose with UI): |
| 111 | + |
| 112 | +```bash |
| 113 | +# Launch Odoo UI for development |
| 114 | +docker compose --profile ui up -d |
| 115 | + |
| 116 | +# Access at: http://localhost:8069 (admin/admin) |
| 117 | + |
| 118 | +# Stop when done |
| 119 | +docker compose --profile ui down |
| 120 | +``` |
| 121 | + |
| 122 | +**With specific demo modules:** |
| 123 | + |
| 124 | +```bash |
| 125 | +# MIS Demo (full demo) |
| 126 | +ODOO_INIT_MODULES=spp_mis_demo_v2 docker compose --profile ui up -d |
| 127 | + |
| 128 | +# DRIMS Demo |
| 129 | +ODOO_INIT_MODULES=spp_drims_sl_demo docker compose --profile ui up -d |
| 130 | + |
| 131 | +# Base modules only |
| 132 | +ODOO_INIT_MODULES=spp_base docker compose --profile ui up -d |
| 133 | +``` |
| 134 | + |
| 135 | +**Clean restart:** |
| 136 | + |
| 137 | +```bash |
| 138 | +# Stop and remove volumes (fresh database) |
| 139 | +docker compose --profile ui down -v |
| 140 | +``` |
| 141 | + |
| 142 | +## Running Tests |
| 143 | + |
| 144 | +**Recommended** (using the `spp` CLI, Docker-based, isolated): |
| 145 | + |
| 146 | +```bash |
| 147 | +./spp test <module_name> |
| 148 | +# or short form: |
| 149 | +./spp t <module_name> |
| 150 | +``` |
| 151 | + |
| 152 | +This creates an isolated test environment and cleans up automatically. Supports parallel runs across multiple clones. |
| 153 | + |
| 154 | +**Alternative** (direct script): |
| 155 | + |
| 156 | +```bash |
| 157 | +./scripts/test_single_module.sh <module_name> |
| 158 | +``` |
| 159 | + |
| 160 | +## Linting and Compliance |
| 161 | + |
| 162 | +**Using `spp` CLI** (preferred): |
| 163 | + |
| 164 | +```bash |
| 165 | +./spp lint # Lint changed files |
| 166 | +``` |
| 167 | + |
| 168 | +**Pre-commit hooks** (run automatically, or manually): |
| 169 | + |
| 170 | +```bash |
| 171 | +pre-commit run ruff --files <changed_files> |
| 172 | +pre-commit run ruff-format --files <changed_files> |
| 173 | +pre-commit run prettier --files <changed_files> |
| 174 | +``` |
| 175 | + |
| 176 | +**Security/Access Rights Audit**: |
| 177 | + |
| 178 | +```bash |
| 179 | +./.Codex/scripts/audit-security.sh # Audit all modules |
| 180 | +./.Codex/scripts/audit-security.sh spp_api # Audit single module |
| 181 | +./.Codex/scripts/fix-security.sh spp_api # Auto-fix security issues (review changes!) |
| 182 | +./.Codex/scripts/fix-security.sh --mechanical-only spp_api # Only mechanical fixes (no AI) |
| 183 | +``` |
| 184 | + |
| 185 | +**Module Audit** (requires cursor-agent): |
| 186 | + |
| 187 | +```bash |
| 188 | +./.Codex/scripts/audit-modules.sh # Check module structure and compliance |
| 189 | +./.Codex/scripts/audit-modules.sh spp_api # Audit single module |
| 190 | +./.Codex/scripts/audit-modules.sh --fix # Auto-fix simple issues |
| 191 | +``` |
| 192 | + |
| 193 | +**Lint Fixes**: |
| 194 | + |
| 195 | +```bash |
| 196 | +./.Codex/scripts/fix-lint.sh spp_api # Run linters + AI-assisted fixes |
| 197 | +./.Codex/scripts/fix-lint.sh --lint-only spp_api # Run linters only, no AI |
| 198 | +``` |
| 199 | + |
| 200 | +When linters suggest fixes, verify the suggestion is correct before applying. Some automated fixes may: |
| 201 | + |
| 202 | +- Use wrong syntax for Odoo 19 |
| 203 | +- Remove intentional patterns |
| 204 | +- Break existing functionality |
| 205 | + |
| 206 | +## Verification Workflow |
| 207 | + |
| 208 | +Before marking any task complete: |
| 209 | + |
| 210 | +1. **Run tests**: `./spp t <module>` |
| 211 | +2. **Run linters**: `pre-commit run --files <changed_files>` |
| 212 | +3. **Run security audit** (if security changed): `./.Codex/scripts/audit-security.sh <module>` |
| 213 | +4. **Verify no tests were removed**: `/verify-tests` or compare test count before/after |
| 214 | +5. **Check demo data** (if modified): Verify records are created correctly |
| 215 | +6. **Test in UI** (for UX changes): Confirm the correct view is displayed |
| 216 | + |
| 217 | +## Custom Commands |
| 218 | + |
| 219 | +Available slash commands in `.Codex/commands/`: |
| 220 | + |
| 221 | +| Command | Purpose | |
| 222 | +| ---------------- | -------------------------------------------------------------- | |
| 223 | +| `/commit` | Create conventional commit (feat/fix/chore/docs/refactor/test) | |
| 224 | +| `/implement` | Full TDD workflow with subagents and expert review | |
| 225 | +| `/expert-review` | Parallel code review from multiple perspectives | |
| 226 | +| `/pr` | Create GitHub PR with OpenProject linking | |
| 227 | +| `/op-task` | Implement OpenProject task end-to-end | |
| 228 | +| `/verify-tests` | Check test integrity after changes (catch removed tests) | |
| 229 | +| `/analyze` | Deep analysis mode - understand before implementing | |
| 230 | + |
| 231 | +### When to Use Each |
| 232 | + |
| 233 | +- **Starting work**: Enter Plan mode (shift+tab twice) for brainstorming |
| 234 | +- **Implementing**: `/implement` for full TDD workflow |
| 235 | +- **After subagent work**: `/verify-tests` to catch removed tests |
| 236 | +- **Debugging**: `/analyze` for structured error/code analysis |
| 237 | +- **Before commit**: `/commit` for conventional commit format |
| 238 | +- **Creating PR**: `/pr` with OpenProject linking |
| 239 | + |
| 240 | +## Subagents |
| 241 | + |
| 242 | +Available agents in `.Codex/agents/`: |
| 243 | + |
| 244 | +| Agent | Model | Use For | |
| 245 | +| ------------------ | ------ | -------------------------------------- | |
| 246 | +| `@odoo-developer` | sonnet | Core implementation work | |
| 247 | +| `@code-reviewer` | opus | Security, naming, Odoo 19 compliance | |
| 248 | +| `@ux-expert` | opus | UI/UX patterns and form layouts | |
| 249 | +| `@code-simplifier` | sonnet | Reduce complexity, improve readability | |
| 250 | +| `@verify-module` | sonnet | Test module installation and tests | |
0 commit comments