erplibre/contracts/note-mapping.md
Mathieu Benoit b689c4ddf1 [ADD] contracts: add Odoo sync API contract and note mapping
Define the integration contract between erplibre_mobile and ERPLibre
platform: JSON-RPC 2.0 call specs, Note→project.task field mapping,
GeoMultiPoint format for geolocation entries, conflict resolution
strategy, re-auth flow, and version compatibility matrix.
Establishes the shared source of truth before implementation begins.

Generated by Claude Code 2.1.87 model claude-sonnet-4-6

Co-Authored-By: Mathieu Benoit <mathben@technolibre.ca>
2026-05-19 15:17:45 -04:00

3.6 KiB

Note mobile → project.task mapping

Field mapping

Note mobile field project.task field Type Notes
(no mobile id sent) id Integer (server) Odoo ID stored in mobile SQLite as odoo_id after first push
title name Char Required
done state Selection 'done' ↔ done=true ; '01_in_progress' ↔ done=false
archived active Boolean false = archived
pinned priority Selection '1' = pinned, '0' = normal
tags tag_ids Many2many Matched by tag name; created if missing
entry text description Html Each entry → <p>text content</p>
entry date date_deadline Datetime First date entry only
entry audio attachment_ids ir.attachment + <p>🎙️ Enregistrement audio — ISO_DATE</p> in description
entry photo attachment_ids ir.attachment + <p>📷 Photo — ISO_DATE</p> in description
entry video attachment_ids ir.attachment + <p>🎥 Vidéo — ISO_DATE</p> in description
entry geolocation geo_task_point GeoMultiPoint All lat/lon → MultiPoint GeoJSON ; <p>📍 text — lat,lon — ISO_DATE</p> in description

Description HTML structure

Each note's description field is built by concatenating all entries in order:

<!-- entry type=text -->
<p>Content of the text entry.</p>

<!-- entry type=text (another one) -->
<p>Another paragraph of notes.</p>

<!-- entry type=date -->
<p>📅 Date : 2026-03-29T14:30:00</p>

<!-- entry type=geolocation -->
<p>📍 Géolocalisation : 45.5017, -73.5673 — Bureau principal — 2026-03-29T14:35:00</p>

<!-- entry type=audio -->
<p>🎙️ Enregistrement audio — 2026-03-29T14:40:00</p>

<!-- entry type=photo -->
<p>📷 Photo — 2026-03-29T14:45:00</p>

<!-- entry type=video -->
<p>🎥 Vidéo — 2026-03-29T14:50:00</p>

GeoMultiPoint format (geo_task_point)

All geolocation entries of a note are stored as a single GeoJSON MultiPoint:

{
  "type": "MultiPoint",
  "coordinates": [
    [-73.5673, 45.5017],
    [-73.5789, 45.4972]
  ]
}

Order matches the order of geolocation entries. Coordinates are [longitude, latitude] per GeoJSON spec. Timestamps and text descriptions are preserved in the HTML description <p> lines.

Sync ID strategy

  • Mobile does not send its internal UUID to Odoo.
  • On first push: project.task.create() returns the Odoo id (integer).
  • Mobile stores it as odoo_id in its local SQLite notes table.
  • Subsequent pushes use project.task.write([[odoo_id], {...}]).
  • Multiple mobile clients: each independently stores the same odoo_id — fully supported.

Conflict resolution

Condition Resolution
write_date (Odoo) > last_synced_at (mobile) Odoo wins — pull overwrites mobile
Mobile modified since last_synced_at, Odoo not changed Mobile wins — push
Both modified since last sync Odoo wins (last-write-wins, v1)

Tag resolution

  1. Mobile sends tag names as strings.
  2. SyncService calls project.tags search_read to find existing tags by name.
  3. Missing tags: project.tags.create() before task create/write.
  4. tag_ids in task payload uses integer IDs from step 2-3.