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  }