odoo/api-reference.md
... ...
@@ -149,7 +149,7 @@ Tous les modèles supportent : `search`, `search_read`, `search_count`, `read`,
149 149
150 150
| Modèle | Description |
151 151
|--------|-------------|
152
-| `sale.order` | **Devis et commandes clients**. Cycle : `draft` (devis) → `sent` (envoyé) → `sale` (commandé) → `done` (livré) → `cancel`. ⚠️ 7 champs obligatoires pour `create` : `name`, `partner_id`, `partner_invoice_id`, `partner_shipping_id`, `company_id`, `date_order`, `picking_policy`. Stocker la référence externe BilletWeb dans `client_order_ref` |
152
+| `sale.order` | **Devis et commandes clients**. Cycle : `draft` (devis) → `sent` (envoyé) → `sale` (commandé) → `done` (livré) → `cancel`. ⚠️ 7 champs obligatoires pour `create` : `name`, `partner_id`, `partner_invoice_id`, `partner_shipping_id`, `company_id`, `date_order`, `picking_policy`. Utiliser `client_order_ref` pour stocker une référence externe |
153 153
| `sale.order.line` | Lignes de commande. Contient le produit (`product_id`), la quantité (`product_uom_qty`), le prix unitaire (`price_unit`), la remise (`discount`), les taxes. Peut être lié à un billet événement (`event_ticket_id`) et des inscriptions (`registration_ids`) |
154 154
| `sale.order.template` | Modèles de devis réutilisables. Prédéfinit un panier de produits/services pour créer des devis en un clic. Contient des lignes via `sale.order.template.line` |
155 155
| `sale.order.template.line` | Lignes des modèles de devis. Mêmes champs que `sale.order.line` mais liées à un template plutôt qu'à une commande réelle |
... ...
@@ -282,8 +282,8 @@ Tous les modèles supportent : `search`, `search_read`, `search_count`, `read`,
282 282
| Modèle | Description |
283 283
|--------|-------------|
284 284
| `event.event` | **Événement** : nom, dates, lieu, places max, responsable. Contient billets (`event_ticket_ids`) et inscriptions (`registration_ids`). ⚠️ Désactiver `auto_confirm` pour éviter l'envoi d'emails en masse à chaque inscription |
285
-| `event.event.ticket` | **Type de billet**. Lié à un produit (`product_id`) — la vente du produit génère l'inscription. Définit le prix, le nombre de places disponibles. Essentiel pour le flux BilletWeb → Odoo |
286
-| `event.registration` | **Inscription / Participant**. Nom, email, code-barres (`barcode` pour QR BilletWeb), état (`draft`/`open`/`done`/`cancel`), billet, commande liée. ⚠️ `description` n'existe pas → utiliser `barcode` pour les références externes |
285
+| `event.event.ticket` | **Type de billet**. Lié à un produit (`product_id`) — la vente du produit génère automatiquement l'inscription. Définit le prix et le nombre de places disponibles. Utilisé pour la billetterie et les inscriptions en ligne |
286
+| `event.registration` | **Inscription / Participant**. Nom, email, code-barres (`barcode` pour QR code externe), état (`draft`/`open`/`done`/`cancel`), billet, commande liée. ⚠️ `description` n'existe pas → utiliser `barcode` pour les références externes |
287 287
| `event.type` | Catégories d'événements : Conférence, Salon, Formation, Concert... Paramètres par défaut (durée, modèle email) |
288 288
| `event.tag` | Étiquettes événement pour filtrage et recherche : "Annuel", "Scolaire", "Entreprise" |
289 289
| `event.mail` | Emails planifiés liés à un événement (quel template, envoyé quand : X jours avant/après). Utilise `mail.template` |
... ...
@@ -501,7 +501,7 @@ Tous les modèles supportent : `search`, `search_read`, `search_count`, `read`,
501 501
| `event_id` | m2o | Événement |
502 502
| `name` | char | Nom participant |
503 503
| `email` | char | Email |
504
-| `barcode` | char | QR/Barcode BilletWeb |
504
+| `barcode` | char | QR/Barcode externe |
505 505
| `state` | selection | `draft`/`open`/`done`/`cancel` |
506 506
| `event_ticket_id` | m2o | Type billet |
507 507
| `sale_order_id` | m2o | Commande liée |
... ...
@@ -511,25 +511,67 @@ Tous les modèles supportent : `search`, `search_read`, `search_count`, `read`,
511 511
512 512
---
513 513
514
-## 5. Flux BilletWeb → Odoo
514
+## 5. Patterns d'intégration
515 515
516
-Ordre : `res.partner` → `product.product` → `event.event.ticket` → `sale.order` → `sale.order.line` → `event.registration` → lien `registration_ids`.
516
+### 5.1 Créer une commande avec inscription événement
517 517
518
-### Anti-doublon
519 518
```python
520
-existing = odoo_call("event.registration", "search_read", [[]], {"fields": ["barcode"]})
521
-done = {r["barcode"] for r in existing if r.get("barcode")}
522
-if barcode in done: continue
519
+# Ordre : partenaire → commande → ligne → inscription → lien
520
+pid = odoo_call("res.partner", "create", [{"name": "Client", "email": "x@y.com", "customer_rank": 1}])
521
+so = odoo_call("sale.order", "create", [{"name": "CMD-001", "partner_id": pid, "partner_invoice_id": pid, "partner_shipping_id": pid, "company_id": 1, "date_order": "2026-01-01 10:00:00", "picking_policy": "direct"}])
522
+line = odoo_call("sale.order.line", "create", [{"order_id": so, "product_id": prod_id, "product_uom_qty": 1, "price_unit": 11.00}])
523
+reg = odoo_call("event.registration", "create", [{"event_id": 1, "name": "Client", "email": "x@y.com", "barcode": "1234567890", "state": "open"}])
524
+odoo_call("sale.order.line", "write", [[line], {"registration_ids": [(6, 0, [reg])]}])
525
+```
526
+
527
+### 5.2 Anti-doublon générique
528
+
529
+```python
530
+existing = odoo_call("model.name", "search_read", [[]], {"fields": ["field_key"]})
531
+done = {r["field_key"] for r in existing if r.get("field_key")}
532
+if key in done: continue
523 533
```
524 534
525
-### Désactiver les emails (6 étapes)
535
+### 5.3 Pagination
536
+
537
+```python
538
+all_records, offset = [], 0
539
+while True:
540
+ batch = odoo_call("model.name", "search_read",
541
+ [[["field", "=", value]]],
542
+ {"fields": ["id", "name"], "offset": offset, "limit": 100})
543
+ if not batch: break
544
+ all_records.extend(batch)
545
+ offset += 100
546
+```
547
+
548
+### 5.4 Désactiver les emails (avant import massif)
549
+
526 550
```python
527
-# 1. mail.mail → unlink stuck
528
-# 2. ir.mail_server → active=False
529
-# 3. fetchmail.server → active=False
530
-# 4. mail.template → auto_delete=True
531
-# 5. ir.cron → active=False (jobs mail/email/send)
532
-# 6. event.event → auto_confirm=False
551
+# 1. Vider la file d'attente
552
+for mid in odoo_call("mail.mail", "search", [[["state", "in", ["outgoing", "exception"]]]]):
553
+ odoo_call("mail.mail", "unlink", [[mid]])
554
+
555
+# 2. Désactiver serveur SMTP
556
+for s in odoo_call("ir.mail_server", "search_read", [], {"fields": ["id"]}):
557
+ odoo_call("ir.mail_server", "write", [[s["id"]], {"active": False}])
558
+
559
+# 3. Désactiver serveur entrant
560
+for s in odoo_call("fetchmail.server", "search_read", [], {"fields": ["id"]}):
561
+ odoo_call("fetchmail.server", "write", [[s["id"]], {"active": False}])
562
+
563
+# 4. Désactiver templates
564
+for t in odoo_call("mail.template", "search_read", [], {"fields": ["id"]}):
565
+ odoo_call("mail.template", "write", [[t["id"]], {"auto_delete": True}])
566
+
567
+# 5. Désactiver cron jobs email
568
+for c in odoo_call("ir.cron", "search_read", [], {"fields": ["id", "name"]}):
569
+ if any(kw in c["name"].lower() for kw in ["mail", "email", "send", "notification"]):
570
+ odoo_call("ir.cron", "write", [[c["id"]], {"active": False}])
571
+
572
+# 6. Désactiver confirmation auto
573
+for ev in event_ids:
574
+ odoo_call("event.event", "write", [[ev], {"auto_confirm": False}])
533 575
```
534 576
535 577
---
... ...
@@ -561,7 +603,7 @@ odoo_call("account.tax", "create", [{"name": "8.5% S", "amount": 8.5, "type_tax_
561 603
| 6 | auto_confirm envoie emails | Désactiver avant import |
562 604
| 7 | `unlink` échoue | `{"active": False}` |
563 605
| 8 | `search_read` limit=80 | `limit=0` pour tout |
564
-| 9 | BilletWeb 403 | `User-Agent: Mozilla/5.0` |
606
+| 9 | API externe 403 | Vérifier `User-Agent` et les headers HTTP requis par l'API tierce |
565 607
| 10 | `sale.order` 7 champs requis | name, partner_id ×3, company_id, date_order, picking_policy |
566 608
567 609
---
... ...
@@ -582,13 +624,33 @@ odoo_call("account.tax", "create", [{"name": "8.5% S", "amount": 8.5, "type_tax_
582 624
583 625
### Créer un client
584 626
```python
585
-pid = odoo_call("res.partner", "create", [{"name": "Jean", "email": "j@mail.com", "customer_rank": 1}])
627
+pid = odoo_call("res.partner", "create", [{"name": "Dupont", "email": "d@mail.com", "customer_rank": 1}])
586 628
```
587 629
588
-### Créer une commande + ligne + inscription
630
+### Créer un produit
589 631
```python
590
-so = odoo_call("sale.order", "create", [{"name": "CMD-001", "partner_id": pid, "partner_invoice_id": pid, "partner_shipping_id": pid, "company_id": 1, "date_order": "2026-05-29 10:00:00", "picking_policy": "direct"}])
591
-line = odoo_call("sale.order.line", "create", [{"order_id": so, "product_id": 13, "product_uom_qty": 1, "price_unit": 11.00}])
592
-reg = odoo_call("event.registration", "create", [{"event_id": 1, "name": "Jean", "email": "j@mail.com", "barcode": "1234567890", "state": "open"}])
593
-odoo_call("sale.order.line", "write", [[line], {"registration_ids": [(6, 0, [reg])]}])
632
+prod_id = odoo_call("product.product", "create", [{"name": "Service Conseil", "type": "service", "list_price": 100.00, "sale_ok": True}])
633
+```
634
+
635
+### Créer une commande complète
636
+```python
637
+so = odoo_call("sale.order", "create", [{"name": "CMD-001", "partner_id": pid, "partner_invoice_id": pid, "partner_shipping_id": pid, "company_id": 1, "date_order": "2026-01-01 10:00:00", "picking_policy": "direct", "state": "draft"}])
638
+line = odoo_call("sale.order.line", "create", [{"order_id": so, "product_id": prod_id, "product_uom_qty": 2, "price_unit": 100.00}])
639
+odoo_call("sale.order", "write", [[so], {"state": "sale"}]) # confirmer
640
+```
641
+
642
+### Créer une facture depuis une commande
643
+```python
644
+# Odoo gère automatiquement la création de facture via le bouton "Créer une facture"
645
+# En API, on peut créer manuellement :
646
+invoice_id = odoo_call("account.move", "create", [{"move_type": "out_invoice", "partner_id": pid, "invoice_date": "2026-01-01", "invoice_line_ids": [(0, 0, {"product_id": prod_id, "quantity": 2, "price_unit": 100.00})]}])
647
+odoo_call("account.move", "write", [[invoice_id], {"state": "posted"}])
648
+```
649
+
650
+### Rechercher avec filtres
651
+```python
652
+# Commandes confirmées > 100€ du mois
653
+orders = odoo_call("sale.order", "search_read",
654
+ [[["state", "=", "sale"], ["amount_total", ">", 100], ["date_order", ">=", "2026-01-01"]]],
655
+ {"fields": ["name", "partner_id", "amount_total"], "order": "date_order desc", "limit": 50})
594 656
```