"""Export Excel de la liste des bénévoles d'une édition — voir `app/api/volunteers.py:export_volunteers`. Même bibliothèque que l'import (`openpyxl`, `app/importing/parser.py`), en écriture cette fois. Texte en dur (en-têtes de colonnes, libellés) : comme `app/sheets/pdf.py` et `app/badges/pdf.py`, un document généré n'est pas un texte d'interface — pas de `app.i18n.t()` ici, contrairement aux réponses de l'API.""" import io import uuid from openpyxl import Workbook from openpyxl.styles import Font from app.api.schemas import VolunteerRead _HEADER = [ "Prénom", "Nom", "Email", "Téléphone", "Disponible", "Postes souhaités", "Artistes souhaités", "Compagnons souhaités", "Note de compagnon", "Cotisation choisie", "Montant (€)", "Statut du paiement", "Payée le", "Mécénat — adresse", "Mécénat — ville", "Mécénat — code postal", "Mécénat — pays", "Commentaire", "Inscrit le", ] _FEE_STATUS_LABELS = { "PENDING": "En attente", "PAID": "Payée", "FAILED": "Échouée", "EXPIRED": "Expirée", } def _yes_no(value: bool) -> str: return "Oui" if value else "Non" def _join_names(ids: list[uuid.UUID], names: dict[uuid.UUID, str]) -> str: return ", ".join(names[i] for i in ids if i in names) def _fmt_dt(value) -> str: return value.strftime("%d/%m/%Y %H:%M") if value else "" def generate_volunteers_xlsx( volunteers: list[VolunteerRead], *, position_names: dict[uuid.UUID, str], artist_names: dict[uuid.UUID, str], volunteer_names: dict[uuid.UUID, str], ) -> bytes: """`position_names`/`artist_names`/`volunteer_names` : cartes id → nom construites une fois par l'appelant (pas de requête par bénévole) — voir `app/api/volunteers.py:export_volunteers`.""" workbook = Workbook() sheet = workbook.active sheet.title = "Bénévoles" sheet.append(_HEADER) for cell in sheet[1]: cell.font = Font(bold=True) for v in volunteers: sheet.append( [ v.first_name, v.last_name, v.email or "", v.phone or "", _yes_no(v.self_declared_available), _join_names(v.wished_position_ids, position_names), _join_names(v.artist_ids, artist_names), _join_names(v.wished_companion_ids, volunteer_names), v.companion_wish_note or "", v.fee_payment_label or "", v.fee_amount if v.fee_amount is not None else "", _FEE_STATUS_LABELS.get(v.fee_payment_status, ""), _fmt_dt(v.fee_paid_at), v.mecenat_address or "", v.mecenat_city or "", v.mecenat_postal_code or "", v.mecenat_country or "", v.comment or "", _fmt_dt(v.created_at), ] ) for column_cells in sheet.columns: length = max( (len(str(c.value)) for c in column_cells if c.value is not None), default=8, ) sheet.column_dimensions[column_cells[0].column_letter].width = min( max(length + 2, 10), 40 ) buffer = io.BytesIO() workbook.save(buffer) return buffer.getvalue()