← Retour aux travaux
2023 · Plateforme de bourses · Odoo 16 + Django

Avataq

Une plateforme hybride Odoo 16 + Django pour la gestion de bourses d'études autochtones, des inscriptions, de la facturation et de la documentation. Deux stacks sur une seule base Postgres, avec les documents dans S3 derrière des URL de téléchargement S3 présignées de courte durée.

Rôle
Implémentation full-stack · architecture
Durée
Depuis 2023, en cours
Équipe
1 ingénieur Hazenfield
VISUEL DE PROJET · PLACEHOLDER
FIG. 01
Contexte

Avataq est une plateforme hybride Odoo 16 + Django pour la gestion de bourses d'études autochtones, des inscriptions et de la documentation. Odoo porte la logique métier — étudiants, écoles, sessions, années scolaires, dossiers d'inscription, feuilles de calcul pour la facturation, réconciliation. Une application Django séparée sert le côté explorateur de documents : accès en lecture seule aux pièces téléchargées avec des URL S3 présignées de soixante secondes, verrouillées par rôle.

Nous l'avons bâtie de bout en bout. Deux applications qui partagent une seule base PostgreSQL et communiquent en REST. Les documents vivent dans AWS S3 sous des clés déterministes (`{status_no}/{scholar_year}/{slug}.{ext}`) — la clé encode le contexte. Les identifiants vivent dans `ir.config_parameter`, pas dans le code. Un mixin abstrait `AvataqDocumentS3Sync` donne à n'importe quel modèle Odoo la capacité d'upload gratuitement ; un endpoint `index_document` côté Django upsert l'index depuis un POST verrouillé par `X-API-Key`.

Sortir l'explorateur de documents d'Odoo n'était pas un accident. Odoo est excellent pour modéliser le métier — étudiants, sessions, feuilles de calcul, réconciliation. Il est moins bon comme visualiseur rapide et ciblé pour des milliers d'enregistrements binaires avec accès par rôle. Alors l'explorateur vit dans Django, lit la même base, demande à S3 des URL présignées de courte durée, et ne garde jamais les documents en mémoire.

Nous sommes sur cette plateforme depuis début 2023. La cadence est régulière — de nouveaux flux à mesure que les workflows de bourses s'étendent, des affinements de flux documentaires à mesure que la cohorte grandit, des sauvegardes S3 nocturnes.

Périmètre

Ce que nous avons bâti.

avataq01

Addon Odoo principal — étudiants, inscriptions, sessions, écoles, feuilles de calcul, réconciliation, modèles de mail, upload de documents S3, sync Django.

avataq_website02

Portail public et templates de site.

avataq_signup03

Personnalisation auth et inscription.

s3_backup04

Sauvegardes planifiées de la base vers S3.

Explorateur de documents Django05

Visualiseur en lecture seule sur la même base Postgres. Verrouillé par permission `documents.can_view_documents`. Génère des URL S3 présignées à la demande.

Mixin AvataqDocumentS3Sync06

Mixin Odoo abstrait — héritez et obtenez upload S3 + notification d'index Django gratuitement. Utilisé sur trois modèles uploaders.

Sync REST inter-stacks07

Odoo POST les métadonnées de document vers Django `/api/index/` après chaque upload réussi, verrouillé par `X-API-Key`. Django upsert la ligne d'index ; n'écrit jamais en retour.

Scaffold de déploiement08

docker-compose pour db / odoo / django ; env conda partagé `avataq_env` sur les deux stacks ; un seul `deploy.sh` pour les rollouts en production.

Approche

À quoi ressemble le travail, en 4 pièces.

01

Deux stacks, une seule base

Sortir l'explorateur de documents d'Odoo n'était pas un accident. Odoo est excellent pour modéliser le métier ; moins bon comme visualiseur binaire rapide avec accès par rôle. Alors l'explorateur vit dans Django, lit la même Postgres, demande à S3 des URL présignées de courte durée, et ne garde jamais les documents en mémoire.

02

Un mixin abstrait pour le pattern d'upload

Trois modèles Odoo avaient besoin du même comportement d'upload S3. Nous avons écrit `AvataqDocumentS3Sync` comme mixin abstrait — héritez et obtenez génération de clé, upload S3 et notification d'index côté Django gratuitement. Un nouveau uploader, c'est une ligne d'héritage.

03

Identifiants dans config_parameter

Tout ce qui est sensible vit dans `ir.config_parameter` : le bucket S3, la région, la clé d'accès, le secret, l'URL et la clé API Django. Pas de substitution au déploiement, pas de secret commité, pas de surprise quand un environnement manque une clé.

04

Des documents qui ne restent pas en mémoire

Les documents uploadés vont droit à S3 avec une clé déterministe. Odoo ne les garde jamais après la fin de l'upload. Les utilisateurs Django authentifiés reçoivent une URL S3 présignée de 60 secondes quand ils demandent un téléchargement — assez long pour cliquer, assez court pour qu'une URL partagée soit déjà morte.

Choix techniques

Les solutions dont nous sommes le plus fiers.

01

Mixin abstrait AvataqDocumentS3Sync

Trois modèles Odoo avaient besoin du même comportement d'upload S3. Nous avons écrit un mixin abstrait : l'héritier déclare ses fichiers, le mixin gère la génération de clé, l'upload S3 et un POST vers l'endpoint Django `/api/index/` avec `X-API-Key`. Un nouveau uploader, c'est une ligne d'héritage.

02

Sync inter-stacks via REST

Odoo écrit ; Django indexe. Après chaque upload S3 réussi, Odoo POSTe les métadonnées (student_reference, scholar_year, s3_key, filename) vers l'endpoint Django `/api/index/`, verrouillé par un header `X-API-Key`. Django upsert une ligne `DocumentIndex`. Le côté Django n'écrit jamais vers S3 ni vers les tables Odoo.

03

URL S3 présignées de 60 secondes

Les téléchargements passent par Django, qui génère une URL S3 présignée de 60 secondes à la demande. Assez long pour cliquer, assez court pour qu'une URL partagée soit morte avant de pouvoir être détournée. Pas de liens publics longue durée.

04

Clés S3 déterministes

Les clés des objets encodent leur contexte : `{status_no}/{scholar_year}/{slug}.{ext}`. Deux opérations sortent gratuites : le listing par cohorte est un simple scan de préfixe S3, et migrer des documents entre environnements devient un renommage de clé plutôt qu'une jointure de métadonnées.

Résultats

Quelques chiffres, en formes brutes.

3+ ans
En continu depuis 2023
2 stacks
Odoo + Django sur une Postgres
60 s
TTL des URL S3 présignées
De bout en bout
Un ingénieur Hazenfield

Stack
Odoo 16Django 4.2PythonPostgreSQLAWS S3RESTDockerGunicorn

Un projet qui mérite ce niveau de soin ?

Démarrer une conversation