# Un carnet de rendez-vous pour un vétérinaire, avec relance par e-mail

> Une table personnalisée et une tâche planifiée suffisent à un cabinet qui n'a pas besoin d'un logiciel métier complet pour gérer ses rendez-vous.

- Auteur : WordPress Développement
- Publié le : 2023-03-18
- Mis à jour le : 2023-03-18
- Catégorie : Extensions
- URL : https://www.wpmoderne.fr/extensions/carnet-rendez-vous-veterinaire-relance-email/

## L’essentiel

- Table dédiée plutôt qu'un type de contenu détourné
- Tâche planifiée quotidienne pour les rappels
- Interface d'administration limitée à l'essentiel

Comment structurer un simple carnet de rendez-vous quand le client n'a besoin ni de facturation, ni de gestion de stock de médicaments, ni de dossier médical complet, seulement d'un calendrier partagé entre deux vétérinaires et d'un rappel automatique envoyé la veille ? La tentation du type de contenu personnalisé (CPT) est forte, car WordPress en fournit l'interface toute prête, mais un rendez-vous n'est pas un contenu éditorial : il porte une date, une heure, un animal, un propriétaire et un statut, des données structurées bien plus proches d'un enregistrement de base de données que d'un article.

Ce tutoriel construit, étape par étape, une extension minimale : une table personnalisée pour les rendez-vous, un écran d'administration simple pour les consulter, et une tâche planifiée qui envoie un e-mail de rappel automatique.

## Étape 1 : la table des rendez-vous

La structure passe par `dbDelta()`, appelée lors de l'activation de l'extension, afin que la table existe dès la première utilisation et puisse évoluer proprement lors des futures versions.

```
register_activation_hook( __FILE__, 'veterinaire_rdv_activation' );

function veterinaire_rdv_activation() {
    global $wpdb;
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';

    $table = $wpdb->prefix . 'veterinaire_rdv';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        nom_animal VARCHAR(100) NOT NULL,
        email_proprietaire VARCHAR(190) NOT NULL,
        date_heure DATETIME NOT NULL,
        statut VARCHAR(20) NOT NULL DEFAULT 'planifie',
        rappel_envoye TINYINT(1) NOT NULL DEFAULT 0,
        PRIMARY KEY  (id),
        KEY date_heure (date_heure)
    ) $charset_collate;";

    dbDelta( $sql );
}
```

Le statut du rendez-vous (`planifie`, `honore`, `annule`) reste une simple chaîne de caractères ici, ce qui suffit largement pour deux praticiens ; un cabinet plus grand justifierait une table de statuts séparée.

## Étape 2 : l'écran d'administration

> L'essentiel à retenir : Table dédiée plutôt qu'un type de contenu détourné ; Tâche planifiée quotidienne pour les rappels ; Interface d'administration limitée à l'essentiel

Une page ajoutée via `add_menu_page()` affiche la liste des rendez-vous à venir, triés par date. Pas besoin de reconstruire un tableau complexe : une requête directe via `$wpdb->get_results()` et une boucle d'affichage suffisent pour ce volume de données.

```
add_action( 'admin_menu', function () {
    add_menu_page(
        'Rendez-vous',
        'Rendez-vous',
        'manage_options',
        'veterinaire-rdv',
        'veterinaire_rdv_page_liste',
        'dashicons-calendar-alt'
    );
} );

function veterinaire_rdv_page_liste() {
    global $wpdb;
    $table = $wpdb->prefix . 'veterinaire_rdv';
    $rdvs = $wpdb->get_results(
        "SELECT * FROM $table WHERE date_heure >= NOW() ORDER BY date_heure ASC"
    );

    echo '<div class="wrap"><h1>Rendez-vous à venir</h1><table class="widefat">';
    foreach ( $rdvs as $rdv ) {
        printf(
            '<tr><td>%s</td><td>%s</td><td>%s</td></tr>',
            esc_html( $rdv->nom_animal ),
            esc_html( $rdv->date_heure ),
            esc_html( $rdv->statut )
        );
    }
    echo '</table></div>';
}
```

## Étape 3 : planifier la vérification quotidienne

Un événement WP-Cron, programmé une seule fois à l'activation, déclenche chaque jour une fonction qui recherche les rendez-vous du lendemain et envoie un e-mail de rappel à chaque propriétaire dont le rappel n'a pas encore été marqué comme envoyé.

```
register_activation_hook( __FILE__, function () {
    if ( ! wp_next_scheduled( 'veterinaire_rdv_verifier_rappels' ) ) {
        wp_schedule_event( time(), 'daily', 'veterinaire_rdv_verifier_rappels' );
    }
} );

add_action( 'veterinaire_rdv_verifier_rappels', 'veterinaire_rdv_envoyer_rappels' );

function veterinaire_rdv_envoyer_rappels() {
    global $wpdb;
    $table = $wpdb->prefix . 'veterinaire_rdv';
    $demain = gmdate( 'Y-m-d', strtotime( '+1 day' ) );

    $rdvs = $wpdb->get_results( $wpdb->prepare(
        "SELECT * FROM $table WHERE DATE(date_heure) = %s AND rappel_envoye = 0",
        $demain
    ) );

    foreach ( $rdvs as $rdv ) {
        $sujet = 'Rappel de rendez-vous pour ' . $rdv->nom_animal;
        $message = 'Votre rendez-vous est prévu le ' . $rdv->date_heure . '.';
        wp_mail( $rdv->email_proprietaire, $sujet, $message );

        $wpdb->update(
            $table,
            [ 'rappel_envoye' => 1 ],
            [ 'id' => $rdv->id ]
        );
    }
}
```

Le champ `rappel_envoye` évite les doublons si l'événement s'exécute plusieurs fois le même jour, un scénario fréquent quand le trafic du site est faible et que WP-Cron dépend des visites.

## Étape 4 : la désactivation propre

À la désactivation de l'extension, l'événement planifié doit être retiré pour éviter qu'il continue de s'exécuter sans plus produire d'effet utile.

- Appeler `wp_clear_scheduled_hook( 'veterinaire_rdv_verifier_rappels' )` dans `register_deactivation_hook()`.
- Laisser la table intacte à la désactivation, pour ne pas perdre les rendez-vous en cas de réactivation ultérieure.
- Documenter dans le fichier principal de l'extension que la suppression définitive des données se fait via un hook de désinstallation distinct.

## En résumé

Un cabinet vétérinaire à deux praticiens n'a pas besoin d'un module de planification complexe : une table, un écran de lecture et une tâche planifiée couvrent l'essentiel du besoin en une centaine de lignes de code. La prise de rendez-vous en ligne par le client final, avec vérification des créneaux disponibles en temps réel, reste un sujet plus vaste qui dépasse ce tutoriel.
