github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/core/utils/pdf/fiche_sanitaire.go (about) 1 package pdf 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "math" 8 "os" 9 "os/exec" 10 "path/filepath" 11 12 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 13 ) 14 15 const ( 16 okR, okG, okB = 20, 140, 30 // couleur pour absence de problème 17 cR, cG, cB = 80, 80, 50 // couleur responsable légal, médecin traitant 18 19 mentionLegale = `Le responsable légal autorise le responsable du séjour à prendre, le cas échéant, 20 <b>toutes mesures</b> (traitement médical, hospitalisation, intervention chirurgicale) 21 rendues nécessaires par l'état du participant. 22 Il autorise également, si nécessaire, le directeur du séjour à faire sortir le participant 23 de l’hôpital après une hospitalisation.` 24 ) 25 26 func line(pdf CustomPdf, lh float64) { 27 pdf.Line(pdf.GetX(), pdf.GetY(), pdf.GetX()+pdf.AreaWidth(), pdf.GetY()) 28 pdf.Ln(0.5 * lh) 29 } 30 31 // Implémente la génération de la fiche sanitaire à partir 32 // des données définies par le package rd. 33 func FicheSanitaire(personne, responsable rd.Personne, out io.Writer) error { 34 pdf := InitPdfDetails(false, true) 35 oneFicheSanitaire(pdf, personne, responsable) 36 return pdf.Output(out) 37 } 38 39 // FicheSanitaires génère une fiche sanitaire par page. 40 func FicheSanitaires(personnes, responsables []rd.Personne, out io.Writer) error { 41 pdf := InitPdfDetails(false, false) 42 for i := range personnes { 43 personne, responsable := personnes[i], responsables[i] 44 oneFicheSanitaire(pdf, personne, responsable) 45 } 46 return pdf.Output(out) 47 } 48 49 // add one page and write the FS 50 func oneFicheSanitaire(pdf CustomPdf, personne, responsable rd.Personne) { 51 fs := personne.FicheSanitaire 52 pdf.AddPage() 53 prenom := rd.FormatPrenom(personne.Prenom) 54 pdf.DrawHeader([]string{ 55 personne.NomPrenom().String(), 56 "né(e) le " + personne.DateNaissance.String(), 57 personne.Sexe.String().String(), 58 }, 36, 28) 59 pdf.SetFont("Arial", "B", 16) 60 pdf.CellFormat(0, 20, "Fiche sanitaire de liaison", "", "MC", false) 61 pdf.Ln(-1) 62 63 pdf.SetFontStyle("") 64 pdf.SetFontSize(10) 65 lh := pdf.LineHeight() 66 h := pdf.HTMLBasicNew() 67 mL, _, mR, _ := pdf.GetMargins() 68 69 if fs.Handicap { 70 h.Write(lh, pdf.Tr(fmt.Sprintf("%s est en situation de <b>handicap</b>.", prenom))) 71 } else { 72 pdf.SetTextColor(okR, okG, okB) 73 h.Write(lh, pdf.Tr(fmt.Sprintf("%s ne présente pas de situation de handicap.", prenom))) 74 pdf.SetTextColor(0, 0, 0) 75 } 76 pdf.Ln(1.5 * lh) 77 78 if fs.TraitementMedical { 79 h.Write(lh, pdf.Tr(fmt.Sprintf("%s suit un <b>traitement médical</b> pendant le séjour.", prenom))) 80 } else { 81 pdf.SetTextColor(okR, okG, okB) 82 h.Write(lh, pdf.Tr(fmt.Sprintf("%s ne suit pas de traitement médical pendant le séjour.", prenom))) 83 pdf.SetTextColor(0, 0, 0) 84 } 85 pdf.Ln(1.5 * lh) 86 87 maladies := fs.Maladies.List() 88 if len(maladies) == 0 { 89 pdf.SetTextColor(okR, okG, okB) 90 h.Write(lh, pdf.Tr(fmt.Sprintf("%s n'a eu aucune maladie.", prenom))) 91 pdf.SetTextColor(0, 0, 0) 92 } else { 93 h.Write(lh, pdf.Tr(fmt.Sprintf("%s a eu les <b>maladies</b> suivantes:", prenom))) 94 } 95 for index, mal := range maladies { 96 if index%2 == 0 { 97 pdf.Ln(-1) 98 } 99 offset := float64(index%2) * pdf.AreaWidth() / 2 100 pdf.Circle(mL+leftListSpacing+offset, pdf.GetY()+2, 0.7, "F") 101 pdf.SetX(mL + leftListSpacing + 2 + offset) 102 h.Write(lh, pdf.Tr("<i>"+mal+"</i>")) 103 } 104 pdf.Ln(1.5 * lh) 105 106 line(pdf, lh) 107 allergies := fs.Allergies.List() 108 if len(allergies) == 0 { 109 pdf.SetTextColor(okR, okG, okB) 110 h.Write(lh, pdf.Tr(fmt.Sprintf("%s ne présente aucune allergie.", prenom))) 111 pdf.SetTextColor(0, 0, 0) 112 } else { 113 h.Write(lh, pdf.Tr(fmt.Sprintf("%s présente les <b>allergies</b> suivantes:", prenom))) 114 } 115 for index, al := range allergies { 116 if index%2 == 0 { 117 pdf.Ln(-1) 118 } 119 offset := float64(index%2) * pdf.AreaWidth() / 2 120 pdf.Circle(mL+leftListSpacing+offset, pdf.GetY()+2, 0.7, "F") 121 pdf.SetX(mL + leftListSpacing + 2 + offset) 122 h.Write(lh, pdf.Tr("<i>"+al+"</i>")) 123 } 124 pdf.Ln(1.5 * lh) 125 if fs.Allergies.ConduiteATenir != "" { 126 pdf.Ln(0.3 * lh) 127 h.Write(lh, pdf.Tr("<b>Conduite à tenir :</b>")) 128 pdf.Ln(-1) 129 pdf.SetFontSize(9) 130 pdf.SetFontStyle("I") 131 pdf.MultiCell(0, pdf.LineHeight(), pdf.Tr(fs.Allergies.ConduiteATenir), "", "", false) 132 pdf.Ln(1.5 * lh) 133 pdf.SetFontSize(10) 134 line(pdf, lh) 135 } 136 137 if fs.DifficultesSante != "" { 138 h.Write(lh, pdf.Tr("<b>Difficultés de santé :</b>")) 139 pdf.Ln(-1) 140 pdf.SetFontSize(9) 141 pdf.SetFontStyle("I") 142 pdf.MultiCell(0, pdf.LineHeight(), pdf.Tr(fs.DifficultesSante), "", "", false) 143 pdf.Ln(0.5 * lh) 144 pdf.SetFontSize(10) 145 } 146 147 if fs.Recommandations != "" { 148 h.Write(lh, pdf.Tr("<b>Recommandations :</b>")) 149 pdf.Ln(-1) 150 pdf.SetFontSize(9) 151 pdf.SetFontStyle("I") 152 pdf.MultiCell(0, pdf.LineHeight(), pdf.Tr(fs.Recommandations), "", "", false) 153 pdf.Ln(0.5 * lh) 154 pdf.SetFontSize(10) 155 } 156 157 pdf.SetTextColor(cR, cG, cB) 158 line(pdf, lh) 159 h.Write(lh, pdf.Tr("<b>Coordonnées du responsable légal :</b>")) 160 pdf.Ln(-1) 161 y := pdf.GetY() 162 pdf.SetRightMargin(mL + pdf.AreaWidth()/2 - 5) 163 pdf.SetFontSize(9) 164 h.Write(lh, pdf.Tr(responsable.NomPrenom().String())) 165 pdf.Ln(-1) 166 h.Write(lh, pdf.Tr("<b>Sécurité sociale :</b> "+rd.FormatSecuriteSocial(responsable.SecuriteSociale).String())) 167 pdf.Ln(-1) 168 if fs.Tel != "" { 169 h.Write(lh, pdf.Tr("<b>Numéro d'urgence :</b> "+rd.FormatTel(fs.Tel))) 170 } 171 172 pdf.SetRightMargin(mR) 173 pdf.SetLeftMargin(mL + pdf.AreaWidth()/2 + 5) 174 y1 := pdf.GetY() 175 pdf.SetY(y) 176 177 pdf.MultiCell(0, lh, pdf.Tr(string(responsable.Adresse)), "", "", false) 178 h.Write(lh, pdf.Tr(fmt.Sprintf("%s %s %s", responsable.CodePostal, responsable.Ville, responsable.Pays))) 179 pdf.Ln(-1) 180 h.Write(lh, fmt.Sprintf("<b>Tels. :</b> %s", responsable.Tels.String())) 181 pdf.SetY(math.Max(y1, pdf.GetY())) 182 183 pdf.SetLeftMargin(mL) 184 pdf.SetFontSize(10) 185 pdf.Ln(1.5 * lh) 186 line(pdf, lh) 187 h.Write(lh, pdf.Tr(fmt.Sprintf("<b>Médecin traitant:</b> %s <b>Tél. :</b> %s", fs.Medecin.Nom, rd.FormatTel(fs.Medecin.Tel)))) 188 189 // autorisations 190 191 pdf.SetTextColor(0, 0, 0) 192 pdf.Ln(1.5 * lh) 193 line(pdf, lh) 194 pdf.Ln(-1) 195 // TODO: cleanup selon décision 196 // h.Write(lh, pdf.Tr("<b>Autorisation et signature</b>")) 197 h.Write(lh, pdf.Tr("<b>Autorisation</b>")) 198 pdf.Ln(1.5 * lh) 199 h.Write(lh, pdf.Tr(mentionLegale)) 200 } 201 202 func CheckPdfToolkit() error { 203 cmd := exec.Command("pdftk", "--version") 204 if err := cmd.Run(); err != nil { 205 return fmt.Errorf("L'utilitaire pdftk n'est pas disponible : %v", err) 206 } 207 return nil 208 } 209 210 func MergePdfs(pages [][]byte, out io.Writer) error { 211 dir, err := ioutil.TempDir("", "merge_fiche_sanitaire") 212 if err != nil { 213 return fmt.Errorf("Création d'un dossier temporaire pour pdftk impossible: %s", err) 214 } 215 defer os.RemoveAll(dir) 216 217 pagePaths := make([]string, len(pages)) 218 for i, page := range pages { 219 pagePaths[i] = filepath.Join(dir, fmt.Sprintf("page%d.pdf", i)) 220 if err := ioutil.WriteFile(pagePaths[i], page, os.ModePerm); err != nil { 221 return fmt.Errorf("Enregistrement de la page %d impossible: %s", i, err) 222 } 223 } 224 225 args := append(pagePaths, "cat", "output", "-") 226 cmd := exec.Command("pdftk", args...) 227 cmd.Stdout = out 228 err = cmd.Run() 229 if err != nil { 230 return fmt.Errorf("Exécution de la commande externe pdftk impossible: %s", err) 231 } 232 return err 233 }