Commit Graph
667 Commits
Author SHA1 Message Date
frommeandClaude Opus 5 c5685e6d7c feat: add paginated travel export endpoint for the teamer app
GET /api/travels/export flattens the XML export into one row per travel
date x hotel with its pickups resolved, so the Teamer app can import the
disposition in one walk instead of fanning out over /api/travels.

Built from the XML file map, not travel_snapshot: the snapshot table sits
at this grain but refreshes on its own schedule, while the loaders share
the bpn.cache pool under the xml-sync tag. That is what makes /api/hotels,
/api/pickups and this export move together for free.

Each Ziel_*.xml is walked once and TravelParser::getPickups() does the
zeit parsing, which buys both zeit shapes and adjustOvernightTimes() --
a time-only 02:15 listed after a 23:59 rolls onto the next calendar day.
Pickups join against PickupLoader::loadAll() rather than
patchPickupsDetails(), which sorts: the contract is source order.

The whole assembled export is cached, not a page, so skipped, total and
pickupsWithoutMasterData are whole-export figures identical on every page
and a consumer can abort after the first one. Errors stay real status
codes; the builder is deliberately not wrapped in a catch that would
answer 200 with an error body the way hotelAvailability() does.

The route is declared before api_travel_single_code and that route grows
a requirement, or /api/travels/export resolves to byCode('export') and
404s as though the endpoint existed with no data.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-29 12:13:55 +02:00
frommeandClaude Opus 5 0a5602fd41 fix: skip travels whose hotel is missing from the master data
generateFilesMap() read ->name straight off $hotels[$hotelId] with no
guard, so a travel referencing a hotel absent from hotel.xml produced an
undefined-key warning and an entry with a null label -- a hotel in
/api/travels that resolves nowhere. No row hits this in the current
snapshot, which is why it has never surfaced.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-29 12:08:07 +02:00
frommeandClaude Opus 5 f3745f918e feat: expose hotel cost unit and iso country code via the api
The Teamer app groups hotels by cost unit and renders a flag per
destination, and cannot derive either from what /api/hotels returns
today.

costUnit is the raw kostenstelle and stays a string: only 281 of 1931
hotels carry one and some hold a space-separated list such as "84 85".

countryCode goes through CountryCodeMapper, whose table is part of the
API contract: BusPro's land column mixes ISO-2, ISO-3 and European
vehicle registration codes for the same country, and a wrong entry
mislabels a destination's flag silently. An unmappable token is null and
warns on the bpn channel, never a guess. country itself is untouched --
it remains the join key into /api/countries[].token.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-29 12:07:13 +02:00
fromme d0e7ba017c fix: resync room selections with travel data before step 2 2026-09-29 10:59:13 +02:00
fromme f5e6d2105d feat: make boarding point price levelling switchable 2026-09-29 10:11:03 +02:00
fromme 0c6126010f fix: always adopt outbound pickup price for inbound when set 2026-09-28 16:33:36 +02:00
fromme 29f295abf6 feat: duplicate an accommodation booking into a new draft
addresses #869f6z44f
2026-09-28 08:55:01 +02:00
fromme 2aa98b81fe feat: dedicated login page for oauth2 logins 2026-09-27 13:43:17 +02:00
fromme 56adf72d12 fix: refuse implausible accommodation booking prices 2026-09-26 15:39:04 +02:00
fromme 773cd4f847 fix: keep post-booking newsletter failures out of the booking flow 2026-09-26 14:00:26 +02:00
fromme 876e69e62c feat: offer a newsletter opt-in for the other participants
addresses #869etn6c5
2026-09-26 13:53:10 +02:00
fromme 96b7b3f451 fix: anonymize user first and last names 2026-09-23 17:22:19 +02:00
fromme bad916cfb7 feat: identify accounts by a uuid in the oauth2 sub claim 2026-09-23 15:17:09 +02:00
fromme cc3d32fcbb feat: gate oauth2 authorization on per-client roles 2026-09-23 13:46:56 +02:00
fromme ab7d00b35d feat: emit team admin role in userinfo claims when applicable 2026-09-21 11:43:36 +02:00
frommeandClaude Opus 5 f080d05dd6 fix: normalize the login email case
The login address was only trimmed, so the casing somebody happened to type at
their very first login was frozen into the user row forever — createOrUpdateLocalUser()
never wrote the address back. Everything downstream re-sends the stored address
rather than the one just authenticated with, which also leaked that casing into the
OAuth2 email claim and the log identities.

