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  }