Skip to content

Commit c933b42

Browse files
committed
Review GIS operator buffer change
1 parent 85db617 commit c933b42

6 files changed

Lines changed: 422 additions & 1 deletion

File tree

.agents/skills/openspp-ui/SKILL.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
name: openspp-ui
3+
description:
4+
OpenSPP UI design patterns for Odoo 19 views. Use when creating or modifying forms, lists, kanban, dashboards, or
5+
search views in spp_* modules.
6+
---
7+
8+
# OpenSPP UI Design
9+
10+
Enforce consistent UI for OpenSPP's social protection platform on Odoo 19.
11+
12+
## Design Personality
13+
14+
OpenSPP serves **government agencies and NGOs**. The UI must convey:
15+
16+
- **Trust** - Government-grade reliability, no flashy effects
17+
- **Clarity** - Dense but organized, scannable information
18+
- **Accessibility** - Works for field officers on varying devices
19+
- **Efficiency** - Power users need speed, not hand-holding
20+
21+
## Before Creating a View
22+
23+
**Ask: What's the user's task?**
24+
25+
| Task Type | Layout | Key Features |
26+
| --------------- | ---------------------- | ----------------------------------- |
27+
| Data Entry | Multi-column, editable | Inline lists, minimal readonly |
28+
| Review/Approval | Status prominent | Ribbons, history tab, readonly feel |
29+
| Dashboard | KPI cards | Clickable stats, visual counts |
30+
| Configuration | Grouped settings | Heavy help text, toggles |
31+
32+
## State & Color Vocabulary
33+
34+
Use consistently across all modules:
35+
36+
| State | List Decoration | Badge Class | Icon |
37+
| --------- | -------------------- | ------------------- | ------------ |
38+
| Draft | `decoration-muted` | `text-bg-secondary` | `fa-pencil` |
39+
| Pending | `decoration-warning` | `text-bg-warning` | `fa-clock-o` |
40+
| Approved | `decoration-success` | `text-bg-success` | `fa-check` |
41+
| Rejected | `decoration-danger` | `text-bg-danger` | `fa-times` |
42+
| Cancelled | `decoration-muted` | `text-bg-secondary` | `fa-ban` |
43+
44+
## Standard Form Structure
45+
46+
```xml
47+
<form>
48+
<header>
49+
<button name="action_submit" string="Submit" type="object"
50+
class="btn-primary" invisible="state != 'draft'"/>
51+
<field name="state" widget="statusbar"
52+
statusbar_visible="draft,pending,approved"/>
53+
</header>
54+
<sheet>
55+
<widget name="web_ribbon" title="Approved"
56+
invisible="state != 'approved'" bg_color="text-bg-success"/>
57+
<div class="oe_button_box" name="button_box"/>
58+
<div class="oe_title">
59+
<h1><field name="name" placeholder="Name"/></h1>
60+
</div>
61+
<group col="2">
62+
<group name="left_section">...</group>
63+
<group name="right_section">...</group>
64+
</group>
65+
<notebook>
66+
<page name="details" string="Details">...</page>
67+
</notebook>
68+
</sheet>
69+
<chatter/>
70+
</form>
71+
```
72+
73+
**Key rules:**
74+
75+
- Header: only buttons + statusbar
76+
- Sheet: ribbon → button_box → title → groups → notebook
77+
- Always name your groups for extensibility
78+
79+
## Anti-Patterns
80+
81+
### Odoo 19 Gotchas
82+
83+
```xml
84+
<!-- WRONG --> <xpath expr="//div[@class='oe_title']" ...>
85+
<!-- RIGHT --> <xpath expr="//div[hasclass('oe_title')]" ...>
86+
87+
<!-- WRONG --> <group string="Group By"> <!-- in search view -->
88+
<!-- RIGHT --> <group>
89+
```
90+
91+
```python
92+
# WRONG: Tuple syntax
93+
partner.write({'child_ids': [(0, 0, {'name': 'New'})]})
94+
95+
# RIGHT: Command API
96+
from odoo import Command
97+
partner.write({'child_ids': [Command.create({'name': 'New'})]})
98+
```
99+
100+
### OpenSPP Mistakes
101+
102+
- Editable fields in `<header>` → use tabs
103+
- Positional XPath `//page[1]` → use named elements
104+
- Forms without named groups → breaks inheritance
105+
106+
## Detailed Patterns
107+
108+
For comprehensive guidelines, see [UI Design Principles](docs/principles/ui-design.md):
109+
110+
- Multi-column layouts
111+
- Extension points and XPath targets
112+
- Widget selection guide
113+
- Dashboard KPI patterns
114+
- Search and list view patterns

AGENTS.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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 |

spp_gis/operators.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,14 @@ def domain_query(self, operator, value):
509509
# Complex types use ST_GeomFromGeoJSON directly
510510
geom = self.create_from_geojson(geojson_val, self.field.srid)
511511
postgis_fn = self.POSTGIS_SPATIAL_RELATION[operation]
512-
return SQL("%s(%s, %s)", SQL(postgis_fn), geom, SQL(self.qualified_field_name))
512+
right = SQL(self.qualified_field_name)
513+
if distance:
514+
left = geom
515+
if self.field.srid == 4326:
516+
left = SQL("ST_Transform(%s, %s)", geom, 3857)
517+
right = SQL("ST_Transform(%s, %s)", right, 3857)
518+
return SQL("%s(ST_Buffer(%s, %s), %s)", SQL(postgis_fn), left, distance, right)
519+
return SQL("%s(%s, %s)", SQL(postgis_fn), geom, right)
513520

514521
coordinates = geojson_val["coordinates"]
515522
return SQL(self.get_postgis_query(operation, coordinates, distance=distance, layer_type=layer_type))

0 commit comments

Comments
 (0)