-- ================================================================================
-- LE PRIX D'UNE OFFRE DEPEND DE LA FREQUENCE DE PRELEVEMENT
-- ================================================================================
--
-- CE QUI EXISTAIT, ET POURQUOI CA NE SUFFISAIT PAS.
--
-- La migration 037 avait pose « offres.prix_cents » et « abonnements.prix_cents », un montant
-- unique declare mensuel dans le domaine. La colonne n'a jamais ete lue ni ecrite par un
-- ecran : OffreRepository ne la selectionne pas, le formulaire du catalogue ne la propose pas.
-- Un prix pose en base et jamais branche, c'est-a-dire un catalogue sans tarif.
--
-- CE QUI EST DEMANDE : quatre prix HT par offre — mensuel, trimestriel, semestriel, annuel —
-- et une frequence choisie a la souscription. Ce n'est pas un prix mensuel multiplie : un
-- engagement annuel se vend moins cher que douze mois a l'unite, et c'est precisement ce que
-- quatre colonnes permettent d'exprimer.
--
-- ================================================================================
-- LES QUATRE PRIX SONT OBLIGATOIRES
-- ================================================================================
--
-- Choix explicite : toute offre porte les quatre tarifs, donc les quatre frequences sont
-- proposables. Un NULL aurait voulu dire « frequence non proposee » — une lecture parfaitement
-- defendable, mais qui demandait a chaque ecran de distinguer « pas de prix » de « gratuit ».
--
-- ZERO RESTE PERMIS, ET IL VEUT DIRE GRATUIT. C'est l'inverse des quotas, ou zero veut dire
-- « aucun » et interdit : ici un tarif nul est une offre d'essai, ce qui existe. Il n'y a donc
-- aucune ambiguite a lever, et pas de colonne nullable a manipuler.
--
-- EN CENTIMES ENTIERS, comme tout l'argent de ce projet. Un flottant accumule des erreurs a
-- chaque addition : sur douze lignes de facture, le total ne tombe plus juste, et c'est le
-- genre d'ecart qu'un comptable trouve avant nous.

ALTER TABLE offres
    DROP COLUMN prix_cents,
    ADD COLUMN prix_mensuel_cents     INT UNSIGNED NOT NULL DEFAULT 0 AFTER descriptif,
    ADD COLUMN prix_trimestriel_cents INT UNSIGNED NOT NULL DEFAULT 0 AFTER prix_mensuel_cents,
    ADD COLUMN prix_semestriel_cents  INT UNSIGNED NOT NULL DEFAULT 0 AFTER prix_trimestriel_cents,
    ADD COLUMN prix_annuel_cents      INT UNSIGNED NOT NULL DEFAULT 0 AFTER prix_semestriel_cents;

-- ================================================================================
-- LES TROIS FORMULES DE DEPART RECOIVENT UN TARIF
-- ================================================================================
--
-- Sans cela, le catalogue s'ouvrirait sur trois offres a zero euro — et zero euro est une
-- valeur valide ici, donc rien ne signalerait qu'il s'agit d'un oubli. Ce sont des donnees :
-- l'administrateur les corrige a l'ecran en trente secondes, mais il doit voir a quoi
-- ressemble une gamme tarifee.
--
-- LES DEGRESSIFS SONT VOLONTAIREMENT VISIBLES : le trimestre vaut moins que trois mois, et
-- l'annee moins que douze. C'est la raison d'etre de quatre colonnes plutot qu'une.

UPDATE offres SET
    prix_mensuel_cents     = 4900,
    prix_trimestriel_cents = 13900,
    prix_semestriel_cents  = 26400,
    prix_annuel_cents      = 49000
WHERE nom = 'Essentiel';

UPDATE offres SET
    prix_mensuel_cents     = 8900,
    prix_trimestriel_cents = 25400,
    prix_semestriel_cents  = 48000,
    prix_annuel_cents      = 89000
WHERE nom = 'Confort';

