Étape 62 : les fiches de poste intégraient la photo d'origine de chaque bénévole pour chaque créneau (CPU à 300 %, puis erreur) — photos réduites à la vignette une fois par PDF ; badges : photo recadrée une fois par génération et décodée à taille réduite. Étape 61 : sans photo, le cadre de la photo reste vide sur le badge. Étape 60 : vue par bénévole en tranches de 30 min, affectations étirées sur toute leur durée, postes simultanés empilés, ligne de l'heure actuelle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
126 lines
4.3 KiB
Python
126 lines
4.3 KiB
Python
"""Texte résolu des champs du badge — fonctions pures (pas de base)."""
|
||
|
||
import datetime as dt
|
||
import uuid
|
||
|
||
from app.api.badges import _field_text, _positions_table
|
||
from app.models import (
|
||
BadgeField,
|
||
BadgeFieldType,
|
||
Position,
|
||
PositionCategory,
|
||
Shift,
|
||
Volunteer,
|
||
)
|
||
|
||
|
||
def _volunteer(**kw) -> Volunteer:
|
||
return Volunteer(id=uuid.uuid4(), edition_id=uuid.uuid4(), **kw)
|
||
|
||
|
||
def _position(**kw) -> Position:
|
||
return Position(id=uuid.uuid4(), edition_id=uuid.uuid4(), category=PositionCategory.BAR, **kw)
|
||
|
||
|
||
def _shift(start: dt.datetime, end: dt.datetime) -> Shift:
|
||
return Shift(
|
||
id=uuid.uuid4(), edition_id=uuid.uuid4(), position_id=uuid.uuid4(),
|
||
starts_at=start, ends_at=end,
|
||
)
|
||
|
||
|
||
_BOUNDARY = dt.time(2, 0) # journée de festival de 02:00 à 02:00
|
||
|
||
|
||
def test_positions_table_groups_shifts_under_their_day():
|
||
accueil = (
|
||
_position(name="Accueil"),
|
||
_shift(dt.datetime(2026, 7, 11, 9, 0), dt.datetime(2026, 7, 11, 13, 0)),
|
||
)
|
||
bar = (
|
||
_position(name="Bar central"),
|
||
_shift(dt.datetime(2026, 7, 11, 19, 0), dt.datetime(2026, 7, 11, 22, 0)),
|
||
)
|
||
demontage = (
|
||
_position(name="Démontage"),
|
||
_shift(dt.datetime(2026, 7, 12, 14, 0), dt.datetime(2026, 7, 12, 18, 0)),
|
||
)
|
||
|
||
table = _positions_table([accueil, bar, demontage], _BOUNDARY)
|
||
|
||
assert [(s.title, s.rows) for s in table.sections] == [
|
||
("Samedi 11", (("09:00–13:00", "Accueil"), ("19:00–22:00", "Bar central"))),
|
||
("Dimanche 12", (("14:00–18:00", "Démontage"),)),
|
||
]
|
||
|
||
|
||
def test_positions_table_keeps_a_night_shift_on_the_day_it_started():
|
||
night = (
|
||
_position(name="Bar central"),
|
||
_shift(dt.datetime(2026, 7, 12, 0, 0), dt.datetime(2026, 7, 12, 1, 0)),
|
||
)
|
||
|
||
table = _positions_table([night], _BOUNDARY)
|
||
|
||
assert table.sections[0].title == "Samedi 11"
|
||
assert table.sections[0].rows == (("00:00–01:00", "Bar central"),)
|
||
|
||
|
||
def test_positions_table_is_empty_without_any_shift():
|
||
assert _positions_table([], _BOUNDARY) is None
|
||
|
||
|
||
def test_field_text_role_is_referent_only_for_lead_accounts():
|
||
volunteer = _volunteer(first_name="Sam", last_name="Nuit")
|
||
field = BadgeField(
|
||
edition_id=uuid.uuid4(), field_type=BadgeFieldType.ROLE,
|
||
x_mm=0, y_mm=0, width_mm=10, height_mm=10, font_size=9,
|
||
)
|
||
|
||
assert _field_text(field, volunteer, {}, lead_volunteer_ids=set()) == "Bénévole"
|
||
assert _field_text(field, volunteer, {}, lead_volunteer_ids={volunteer.id}) == "Référent"
|
||
|
||
|
||
def test_field_text_free_text_is_the_volunteer_badge_text():
|
||
field = BadgeField(
|
||
edition_id=uuid.uuid4(), field_type=BadgeFieldType.FREE_TEXT,
|
||
x_mm=0, y_mm=0, width_mm=10, height_mm=10, font_size=8, color="#000000",
|
||
)
|
||
with_text = _volunteer(first_name="Alex", last_name="Martin", badge_text="Accès backstage")
|
||
without = _volunteer(first_name="Sam", last_name="Nuit")
|
||
|
||
assert _field_text(field, with_text, {}, set()) == "Accès backstage"
|
||
assert _field_text(field, without, {}, set()) == ""
|
||
|
||
|
||
def test_field_text_free_text_falls_back_to_the_common_editor_text():
|
||
field = BadgeField(
|
||
edition_id=uuid.uuid4(), field_type=BadgeFieldType.FREE_TEXT,
|
||
x_mm=0, y_mm=0, width_mm=10, height_mm=10, font_size=8, color="#000000",
|
||
text="Staff 2026",
|
||
)
|
||
own = _volunteer(first_name="Alex", last_name="Martin", badge_text="Accès backstage")
|
||
other = _volunteer(first_name="Sam", last_name="Nuit")
|
||
|
||
assert _field_text(field, own, {}, set()) == "Accès backstage"
|
||
assert _field_text(field, other, {}, set()) == "Staff 2026"
|
||
|
||
|
||
def test_field_text_full_name_is_first_name_then_last_name_on_two_lines():
|
||
volunteer = _volunteer(first_name="Alex", last_name="Martin")
|
||
field = BadgeField(
|
||
edition_id=uuid.uuid4(), field_type=BadgeFieldType.FULL_NAME,
|
||
x_mm=0, y_mm=0, width_mm=10, height_mm=10, font_size=9,
|
||
)
|
||
assert _field_text(field, volunteer, {}, set()) == "Alex\nMartin"
|
||
|
||
|
||
def test_field_text_photo_is_empty():
|
||
volunteer = _volunteer(first_name="alex", last_name="martin")
|
||
field = BadgeField(
|
||
edition_id=uuid.uuid4(), field_type=BadgeFieldType.PHOTO,
|
||
x_mm=0, y_mm=0, width_mm=10, height_mm=10, font_size=9,
|
||
)
|
||
# Une image, pas un texte : rien n'est imprimé sans photo.
|
||
assert _field_text(field, volunteer, {}, set()) == ""
|