github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/core/rawdata/models.go (about) 1 // Ce package implémentes les fondements de la gestion des données 2 // ACVE. Il est destiné à être utilisé sur le serveur et sur le client. 3 // Il définit les types de donneés utilisés 4 // et permet de changer d'une représentation à une autre (SQL/JSON/mémoire vive) 5 package rawdata 6 7 import ( 8 "time" 9 10 "github.com/lib/pq" 11 ) 12 13 // ----------------------------------- Personne ----------------------------------- // 14 15 // Personne représente les attributs d'une personne 16 type Personne struct { 17 Id int64 `json:"id"` 18 19 BasePersonne 20 21 VersionPapier Bool `json:"version_papier"` 22 PubHiver Bool `json:"pub_hiver"` 23 PubEte Bool `json:"pub_ete"` 24 EchoRocher Bool `json:"echo_rocher"` 25 RangMembreAsso RangMembreAsso `json:"rang_membre_asso"` 26 QuotientFamilial Int `json:"quotient_familial"` 27 Cotisation Cotisation `json:"cotisation"` // dernière année 28 Eonews Bool `json:"eonews"` 29 FicheSanitaire FicheSanitaire `json:"fiche_sanitaire"` 30 31 // Si `true` indique un profil non vérifié. Les personnes temporaires 32 // peuvent être supprimées à tout moment (nécessitant une redirection des tables 33 // documents, participants,...) 34 IsTemporaire Bool `json:"is_temporaire"` 35 } 36 37 // ----------------------------------- Camp ----------------------------------- // 38 39 // Camp représente un séjour proposé par l'ACVE 40 // requis participantsimples 41 // sql:ADD UNIQUE(id,inscription_simple) 42 type Camp struct { 43 Id int64 `json:"id"` 44 Lieu String `json:"lieu"` 45 Nom String `json:"nom"` 46 Prix Euros `json:"prix"` 47 NbPlaces Int `json:"nb_places"` 48 Password String `json:"password"` 49 Ouvert Bool `json:"ouvert"` 50 NbPlacesReservees Int `json:"nb_places_reservees"` 51 NumeroJS String `json:"numero_js"` 52 NeedEquilibreGf Bool `json:"need_equilibre_gf"` 53 AgeMin Int `json:"age_min"` 54 AgeMax Int `json:"age_max"` 55 Options OptionsCamp `json:"options"` 56 DateDebut Date `json:"date_debut"` 57 DateFin Date `json:"date_fin"` 58 59 ListeVetements ListeVetements `json:"liste_vetements"` 60 SchemaPaiement SchemaPaiement `json:"schema_paiement"` 61 JoomeoAlbumId String `json:"joomeo_album_id"` 62 Envois Envois `json:"envois"` 63 LienCompta String `json:"lien_compta"` 64 OptionPrix OptionPrixCamp `json:"option_prix"` 65 66 // Si oui, la procédure d'inscription est simplifiée. 67 InscriptionSimple Bool `json:"inscription_simple"` 68 69 Infos String `json:"infos"` // info additionnelle à afficher sur le formulaire 70 } 71 72 // LettreDirecteur conserve le html utilisé pour générer la lettre. 73 // En revanche, c'est bien le document stocké dans la base de données 74 // qui est utilisé ensuie. 75 // Le contenu html de la lettre peut contenir des images 76 // et alourdir significativement la table Camps. 77 // sql:ADD UNIQUE(id_camp) 78 type Lettredirecteur struct { 79 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 80 Html string `json:"html"` 81 UseCoordCentre bool `json:"use_coord_centre"` 82 ShowAdressePostale bool `json:"show_adresse_postale"` 83 ColorCoord string `json:"color_coord"` 84 } 85 86 // Images contenues dans les lettres aux parents 87 // sql: ADD UNIQUE(id_camp, lien) 88 type Imageuploaded struct { 89 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 90 Filename string `json:"filename"` 91 Lien string `json:"lien"` 92 Content []byte `json:"content"` 93 } 94 95 // Groupe représente un groupe de participants 96 // Un séjour peut définir (ou non) une liste de groupes 97 // sql:ADD UNIQUE(id_camp, nom) 98 // sql:ADD UNIQUE(id, id_camp) 99 // assure qu'un groupe est lié à un camp complet 100 // sql:ALTER COLUMN isSimple SET DEFAULT false 101 // sql:ADD CHECK(isSimple = false) 102 // sql:ADD FOREIGN KEY (id_camp, isSimple) REFERENCES camps(id,inscription_simple) 103 type Groupe struct { 104 Id int64 `json:"id"` 105 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 106 107 // un nom vide indique un groupe par défaut 108 Nom String `json:"nom"` 109 // indication: ignorée forcément pour un groupe par défaut 110 Plage Plage `json:"plage"` 111 // Hex color, optionnelle 112 Couleur string `json:"couleur"` 113 114 isSimple bool 115 } 116 117 // Sondage enregistre les retours sur un séjour 118 // sql:ADD UNIQUE(id_camp, id_facture) 119 type Sondage struct { 120 Id int64 `json:"id"` 121 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 122 IdFacture int64 `json:"id_facture" sql_on_delete:"CASCADE"` 123 Modified time.Time `json:"modified"` 124 125 RepSondage 126 } 127 128 // ------------------------------ Inscriptions ------------------------------ 129 130 // Inscription enregistre l'inscription faite via le formulaire publique. 131 // L'inscription publique est transformée en facture dès réception, 132 // cette table ne sert donc qu'à garder une trace en cas de problème. 133 // Entre autre, l'intégrité des camps n'est pas assurée 134 type Inscription struct { 135 Id int64 `json:"id"` 136 Info String `json:"info"` 137 DateHeure Time `json:"date_heure"` 138 CopiesMails pq.StringArray `json:"copies_mails"` 139 140 Responsable ResponsableLegal `json:"responsable"` 141 Participants ParticipantInscriptions `json:"participants"` 142 143 PartageAdressesOK bool `json:"partage_adresses_ok"` 144 } 145 146 // -------------------------- Participants -------------------------- 147 148 // Participant représente un inscrit sur un séjour complet (éventuellement sur liste d'attente) 149 // sql:ADD UNIQUE(id_personne, id_camp) 150 // nécessaire pour être référencé 151 // sql:ADD UNIQUE(id, id_camp) 152 // assure qu'un participant est lié à un camp complet 153 // sql:ALTER COLUMN isSimple SET DEFAULT false 154 // sql:ADD CHECK(isSimple = false) 155 // sql:ADD FOREIGN KEY (id_camp, isSimple) REFERENCES camps(id,inscription_simple) 156 type Participant struct { 157 Id int64 `json:"id"` 158 IdCamp int64 `json:"id_camp"` 159 IdPersonne int64 `json:"id_personne" sql_on_delete:"CASCADE"` 160 IdFacture OptionnalId `json:"id_facture" sql_on_delete:"SET NULL"` 161 162 ListeAttente ListeAttente `json:"liste_attente"` 163 Remises Remises `json:"remises"` 164 OptionPrix OptionPrixParticipant `json:"option_prix"` 165 Options OptionsParticipant `json:"options"` 166 167 // Moment d'inscription 168 DateHeure Time `json:"date_heure"` 169 170 isSimple bool 171 } 172 173 // GroupeParticipant défini le contenu des groupes 174 // sql:ADD UNIQUE (id_participant) 175 // sql:ADD UNIQUE (id_participant, id_groupe) 176 // sql:ADD FOREIGN KEY (id_participant, id_camp) REFERENCES participants(id,id_camp) 177 // sql:ADD FOREIGN KEY (id_groupe, id_camp) REFERENCES groupes(id,id_camp) 178 type GroupeParticipant struct { 179 IdParticipant int64 `json:"id_participant" sql_on_delete:"CASCADE"` 180 IdGroupe int64 `json:"id_groupe" sql_on_delete:"CASCADE"` 181 // redondance pour assurer l'intégrité 182 IdCamp int64 `json:"id_camp"` 183 // indique si l'attribuation a été faite 184 // en modifiant directement la fiche du participant ou 185 // en fonction de l'âge 186 Manuel bool `json:"manuel"` 187 } 188 189 // Equipier représente un participant dans l'équipe d'un séjour 190 // sql:ADD UNIQUE(id_personne, id_camp) 191 // requise par la contrainte ParticipantEquipier 192 // sql:ADD UNIQUE(id, id_camp) 193 type Equipier struct { 194 Id int64 `json:"id"` 195 IdCamp int64 `json:"id_camp"` 196 IdPersonne int64 `json:"id_personne" sql_on_delete:"CASCADE"` 197 198 Roles Roles `json:"roles"` 199 Diplome Diplome `json:"diplome"` 200 Appro Approfondissement `json:"appro"` 201 Presence OptionnalPlage `json:"presence"` 202 InvitationEquipier InvitationEquipier `json:"invitation_equipier"` 203 204 // validation de la charte ACVE 205 Charte OptionnalBool `json:"charte"` 206 } 207 208 // GroupeEquipiers définit les animateurs d'un groupe 209 // sql:ADD UNIQUE(id_groupe, id_equipier) 210 // sql:ADD FOREIGN KEY (id_equipier, id_camp) REFERENCES equipiers(id,id_camp) 211 // sql:ADD FOREIGN KEY (id_groupe, id_camp) REFERENCES groupes(id,id_camp) 212 type GroupeEquipier struct { 213 IdGroupe int64 `json:"id_groupe" sql_on_delete:"CASCADE"` 214 IdEquipier int64 `json:"id_equipier" sql_on_delete:"CASCADE"` 215 // redondance pour assurer l'intégrité 216 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 217 } 218 219 // ParticipantEquipier associe un animateur de référence à un inscrit 220 // sql:ADD UNIQUE (id_participant) 221 // sql:ADD FOREIGN KEY (id_participant, id_groupe) REFERENCES groupe_participants(id_participant, id_groupe) 222 // sql:ADD FOREIGN KEY (id_equipier, id_groupe) REFERENCES groupe_equipiers(id_equipier, id_groupe) ON DELETE CASCADE 223 type ParticipantEquipier struct { 224 IdParticipant int64 `json:"id_participant" sql_on_delete:"CASCADE"` 225 IdEquipier int64 `json:"id_equipier" sql_on_delete:"CASCADE"` 226 // redondance pour assurer l'intégrité 227 IdGroupe int64 `json:"id_groupe" sql_on_delete:"CASCADE"` 228 } 229 230 // Participantsimple représente un inscrit sur un séjour simplifié, 231 // sans dossier ni groupe associé. 232 // sql:ADD UNIQUE(id_personne, id_camp) 233 // assure qu'un participant simple appartient à un camp simple 234 // sql:ALTER COLUMN isSimple SET DEFAULT TRUE 235 // sql:ADD CHECK(isSimple = TRUE) 236 // sql:ADD FOREIGN KEY (id_camp, isSimple) REFERENCES camps(id,inscription_simple) 237 type Participantsimple struct { 238 Id int64 `json:"id"` 239 IdPersonne int64 `json:"id_personne" sql_on_delete:"CASCADE"` 240 IdCamp int64 `json:"id_camp"` // devrait être simple 241 242 // Moment d'inscription 243 DateHeure Time `json:"date_heure"` 244 Info String `json:"info"` 245 246 isSimple bool 247 } 248 249 type Structureaide struct { 250 Id int64 `json:"id"` 251 Nom String `json:"nom"` 252 Immatriculation String `json:"immatriculation"` 253 Adresse String `json:"adresse"` 254 CodePostal String `json:"code_postal"` 255 Ville String `json:"ville"` 256 Telephone String `json:"telephone"` 257 Info String `json:"info"` 258 } 259 260 type Aide struct { 261 Id int64 `json:"id"` 262 IdStructureaide int64 `json:"id_structureaide"` 263 IdParticipant int64 `json:"id_participant" sql_on_delete:"CASCADE"` 264 Valeur Euros `json:"valeur"` 265 Valide Bool `json:"valide"` 266 ParJour Bool `json:"par_jour"` 267 NbJoursMax Int `json:"nb_jours_max"` 268 } 269 270 // Organisme désigne un groupe de personne (typiquement une église) 271 // Un organisme a soit des coordonnées propre, soit une personne de contact 272 // En plus, un contact pour les dons peut être ajouté. 273 // sql:ADD CHECK(contact_propre <> (id_contact IS NOT NULL)) 274 type Organisme struct { 275 Id int64 `json:"id"` 276 Nom String `json:"nom"` 277 278 ContactPropre Bool `json:"contact_propre"` 279 Contact Coordonnees `json:"contact"` 280 IdContact OptionnalId `json:"id_contact" sql_foreign_key:"personne"` 281 282 IdContactDon OptionnalId `json:"id_contact_don" sql_foreign_key:"personne"` 283 Exemplaires Exemplaires `json:"exemplaires"` // pour les communications 284 } 285 286 type Don struct { 287 Id int64 `json:"id"` 288 Valeur Euros `json:"valeur"` 289 ModePaiement ModePaiment `json:"mode_paiement"` 290 DateReception Date `json:"date_reception"` 291 RecuEmis Date `json:"recu_emis"` 292 Infos InfoDon `json:"infos"` 293 Remercie Bool `json:"remercie"` // `true` si le remerciement a été envoyé 294 Details String `json:"details"` // détails additionels 295 Affectation String `json:"affectation"` // indicatif 296 } 297 298 // DonDonateur est une table de lien indiquant l'origine d'un don, 299 // groupe ou personne 300 // sql:ADD CHECK(id_personne <> null OR id_organisme <> null) 301 // sql:ADD CHECK(id_personne = null OR id_organisme = null) 302 // sql:ADD UNIQUE(id_don) 303 type DonDonateur struct { 304 IdDon int64 `json:"id_don" sql_on_delete:"CASCADE"` 305 IdPersonne OptionnalId `json:"id_personne"` 306 IdOrganisme OptionnalId `json:"id_organisme"` 307 } 308 309 // ---------------------------- Documents et contraintes ---------------------------- 310 311 // Contrainte encode la catégorie d'un document à fournir 312 // L'attribut 'builtin' permet d'identifier des contraintes universelles 313 // 314 // sql:ADD UNIQUE(nom, builtin, id_personne) 315 // sql:ADD CHECK(builtin <> '' OR id_personne IS NOT NULL) 316 type Contrainte struct { 317 Id int64 `json:"id"` 318 IdPersonne OptionnalId `json:"id_personne" sql_on_delete:"CASCADE"` // proprietaire de la contrainte 319 IdDocument OptionnalId `json:"id_document"` // document à remplir 320 321 Builtin BuiltinContrainte `json:"builtin"` 322 Nom String `json:"nom"` 323 Description String `json:"description"` 324 // nombre max de documents qui peuvent satisfaire la contrainte 325 MaxDocs int `json:"max_docs"` 326 // si > 0 indique un document temporaire : 327 // les documents liés seront supprimés JoursValide jours 328 // après leur dernière modification 329 JoursValide int `json:"jours_valide"` 330 } 331 332 // sql:ADD UNIQUE(id_equipier, id_contrainte) 333 type EquipierContrainte struct { 334 IdEquipier int64 `json:"id_equipier" sql_on_delete:"CASCADE"` 335 IdContrainte int64 `json:"id_contrainte"` 336 Optionnel bool `json:"optionnel"` 337 } 338 339 // CampContrainte représente une contrainte demandée 340 // à tous les participants 341 // sql:ADD UNIQUE(id_camp, id_contrainte) 342 type CampContrainte struct { 343 IdCamp int64 `json:"id_camp" sql_on_delete:"CASCADE"` 344 IdContrainte int64 `json:"id_contrainte"` 345 } 346 347 // GroupeContrainte représente une contrainte 348 // attribuée à un groupe spécifique (de façon cumulative 349 // avec les contraintes camps) 350 // sql:ADD UNIQUE(id_groupe, id_contrainte) 351 type GroupeContrainte struct { 352 IdGroupe int64 `json:"id_groupe" sql_on_delete:"CASCADE"` 353 IdContrainte int64 `json:"id_contrainte"` 354 } 355 356 // Document représente les méta données d'un document stocké sur le serveur 357 // Son contenu et son utilisation sont définis par les objets `TargetDocument` et `ContenuDocument` 358 type Document struct { 359 Id int64 `json:"id"` 360 361 // En bytes 362 Taille Taille `json:"taille"` 363 NomClient String `json:"nom_client"` 364 Description String `json:"description"` 365 DateHeureModif Time `json:"date_heure_modif"` 366 } 367 368 // ContenuDocument stocke le contenu effectif du document, compressé 369 // ainsi qu'une miniature 370 // sql:ADD UNIQUE(id_document) 371 type ContenuDocument struct { 372 IdDocument int64 `json:"id_document" sql_on_delete:"CASCADE"` 373 Contenu []byte `json:"contenu"` 374 Miniature []byte `json:"miniature"` 375 } 376 377 // table de lien pour les lettres des séjours et les documents additionnels 378 // sql: ADD UNIQUE(id_document) 379 type DocumentCamp struct { 380 IdDocument int64 `json:"id_document" sql_on_delete:"CASCADE"` 381 IdCamp int64 `json:"id_camp"` 382 IsLettre bool `json:"is_lettre"` // sinon, document additionnel 383 } 384 385 // table de lien pour les documents liés aux personnes 386 // un document peut remplir une contrainte personnalisée 387 // sql:ADD UNIQUE(id_document) 388 type DocumentPersonne struct { 389 IdDocument int64 `json:"id_document" sql_on_delete:"CASCADE"` 390 IdPersonne int64 `json:"id_personne"` 391 IdContrainte int64 `json:"id_contrainte"` 392 } 393 394 // table de lien pour les justificatifs des aides 395 // sql:ADD UNIQUE(id_document) 396 type DocumentAide struct { 397 IdDocument int64 `json:"id_document" sql_on_delete:"CASCADE"` 398 IdAide int64 `json:"id_aide"` 399 } 400 401 // --------------------------------- --------------------------------- 402 type Paiement struct { 403 Id int64 `json:"id"` 404 IdFacture int64 `json:"id_facture"` 405 406 IsAcompte Bool `json:"is_acompte"` 407 IsRemboursement Bool `json:"is_remboursement"` 408 InBordereau Time `json:"in_bordereau"` 409 LabelPayeur String `json:"label_payeur"` 410 NomBanque String `json:"nom_banque"` 411 ModePaiement ModePaiment `json:"mode_paiement"` 412 Numero String `json:"numero"` 413 Valeur Euros `json:"valeur"` 414 IsInvalide Bool `json:"is_invalide"` 415 DateReglement Time `json:"date_reglement"` 416 Details String `json:"details"` 417 } 418 419 type Facture struct { 420 Id int64 `json:"id"` 421 IdPersonne int64 `json:"id_personne"` 422 DestinatairesOptionnels DestinatairesOptionnels `json:"destinataires_optionnels"` 423 Key String `json:"key"` 424 CopiesMails pq.StringArray `json:"copies_mails"` // liste d'adresse en copies des mails envoyés 425 426 LastConnection time.Time `json:"last_connection"` // connection sur l'espace de suivi 427 428 IsConfirmed bool `json:"is_confirmed"` // mail confirmé par les parents 429 IsValidated bool `json:"is_validated"` // validée par le centre 430 431 // Autorisation de partage des adresses 432 PartageAdressesOK bool `json:"partage_adresses_ok"` 433 } 434 435 // Message encode un échange entre le centre d'inscription 436 // et le responsable d'un dossier 437 // sql:ADD UNIQUE(id, kind) 438 // Les définitions suivantes sont temporaires et permettent de 439 // solidifer la migration 440 // noTableSql:CREATE FUNCTION m_responsable() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MResponsable'; 441 // noTableSql:CREATE FUNCTION m_centre() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MCentre'; 442 // noTableSql:CREATE FUNCTION m_accuse_reception() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MAccuseReception'; 443 // noTableSql:CREATE FUNCTION m_facture() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MFacture'; 444 // noTableSql:CREATE FUNCTION m_documents() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MDocuments'; 445 // noTableSql:CREATE FUNCTION m_facture_acquittee() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MFactureAcquittee'; 446 // noTableSql:CREATE FUNCTION m_attestation_presence() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MAttestationPresence'; 447 // noTableSql:CREATE FUNCTION m_sondage() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MSondage'; 448 // noTableSql:CREATE FUNCTION m_inscription() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MInscription'; 449 // noTableSql:CREATE FUNCTION m_place_liberee() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #MessageKind.MPlaceLiberee'; 450 type Message struct { 451 Id int64 `json:"id"` 452 IdFacture int64 `json:"id_facture" sql_on_delete:"CASCADE"` 453 Kind MessageKind `json:"kind"` 454 Created Time `json:"created"` 455 Modified Time `json:"modified"` 456 Vu bool `json:"vu"` // indique si le message a été vu (dépend du contexte) 457 } 458 459 // Définit les tables complétant un message (à garder synchronisé) 460 var ComplementMessagesTables = [5]string{ 461 "message_documents", 462 "message_sondages", 463 "message_placeliberes", 464 "message_attestations", 465 "message_messages", 466 } 467 468 // MessageDocument complete un message 'documents' 469 // en donnant le camp concerné. 470 // sql:ADD UNIQUE(id_message) 471 // contraintes d'intégrité : 472 // sql:ADD CHECK(guardKind = #MessageKind.MDocuments) 473 // sql:ALTER COLUMN guardKind SET DEFAULT #MessageKind.MDocuments 474 // sql:ADD FOREIGN KEY (id_message, guardKind) REFERENCES messages(id,kind) 475 type MessageDocument struct { 476 IdMessage int64 `json:"id_message" sql_on_delete:"CASCADE"` 477 IdCamp int64 `json:"id_camp"` 478 479 guardKind MessageKind 480 } 481 482 // MessageSondage complete un message 'sondage' 483 // en donnant le camp concerné. 484 // sql:ADD UNIQUE(id_message) 485 // contraintes d'intégrité : 486 // sql:ADD CHECK(guardKind = #MessageKind.MSondage) 487 // sql:ALTER COLUMN guardKind SET DEFAULT #MessageKind.MSondage 488 // sql:ADD FOREIGN KEY (id_message, guardKind) REFERENCES messages(id,kind) 489 // sql:ALTER COLUMN isSimple SET DEFAULT FALSE 490 // sql:ADD CHECK(isSimple = FALSE) 491 // sql:ADD FOREIGN KEY (id_camp, isSimple) REFERENCES camps(id,inscription_simple) 492 type MessageSondage struct { 493 IdMessage int64 `json:"id_message" sql_on_delete:"CASCADE"` 494 IdCamp int64 `json:"id_camp"` 495 496 guardKind MessageKind 497 isSimple bool 498 } 499 500 // MessagePlacelibere complète une notification de place libérée 501 // sql:ADD UNIQUE(id_message) 502 // contraintes d'intégrité : 503 // sql:ADD CHECK(guardKind = #MessageKind.MPlaceLiberee) 504 // sql:ALTER COLUMN guardKind SET DEFAULT #MessageKind.MPlaceLiberee 505 // sql:ADD FOREIGN KEY (id_message, guardKind) REFERENCES messages(id,kind) 506 type MessagePlacelibere struct { 507 IdMessage int64 `json:"id_message" sql_on_delete:"CASCADE"` 508 IdParticipant int64 `json:"id_participant"` 509 510 guardKind MessageKind 511 } 512 513 // MessageAttestation complète l'accès 514 // à une facture acquittée/attestation de présence 515 // sql:ADD UNIQUE(id_message) 516 // contraintes d'intégrité : 517 // sql:ADD CHECK(guard_kind = #MessageKind.MFactureAcquittee OR guard_kind = #MessageKind.MAttestationPresence) 518 // sql:ADD FOREIGN KEY (id_message, guard_kind) REFERENCES messages(id,kind) 519 // pour la migration 520 // noTableSql:CREATE FUNCTION d_mail() RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS 'SELECT #Distribution.DMail'; 521 type MessageAttestation struct { 522 IdMessage int64 `json:"id_message" sql_on_delete:"CASCADE"` 523 Distribution Distribution `json:"distribution"` 524 525 GuardKind MessageKind `json:"guard_kind"` 526 } 527 528 // MessageMessage complète l'accès à un message libre 529 // sql:ADD UNIQUE(id_message) 530 // contraintes d'intégrité : 531 // sql:ADD CHECK(guard_kind = #MessageKind.MResponsable OR guard_kind = #MessageKind.MCentre) 532 // sql:ADD FOREIGN KEY (id_message, guard_kind) REFERENCES messages(id,kind) 533 type MessageMessage struct { 534 IdMessage int64 `json:"id_message" sql_on_delete:"CASCADE"` 535 Contenu String `json:"contenu"` 536 537 GuardKind MessageKind `json:"guard_kind"` 538 } 539 540 // ---------------------------- Users ---------------------------- 541 542 // User représente un utilisateur du client 543 type User struct { 544 Id int64 `json:"id"` 545 Label String `json:"label"` 546 Mdp String `json:"mdp"` 547 IsAdmin Bool `json:"is_admin"` 548 Modules Modules `json:"modules"` 549 }