Harmless in practice, since BusPro matches an address case-insensitively and so does
the utf8mb4_unicode_ci column, but it left User out of step with the newsletter
entities, which have always normalized.

Fold the case once in authenticate(), which covers the BusPro calls, the lookup and a
new account alike, and write the address back on every login so an account created
before this converges instead of staying frozen. No backfill: a row nobody logs into
again is matched case-insensitively either way.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 10:03:06 +02:00
fromme fbb3ebb8c1 fix: make bpn response failures diagnosable 2026-09-19 11:51:15 +02:00
fromme ec83ad598f feat: identify the authenticated account in the userinfo claims 2026-09-19 10:54:06 +02:00
fromme 2cb4871268 chore: update wording of role labels 2026-09-17 18:18:13 +02:00
fromme 540cd8eeb7 feat: reserve administrative roles for staff email addresses 2026-09-17 18:13:52 +02:00
fromme 725e32daab feat: gender role label correctly 2026-09-16 15:33:40 +02:00
fromme 160ebef39e fix: stop offering unbookable services in the booking edit flow 2026-09-16 15:28:07 +02:00
fromme 12fe4d8e15 feat: offer contact validation flow 2026-09-16 10:40:01 +02:00
fromme 5d7ffd7d58 feat: configurable recipient list for notifications of role nominations 2026-09-16 09:21:04 +02:00
fromme 019de4e705 feat: surface stuck booking edits to customer experts 2026-09-15 15:13:47 +02:00
fromme a1d1fdde14 feat: gate functionality for customer expert users 2026-09-15 15:13:47 +02:00
fromme 1d14f00bb7 feat: additional role 'customer expert' 2026-09-15 15:00:59 +02:00
fromme 042037867b feat: cli command to repair corrupted booking snapshots 2026-09-15 13:57:41 +02:00
fromme 91522ab32d fix: anonymize the person ids, not the participant slot ids 2026-09-14 15:37:38 +02:00
fromme a3e8c737de fix: key participant status like the participants they belong to 2026-09-14 15:13:21 +02:00
fromme 7aad54e6f2 fix: keep the booking room assignment when restoring an edit draft 2026-09-14 15:02:04 +02:00
fromme b41820c39d feat: email the administrators when a role nomination appears 2026-09-13 12:50:01 +02:00
fromme fab89dead6 feat: derive ROLE_EMPLOYEE from the account's email domain 2026-09-13 12:49:51 +02:00
fromme 5b133f724d chore: cgl fixes 2026-09-11 19:37:00 +02:00
fromme 5f8a586385 fix: derive contingent change signal from the sync diff 2026-09-11 19:34:29 +02:00
fromme 1d3263373e feat: update filename formatting of booking confirmation pdf 2026-09-09 08:39:10 +02:00
fromme f8ff4b82a3 feat: replace custom discount with absolute value in favor of percentage 2026-09-08 17:11:00 +02:00
fromme d6c2cfaf1c fix: remove incorrect validation group 2026-09-08 16:25:43 +02:00
fromme cfe901b9c2 feat: include accommodation bookings in db anonymization 2026-09-08 15:41:28 +02:00
fromme 8443dae5ad feat: additional custom discount applied to total price 2026-09-08 15:29:00 +02:00
fromme 45ca0d2b46 feat: maintenance mode 2026-09-08 12:35:50 +02:00
fromme 976b30ccc0 feat: add cms product code for future use 2026-09-03 17:40:29 +02:00
fromme f595183c05 fix: don't require email address from participants under 16 2026-09-01 15:15:58 +02:00
Björn Fromme e14d29f7d4 fix: restore room occupancy lost to case-sensitive xml attribute lookup 2026-08-31 14:15:21 +02:00
Björn Fromme 81b724c11a fix: false draft-restored message 2026-08-31 09:31:00 +02:00
Björn Fromme 010cfe56b2 feat: upgrade project to symfony 7.4 2026-08-31 09:03:44 +02:00
Björn Fromme bbc1b6c68a feat: make booking init flow entry-point post only 2026-08-29 09:37:23 +02:00
Björn Fromme 80d734e7d6 feat: derive calendar date range from price configurations 2026-08-26 13:32:25 +02:00
Björn Fromme 61e020c3d0 feat: sort bookings by creation date in dashboard widget 2026-08-25 16:37:27 +02:00
Björn Fromme 4e6aaba9ff feat: admin dashboard widgets 2026-08-25 16:31:45 +02:00