-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(PC-30007)[API] feat: add pdf to beneficiary extract #12936
base: master
Are you sure you want to change the base?
Conversation
a603d49
to
fb6aa7b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
J'ai pas mal de commentaires mais sur la seule lecture du code.
Je n'ai pas testé ce que ça rend visuellement.
pdf_bytes = generate_pdf_from_html(html_content=html_content) | ||
file_info = zipfile.ZipInfo( | ||
filename=f"{container.internal.user.firstName} {container.internal.user.lastName}.pdf", | ||
date_time=datetime.utcnow().timetuple()[:6], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il n'y a pas de notion de fuseau horaire dans ce champ.
Ne voudrait-on pas la date locale dans le fichier ?
Cela n'a cependant pas une extrême importance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tu veux dire en se basant sur le département du user ? cette méthode étant appelée avec une cloud task potentiellement des heures/jours après la demande je en sais pas si ça a du sens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oui ça pourrait être tout simplement :
date_time=utc_datetime_to_department_timezone(datetime.utcnow(), container.internal.user.departementCode).timetuple()[:6]
voire même sans le second paramètre si on considère que c'est généré à Paris.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mais c'est assez secondaire, c'est juste une date de fichier.
<meta charset="utf-8"> | ||
<title>Réponse à ta demande d'accès</title> | ||
<style> | ||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,600;0,700;0,800;1,400'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il me semblait qu'on avait souhaité avoir toutes les ressources locales, et ne pas importer des URL externes dans le code. Cela ne serait-il pas le cas ici aussi ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C'est repris de la template utilisée en Finance. Je pars du principe que si c'est ok pour eux ça l'est aussi pour nous (si l'appel échoue ça ne fait pas échouer le rendu, ça met juste pas la bonne police)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je ne crois pas que ce soit une question de disponibilité de la ressource, mais plus une question de sécurité.
margin: 2cm 1cm; | ||
@bottom-left { | ||
font-size: 6pt; | ||
content: "Pass Culture - SAS au capital de 1,000,000 € - 87/89 rue de la Boétie 75008 PARIS - RCS Paris B 853 318 459 – Siren 853318459 – NAF 7021 Z - N° TVA FR65853318459"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1,000,000 € est une écriture anglophone.
content: "Pass Culture - SAS au capital de 1,000,000 € - 87/89 rue de la Boétie 75008 PARIS - RCS Paris B 853 318 459 – Siren 853318459 – NAF 7021 Z - N° TVA FR65853318459"; | |
content: "Pass Culture - SAS au capital de 1 000 000 € - 87/89 rue de la Boétie 75008 PARIS - RCS Paris B 853 318 459 – Siren 853318459 – NAF 7021 Z - N° TVA FR65853318459"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c'est le pieds de page de la Finance, donc je ne pense pas le modifier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ou alors modifier aussi dans la page de finance ? 🙂
Qui est responsable du modèle ?
b1b94aa
to
1156d48
Compare
1156d48
to
9d5997e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Voici mes remarques en testant la branche dans mon environnement de développement.
Même s'il y a des petites choses à corriger dans le formatage, je trouve le rendu super propre !
@@ -1263,6 +1262,9 @@ def create_extract_user_gdpr_data(user_id: int) -> utils.BackofficeResponse: | |||
if not user: | |||
raise NotFound() | |||
|
|||
if not (user.is_beneficiary or user.roles == []): | |||
raise NotFound() | |||
|
|||
if has_gdpr_extract(user=user): | |||
flash("Une extraction de données est déjà en cours pour cet utilisateur.", "error") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Par homogénéité et parce qu'en testant, "error"
n'affiche aucun fond :
flash("Une extraction de données est déjà en cours pour cet utilisateur.", "error") | |
flash("Une extraction de données est déjà en cours pour cet utilisateur.", "warning") |
@@ -175,16 +180,27 @@ def _extract_brevo_data(user: users_models.User) -> dict: | |||
def _dump_as_json_bytes(container: serializers.DataContainer) -> tuple[zipfile.ZipInfo, bytes]: | |||
json_bytes = container.json(indent=4).encode("utf-8") | |||
file_info = zipfile.ZipInfo( | |||
filename=f"{container.internal.user.firstName}_{container.internal.user.lastName}.json", | |||
filename=f"{container.internal.user.firstName} {container.internal.user.lastName}.json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
je ne suis aps fan d'avoir un @
dans un nom de fichier mais je vais chercher une solution a ce probleme
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tu peux mettre le User ID, je proposais l'email car c'est le nom du fichier zip au moment du téléchargement, donc je pensais que ça te convenait 🙂
<tr><td>Nom</td><td>{{container.internal.user.firstName}}</td></tr> | ||
<tr><td>Prénom</td><td>{{container.internal.user.lastName}}</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<tr><td>Valeur</td><td>{{('%0.2f' % deposit.amount|float) | replace('.', ',')}}€</td></tr> | ||
<tr><td>Source</td><td>{{deposit.source}}</td></tr> | ||
{% if deposit.dateUpdated %}<tr><td>Dernière modification</td><td>{{deposit.dateUpdated.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr>{% endif %} | ||
<tr><td>Type de crédit</td><td>{{deposit.type.value}}</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<table class="borderless"> | ||
<tr><td>Date d'obtention</td><td>{{deposit.dateCreated.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr> | ||
{% if deposit.expirationDate %}<tr><td>Date d'expiration</td><td>{{deposit.expirationDate.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr>{% endif %} | ||
<tr><td>Valeur</td><td>{{('%0.2f' % deposit.amount|float) | replace('.', ',')}}€</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<tr><td>Valeur</td><td>{{('%0.2f' % deposit.amount|float) | replace('.', ',')}}€</td></tr> | |
<tr><td>Valeur</td><td>{{('%0.2f' % deposit.amount|float) | replace('.', ',')}} €</td></tr> |
<table class="borderless"> | ||
<tr><td>Nom</td><td>{{booking.name}}</td></tr> | ||
<tr><td>Quantité</td><td>{{booking.quantity}}</td></tr> | ||
<tr><td>Prix unitaire</td><td>{{'%0.2f' % booking.amount|float }}€</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<tr><td>Date de réservation</td><td>{{booking.dateCreated.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr> | ||
{% if booking.dateUsed %}<tr><td>Date de retrait</td><td>{{booking.dateUsed.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr>{% endif %} | ||
{% if booking.cancellationDate %}<tr><td>Date d'annulation</td><td>{{booking.cancellationDate.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr>{% endif %} | ||
<tr><td>État</td><td>{{booking.status.value}}</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<table class="borderless"> | ||
<tr><td>Date de la validation</td><td>{{validation.dateCreated.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr> | ||
<tr><td>Moyen de la validation</td><td>{{validation.type.value}}</td></tr> | ||
{% if validation.status %}<tr><td>Résultat</td><td>{{validation.status.value}}</td></tr>{%endif%} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{% endif %} | ||
|
||
{% if history in container.internal.emailsHistory %} | ||
<h3>📧 <span class=underline>Historique des changements d'adresse de messagerie</span></h3> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
J'ai testé sur un utilisateur pour lequel j'ai changé deux fois l'email depuis le backoffice : cet historique n'apparaît pas. Dans la table user_email_history
, l'eventType
est ADMIN_UPDATE
, qui n'est pas dans la liste de la fonction _extract_email_history
. Cela mériterait d'étoffer le test auto pour s'assurer que ce cas fonctionne, car il s'agit d'une information personnelle importante.
De plus, dans cette même fonction, ne devrait-on pas se baser sur CONFIRMATION
plutôt que UPDATE_REQUEST
? À tester de bout en bout.
{% for action in container.internal.actionsHistory %} | ||
<table class="borderless"> | ||
<tr><td>Date</td><td>{{action.actionDate.strftime('%d/%m/%Y %H:%M:%S')}}</td></tr> | ||
<tr><td>Action</td><td>{{action.actionType.value}}</td></tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Peut-être souhaite-t-on garder la raison la suspension confidentielle, cependant je pense qu'on devrait au moins préciser si la suspension est à la demande de l'utilisateur ou par le pass Culture. Qu'en pense le DPO ?
But de la pull request
Ticket Jira (ou description si BSR) : https://passculture.atlassian.net/browse/PC-30007
Note le rendu du pdf final a été validé par le DPO (le client de la feature)
Vérifications