UPDATE offres SET
    prix_mensuel_cents     = 14900,
    prix_trimestriel_cents = 42500,
    prix_semestriel_cents  = 80400,
    prix_annuel_cents      = 149000
WHERE nom = 'Illimite';

-- ================================================================================
-- L'ABONNEMENT PORTE SA FREQUENCE ET SON MONTANT PAR PERIODE
-- ================================================================================
--
-- MEME PRINCIPE QUE LES QUOTAS : l'offre porte le catalogue, l'abonnement porte l'ENGAGE. Une
-- hausse de tarif ne remonte pas retroactivement chez ceux qui ont signe avant, et ne change
-- aucune facture deja emise.
--
-- « prix_cents » DEVIENT « prix_periode_cents », ET LE NOM EST LA CORRECTION.
--
-- L'ancien nom ne disait pas par quoi le montant etait divise. Le domaine tranchait « c'est
-- mensuel » dans un commentaire de classe — la seule trace de cette decision. Un montant sans
-- unite est une absence deguisee en valeur, exactement comme un quota NULL lu comme zero, et
-- l'ecart entre les deux lectures possibles est ici un facteur douze.
--
-- Le nouveau nom porte l'unite : c'est le montant d'UN prelevement, quelle que soit la
-- frequence. « periodicite » dit laquelle.

ALTER TABLE abonnements
    CHANGE COLUMN prix_cents prix_periode_cents INT UNSIGNED NULL;

-- ================================================================================
-- LA PERIODICITE : EN TROIS TEMPS, ET SANS VALEUR PAR DEFAUT
-- ================================================================================
--
-- On l'ajoute NULLABLE, on remplit les lignes existantes, puis on la rend obligatoire. Le
-- detour n'est pas de la prudence de facade : une colonne NOT NULL ajoutee d'un coup remplit
-- les lignes existantes avec la chaine vide en mode permissif, et echoue en mode strict. Les
-- deux sont mauvais, et le second au pire moment — pendant un deploiement.
--
-- AUCUN « DEFAULT », ET C'EST LE POINT IMPORTANT. Un defaut a « mensuelle » ferait qu'un INSERT
-- qui oublie la colonne produirait un abonnement mensuel en silence : quelqu'un qui a signe
-- pour l'annee serait preleve douze fois. Sans defaut, cet INSERT ECHOUE — bruyamment, tout de
-- suite, chez nous et non chez le client.

ALTER TABLE abonnements
    ADD COLUMN periodicite VARCHAR(16) NULL AFTER prix_periode_cents;

-- Les abonnements deja souscrits l'ont ete sous un prix declare mensuel : c'est la seule
-- valeur qui ne change retroactivement le montant de personne.
UPDATE abonnements SET periodicite = 'mensuelle' WHERE periodicite IS NULL;

ALTER TABLE abonnements
    MODIFY COLUMN periodicite VARCHAR(16) NOT NULL;

-- ================================================================================
-- LA BASE REFUSE UNE PERIODICITE QUE LE DOMAINE NE CONNAIT PAS
-- ================================================================================
--
-- Le CHECK double l'enum PHP, et ce n'est pas un doublon : le domaine protege ce qui passe par
-- lui, la base protege ce qui passe a cote — un import, une correction faite a la main dans un
-- client SQL, un script de reprise. Une valeur inconnue rendrait « periodicite illisible » a
-- la lecture, et l'echeancier cesserait d'emettre des factures en silence.
--
-- VARCHAR PLUTOT QU'UN ENUM SQL : un ENUM se modifie par un ALTER TABLE qui reecrit la table,
-- et il rend la valeur hors liste par une CHAINE VIDE plutot que par une erreur — encore une
-- absence deguisee en valeur.

ALTER TABLE abonnements
    ADD CONSTRAINT ck_abonnements_periodicite
        CHECK (periodicite IN ('mensuelle', 'trimestrielle', 'semestrielle', 'annuelle'));
