github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/client/controllers/cont_personnes.go (about) 1 package controllers 2 3 import ( 4 "fmt" 5 "net/http" 6 "strings" 7 8 "github.com/benoitkugler/goACVE/server/core/apiserver" 9 dm "github.com/benoitkugler/goACVE/server/core/datamodel" 10 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 11 ) 12 13 const ( 14 HistoriqueCamp rd.Field = iota 15 HistoriqueAnnee 16 HistoriqueRole 17 ) 18 19 type ButtonsPersonnes struct { 20 Creer, AfficherCriteres, AfficherDocuments, Supprimer EtatSideButton 21 } 22 23 type OngletPersonnes interface { 24 baseOnglet 25 26 ConfirmeSupprimePersonne(pers dm.AccesPersonne) bool 27 ConfirmeSupprimeOrganisme(org dm.AccesOrganisme) bool 28 } 29 30 type EtatPersonnes struct { 31 ItemCurrent rd.IId // personne ou organisme 32 Recherche string 33 CriteresTri dm.CriteresTri 34 CritereShowTemporaire rd.Bool 35 CritereShowOrganismes rd.OptionnalBool // oui = orga seul, non = personnes seul, indif = tous 36 } 37 38 type Personnes struct { 39 Onglet OngletPersonnes 40 main *MainController 41 Liste rd.Table 42 Header []rd.Header 43 Base *dm.BaseLocale 44 Etat EtatPersonnes 45 DeleteRight, EditRight bool // Droit de suppression, droit d'ajout/edition 46 } 47 48 func NewPersonnes(main *MainController, permission int) *Personnes { 49 p := Personnes{main: main, Base: main.Base, DeleteRight: permission >= 4, EditRight: permission >= 2, 50 Header: []rd.Header{ 51 {Field: dm.PersonneNomPrenom, Label: "Nom"}, 52 {Field: dm.PersonneSexe, Label: "Sexe"}, 53 {Field: dm.PersonneDateNaissance, Label: "Date de naissance"}, 54 {Field: dm.PersonneMail, Label: "Adresse mail"}, 55 {Field: dm.PersonneAdresse, Label: "Adresse"}, 56 {Field: dm.PersonneCodePostal, Label: "Code postal"}, 57 {Field: dm.PersonneVille, Label: "Ville"}, 58 {Field: dm.PersonnePays, Label: "Pays"}, 59 {Field: dm.PersonneRangMembreAsso, Label: "Association"}, 60 {Field: dm.PersonneCotisation, Label: "Cotisation"}, 61 }, 62 Etat: EtatPersonnes{CriteresTri: dm.CriteresTri{Fields: []dm.Critere{{Field: dm.PersonneNomPrenom}}}}, 63 } 64 p.resetData() 65 return &p 66 } 67 68 func (c *Personnes) resetData() { 69 c.Liste = nil 70 71 if c.Etat.CritereShowOrganismes != rd.OBOui { 72 for id, p := range c.Base.Personnes { 73 if c.Etat.CritereShowTemporaire == p.IsTemporaire { 74 c.Liste = append(c.Liste, c.Base.NewPersonne(id).AsItem(0)) 75 } 76 } 77 } 78 79 if c.Etat.CritereShowOrganismes != rd.OBNon { 80 // on affiche aussi les organismes 81 for id := range c.Base.Organismes { 82 c.Liste = append(c.Liste, c.Base.NewOrganisme(id).AsItem()) 83 } 84 } 85 86 if search := strings.TrimSpace(c.Etat.Recherche); search != "" { 87 c.Liste = dm.RechercheDetaillee(c.Liste, search, c.Header) 88 } 89 // besoin de déselectionner si absent de la Recherche : 90 if c.Etat.ItemCurrent != nil && !HasId(c.Liste, c.Etat.ItemCurrent) { 91 c.Etat.ItemCurrent = nil 92 } 93 dm.SortCriteres(c.Liste, c.Etat.CriteresTri) 94 } 95 96 func (c *Personnes) SideButtons() ButtonsPersonnes { 97 bs := ButtonsPersonnes{ 98 AfficherCriteres: ButtonActivated, 99 AfficherDocuments: ButtonActivated, 100 } 101 if c.EditRight { 102 bs.Creer = ButtonActivated 103 } 104 if c.DeleteRight { 105 bs.Supprimer = ButtonPresent 106 if c.Etat.ItemCurrent != nil { 107 bs.Supprimer = ButtonActivated 108 } 109 } 110 return bs 111 } 112 113 // GetStats renvoi les statistiques courantes 114 func (c *Personnes) GetStats() []Stat { 115 var ph, pe, er, vp, as, ca, bu, nbTmp int 116 for _, p := range c.Base.Personnes { 117 if p.IsTemporaire { 118 nbTmp += 1 119 continue 120 } 121 if p.PubHiver { 122 ph += 1 123 } 124 if p.PubEte { 125 pe += 1 126 } 127 if p.EchoRocher { 128 er += 1 129 } 130 if p.VersionPapier { 131 vp += 1 132 } 133 switch p.RangMembreAsso { 134 case "1": 135 as += 1 136 case "2": 137 as += 1 138 ca += 1 139 case "3": 140 as += 1 141 ca += 1 142 bu += 1 143 } 144 } 145 return []Stat{ 146 {Label: "Nombre total de personnes", Value: fmt.Sprintf("%d (+ %d temporaires)", len(c.Base.Personnes)-nbTmp, nbTmp)}, 147 {Label: "Publicités Hiver / Eté", Value: fmt.Sprintf("%d / %d", ph, pe)}, 148 {Label: "Echo du Rocher (version papier)", Value: fmt.Sprintf("%d (%d)", er, vp)}, 149 {Label: "Membres Association / C.A. / Bureau", Value: fmt.Sprintf("%d / %d / %d", as, ca, bu)}, 150 } 151 } 152 153 // GetParentsEnfants renvoie les liens familliaux de la personne `id`, 154 // au sens des dossiers (responsable/participants) 155 func (c *Personnes) GetParentsEnfants(id rd.IdPersonne) (parents []dm.AccesPersonne, enfants []dm.AccesPersonne) { 156 cache, _ := c.Base.ResoudParticipants() 157 cribleEnfants, cribleParents := rd.NewSet(), rd.NewSet() 158 for _, dossier := range c.Base.Factures { 159 if dossier.IdPersonne == id.Int64() { 160 // on ajoute les participants comme 'enfants' 161 for _, part := range c.Base.NewFacture(dossier.Id).GetDossiers(cache) { 162 cribleEnfants.Add(part.GetPersonne().Id) 163 } 164 } 165 } 166 for _, part := range c.Base.Participants { 167 if part.IdPersonne == id.Int64() { 168 // on ajoute le responsable du dossier comme parent 169 if fac, has := c.Base.NewParticipant(part.Id).GetFacture(); has { 170 cribleParents.Add(fac.GetPersonne().Id) 171 } 172 } 173 } 174 for i := range cribleParents { 175 parents = append(parents, c.Base.NewPersonne(i)) 176 } 177 for i := range cribleEnfants { 178 enfants = append(enfants, c.Base.NewPersonne(i)) 179 } 180 return 181 } 182 183 // GetHistorique renvoie l'historique (comme participant et équipier) de la personne donnée 184 func (c *Personnes) GetHistorique(idPersonne int64) rd.Table { 185 var out rd.Table 186 for _, part := range c.Base.Participants { 187 if part.IdPersonne == idPersonne { 188 camp := c.Base.NewParticipant(part.Id).GetCamp().RawData() 189 fields := rd.F{ 190 HistoriqueCamp: camp.Label(), 191 HistoriqueAnnee: camp.Annee(), 192 HistoriqueRole: part.ListeAttente.String(), 193 } 194 out = append(out, rd.Item{Fields: fields}) 195 } 196 } 197 for _, part := range c.Base.Equipiers { 198 if part.IdPersonne == idPersonne { 199 camp := c.Base.NewParticipant(part.Id).GetCamp().RawData() 200 fields := rd.F{ 201 HistoriqueCamp: camp.Label(), 202 HistoriqueAnnee: camp.Annee(), 203 HistoriqueRole: part.Roles, 204 } 205 out = append(out, rd.Item{Fields: fields}) 206 } 207 } 208 return out 209 } 210 211 // CreePersonne crée un nouveau profil sur le serveur 212 func (c *Personnes) CreePersonne(pers rd.Personne) { 213 job := func() (interface{}, error) { 214 var out rd.Personne 215 err := requete(apiserver.UrlPersonnes, http.MethodPut, pers, &out) 216 return out, err 217 } 218 onSuccess := func(_out interface{}) { 219 out := _out.(rd.Personne) 220 c.Base.Personnes[out.Id] = out 221 c.Etat.ItemCurrent = rd.IdPersonne(out.Id) 222 c.main.ShowStandard(fmt.Sprintf("Personne %s créée avec succès.", out.NomPrenom()), false) 223 c.Reset() 224 } 225 c.main.ShowStandard("Création de la personne...", true) 226 c.main.Background.Run(job, onSuccess) 227 } 228 229 // UpdatePersonne met à jour le profil transmis sur le serveur 230 func (c *Personnes) UpdatePersonne(pers rd.Personne) { 231 job := func() (interface{}, error) { 232 var out rd.Personne 233 err := requete(apiserver.UrlPersonnes, http.MethodPost, pers, &out) 234 return out, err 235 } 236 onSuccess := func(_out interface{}) { 237 out := _out.(rd.Personne) 238 c.Base.Personnes[out.Id] = out 239 c.main.ShowStandard(fmt.Sprintf("Personne %s mise à jour avec succès.", out.NomPrenom()), false) 240 c.main.ResetAllControllers() 241 } 242 243 c.main.ShowStandard("Mise à jour de la personne...", true) 244 c.main.Background.Run(job, onSuccess) 245 } 246 247 // CreeOrganisme crée un nouveau profil sur le serveur 248 func (c *Personnes) CreeOrganisme(org rd.Organisme) { 249 job := func() (interface{}, error) { 250 var out rd.Organisme 251 err := requete(apiserver.UrlOrganismes, http.MethodPut, org, &out) 252 return out, err 253 } 254 onSuccess := func(_out interface{}) { 255 out := _out.(rd.Organisme) 256 c.Base.Organismes[out.Id] = out 257 c.Etat.ItemCurrent = rd.IdOrganisme(out.Id) 258 c.main.ShowStandard(fmt.Sprintf("Organisme %s créé avec succès.", out.Nom), false) 259 c.Reset() 260 } 261 c.main.ShowStandard("Création de l'organisme...", true) 262 c.main.Background.Run(job, onSuccess) 263 } 264 265 // UpdateOrganisme met à jour le profil transmis sur le serveur, 266 // de manière asynchrone. 267 func (c *Personnes) UpdateOrganisme(org rd.Organisme) { 268 job := func() (interface{}, error) { 269 var out rd.Organisme 270 err := requete(apiserver.UrlOrganismes, http.MethodPost, org, &out) 271 return out, err 272 } 273 onSuccess := func(_out interface{}) { 274 out := _out.(rd.Organisme) 275 c.Base.Organismes[out.Id] = out 276 c.main.ShowStandard(fmt.Sprintf("Organisme %s mis à jour avec succès.", out.Nom), false) 277 c.main.ResetAllControllers() 278 } 279 280 c.main.ShowStandard("Mise à jour de l' organisme...", true) 281 c.main.Background.Run(job, onSuccess) 282 } 283 284 // checkSupprimePersonne vérifie que la personne donnée peut être supprimée 285 func (c *Personnes) checkSupprimePersonne(id int64) error { 286 for _, doc := range c.Base.DocumentPersonnes { 287 if doc.IdPersonne == id { 288 return fmt.Errorf("Id %d présent dans le document %d!", id, doc.IdDocument) 289 } 290 } 291 for _, donateur := range c.Base.DonDonateurs { 292 if donateur.IdPersonne.Is(id) { 293 return fmt.Errorf("Id %d présent dans le don %d !", id, donateur.IdDon) 294 } 295 } 296 for _, part := range c.Base.Participants { 297 if part.IdPersonne == id { 298 return fmt.Errorf("Id %d présent dans le participant %d !", id, part.Id) 299 } 300 } 301 for _, part := range c.Base.Participantsimples { 302 if part.IdPersonne == id { 303 return fmt.Errorf("Id %d présent dans le participant %d !", id, part.Id) 304 } 305 } 306 for _, equipier := range c.Base.Equipiers { 307 if equipier.IdPersonne == id { 308 return fmt.Errorf("Id %d présent dans l'équipier %d !", id, equipier.Id) 309 } 310 } 311 for _, fac := range c.Base.Factures { 312 if fac.IdPersonne == id { 313 return fmt.Errorf("Id %d présent dans la facture %d !", id, fac.Id) 314 } 315 } 316 for _, contrainte := range c.Base.Contraintes { 317 if contrainte.IdPersonne.Is(id) { 318 return fmt.Errorf("Id %d présent dans la contrainte %d !", id, contrainte.Id) 319 } 320 } 321 return nil 322 } 323 324 func (c *Personnes) supprimePersonne(id rd.IdPersonne) { 325 idP := id.Int64() 326 err := c.checkSupprimePersonne(idP) 327 if err != nil { 328 c.main.ShowError(err) 329 return 330 } 331 if !c.Onglet.ConfirmeSupprimePersonne(c.Base.NewPersonne(idP)) { 332 c.main.ShowStandard("Suppression annulée", false) 333 return 334 } 335 336 job := func() (interface{}, error) { 337 var out rd.Personne 338 err = requete(apiserver.UrlPersonnes, http.MethodDelete, IdAsParams(idP), &out) 339 return out, err 340 } 341 onSuccess := func(_out interface{}) { 342 out := _out.(rd.Personne) 343 c.main.ShowStandard(fmt.Sprintf("Personne %s supprimée avec succès.", out.NomPrenom()), false) 344 c.Etat.ItemCurrent = nil 345 delete(c.Base.Personnes, out.Id) 346 c.Reset() 347 } 348 349 c.main.ShowStandard("Suppression de la personne...", true) 350 c.main.Background.Run(job, onSuccess) 351 } 352 353 func (c *Personnes) supprimeOrganisme(id rd.IdOrganisme) { 354 idO := id.Int64() 355 if !c.Onglet.ConfirmeSupprimeOrganisme(c.Base.NewOrganisme(idO)) { 356 c.main.ShowStandard("Suppression annulée", false) 357 return 358 } 359 360 job := func() (interface{}, error) { 361 var out apiserver.DeleteOrganismeOut 362 err := requete(apiserver.UrlOrganismes, http.MethodDelete, IdAsParams(idO), &out) 363 return out, err 364 } 365 onSuccess := func(_out interface{}) { 366 out := _out.(apiserver.DeleteOrganismeOut) 367 c.main.ShowStandard(fmt.Sprintf("Organisme (id %d) supprimé avec succès.", out.Id), false) 368 c.Etat.ItemCurrent = nil 369 delete(c.Base.Organismes, out.Id) 370 for _, idDon := range out.Dons { 371 delete(c.Base.Dons, idDon) 372 delete(c.Base.DonDonateurs, idDon) 373 } 374 c.Reset() 375 } 376 377 c.main.ShowStandard("Suppression de l'organismes...", true) 378 c.main.Background.Run(job, onSuccess) 379 } 380 381 // SupprimeItem supprime l'item courant, après vérification 382 func (c *Personnes) SupprimeItem() { 383 switch item := c.Etat.ItemCurrent.(type) { 384 case rd.IdPersonne: 385 c.supprimePersonne(item) 386 case rd.IdOrganisme: 387 c.supprimeOrganisme(item) 388 } 389 } 390 391 // SelectPersonne sélectionne la personne donnée, en remettant à zéro la recherche 392 // si nécessaire. 393 func (c *Personnes) SelectPersonne(item dm.PersonneOrganisme) { 394 var id rd.IId 395 switch item := item.(type) { 396 case dm.AccesPersonne: 397 if _, in := c.Base.Personnes[item.Id]; !in { 398 c.main.ShowError(fmt.Errorf("La personne demandée (id %d) n'est pas dans la base !", item.Id)) 399 return 400 } 401 id = rd.IdPersonne(item.Id) 402 case dm.AccesOrganisme: 403 if _, in := c.Base.Organismes[item.Id]; !in { 404 c.main.ShowError(fmt.Errorf("L'organisme demandé (id %d) n'est pas dans la base !", item.Id)) 405 return 406 } 407 id = rd.IdOrganisme(item.Id) 408 default: 409 return 410 } 411 412 c.Etat.ItemCurrent = id 413 414 if !HasId(c.Liste, id) { 415 c.Etat.Recherche = "" // affiche toutes les personnes 416 c.Etat.CritereShowOrganismes = rd.OBPeutEtre 417 c.resetData() 418 } 419 c.Onglet.GrabFocus() 420 c.ResetRender() 421 }