erplibre/contracts/note-mapping.md
Mathieu Benoit 394be35324 [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.

--- FR ---

Définit le contrat d'intégration entre erplibre_mobile et la plateforme
ERPLibre : spécifications des appels JSON-RPC 2.0, correspondance des champs
Note→project.task, format GeoMultiPoint pour les entrées de géolocalisation,
stratégie de résolution des conflits, flux de réauthentification et matrice
de compatibilité des versions. Établit la source de vérité commune avant que
l'implémentation ne commence.

Assisted-by: Claude Sonnet 4.6
2026-08-07 01:05:37 -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.