# Documentation Technique KoboToolbox — IFPB

## API v2 — Référence Rapide

### Endpoint Principaux

```
BASE_URL = https://kc.kobotoolbox.org/api/v2

# Assets (formulaires)
GET  /assets                    → Liste formulaires
GET  /assets/{uid}              → Détail formulaire
POST /assets/{uid}/deployment   → Déployer version

# Data (soumissions)
GET  /assets/{uid}/data         → Toutes les soumissions
GET  /assets/{uid}/data/{id}    → Soumission spécifique
POST /assets/{uid/submission    → Nouvelle soumission

# Users
GET  /users                     → Liste utilisateurs
GET  /users/{username}          → Détail utilisateur
```

### Pagination

```python
import requests

def fetch_all_submissions(asset_uid, token):
    """Extraction paginée complète des soumissions Kobo"""
    url = f"https://kc.kobotoolbox.org/api/v2/assets/{asset_uid}/data/"
    headers = {"Authorization": f"Token {token}"}
    all_data = []
    
    while url:
        resp = requests.get(url, headers=headers, params={"limit": 1000})
        resp.raise_for_status()
        data = resp.json()
        all_data.extend(data["results"])
        url = data.get("next")  # None si dernière page
    
    return all_data
```

## Syntaxe XLSForm — Référence

### Types de Champs

| Type | Description | Exemple |
|------|-------------|---------|
| `text` | Texte libre | Nom, adresse |
| `integer` | Entier | Nombre d'étages |
| `decimal` | Décimal | Surface en m² |
| `select_one` | Choix unique | Zone géographique |
| `select_multiple` | Choix multiples | Équipements |
| `geopoint` | GPS (lat, lon, alt, précision) | Localisation parcelle |
| `image` | Photo | Preuve matériaux |
| `calculate` | Calcul caché (read-only) | Montant IFTB |
| `note` | Texte affiché (non saisi) | Récapitulatif |

### Contraintes (Constraints)

```yaml
# Regex CIN malgache : 12 chiffres
constraint: "^[0-9]{12}$"
message: "La CIN doit comporter exactement 12 chiffres"

# GPS précision < 10m (index 3 du geopoint)
constraint: ".[3] <= 10"
message: "Précision GPS insuffisante (>10m)"

# Surface positive
constraint: ". > 0"
message: "La surface doit être supérieure à 0"

# Au moins 1 bâtiment
constraint: ". > 0"
message: "Il doit y avoir au moins 1 bâtiment"
```

### Relevance (Skip Logic)

```yaml
# CIN visible seulement si propriétaire
relevant: "${statut_occupant} = 'proprietaire'"

# Exonération seulement si occupation effective
relevant: "${occupation_effective} = 'oui'"
```

### Calculate (Champs Calculés)

```xls
# Valeur locative étage
tarif_m2 = if(${usage_visuel}='industriel', 5000,
          if(${usage_visuel}='commercial', 2500,
          if(${materiau_visuel}='dur', 1000, 2000)))
valeur_locative_etage = ${surface_etage} * ${tarif_m2}

# Impôt principal
taux_applicable = if(${usage_visuel}='industriel', 0.10,
                 if(${usage_visuel}='commercial', 0.07,
                 if(${materiau_visuel}='dur', 0.05, 0.02)))
impot_principal_etage_brut = ${valeur_locative_etage} * ${taux_applicable}

# Total bâtiment avec exonération
principal_batiment = if(${eligible_exon_temp}='oui', 0, ${principal_batiment_somme})
cac_batiment = ${principal_batiment} * 0.10
total_batiment = ${principal_batiment} + ${cac_batiment}
```

## Structure du XLSForm IFPB

### Feuille survey (38 lignes)

| Groupe | Champ | Type | Rôle |
|--------|-------|------|------|
| **S1** | fokontany | select_one | Quartier (13 options) |
| **S1** | gps_parcelle | geopoint | Localisation (<10m) |
| **S2** | statut_occupant | select_one | Propriétaire/Locataire/Gratuit |
| **S2** | nom_proprietaire | text | Identité contribuable |
| **S2** | cin_proprietaire | text | CIN 12 chiffres |
| **S2** | contact_mobile | text | Téléphone 10 chiffres |
| **S2** | nbre_batiments | integer | ≥1 |
| **S3** | zone_visuelle | select_one | rn/centre/peripherie/enclave |
| **S3** | occupation_effective | select_one | oui/non |
| **S3** | nb_etages | integer | ≥0 |
| **S3-r** | usage_visuel | select_one | industriel/commercial/habitation |
| **S3-r** | materiau_visuel | select_one | dur/semi_dur/traditionnel |
| **S3-r** | surface_etage | integer | >0 m² |
| **S3-r** | photo_facade_etage | image | ⚠️ obligatoire |
| **S4** | total_parcelle | calculate | Somme totale (caché) |
| **S4** | r3 | note | 💰 Montant estimé (visible) |

### Feuille choices (28 choix)

| list_name | Options |
|-----------|---------|
| type_fokontany | 13 quartiers Moramanga |
| zone_geographique | rn, centre, peripherie, enclave |
| statut_occupation | proprietaire, locataire, occupant_gratuit |
| type_usage | industriel, commercial, habitation |
| type_materiau | dur, semi_dur, traditionnel |
| exoneration_oui_non | oui, non |

### Feuille settings (4 paramètres)

| Setting | Valeur |
|---------|--------|
| form_title | IFPB — Recensement Foncier Moramanga |
| form_id | ifpb_recensement_foncier_2026 |
| version | YYYY.MM.DD (incrémenter à chaque déploiement) |
| max_bytes | 10000000 (10MB max/photo) |

## Bonnes Pratiques Déploiement

1. **Toujours incrémenter la version** dans settings avant déploiement
2. **Jamais renommer/supprimer un champ** existant (compatibilité soumissions)
3. **Toujours ajouter de nouveaux champs** à la fin du groupe
4. **Tester en preview** avant déploiement production
5. **Monitorer les erreurs de validation** pendant 48h post-déploiement
6. **Notifier les agents** de mise à jour KoboCollect

---
*Document généré par IFPB Platform — v2026.06.02*
