763 Commits
Author SHA1 Message Date
fromme 67c685f6c1 chore: update project dependencies 2026-09-14 15:03:33 +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 443a3ed248 chore: update deployer config after final migration to new host 2026-09-12 08:22:11 +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 e863025fb1 chore: align local dev environment with prod 2026-09-11 19:24:32 +02:00
fromme 91a38faecd chore: update scheduler notification config 2026-09-11 12:58:09 +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 dea7a3dc97 chore: update wording of maintenance mode message 2026-09-08 13:53:08 +02:00
fromme 9e3be24c51 chore: cleanup obsolete environment variables 2026-09-08 13:02:08 +02:00
fromme e744ebbe33 chore: update project dependencies 2026-09-08 12:40:25 +02:00
fromme 45ca0d2b46 feat: maintenance mode 2026-09-08 12:35:50 +02:00
fromme f12561c62b feat: switch to sftp source for buspro xml data 2026-09-04 11:57:03 +02:00
fromme 976b30ccc0 feat: add cms product code for future use 2026-09-03 17:40:29 +02:00
fromme 198fbfe6a2 chore: prepare switching to sftp source for buspro xml data 2026-09-03 16:23:49 +02:00
fromme acb719730c feat: add root config option for sftp connection in flysystem 2026-09-03 10:24:01 +02:00
fromme 0e3d4cbedb chore: adjust deployer config for new hetzner host 2026-09-03 10:23:40 +02:00
fromme 715fae8e33 chore: add bpn xml api documentation extract for agents 2026-09-02 10:33:47 +02:00
fromme f595183c05 fix: don't require email address from participants under 16 2026-09-01 15:15:58 +02:00
fromme 98e0cfcf6f chore: remove obsolete deployer rsync fix 2026-09-01 10:58:39 +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 24df764efb chore: update project dependencies 2026-08-31 12:56:21 +02:00
Björn Fromme e3c08afe73 fix: adjust deployer config to prevent symlink loop issue with rsync 2026-08-31 12:55:28 +02:00
Björn Fromme 81b724c11a fix: false draft-restored message 2026-08-31 09:31:00 +02:00
Björn Fromme bfad61f1dd feat: upgrade phpunit to 12.5 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 c1fa08fed0 chore: add clickup http request file and credentials 2026-08-31 08:58:55 +02:00
Björn Fromme ec41e2b02d chore: update project dependencies 2026-08-31 08:58:34 +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
Björn Fromme 578a21d327 fix: stop mutating booking state on edit-mode page views 2026-08-24 17:13:19 +02:00
Björn Fromme c9c28792e5 fix: resolve stale dependent selections after booking family insurance 2026-08-24 16:58:09 +02:00
Björn Fromme 35826088cb feat: relax filtering constraints for non-admin groups price users 2026-08-24 14:32:45 +02:00
Björn Fromme 178df9b787 feat: update wording of booking button to better match actual function 2026-08-24 14:01:53 +02:00
Björn Fromme 96a39d5cb2 chore: update project dependencies 2026-08-24 14:01:53 +02:00
Björn Fromme 83b8ba7f8d docs: include previously ignored documentation files 2026-08-24 09:20:56 +02:00
Björn Fromme 1796ec4964 chore: update wording of inline comments 2026-08-24 09:19:32 +02:00
Björn Fromme 48db290625 feat: manually create customer access link for offer and update status
addresses #869eea8d7
2026-08-24 09:19:16 +02:00
Björn Fromme 7c5f6dd5ef feat: create ClickUp task after confirming accommodation booking 2026-08-20 17:56:29 +02:00
Björn Fromme 0a1683667f feat: explicit icon map for hotel cms-data response 2026-08-20 14:45:05 +02:00
Björn Fromme ef439f6faf feat: re-generate access links for bookings when sent via email 2026-08-20 14:21:02 +02:00
Björn Fromme 98a303e941 feat: delete accommodation bookings in draft 2026-08-20 12:39:45 +02:00
Björn Fromme 3db1850e4f feat: edit selected accommodation of bookings in draft 2026-08-20 12:34:44 +02:00
Björn Fromme c1f0cda479 feat: always sync full 24 months horizon of contingents 2026-08-20 12:03:21 +02:00
Björn Fromme 351fbab498 feat: improved contingents api performance with db backed snapshots 2026-08-20 11:46:03 +02:00
Björn Fromme d5f9f4ef10 chore: adopt namespace pattern for accommodation booking controllers 2026-08-19 17:07:57 +02:00
Björn Fromme e105c611be feat: flip region and additional info in accommodation offer view 2026-08-19 15:39:58 +02:00
Björn Fromme 6cdb331aae feat: return to detail view after editing accommodation booking 2026-08-19 15:39:30 +02:00
Björn Fromme 7b0bf9ec94 feat: make cells clickable in accommodation booking list view 2026-08-19 15:39:09 +02:00
Björn Fromme 8617bf6c86 fix: prevent generating offer links while booking is in draft 2026-08-19 13:00:43 +02:00
Björn Fromme 2601e46ec4 fix: never persist a half-built user on first login 2026-08-19 12:30:42 +02:00
Björn Fromme 0c667d6b69 feat: align role assignment logic with myep-team 2026-08-19 12:14:09 +02:00
Björn Fromme 5a3957e143 feat: refactored accommodation booking status model 2026-08-19 11:46:52 +02:00
Björn Fromme e8accbb3ed feat: replace logo png with optimized version 2026-08-18 14:40:10 +02:00
Björn Fromme 2d7a02341d feat: booking details pdf 2026-08-18 14:26:24 +02:00
Björn Fromme d3666c4618 fix: skip discounts with value 0€ 2026-08-18 13:07:31 +02:00
Björn Fromme ef24c9a616 fix: streamlined discount display in all breakdowns 2026-08-18 13:04:33 +02:00
Björn Fromme 8dee65d0dc feat: additional confirmation cycle and status for groups inquiries 2026-08-18 12:48:17 +02:00
Björn Fromme 5045846eed fix: propagate updated at timestamp to parent entity 2026-08-18 09:52:28 +02:00
Björn Fromme e8143c055b fix: always redirect to account page first on login 2026-08-17 16:38:35 +02:00
Björn Fromme 920b09dacc fix: render admin menus conditionally 2026-08-17 16:30:12 +02:00
Björn Fromme b5f1163e2d fix: handle access denied errors properly 2026-08-17 16:29:58 +02:00
Björn Fromme 8271a69f45 fix: avoid content shift caused by scrollbar 2026-08-17 16:14:25 +02:00
Björn Fromme f00351706e feat: extract collapsible container into partial 2026-08-17 16:07:26 +02:00
Björn Fromme a5d97f1206 feat: enable entering additional remarks in offer confirmation 2026-08-17 15:30:17 +02:00
Björn Fromme 582e54ddc4 feat: insert final email texts 2026-08-17 14:36:10 +02:00
Björn Fromme adee913568 chore: update project dependencies 2026-08-17 14:25:56 +02:00
Björn Fromme 396aa0bac6 fix: correct semantic html structure in offer template 2026-08-17 14:25:27 +02:00
Björn Fromme 77de1643f0 feat: import users` real names from bpn API 2026-08-17 14:24:56 +02:00
Björn Fromme bf69fcceff feat: reword flash messages, add logging 2026-08-13 15:08:34 +02:00
Björn Fromme d74127ebe2 fix: drop the implicit ROLE_USER from the userinfo roles claim 2026-08-12 17:47:44 +02:00
Björn Fromme aa486a4931 feat: expose person_id and address_id as separate userinfo claims 2026-08-12 17:47:29 +02:00
Björn Fromme 7ebd2dad1a feat: restrict admin role assignment to the privileged roles 2026-08-12 17:47:21 +02:00
Björn Fromme 7a82127494 feat: sync non-privileged BusPro roles on every login 2026-08-12 17:47:15 +02:00
Björn Fromme 490acc2e8b chore: correct stale role_hierarchy comments 2026-08-12 17:47:01 +02:00
Björn Fromme 6af8044f7c fix: collect hotel codes from every CRM selection group 2026-08-12 17:46:33 +02:00
Björn Fromme 70a10c4dba fix: make email readonly in personal data form to prevent user lockout 2026-08-11 18:08:48 +02:00
Björn Fromme a1506ef58d chore: update project dependencies, fix deprecated config setting 2026-08-11 11:45:58 +02:00
Björn Fromme af04ff690d fix: enable bookings without ski passes 2026-08-11 11:16:11 +02:00
Björn Fromme 6c1073e41c feat: admin-managed roles and hotel codes 2026-08-10 10:07:24 +02:00
Björn Fromme 124c0af0f5 fix: assign proper administrative permissions 2026-08-07 08:42:54 +02:00
Björn Fromme 212bb660a1 chore: update project dependencies 2026-08-06 13:12:40 +02:00
Björn Fromme 6ee00f2bee feat: hide unavailable ski passes from selection in create flow 2026-08-06 13:08:46 +02:00
Björn Fromme b82e017f73 fix: exclude past dates in price tables 2026-08-06 12:19:30 +02:00
Björn Fromme 577f7445ab fix: correctly calculate undersubscription fees 2026-08-06 12:05:03 +02:00
Björn Fromme 3a5895e356 feat: extended role hierarchy 2026-08-06 11:18:38 +02:00
Björn Fromme dd658bf9d6 feat: admin list filtering and search 2026-08-06 10:57:36 +02:00
Björn Fromme aa8fa5c1b2 feat: accommodation booking type and status as dedicated properties 2026-08-06 08:52:09 +02:00
Björn Fromme 2cfa87f44b feat: indicate family insurance eligibility 2026-08-05 15:11:58 +02:00
Björn Fromme 0b642dcfe4 fix: reconcile assigned family insurance rate on updated participant 2026-08-05 15:11:48 +02:00
Björn Fromme 8a46908856 fix: incorrect rules around family insurances
addresses #869dr80qj
2026-08-05 15:11:37 +02:00
Björn Fromme 736128476b feat: assignable managers for accommodation bookings 2026-08-05 13:45:33 +02:00
Björn Fromme 8e4afc0813 feat: dedicated terms urls per country for accommodation bookings 2026-08-05 12:38:34 +02:00
Björn Fromme e5fa63b7e8 feat: dedicated logos per country for accommodation bookings 2026-08-05 12:28:43 +02:00
Björn Fromme 84df3a94d9 chore: update project dependencies 2026-08-05 09:02:14 +02:00
Björn Fromme 2c381ee741 feat: additional status 2026-08-04 18:09:40 +02:00
Björn Fromme dc86e715cb feat: create new bookings or inquiries on behalf of customer 2026-08-04 17:29:05 +02:00
Björn Fromme 5f2252af71 fix: render field in order with other fields 2026-08-04 17:11:53 +02:00
Björn Fromme 455456b6bc feat: manual sorting of additional services 2026-08-04 17:06:41 +02:00
Björn Fromme 045fdea923 chore: cleanup documents 2026-08-04 16:43:06 +02:00
Björn Fromme 8ff13614d2 fix: treat dates without price as unavailable 2026-08-04 11:29:58 +02:00
Björn Fromme 331c88c38e feat: exclusion groups for additional services 2026-08-04 10:24:29 +02:00
Björn Fromme c31d086356 fix: avoid form jumping to top after making a selection 2026-08-04 09:42:01 +02:00
Björn Fromme dde36ccba2 feat: use dedicated sender for accommodation related emails 2026-08-04 09:21:00 +02:00
Björn Fromme 97d98f7f12 fix: show missing fields' label in flash message 2026-08-03 19:51:38 +02:00
Björn Fromme 0546f223f0 fix: correct icon rendering on offer page 2026-08-03 19:37:04 +02:00
Björn Fromme 6b807f358e fix: correctly generate redirect url after form submission 2026-08-03 18:28:16 +02:00
Björn Fromme 6f84fc755b feat: replace board service placeholder to avoid duplicate entries 2026-08-03 18:22:07 +02:00
Björn Fromme b54c8917c9 feat: add logging to contingent api endpoint 2026-08-03 17:59:19 +02:00
Björn Fromme efc385bf54 fix: remove irrelevant schema drift from migration 2026-08-03 17:24:31 +02:00
Björn Fromme 18b59534f0 fix: typos in migration classes 2026-08-03 17:20:14 +02:00
Björn Fromme 8a361ee703 chore: update placehoder text 2026-08-03 16:37:35 +02:00
Björn Fromme 0f1f65fb79 feat: control menu items visibility per role 2026-08-03 16:29:21 +02:00
Björn Fromme 0b21bb00cb feat: sort groups price services by price first, then alphabetically 2026-08-03 16:23:47 +02:00
Björn Fromme 9d2aa11fdb feat: groups price calculator admin crud, booking/offer flow and api 2026-08-03 15:25:10 +02:00
Björn Fromme eabed8295a feat: adopt provided label for parking space service from xml data 2026-08-03 09:07:18 +02:00
Björn Fromme 7ec3903bdf chore: update project dependencies 2026-08-01 16:19:50 +02:00
Björn Fromme c929d4da3b feat: show tooltips for parking space option and omit price when 0,00
addresses #869ebkmhw
2026-08-01 16:19:14 +02:00
Björn Fromme 10d5356381 chore: update project dependencies 2026-07-23 17:54:47 +02:00
Björn Fromme b323c120f9 fix: consider parking space availability 2026-07-23 17:44:08 +02:00
Björn Fromme fafc60eba9 fix: retain original date of birth when anonymizing xml dumps 2026-07-16 15:53:33 +02:00
Björn Fromme bd2d8b58a3 chore: update documentation 2026-07-15 18:00:30 +02:00
Björn Fromme 52327864d6 chore: adjust cypress base url 2026-07-15 17:47:37 +02:00
Björn Fromme 3cc5d00587 feat: add insurance revocation link to footer 2026-07-14 12:27:29 +02:00
Björn Fromme f620cae4f9 chore: update project dependencies 2026-07-14 09:47:48 +02:00
Björn Fromme 6c4ea07e6e fix: prevent race condition on newsletter consent confirmation 2026-07-14 09:47:22 +02:00
Björn Fromme b95944701e chore: update project dependencies 2026-07-13 14:19:15 +02:00
Björn Fromme 2f8701c2e0 chore: fix cgl issues flagged by phpstan 2026-07-10 14:33:09 +02:00
Björn Fromme f47142c465 chore: add missing branch coverage for BookingEditPreFlightChecker 2026-07-10 14:33:09 +02:00
Björn Fromme 3105f2e7a0 fix: position loading indicator above modal 2026-07-10 14:33:09 +02:00
Björn Fromme 0ea43d0c6b fix: correct edit reload dirty-state 2026-07-10 14:33:09 +02:00
Björn Fromme 99b6876ce2 fix: ensure mandatory services are preselected in edit mode 2026-07-10 14:33:09 +02:00
Björn Fromme 4e26b8acc0 fix: reload booking data from API when no user edits are pending 2026-07-10 14:33:09 +02:00
Björn Fromme 0b2a16d117 fix: add placeholders for fields nationality and country 2026-07-10 14:33:09 +02:00
Björn Fromme b41b19d4c6 feat: pre-flight check of agency bookings
addresses #869bqxr4q
2026-07-10 14:33:09 +02:00
Björn Fromme f9142e3080 chore: update frontend tooling and dependencies 2026-07-10 14:31:47 +02:00
Björn Fromme 9660149c67 fix: prevent stale htmx cache on login potentially causing csrf issues
addresses #869dd1fch
2026-07-10 14:30:31 +02:00
Björn Fromme 2b957e1887 feat: revert password grant in favor of pkce 2026-07-10 12:26:26 +02:00
Björn Fromme 57a2503da2 chore: update project dependencies 2026-07-10 09:07:22 +02:00
Björn Fromme f5f84ad98e feat: password grant 2026-07-10 09:02:33 +02:00
Björn Fromme de37186706 feat: make server errors visible to the user for htmx requests 2026-07-02 10:02:05 +02:00
Björn Fromme 4d3fc69faa fix: register field handler in service container correctly 2026-07-02 09:33:16 +02:00
Björn Fromme 022819cbe6 feat: reveal password toggle for login form
addresses #869cqrw6w
2026-07-01 10:29:30 +02:00
Björn Fromme 1b0d7ce1a9 chore: update project dependencies 2026-07-01 10:21:41 +02:00
Björn Fromme a6ed60462d refactor: inject AgeConstraintParserRegistry into TravelParser 2026-06-26 17:20:42 +02:00
Björn Fromme a8d2852313 fix: log swallowed exceptions in date parsing and webhook 2026-06-26 17:17:49 +02:00
Björn Fromme 8907233ef5 fix: adopt response format of bpn personal data endpoint 2026-06-25 15:06:15 +02:00
Björn Fromme 7a3d3a3a96 fix: handle bpn notification response on personal data update 2026-06-25 15:06:15 +02:00
Björn Fromme 23a3430ea5 fix: skip blank xml nodes and attributes when anonymizing data 2026-06-24 13:59:04 +02:00
Björn Fromme a15c7578c3 fix: do not copy applicant address into participant for agency bookings 2026-06-24 13:13:14 +02:00
Björn Fromme 08f6633507 fix: sync booking model when transportation discount is replaced 2026-06-23 16:24:15 +02:00
Björn Fromme dbe33ec760 fix: exclude name and date of birth from editable fields for now 2026-06-23 15:47:33 +02:00
Björn Fromme 145f7de781 fix: make personal data editable in bookings as permitted by bpn 2026-06-23 15:24:10 +02:00
Björn Fromme 287ec30cf7 chore: simplify datatable css 2026-06-23 15:22:33 +02:00
Björn Fromme c29634b0d2 fix: narrow scope of table styles 2026-06-23 15:19:26 +02:00
Björn Fromme ffa2038acb fix: correct test references to use selection ID 1475 for exemption 2026-06-23 13:41:03 +02:00
Björn Fromme febbf8dd1d fix: pass hotelId when loading travel data for booking edit 2026-06-23 13:36:15 +02:00
Björn Fromme 09610ab3cd chore: update deployer config with basic auth for staging environment 2026-06-23 12:15:08 +02:00
Björn Fromme 33328074b0 chore: update project dependencies 2026-06-23 08:18:31 +02:00
Björn Fromme 1dc14a193a chore: update project dependencies 2026-06-22 09:03:47 +02:00
Björn Fromme 2fc7ffe458 feat: remove easy admin bundle, adopt admin theme 2026-06-22 08:59:47 +02:00
Björn Fromme 52ee6b26b1 feat: full anonymization of buspro xml dumps 2026-06-21 16:49:54 +02:00
Björn Fromme d77f92b6f0 fix: increase width of modal container 2026-06-18 10:06:06 +02:00
Björn Fromme e65cd3a96e chore: update project dependencies 2026-06-17 10:32:23 +02:00
Björn Fromme 80569e0977 feat: cli command to anonymize local database 2026-06-17 10:32:02 +02:00
Björn Fromme 66d0f511df chore: update project dependencies 2026-06-15 14:24:32 +02:00
Björn Fromme 93201fbd20 feat: disable body dimensions validation for selection id 1475
closes #869dne7qt
2026-06-12 11:39:32 +02:00
Björn Fromme b2fccae431 chore: remote obsolete contingents-related plumbing 2026-06-11 16:19:14 +02:00
Björn Fromme 8c99fba6fa chore: update project dependencies 2026-06-11 15:54:26 +02:00
Björn Fromme d207bc74cb feat: force booking status 'O' for selection id 1473
addresses #869d79q0r
2026-06-11 15:53:56 +02:00
Björn Fromme bcf75ce3c3 chore: update project dependencies 2026-06-10 11:44:29 +02:00
Björn Fromme d08d9dbb9f feat: make body dimensions optional even with rentals selected 2026-06-10 11:43:59 +02:00
Björn Fromme 33f0cb04e0 feat: update newsletter list ids 2026-06-09 14:18:01 +02:00
Björn Fromme 3fb95cab92 fix: prefill correct value for country in dummy data 2026-06-08 17:18:42 +02:00
Björn Fromme b768af15fe chore: update project dependencies 2026-06-08 08:33:33 +02:00
Björn Fromme 00889318ee fix: validate body dimensions when rentals are selected only 2026-06-02 14:22:47 +02:00
Björn Fromme f023bd9772 chore: remove redundant instance check flagged by phpstan 2026-05-28 15:49:09 +02:00
Björn Fromme 4ec1935eef fix: avoid phpstan crashing with multiple processes in parallel 2026-05-28 15:46:56 +02:00
Björn Fromme ee8c6a6545 fix: normalize non-numeric body dimension values of existing drafts 2026-05-28 15:35:34 +02:00
Björn Fromme 02b1cbfd6c chore: update project dependencies 2026-05-28 15:34:53 +02:00
Björn Fromme 97f88d5eeb fix: accept response code 422 in htmx as 'should swap' 2026-05-28 15:02:53 +02:00
Björn Fromme 5561a24050 chore: fix deprecations in flysystem config 2026-05-28 13:59:55 +02:00
Björn Fromme bdf8cffd04 feat: replace dropdowns with individual fields for body dimensions 2026-05-28 13:59:30 +02:00
Björn Fromme fa7e5c2091 chore: update project dependencies 2026-05-28 09:37:12 +02:00
Björn Fromme f1a5d478f3 chore: update project dependencies 2026-05-18 12:48:22 +02:00
Björn Fromme de4dadb9e5 feat: mention selected port by api client in log messages 2026-05-18 12:48:07 +02:00
Björn Fromme b18b09d4a5 chore: update project dependencies 2026-05-15 09:40:27 +02:00
Björn Fromme 3f66cb89e6 fix: cleanup mailjet webhook logging 2026-05-13 17:34:15 +02:00
Björn Fromme 495c130e79 chore: update project dependencies 2026-05-13 08:30:50 +02:00
Björn Fromme 7dfbc06bd1 feat: only handle unsubscribe events for configured list ids 2026-05-13 08:30:22 +02:00
Björn Fromme 132dfc6860 chore: update project dependencies 2026-05-11 11:04:22 +02:00
Björn Fromme e647b6c1f0 fix: remove messenger task from schedule to be run separately 2026-05-11 11:03:20 +02:00
Björn Fromme 8b3ef0df95 chore: update deployer config to be run on the host 2026-05-10 14:57:09 +02:00
Björn Fromme 224673a2c4 chore: update project dependencies 2026-05-07 11:41:09 +02:00
Björn Fromme eaff989bdd fix: always filter ski passes by participant's age 2026-05-07 11:40:45 +02:00
Björn Fromme 8ac62d2a02 chore: update project dependencies 2026-05-04 17:21:16 +02:00
Björn Fromme 1fa8f88a6d chore: code cleanup with rector and php-cs-fixer 2026-05-04 17:20:01 +02:00
Björn Fromme d211425ff2 chore: integrate with rector 2026-05-04 17:19:35 +02:00
Björn Fromme 5b16a515f3 fix: add missing scheduler task for messenger 2026-05-02 14:17:09 +02:00
Björn Fromme 259cbd02c5 fix: reduce logger noise 2026-04-30 15:17:21 +02:00
Björn Fromme 014a057164 chore: cleanup email template 2026-04-30 14:49:34 +02:00
Björn Fromme 9ebfdb3d95 chore: update project dependencies 2026-04-30 12:32:09 +02:00
Björn Fromme 4f6b82daa8 chore: fix phpstan errors, add inline docs 2026-04-30 12:31:58 +02:00
Björn Fromme 77ad96baf9 fix: ensure MailJet exclusion flag is revoked for new subscriptions 2026-04-30 12:24:42 +02:00
Björn Fromme 68900dd4ea fix: use plain password in configuration for MailJet webhook url 2026-04-30 11:44:17 +02:00
Björn Fromme c0c8ad515c fix: properly handle 'veg' services in booking edit flow 2026-04-29 11:59:39 +02:00
Björn Fromme 287c299c41 feat: improved performance by avoiding redundant MailJet API calls 2026-04-29 11:18:52 +02:00
Björn Fromme a2bcedafc4 feat: cli command to un-/register MailJet webhook url 2026-04-29 10:36:04 +02:00
Björn Fromme daf89f9189 fix: initialize DOI in booking create flow with newsletter subscription 2026-04-29 10:10:18 +02:00
Björn Fromme 2f96af9254 chore: remove obsolete command 2026-04-29 10:09:16 +02:00
Björn Fromme 18a97394e8 chore: cleanup, update project dependencies 2026-04-29 09:58:40 +02:00
Björn Fromme e4ef2f7adc feat: MailJet list handling with DOI, webhook receiver and API endpoint
addresses #869cut134
2026-04-29 09:51:57 +02:00
Björn Fromme df7885ca1c chore: update documentation files 2026-04-22 11:33:08 +02:00
Björn Fromme d5dfb6c550 fix: collect dataset transfer failures instead of breaking execution 2026-04-22 11:23:52 +02:00
Björn Fromme 9b84893d88 feat: api endpoints and xml sync for contingents data 2026-04-22 11:23:52 +02:00
Björn Fromme a1f68ec11d chore: adopt changed behavior from 02a1640b in test 2026-04-22 11:23:14 +02:00
Björn Fromme b9c6ace1da chore: remove obsolete packages, update dependencies 2026-04-22 11:22:38 +02:00
Björn Fromme c1c7466dc7 fix: add missing field handler registration 2026-04-21 16:01:48 +02:00
Björn Fromme 02a1640b51 feat: additional notification about invoice download
closes #869cxbk6c
2026-04-21 15:34:04 +02:00
Björn Fromme 083e68ee4d feat: placeholder text for room remarks field
closes #869ch2wv8
2026-04-21 15:10:50 +02:00
Björn Fromme 4f7cd2c025 chore: update project dependencies 2026-04-21 15:10:23 +02:00
Björn Fromme 80969d1da0 chore: further cleanup and refactor 2026-04-19 15:45:02 +02:00
Björn Fromme 5a0bf11c81 chore: update project dependencies 2026-04-19 13:58:39 +02:00
Björn Fromme ca6e38cb9c chore: replace global binds with dedicated service definition 2026-04-16 17:11:02 +02:00
Björn Fromme ca5a604a3e fix: corrupted logic of model transformer 2026-04-16 16:40:38 +02:00
Björn Fromme 0fcecc9c58 chore: fix phpstan errors 2026-04-16 16:27:35 +02:00
Björn Fromme 4e925171b3 chore: update frontend tooling 2026-04-16 13:47:26 +02:00
Björn Fromme 41e2fe19bc chore: update project dependencies 2026-04-16 13:39:35 +02:00
Björn Fromme a927d6bf59 chore: cgl cleanup 2026-04-16 13:34:54 +02:00
Björn Fromme c0cc183c59 feat: rename BookingSessionStore to BookingSessionManager 2026-04-16 13:34:54 +02:00
Björn Fromme b68c4ff9b4 chore: update booking-flow reference to current class names in docs 2026-04-16 13:34:54 +02:00
Björn Fromme 132329361f fix: pass logger explicitly to BookingCreateTrait::handleApiError 2026-04-16 13:34:54 +02:00
Björn Fromme 4d86629315 feat: move display-assembly out of BookingPriceCalculator 2026-04-16 13:34:54 +02:00
Björn Fromme d1c92f2957 feat: replace *Service suffix with role-based class names 2026-04-16 13:34:54 +02:00
Björn Fromme 0d2cc5b998 feat: consolidate micro-services and unify draft merge logic 2026-04-16 13:34:54 +02:00
Björn Fromme fdfd5d56c9 chore: add booking flow reference document 2026-04-16 13:34:54 +02:00
Björn Fromme 059c520a50 fix: link header logo with user profile page 2026-04-13 12:24:15 +02:00
Björn Fromme d8818dc435 feat: extract shared booking summary travel partial 2026-04-13 12:24:15 +02:00
Björn Fromme 2baa147afa feat: clarify booking summary participant count 2026-04-13 12:24:09 +02:00
Björn Fromme e179bbe259 feat: remove deprecated booking service alias 2026-04-13 12:23:57 +02:00
Björn Fromme 16cab4b768 feat: add typed dto for cms data 2026-04-12 18:17:54 +02:00
Björn Fromme 6ab34fa87c chore: merge service methods 2026-04-12 17:55:29 +02:00
Björn Fromme fcfd366dec chore: flatten namespace 2026-04-12 17:54:24 +02:00
Björn Fromme 98dd685679 feat: extract participant draft field applier 2026-04-12 14:40:05 +02:00
Björn Fromme 2597318488 chore: stabilize Bpn XML sync CLI assertions 2026-04-12 13:49:10 +02:00
Björn Fromme aa997826f8 feat: split summary DTOs into typed sub-objects 2026-04-12 11:23:19 +02:00
Björn Fromme 69705052b3 feat: centralize create/edit flow contexts, extract edit submit service 2026-04-12 10:17:04 +02:00
Björn Fromme f903f17ebd feat: replace edit participant facade with context factory 2026-04-11 18:28:32 +02:00
Björn Fromme 95d50e9833 fix: return proper response for stale participant edit urls 2026-04-11 18:28:32 +02:00
Björn Fromme 63e8a068b3 feat: move prepopulation guards into participant service 2026-04-11 18:28:32 +02:00
Björn Fromme dbc0b4acee feat: extract booking participant count service 2026-04-11 18:28:32 +02:00
Björn Fromme f31ac660d2 feat: extract room grouping from booking service 2026-04-11 18:28:32 +02:00
Björn Fromme 8b72f8c277 feat: extract booking session handling 2026-04-11 18:28:32 +02:00
Björn Fromme ca052682bb feat: simplify pricing and room selection display 2026-04-11 18:28:32 +02:00
Björn Fromme 1b0e479e49 feat: refactor participant card DTOs and labels 2026-04-11 18:28:32 +02:00
Björn Fromme f22ceae41c feat: split booking participant controllers 2026-04-11 18:28:32 +02:00
Björn Fromme 346256f895 feat: simplify booking pricing flow 2026-04-11 18:28:32 +02:00
Björn Fromme a0cbd5a23f chore: adjust http client config for mailjet api 2026-04-11 18:28:09 +02:00
Björn Fromme 803b0608cc chore: add test 2026-04-03 15:24:56 +02:00
Björn Fromme 7eb1cbdabd fix: remove redundant insurance hydration, cache snapshots and files map 2026-04-03 15:20:37 +02:00
Björn Fromme ca873a99f4 feat: improved button sizes in mobile view 2026-04-03 14:57:41 +02:00
Björn Fromme 8d666baf28 feat: back-button in booking create flow 2026-04-03 14:20:19 +02:00
Björn Fromme be0c9d67bb chore: update tests to adopt recent changes 2026-04-03 13:49:50 +02:00
Björn Fromme f0594ba09c chore: update project dependencies 2026-04-03 13:46:13 +02:00
Björn Fromme fce6d1615a chore: cleanup, add PHPStan type annotations 2026-04-03 13:45:41 +02:00
Björn Fromme a264526127 chore: integrate with PHPStan 2026-04-03 13:45:23 +02:00
Björn Fromme fbfffbb31a fix: simplify trait to address incorrect arguments 2026-03-28 10:18:34 +01:00
Björn Fromme bca3610cff feat: delete orphaned future snapshots after xml sync 2026-03-25 15:35:12 +01:00
Björn Fromme facd91375c chore: update project dependencies 2026-03-25 14:11:00 +01:00
Björn Fromme 96321005e0 feat: combine log entries into single sum-up entry 2026-03-25 14:10:25 +01:00
Björn Fromme 6f07678f04 fix: reduce snapshot payloads via serializer group and hydration 2026-03-24 17:06:10 +01:00
Björn Fromme 3b6ee90a7e feat: refresh existing snapshots from XML after sync 2026-03-24 11:13:11 +01:00
Björn Fromme 909e8a1d8e chore: update project dependencies 2026-03-23 19:41:04 +01:00
Björn Fromme 8f2baca339 chore: update scheduler config to delete expired oauth2 tokens 2026-03-23 19:38:12 +01:00
Björn Fromme 637166bfd6 chore: remove schema drift 2026-03-23 19:27:37 +01:00
Björn Fromme 45af3a21b7 chore: replace deprecated attribute 2026-03-23 19:23:59 +01:00
Björn Fromme 7e686cef6b chore: add inline documentation 2026-03-23 19:22:18 +01:00
Björn Fromme be43d30cc7 fix: skip snapshots of travels still available as XML from refreshing 2026-03-23 19:15:45 +01:00
Björn Fromme 77b16f287a chore: remove obsolete feature flag 2026-03-23 17:43:12 +01:00
Björn Fromme bc7fb794bf feat: persist travel snapshots and refresh extended availability 2026-03-23 17:29:10 +01:00
Björn Fromme c1ab6d8687 chore: adopt monolog config for staging environment from prod 2026-03-23 17:28:51 +01:00
Björn Fromme ccfafc5da4 fix: allow hotel-less travel data
addresses #869ckkwh7
2026-03-23 16:59:49 +01:00
Björn Fromme 502281e219 chore: add staging to http client environments 2026-03-23 11:50:40 +01:00
Björn Fromme b81cc58d5e chore: update http-client config 2026-03-20 14:24:04 +01:00
Björn Fromme 05ac07d656 fix: delete unavailable files during xml sync
addresses #869chrmp4
2026-03-20 14:23:51 +01:00
Björn Fromme 3234c78f0d feat: harden xml parsing to avoid uncaught errors 2026-03-20 12:14:02 +01:00
Björn Fromme 3849ae306c feat: extended log view and searching by error codes 2026-03-20 11:44:55 +01:00
Björn Fromme 301b14f518 feat: dedicated room pricing calculation for step 1 of create flow 2026-03-19 16:40:59 +01:00
Björn Fromme df8566e1b5 feat: move scope of enforced 'option' status to full booking
addresses #869chtfeq
2026-03-19 16:15:07 +01:00
Björn Fromme 45d05786da fix: correctly calculate room pricing based on participant assignment 2026-03-19 15:45:23 +01:00
Björn Fromme 6a6bebb2d1 feat: update wording and style of password reset flash message 2026-03-19 12:41:06 +01:00
Björn Fromme ea76c808de chore: update field label 2026-03-19 09:46:06 +01:00
Björn Fromme f9069540a9 chore: update project dependencies 2026-03-19 09:44:03 +01:00
Björn Fromme 8a9868b644 chore: update http request config with current travel date 2026-03-19 09:43:37 +01:00
Björn Fromme d1e2bf3e7d feat: integrate with MailJet API for newsletter registration 2026-03-19 09:42:00 +01:00
Björn Fromme 66c55f0722 chore: update project dependencies 2026-03-18 15:25:31 +01:00
Björn Fromme ca7d0b6965 feat: extended price mismatch diagnostics in logs 2026-03-18 15:24:52 +01:00
Björn Fromme 02ff28acdd fix: use correct amount of rooms to calculate rooms pricing 2026-03-18 15:24:29 +01:00
Björn Fromme cb56a4fe46 feat: implement mutability cutoff for rentals
addresses #869cca42x
2026-03-17 10:29:43 +01:00
Björn Fromme 752e6752b4 feat: limit room remarks field to 200 characters to align with buspro 2026-03-17 10:01:40 +01:00
Björn Fromme 00df76269a chore: cleanup after master flatten rewrite 2026-03-17 09:44:50 +01:00
Björn Fromme 99483b3506 chore: update project dependencies 2026-03-17 08:58:44 +01:00
Björn Fromme 5619a6f22f fix: XML scope for services too broad 2026-03-16 20:25:56 +01:00
Björn Fromme c510cbf590 feat: auto-booking services
addresses #869cfcptv
2026-03-16 20:24:58 +01:00
Björn Fromme 6d9265de0f fix: restore unintended file changes after master flatten rewrite 2026-03-16 14:15:51 +01:00
Björn Fromme 49ea562322 fix: enforce submit-time immutability, scope booking cache per user 2026-03-16 12:03:00 +01:00
Björn Fromme 1f087b6c08 chore: update test to recent changes 2026-03-16 12:03:00 +01:00
Björn Fromme 37c839600e fix: reduce mutability data cache ttl to avoid staleness
addresses #869cdzmkq
2026-03-16 12:03:00 +01:00
Björn Fromme cef2e4fa49 fix: ensure mutability is accounted for when restoring drafts
addresses #869cdzmkq
2026-03-16 12:03:00 +01:00
Björn Fromme 11ff2b9084 fix: assign mandatory services when applying dummy data 2026-03-16 12:03:00 +01:00
Björn Fromme 69f16b59cb chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme 0e644260b6 feat: update wording 2026-03-16 12:03:00 +01:00
Björn Fromme 33609ab534 feat: shortened and filename-safe request ids 2026-03-16 12:03:00 +01:00
Björn Fromme 1cc7a025a1 fix: ensure pickups node exists in api payload 2026-03-16 12:03:00 +01:00
Björn Fromme 709b0ff61e fix: ensure drop-offs are submitted when same as pickups 2026-03-16 12:03:00 +01:00
Björn Fromme 0d7d90a442 feat: anonymization command for request/response XML dumps 2026-03-16 12:03:00 +01:00
Björn Fromme 5cbdc5eaf2 chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme a7c3064df6 feat: adopt new pickups planning payload JSON structure 2026-03-16 12:03:00 +01:00
Björn Fromme f63d52c9d6 chore: cleanup 2026-03-16 12:03:00 +01:00
Björn Fromme b752256bda fix: validate mandatory services selection 2026-03-16 12:03:00 +01:00
Björn Fromme 474d171779 fix: correctly validate pickup selection
closes #869c94jqn
2026-03-16 12:03:00 +01:00
Björn Fromme 51ce9b6e45 fix: don't restore selections from draft for immutable fields 2026-03-16 12:03:00 +01:00
Björn Fromme 9cef24f827 fix: enforce mutability checks for all fields 2026-03-16 12:03:00 +01:00
Björn Fromme e6880b7fed chore: remove dead code 2026-03-16 12:03:00 +01:00
Björn Fromme e505eba111 chore: add git ignored temp directory 2026-03-16 12:03:00 +01:00
Björn Fromme 4e067d13b3 feat: avoid indexing of content by crawlers 2026-03-16 12:03:00 +01:00
Björn Fromme 40c0042158 feat: use normalized checkbox values in field handlers 2026-03-16 12:03:00 +01:00
Björn Fromme 6abfa122e4 chore: update plan for symfony 7.4 upgrade 2026-03-16 12:03:00 +01:00
Björn Fromme 032540a712 chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme cf95048f2b fix: prevent race conditions in htmx boost response handling 2026-03-16 12:03:00 +01:00
Björn Fromme 29a1ce7de7 fix: ensure loading indicator when entering booking flow in Chrome 2026-03-16 12:03:00 +01:00
Björn Fromme 1670b8b8d2 fix: avoid selection trap for mandatory services with age constraints 2026-03-16 12:03:00 +01:00
Björn Fromme 3644b935fd fix: always fill-in empty participants names when submitting to api 2026-03-16 12:03:00 +01:00
Björn Fromme 20162cceef chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme 44a9de7db7 fix: correct sort order of pickups and drop-offs 2026-03-16 12:03:00 +01:00
Björn Fromme f99a2d99a2 fix: show pickup select field for outbound bus travel only 2026-03-16 12:03:00 +01:00
Björn Fromme f795a3ea21 feat: selectable drop-offs for inbound bus travel 2026-03-16 12:03:00 +01:00
Björn Fromme f8a56b7de2 chore: split scheduler config for prod and staging 2026-03-16 12:03:00 +01:00
Björn Fromme 8a667ccaba chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme 6ddd0b00bd fix: handle empty api responses more gracefully 2026-03-16 12:03:00 +01:00
Björn Fromme c597cfda51 feat: legal links in page footer 2026-03-16 12:03:00 +01:00
Björn Fromme f673bc59d0 fix: catch unexpected api response for personal data 2026-03-16 12:03:00 +01:00
Björn Fromme 78b925daa6 fix: backward compatibility for new session format 2026-03-16 12:03:00 +01:00
Björn Fromme 4e05c94912 fix: correctly determine file size and avoid type mismatch 2026-03-16 12:03:00 +01:00
Björn Fromme acb599b760 feat: show booking status in sidebar 2026-03-16 12:03:00 +01:00
Björn Fromme c7b70dbd56 feat: dummy data fill
closes #869c3khk0
2026-03-16 12:03:00 +01:00
Björn Fromme b4f7299f27 chore: update project dependencies 2026-03-16 12:03:00 +01:00
Björn Fromme 6fd5a218a3 feat: reduce session payload 2026-03-16 12:03:00 +01:00
Björn Fromme a1518c06fb chore: use correct database type to replicate prod environment 2026-03-16 12:03:00 +01:00
Björn Fromme c517a0b41f chore: add staging environment to deployer config 2026-03-16 12:03:00 +01:00
Björn Fromme ded904fac8 fix: correct room assignment and count
closes #869c2jnzr
2026-03-16 12:03:00 +01:00
Björn Fromme abea6bff7b chore: align node and npm versions of DDEV with host, use npm ci 2026-03-16 12:03:00 +01:00
Björn Fromme 06f53ba6eb feat: fill default names for canceled participants in agency bookings 2026-03-16 12:03:00 +01:00
Björn Fromme eda0919f52 chore: update frontend tooling 2026-03-16 12:03:00 +01:00
Björn Fromme 1f27c744d2 chore: code cleanup 2026-03-16 12:02:59 +01:00
Björn Fromme bbc011ddb9 feat: update personal data of canceled participants as well
addresses #869bze0kq
2026-03-16 12:02:59 +01:00
Björn Fromme c2054a1ef6 chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme f9d420fecd feat: revert allow updating room assignments in edit mode 2026-03-16 12:02:59 +01:00
Björn Fromme 3e1d719512 chore: update platform specs in composer.json for prod 2026-03-16 12:02:59 +01:00
Björn Fromme f685bd18ab chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme f46cc59041 fix: allow updating room assignments in edit mode 2026-03-16 12:02:59 +01:00
Björn Fromme 380b1ed329 chore: streamline namespacing 2026-03-16 12:02:59 +01:00
Björn Fromme 1056b4fba6 chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme 19031dba99 fix: enforce profile completion of applicant in all situations 2026-03-16 12:02:59 +01:00
Björn Fromme 028db7a7ee fix: ensure complete participant data even when canceled 2026-03-16 12:02:59 +01:00
Björn Fromme a1764faaeb chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme 8529bb0e21 fix: streamline datalayer integration for all events 2026-03-16 12:02:59 +01:00
Björn Fromme 9eefdd1858 fix: properly initialize CMP, GTM and data layer for tracking 2026-03-16 12:02:59 +01:00
Björn Fromme e5803860df feat: remove street from hotel address in sidebar
addresses #869bwq1vh
2026-03-16 12:02:59 +01:00
Björn Fromme 2754d734aa chore: update frontend dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme 3487ca4822 chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme 02ebddc34a feat: require all personal data fields for registration 2026-03-16 12:02:59 +01:00
Björn Fromme 3957f6bd09 feat: tracking integration with GTM and CMP 2026-03-16 12:02:59 +01:00
Björn Fromme 11ab98b3d8 feat: domain-based theme-detection 2026-03-16 12:02:59 +01:00
Björn Fromme e24403949c chore: update database and php versions to match prod environment 2026-03-16 12:02:59 +01:00
Björn Fromme 288f6b91d0 chore: update deployer config for new hosting environment 2026-03-16 12:02:59 +01:00
Björn Fromme 8ca105966d fix: don't normalize hotel and product codes when fetching cms data 2026-03-16 12:02:59 +01:00
Björn Fromme 592cd517ff chore: update project url in ddev 2026-03-16 12:02:59 +01:00
Björn Fromme 586b410a66 chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme a444940db2 feat: display error codes in admin overview 2026-03-16 12:02:59 +01:00
Björn Fromme afe5aef9f7 feat: error-codes in flash messages to reference log entries 2026-03-16 12:02:59 +01:00
Björn Fromme 21a3e8fafc feat: user-friendly error messages on login 2026-03-16 12:02:59 +01:00
Björn Fromme 26bbba5a2e feat: streamlined flash messages 2026-03-16 12:02:59 +01:00
Björn Fromme b68d5c9398 fix: revert pickup pricing to match current BusPro behavior
Reverts split pricing calculation to use outbound-only pricing,
matching BusPro's current behavior where pickup is only charged when
outbound transportation is BUS.

- Use pickup->price directly instead of calculateEffectivePrice()
- PKW+BUS scenario now correctly charges €0 (matches BusPro loophole)
- priceOutbound/priceInbound remain populated for future activation
- Updated documentation with current behavior and future plan
2026-03-16 12:02:59 +01:00
Björn Fromme c1425f0562 feat: extensible participant status determination for booking creation
Adds a rule-based system to determine participant status in CREATE
payloads. Participants selecting a 'Begleitperson' service now receive
status 'O' (Option), all others default to 'F' (Final).

- Add ParticipantStatusRuleInterface for defining status rules
- Add ParticipantStatusRuleRegistry for priority-based rule evaluation
- Add ChaperonServiceStatusRule for Begleitperson detection
- Integrate status evaluation into BookingPayloadBuilder
2026-03-16 12:02:59 +01:00
Björn Fromme e1f1b60608 feat: infotext for insurance booking conditions
closes #869bvcu2p
2026-03-16 12:02:59 +01:00
Björn Fromme ea1c95528c chore: update httpclient config to use random values for contactform 2026-03-16 12:02:59 +01:00
Björn Fromme 0cac2969ae feat: log contact form submissions 2026-03-16 12:02:59 +01:00
Björn Fromme b856c51389 chore: remove debug logging in toast controller 2026-03-16 12:02:59 +01:00
Björn Fromme aa3b23ecb8 feat: info text and correct field type for service group 'VEG'
addresses #869bvch71
2026-03-16 12:02:59 +01:00
Björn Fromme 1e653e213a fix: don't hide voucher fields for booking status 'O'
closes #869bvbkrd
2026-03-16 12:02:59 +01:00
Björn Fromme 7d91dcfb70 chore: update test to fix deprecation warning 2026-03-16 12:02:59 +01:00
Björn Fromme 8e7e6266f0 chore: update project dependencies 2026-03-16 12:02:59 +01:00
Björn Fromme 167ccf5151 feat: ignored room types
closes #869bvbmcw
2026-03-16 12:02:59 +01:00
Björn Fromme c582e0820a feat: move profile completeness check from login to booking flow entry
- Add profileComplete flag to User entity to avoid API calls
- Set flag during login (BpnAuthenticator) and profile save
- Check flag in IndexController when entering booking flow
- Remove ProfileCompletionSubscriber (no longer needed)

Users with incomplete profiles are only redirected when starting
a new booking, not on every login. Eliminates extra API call by
caching completeness status on the user entity.
2026-03-16 12:02:59 +01:00
Björn Fromme 7d3a63d744 chore: update alert wording to be more descriptive 2026-03-16 12:02:59 +01:00
Björn Fromme 0a0987873f feat: enforce profile data completeness before entering booking flow 2026-03-16 12:02:59 +01:00
Björn Fromme 18d60c8781 feat: allow editing of nationality in personal data 2026-03-16 12:02:59 +01:00
Björn Fromme 7708ea6a0f fix: default participant's nationality to German to avoid missing data 2026-03-16 12:02:59 +01:00
Björn Fromme 71a46c6b63 chore: update rsync excludes in deployer config 2026-03-16 12:02:55 +01:00
Björn Fromme 667324df69 feat: body dimensions mandatory with selected rentals, updated help text
feat: body dimensions mandatory with selected rentals
2026-03-16 12:02:28 +01:00
Björn Fromme 957e20d763 fix: preserve selected services from booking even when unavailable
When editing a booking, services that were previously booked but are no
longer available in the travel catalog were being dropped. This caused
API error 650 ("Anzahl Leistung stimmt nicht mit Teilnehmerzuordnung
überein") because the service participant counts no longer matched.

The fix ensures that in edit mode, booked services are merged with
travel data services in both:
- Form rendering (ParticipantFieldOptionsProvider): so checkboxes appear
- Handler validation (AbstractParticipantFieldHandler): so selections
  are accepted

This allows users to keep their existing service selections or
deliberately replace them with other available options. Create mode
remains unchanged.
2026-03-16 12:02:28 +01:00
Björn Fromme 029a87c6ca doc: add technical documentation 2026-03-16 12:02:28 +01:00
Björn Fromme baa4609102 fix: ensure unique services mapping when creating api payload 2026-03-16 12:02:28 +01:00
Björn Fromme 875943e4da feat: match modes for room selection condition to detect MBZ*
addresses #869btdcyh
2026-03-16 12:02:28 +01:00
Björn Fromme 10e674cdd0 feat: improved logic to control field visibility
addresses #869btdphv
2026-03-16 12:02:28 +01:00
Björn Fromme 0bf78b0b81 fix: correctly handle discounts applied by dpn api 2026-03-16 12:02:28 +01:00
Björn Fromme c90b93556a feat: cli command to download travel xml data from buspro api 2026-03-16 12:02:28 +01:00
Björn Fromme f45718ea06 fix: correct body dimensions values 2026-03-16 12:02:28 +01:00
Björn Fromme 6d418ee8cc fix: account for discounts applied by bpn api in validation request 2026-03-16 12:02:28 +01:00
Björn Fromme 4851b1b72d feat: revert room price fetching for performance reasons 2026-03-16 12:02:28 +01:00
Björn Fromme dfb6f88be9 feat: trigger form refresh for dob when completely entered only 2026-03-16 12:02:28 +01:00
Björn Fromme f28227384d fix: fetch fresh room prices from api to avoid calculation mismatch 2026-03-16 12:02:28 +01:00
Björn Fromme cef9be92f3 fix: consider booking status O correctly 2026-03-16 12:02:28 +01:00
Björn Fromme f849d67a79 fix: correctly compare age range 2026-03-16 12:02:28 +01:00
Björn Fromme fba3becb06 feat: always load fresh api data when starting to edit booking 2026-03-16 12:02:28 +01:00
Björn Fromme a23ff6d119 chore: update project dependencies 2026-03-16 12:02:28 +01:00
Björn Fromme 384744c958 feat: xlsx export of booking edit draft data for admins 2026-03-16 12:02:28 +01:00
Björn Fromme 70c6617e88 feat: merge draft data with api response for selected fields 2026-03-16 12:02:28 +01:00
Björn Fromme 9afe3b334e fix: ensure nationality is assigned when editing booking data 2026-03-16 12:02:28 +01:00
Björn Fromme ad67d4c7ae chore: update project dependencies 2026-03-16 12:02:28 +01:00
Björn Fromme b7eaed3ac3 fix: populate booking number with edit drafts 2026-03-16 12:02:28 +01:00
Björn Fromme 136e2d68a2 feat: integrate with easy admin bundle 2026-03-16 12:02:27 +01:00
Björn Fromme bdcd54687d feat: streamlined booking number property 2026-03-16 12:02:27 +01:00
Björn Fromme 99190b0ef1 wip: integrate with easy admin bundle 2026-03-16 12:02:27 +01:00
Björn Fromme c7702b0c37 feat: cleanup favicons 2026-03-16 12:02:27 +01:00
Björn Fromme 9b88a2c14d feat: custom hx redirect class 2026-03-16 12:02:27 +01:00
Björn Fromme 6a945e6a08 feat: adjust xml dump reader command to new filename format 2026-03-16 12:02:27 +01:00
Björn Fromme 9c7cf0778f chore: update lts upgrade plan with current state of the project 2026-03-16 12:02:27 +01:00
Björn Fromme dd0f1a25d0 feat: always allow editing of participants for internal bookings
Prior to this commit the mutability flag from BusProNet was evaluated
and would potentially conflict with this rule. This flag is now
completely ignored for internal bookings.
2026-03-16 12:02:27 +01:00
Björn Fromme 7f4cf3060e fix: add suffix to request id in xml-dump filenames to avoid overwrites 2026-03-16 12:02:27 +01:00
Björn Fromme 30496a4875 feat: cleanup, log successful bookings 2026-03-16 12:02:27 +01:00
Björn Fromme 027508f495 chore: add draft cleanup command to schedule 2026-03-16 12:02:27 +01:00
Björn Fromme b5e2b2a2ad fix: use correct property path for travel date determination 2026-03-16 12:02:27 +01:00
Björn Fromme 9c9db05b86 feat: cli command to backfill travel dates on draft records, single use 2026-03-16 12:02:27 +01:00
Björn Fromme 1fa17a7df7 feat: cli command to clean up outdated or stale booking draft records 2026-03-16 12:02:27 +01:00
Björn Fromme e09e5858d8 fix: don't update booking session and draft on form refresh
Each form refresh would create a draft even for users that just explore
booking options causing stale draft records in the database.
2026-03-16 12:02:27 +01:00
Björn Fromme 6ede062a66 feat: streamlined display of hotel image, name and address 2026-03-16 12:02:27 +01:00
Björn Fromme b351b4042f chore: update project dependencies 2026-03-16 12:02:27 +01:00
Björn Fromme 95d0ce33d4 feat: new service category 'VEG' 2026-03-16 12:02:27 +01:00
Björn Fromme 75366167e8 chore: update httpclient config 2026-03-16 12:02:27 +01:00
Björn Fromme 7fa7e4be45 feat: command to read xml-dumps from bpn api by provided request id 2026-03-16 12:02:27 +01:00
Björn Fromme d14dafbade fix: include gender and nationality into group of mandatory fields 2026-03-16 12:02:27 +01:00
Björn Fromme e222f448bb feat: proper determination of agency initiated bookings
For booking that are agency initiated (groups) different rules apply
concerning mutability and requirement of personal data and whether the
first participant is the applicant or not. This commit adds logic to
evaluate the agency id assigned to the booking data to decide.
2026-03-16 12:02:27 +01:00
Björn Fromme f55ed3dc4c feat: log request ids to map xml dumps of bpn api communication 2026-03-16 12:02:27 +01:00
Björn Fromme fedfcc247e fix: update draft together with session on refresh 2026-03-16 12:02:27 +01:00
Björn Fromme 8186adfaeb fix: show actual error message 2026-03-16 12:02:27 +01:00
Björn Fromme 00304facba fix: allow null argument for gender mapping 2026-03-16 12:02:27 +01:00
Björn Fromme ff241f437f fix: insurance ids are strings 2026-03-16 12:02:27 +01:00
Björn Fromme 4a6b9cd64d fix: exclude pickup surcharge when self-organized outbound 2026-03-16 12:02:27 +01:00
Björn Fromme 8646dfbf02 fix: avoid float rounding errors when comparing 2026-03-16 12:02:27 +01:00
Björn Fromme d6f2681c61 feat: load hotel data locally for sidebar 2026-03-16 12:02:27 +01:00
Björn Fromme 5a47ca6053 feat: default status of new bookings to option during beta phase
addresses #869bpb7fg
2026-03-16 12:02:22 +01:00
Björn Fromme d7fd273475 fix: ensure rental insurance is selectable when insurance is available
addresses #869bp9ev5
2026-03-16 12:01:09 +01:00
Björn Fromme ce828a6ef5 fix: correctly distinguish between first participant and applicant 2026-03-16 12:01:09 +01:00
Björn Fromme 15dbd72f93 fix: don't include default date of birth in contact form submissions 2026-03-16 12:01:09 +01:00
Björn Fromme e3bdd8737f feat: update field label 2026-03-16 12:01:09 +01:00
Björn Fromme 7942656026 fix: redirect to dashboard as default when logged in 2026-03-16 12:01:09 +01:00
Björn Fromme 1fe8a2cb17 feat: load balancing of api requests, cleanup api client 2026-03-16 12:01:09 +01:00
Björn Fromme ab48b1f867 fix: properly handle parking service selection 2026-03-16 12:01:09 +01:00
Björn Fromme 3043842254 fix: add missing LoggerInterface dependency to BookingDataProcessorTest 2026-03-16 12:01:09 +01:00
Björn Fromme 249e326de4 feat: retry api requests when closed immediately due to overload 2026-03-16 12:01:09 +01:00
Björn Fromme b3cace3b43 fix: avoid null pointer exceptions, log warning about removed services 2026-03-16 12:01:09 +01:00
Björn Fromme ad578179d8 fix: avoid scrolling to the bottom when making a selection
closes #869bnn1bw
2026-03-16 12:01:09 +01:00
Björn Fromme c57351f8b5 chore: update scheduler config 2026-03-16 12:01:09 +01:00
Björn Fromme c5934e4c5b chore: reduce logger noise 2026-03-16 12:01:09 +01:00
Björn Fromme 06e64bd3b8 fix: only assign dummy data to the applicant 2026-03-16 12:01:09 +01:00
Björn Fromme 48572812a9 fix: assign dummy values to missing applicant data fields
This fix avoids rejection of API requests due to missing data of the
applicant. The current user most probably is not aware about this so
they get confused about the error messages otherwise.
2026-03-16 12:01:09 +01:00
Björn Fromme 46b610370a feat: draft inspection cli command 2026-03-16 12:01:09 +01:00
Björn Fromme 96d4b8ed45 fix: apply correct return type and response handling 2026-03-16 12:01:09 +01:00
Björn Fromme c18ba3d815 fix: only invalidate cache and remove draft on successful edit 2026-03-16 12:01:09 +01:00
Björn Fromme fd81079247 chore: code cleanup 2026-03-16 12:01:09 +01:00
Björn Fromme e5781fbabc fix: invalidate booking data caches after updating personal data 2026-03-16 12:01:09 +01:00
Björn Fromme 8887b06583 fix: streamline price label for transportation services 2026-03-16 12:01:09 +01:00
Björn Fromme 9955ff7df9 feat: link terms in confirmation checkbox label 2026-03-16 12:01:09 +01:00
Björn Fromme db74b6049c feat: remove cancel confirmation since obsolete because of drafts 2026-03-16 12:01:09 +01:00
Björn Fromme 0b5c7af4be feat: automatic saving of drafts when editing bookings 2026-03-16 12:01:09 +01:00
Björn Fromme 721016a00e fix: adopt general styles to error page template 2026-03-16 12:01:09 +01:00
Björn Fromme 563522d261 chore: update deployer config 2026-03-16 12:01:09 +01:00
Björn Fromme 04f4455491 chore: update project dependencies 2026-03-16 12:01:09 +01:00
Björn Fromme b976ce480a fix: restore .user.ini from master 2026-03-16 12:01:09 +01:00
Björn Fromme 6d5f7cfd22 chore: update upgrade plan with current state of the project 2026-03-16 12:01:09 +01:00
Björn Fromme 9baed0987e chore: update project dependencies 2026-03-16 12:01:09 +01:00
Björn Fromme b76d17d35c feat: add env variable for website base url 2026-03-16 12:01:09 +01:00
Björn Fromme 4e182612e8 chore: complete scheduler config for email notifications 2026-03-16 12:01:09 +01:00
Björn Fromme 645729a518 feat: remove outdated log entries scheduled 2026-03-16 12:01:09 +01:00
Björn Fromme 9ee4c1cd5c fix: fail gracefully when remote XML data cannot be read during sync 2026-03-16 12:01:09 +01:00
Björn Fromme 02742aef5b fix: catch travel data not found errors to show proper flash message 2026-03-16 12:01:09 +01:00
Björn Fromme 87af2c3855 chore: update project dependencies 2026-03-16 12:01:09 +01:00
Björn Fromme ea1ce4a029 docs: add inline documentation where missing 2026-03-16 12:01:09 +01:00
Björn Fromme 2fe9185a6f feat: cron controlled cli command to sync xml data with remote 2026-03-16 12:00:56 +01:00
Björn Fromme ef191c55be chore: cleanup flysystem config 2026-03-16 12:00:56 +01:00
Björn Fromme abd74a127a chore: update json test-data for pickups planning 2026-03-16 12:00:56 +01:00
Björn Fromme 52ac269b8d fix: avoid duplicated pickup planning entries 2026-03-16 12:00:56 +01:00
Björn Fromme 643f65ce3b chore: reduce noise in logs 2026-03-16 12:00:56 +01:00
Björn Fromme 465ce3e69a feat: add logging to api endpoint 2026-03-16 12:00:56 +01:00
Björn Fromme 207b648f36 fix: don't show bulk insurance labels in summary 2026-03-16 12:00:56 +01:00
Björn Fromme 7f2d52a5ce feat: accept multiple travel codes per pickup planning 2026-03-16 12:00:56 +01:00
Björn Fromme f1eaa95c44 chore: update project dependencies 2026-03-16 12:00:56 +01:00
Björn Fromme e203de172d chore: rotate auth log 2026-03-16 12:00:56 +01:00
Björn Fromme 79b7e2aaa5 feat: forcibly invalidate availabilities cache on booking start 2026-03-16 12:00:56 +01:00
Björn Fromme 3c2ade9299 feat: loading indicator on initial page load 2026-03-16 12:00:56 +01:00
Björn Fromme f3f2dc6cec fix: adopt changes in test 2026-03-16 12:00:56 +01:00
Björn Fromme 12b69bd681 feat: load availability data once per booking session 2026-03-16 12:00:56 +01:00
Björn Fromme 8f542ff448 chore: disable saving cookies for api requests 2026-03-16 12:00:56 +01:00
Björn Fromme 80c81c11fb feat: log pickups planning data api calls 2026-03-16 12:00:56 +01:00
Björn Fromme e3809bd930 chore: update project dependencies 2026-03-16 12:00:56 +01:00
Björn Fromme d755e29459 chore: reduce logger noise 2026-03-16 12:00:56 +01:00
Björn Fromme 105eb5a9cd chore: retain xml dumps for three days to save on webspace 2026-03-16 12:00:56 +01:00
Björn Fromme 65f8436aa7 feat: extended oauth2 user info and refactored authenticator 2026-03-16 12:00:56 +01:00
Björn Fromme 4afdd79252 fix: ensure template variable exists 2026-03-16 12:00:56 +01:00
Björn Fromme d1e807b11f feat: adjust oauth2 implementation for TYPO3 backend login 2026-03-16 12:00:56 +01:00
Björn Fromme ee84690cd9 feat: basic themes for event sites 2026-03-16 12:00:56 +01:00
Björn Fromme c7a27f1dc7 feat: api endpoints for pickups planning 2026-03-16 12:00:56 +01:00
Björn Fromme 1fd9f8d1f8 feat: always show all available ski passes but readonly if age doesn't match 2026-03-16 12:00:56 +01:00
Björn Fromme b57d849ecd feat: update labels of voucher fields
addresses #869bf8tzv
2026-03-16 12:00:56 +01:00
Björn Fromme 654ae4dc0b feat: use query parameters for booking urls 2026-03-16 12:00:56 +01:00
Björn Fromme 3984a623bf fix: properly assign readonly state to form fields for unavailable services 2026-03-16 12:00:56 +01:00
Björn Fromme 96619c6cec fix: reset room assignments after updated selection if required 2026-03-16 12:00:56 +01:00
Björn Fromme 3dd92ccdb4 feat: consistent display of included services and prices 2026-03-16 12:00:56 +01:00
Björn Fromme b111a615a9 feat: show unavailable transportation services as readonly 2026-03-16 12:00:56 +01:00
Björn Fromme 2372958713 fix: don't show incorrect notification about updated rentals 2026-03-16 12:00:56 +01:00
Björn Fromme 82a8541af1 feat: show inquiry status with rooms in step 1 2026-03-16 12:00:56 +01:00
Björn Fromme ea162972fa feat: hide parking from participants under 18 2026-03-16 12:00:55 +01:00
Björn Fromme 094d6858d1 fix: don't auto assign discounted transport to babies 2026-03-16 12:00:55 +01:00
Björn Fromme 65398d59d4 chore: simplify parameter handling 2026-03-16 12:00:55 +01:00
Björn Fromme 3df9659ce2 feat: configurable choices for body dimensions
closes #8697phk21
2026-03-16 12:00:55 +01:00
Björn Fromme c4f4f53fd6 chore: update deployer config for prod 2026-03-16 12:00:55 +01:00
Björn Fromme b567b6a840 feat: re-implement contact form submissions api endpoint for website 2026-03-16 12:00:55 +01:00
Björn Fromme ab18e5f134 feat: adjust participant number size depending on value 2026-03-16 12:00:55 +01:00
Björn Fromme 929115c02b feat: update deployer config to build assets upfront 2026-03-16 12:00:55 +01:00
Björn Fromme e26884c099 feat: align rendering of pickups field with other services 2026-03-16 12:00:55 +01:00
Björn Fromme 077bcdcaf5 fix: avoid loading indicator issues when using browser history for navigation 2026-03-16 12:00:55 +01:00
Björn Fromme 685ac5a94a chore: update project dependencies 2026-03-16 12:00:55 +01:00
Björn Fromme 3d1b75b591 fix: ensure flash message is displayed after redirect 2026-03-16 12:00:55 +01:00
Björn Fromme e1bfe9b93c feat: show room prices in room assignment form field 2026-03-16 12:00:55 +01:00
Björn Fromme 5b75a165ce fix: account for htmx issues in mobile safari with select fields 2026-03-16 12:00:55 +01:00
Björn Fromme e12fbc85d4 fix: disable autocomplete in chrome for good 2026-03-16 12:00:55 +01:00
Björn Fromme 6bbef0a975 feat: various improvements in styles and layout 2026-03-16 12:00:55 +01:00
Björn Fromme bc175ca438 fix: avoid stale caches 2026-03-16 12:00:55 +01:00
Björn Fromme ef15772b97 feat: streamlined rendering of fields as static text in forms 2026-03-16 12:00:55 +01:00
Björn Fromme da5b913757 feat: render room assignment as radio buttons 2026-03-16 12:00:55 +01:00
Björn Fromme 6b5a51f652 feat: replace overly complex and unnecessary form choice loader for rooms 2026-03-16 12:00:55 +01:00
Björn Fromme af2620c8b3 fix: ensure footer bar is visible on mobile safari 2026-03-16 12:00:55 +01:00
Björn Fromme 15fdfdc42e feat: load cms data early to display image on login page 2026-03-16 12:00:55 +01:00
Björn Fromme ce88e1f97b feat: improved layout for participant form 2026-03-16 12:00:55 +01:00
Björn Fromme a67e3a5eac fix: disable autocompletion on personal data fields 2026-03-16 12:00:55 +01:00
Björn Fromme cc747f0690 feat: body dimensions optional 2026-03-16 12:00:55 +01:00
Björn Fromme a6d2661562 feat: improved error handling and redirect on invalid session 2026-03-16 12:00:55 +01:00
Björn Fromme 4b95b12a7b feat: indicate incomplete participant data in cards 2026-03-16 12:00:55 +01:00
Björn Fromme cca8554e3d feat: special treatment of services for participants of age 0-2 2026-03-16 12:00:55 +01:00
Björn Fromme 28c426ca3c feat: increase availability cache ttl and ensure fresh data when entering form 2026-03-16 12:00:55 +01:00
Björn Fromme be83a4295a docs: upgrade plan to symfony 7.4 2026-03-16 12:00:55 +01:00
Björn Fromme 87439ee509 feat: optional return url 2026-03-16 12:00:41 +01:00
Björn Fromme 36ef54d541 chore: cleanup 2026-03-16 11:59:12 +01:00
Björn Fromme 400407358d fix: remove obsolete htmx attributes from forms 2026-03-16 11:59:12 +01:00
Björn Fromme 502b121e43 chore: cleanup 2026-03-16 11:59:12 +01:00
Björn Fromme 61447ced4f fix: enforce https 2026-03-16 11:59:12 +01:00
Björn Fromme 1e107c68b4 feat: implement hx-boost for reliable loading indication 2026-03-16 11:59:12 +01:00
Björn Fromme 602fb31f27 fix: ensure loading indicator is triggered 2026-03-16 11:59:12 +01:00
Björn Fromme 2a8531a025 chore: update project dependencies 2026-03-16 11:59:12 +01:00
Björn Fromme 980589e190 fix: remove form options cache causing issues 2026-03-16 11:59:12 +01:00
Björn Fromme 4a2d1f4a02 feat: implement screendesign 2026-03-16 11:59:12 +01:00
Björn Fromme 39e6cc4d68 chore: update project dependencies 2026-03-16 11:59:12 +01:00
Björn Fromme e5018432cb feat: adjust loading indicator styles 2026-03-16 11:59:12 +01:00
Björn Fromme dbf0b03bac fix: add loading indicator to all 'back' buttons 2026-03-16 11:59:12 +01:00
Björn Fromme 01060035bc fix: consider mode in summary 2026-03-16 11:59:12 +01:00
Björn Fromme fa0cf5a654 fix: correctly handle email uniqueness by excluding the applicant from validation 2026-03-16 11:59:12 +01:00
Björn Fromme 4f1a1cad8e feat: request replay command for bpn api 2026-03-16 11:59:12 +01:00
Björn Fromme 8c8aae9a1e feat: refactoring and cleanup 2026-03-16 11:59:12 +01:00
Björn Fromme 230c53875f feat: finalize voucher handling and discount display in summary and overview 2026-03-16 11:59:12 +01:00
Björn Fromme 2e40cbc7c7 feat: special treatment of participants with age 0-2 (babies) 2026-03-16 11:59:12 +01:00
Björn Fromme cd1ffc3e9a fix: don't disable room selection field with single option 2026-03-16 11:59:12 +01:00
Björn Fromme 4db2cd7eda fix: clear target path when canceling booking flow 2026-03-16 11:59:12 +01:00
Björn Fromme f230b36382 feat: conditionally render room assignment field in participant edit form 2026-03-16 11:59:12 +01:00
Björn Fromme b872f2a5db feat: prevent selection of baby rooms without regular rooms 2026-03-16 11:59:11 +01:00
Björn Fromme c6678d16a6 feat: step input for room type selection 2026-03-16 11:59:11 +01:00
Björn Fromme b73a02048e fix: correctly determine number of participants 2026-03-16 11:59:11 +01:00
Björn Fromme 1f2f2751e4 feat: correct determination of inquiry status and conditional voucher field display 2026-03-16 11:59:11 +01:00
Björn Fromme 85998534fe feat: correct handling of vouchers 2026-03-16 11:59:11 +01:00
Björn Fromme 8e7b8bd75f feat: layout improvements 2026-03-16 11:59:11 +01:00
Björn Fromme fb983f23dd feat: improved promotional and purchase vouchers 2026-03-16 11:59:11 +01:00
Björn Fromme 7df99521c4 feat: promotional and purchase vouchers 2026-03-16 11:59:11 +01:00
Björn Fromme a8c0a1aa61 feat: fetch additional content from cms via api 2026-03-16 11:59:11 +01:00
Björn Fromme fc05350ae4 feat: sort pickups by their times 2026-03-16 11:59:11 +01:00
Björn Fromme ba7de8fa01 fix: never validate insurance selection in edit mode 2026-03-16 11:59:11 +01:00
Björn Fromme 778cf80e6b fix: don't validate insurance selection of participants when in bulk assignment 2026-03-16 11:59:11 +01:00
Björn Fromme f01bb7d271 chore: update project dependencies 2026-03-16 11:59:11 +01:00
Björn Fromme 6a031e5a71 feat: loading indicators for regular get requests 2026-03-16 11:59:11 +01:00
Björn Fromme 37924841e1 feat: improved timeout handling for api client 2026-03-16 11:59:11 +01:00
Björn Fromme be90248fc7 feat: remove 'remember me' functionality from login form in booking process 2026-03-16 11:59:11 +01:00
Björn Fromme cb38beb32c feat: surcharges and discounts per participant and in summary 2026-03-16 11:59:11 +01:00
Björn Fromme cc8500d0f4 fix: don't rely on individual prices being available for all participants 2026-03-16 11:59:11 +01:00
Björn Fromme 61d4e36f1f feat: ensure inquiry info is always visible 2026-03-16 11:59:11 +01:00
Björn Fromme 5c5f164aa2 feat: improved dynamic validation 2026-03-16 11:59:11 +01:00
Björn Fromme 5275e6c732 fix: ensure validation of participant data 2026-03-16 11:59:11 +01:00
Björn Fromme f3ea6734a1 fix: keep browser history intact when navigating between cards view and participant form 2026-03-16 11:59:11 +01:00
Björn Fromme bb20176c76 wip: integrate with typo3 to fetch product and hotel data 2026-03-16 11:59:11 +01:00
Björn Fromme beee44a10e fix: streamlined single room selection handling 2026-03-16 11:59:11 +01:00
Björn Fromme 43823dbda1 feat: improved mutability checks for personal data in edit or create mode 2026-03-16 11:59:11 +01:00
Björn Fromme ff39bf365c feat: improved handling of fields to be rendered as static text 2026-03-16 11:59:11 +01:00
Björn Fromme 5d69e4a8aa feat: gravatar integration 2026-03-16 11:59:11 +01:00
Björn Fromme 142db19627 feat: integrate with scheduler bundle 2026-03-16 11:59:11 +01:00
Björn Fromme 7b84ecbb56 fix: adapt changes in create mode for edit mode, cleanup 2026-03-16 11:59:11 +01:00
Björn Fromme dc6de1734a feat: authenticated booking 2026-03-16 11:59:11 +01:00
Björn Fromme 1e464cef0a feat: performance improvements 2026-03-16 11:59:11 +01:00
Björn Fromme 4decaa6789 chore: fix deprecations in preparation uf upgrading to symfony 7.3 2026-03-16 11:59:11 +01:00
Björn Fromme a057088808 fix: incorrect and unnecessary template inheritance 2026-03-16 11:59:11 +01:00
Björn Fromme e46053a7b7 chore: consolidate documentation 2026-03-16 11:59:11 +01:00
Björn Fromme 91d9e82d84 feat: price info tooltip for bulk insurance booking
addresses #869axbjzz
2026-03-16 11:59:11 +01:00
Björn Fromme 608f5ed3e9 feat: rearrange field order
addresses #869axbhz3
2026-03-16 11:59:11 +01:00
Björn Fromme 9b2e209b4f feat: group rentals and rental insurance fields visually
addresses #869ay16cp
2026-03-16 11:59:11 +01:00
Björn Fromme bae1582631 feat: dedicated section for discounts in summary
addresses #869ay1724
2026-03-16 11:59:11 +01:00
Björn Fromme c3fe76d78c feat: automatic unselection of discounted transportation 2026-03-16 11:59:11 +01:00
Björn Fromme 8abab0e379 fix: improved position of info icon 2026-03-16 11:59:11 +01:00
Björn Fromme d31204188b fix: adopt wrapper dto to dynamic form field 2026-03-16 11:59:11 +01:00
Björn Fromme a74f34b559 feat: display service descriptions as tooltip with info icon
addresses #869axbnj0
2026-03-16 11:59:11 +01:00
Björn Fromme 37cda348b0 feat: remove room selection field entirely for single room type
addresses #869axcukn
2026-03-16 11:59:11 +01:00
Björn Fromme 38656e73c5 chore: cleanup, update documentation 2026-03-16 11:59:11 +01:00
Björn Fromme 03ac430be4 fix: validation error indication on cards 2026-03-16 11:59:11 +01:00
Björn Fromme 89979d6ce4 wip: email uniqueness validation 2026-03-16 11:59:11 +01:00
Björn Fromme 54a3145710 wip: improved validation and feedback 2026-03-16 11:59:11 +01:00
Björn Fromme 7aea149b6c feat: unique email addresses of participants unless child, cleanup
addresses #869axbn21
2026-03-16 11:59:11 +01:00
Björn Fromme f50aa55e8b feat: additional conformation checkbox for terms and conditions
addresses #869axbm44
2026-03-16 11:59:11 +01:00
Björn Fromme 6c0d7c30c6 feat: improved layout for pickup selection to make price visible
addresses #869axbjmd
2026-03-16 11:59:11 +01:00
Björn Fromme af163d597e feat: prefer discounted transportation services
addresses #869axbjbz
2026-03-16 11:59:11 +01:00
Björn Fromme d0c8302d21 feat: improved form field layout for date of birth 2026-03-16 11:59:11 +01:00
Björn Fromme 44e2d76525 feat: show placeholders for individual date parts in date of birth field 2026-03-16 11:59:11 +01:00
Björn Fromme 8f274bbb44 feat: replace date field for participant's birthday 2026-03-16 11:59:11 +01:00
Björn Fromme 8436124cbc wip: implement e2e tests with cypress 2026-03-16 11:59:11 +01:00
Björn Fromme 647fa8e212 feat: unassign rooms from other participants when unavailable 2026-03-16 11:59:11 +01:00
Björn Fromme 6cc5886073 feat: automatically assign rooms only for unique room type selection 2026-03-16 11:59:11 +01:00
Björn Fromme 513c889926 chore: update project dependencies 2026-03-16 11:59:11 +01:00
Björn Fromme 9c6f4d59b3 chore: cleanup, updated docs 2026-03-16 11:59:11 +01:00
Björn Fromme a0d5768752 feat: consolidated insurance service 2026-03-16 11:59:11 +01:00
Björn Fromme 4f951cdf8a feat: integrate with spatie/ray for debugging and performance optimization 2026-03-16 11:59:11 +01:00
Björn Fromme 619e2ba1ee feat: extended pricing breakdown on confirmation page 2026-03-16 11:59:11 +01:00
Björn Fromme 7d6a80eefa fix: fix floating point precision error 2026-03-16 11:59:11 +01:00
Björn Fromme 2403f8fb29 chore: update documentation 2026-03-16 11:59:11 +01:00
Björn Fromme b485112ed3 chore: adjust and cleanup tests 2026-03-16 11:59:11 +01:00
Björn Fromme 1f5c835f8a wip: bulk insurance refactoring 2026-03-16 11:59:11 +01:00
Björn Fromme a3d7ee63d3 wip: bulk insurance booking fix 2026-03-16 11:59:11 +01:00
Björn Fromme a8cf67728b wip: finalize implementation 2026-03-16 11:59:11 +01:00
Björn Fromme c830fc7841 wip: finalize implementation 2026-03-16 11:59:11 +01:00
Björn Fromme 5ef3bb9cbf wip: finalize implementation 2026-03-16 11:59:11 +01:00
Björn Fromme b882175f36 feat: readonly room selection for single room types 2026-03-16 11:59:11 +01:00
Björn Fromme d20215929d feat: display booked insurance in edit mode 2026-03-16 11:59:11 +01:00
Björn Fromme ea312b9986 chore: remove debug statements 2026-03-16 11:59:11 +01:00
Björn Fromme 0559341f31 fix: show feedback modal 2026-03-16 11:59:10 +01:00
Björn Fromme 1f4dc2d4a2 fix: adopt changed template name 2026-03-16 11:59:10 +01:00
Björn Fromme 14ca0f5c59 fix: adjust deployer config 2026-03-16 11:59:10 +01:00
Björn Fromme e51c4843c5 feat: refactor to cards 2026-03-16 11:59:10 +01:00
Björn Fromme 32a9fac9ed fix: ensure skipass is selected 2026-03-16 11:59:10 +01:00
Björn Fromme de8cbf6178 wip: refactor to cards with individual participant forms 2026-03-16 11:59:10 +01:00
Björn Fromme 33e1aea80c wip: add documentation for plan 2026-03-16 11:59:10 +01:00
Björn Fromme 83589ee677 feat: htmx powered requests, improved loading indicator
feat: loading indicator and htmx form submit
2026-03-16 11:59:10 +01:00
Björn Fromme 023ecdebc9 feat: inquiry bookings 2026-03-16 11:59:10 +01:00
Björn Fromme 2d9cb2c0b9 chore: remove outdated documentation 2026-03-16 11:59:10 +01:00
Björn Fromme 5c0814ef9b wip: modernized edit flow, fix insurance tier calculation 2026-03-16 11:59:10 +01:00
Björn Fromme 28831a3b06 wip: modernized edit flow 2026-03-16 11:59:10 +01:00
Björn Fromme 0d073a36a3 wip: insurance booking in edit flow 2026-03-16 11:59:10 +01:00
Björn Fromme 069600d602 fix: set correct default agency 2026-03-16 11:59:10 +01:00
Björn Fromme d70a27f2fd wip: backport booking create flow form handling to edit flow 2026-03-16 11:59:10 +01:00
Björn Fromme e330626b03 feat: unify pickup selection 2026-03-16 11:59:10 +01:00
Björn Fromme 0f4b16c194 feat: comprehensive booking overview for confirmation 2026-03-16 11:59:10 +01:00
Björn Fromme c89bda86b7 fix: use correct country tokens 2026-03-16 11:59:10 +01:00
Björn Fromme 56fa5355fd chore: update project dependencies 2026-03-16 11:59:10 +01:00
Björn Fromme 7ea52670b9 wip: submit booking to api 2026-03-16 11:59:10 +01:00
Björn Fromme ee264e88d4 wip: confirmation step 2026-03-16 11:59:10 +01:00
Björn Fromme 3f7db4e772 feat: implement payment step 2026-03-16 11:59:10 +01:00
Björn Fromme 3d9fc18a83 fix: don't submit data of removed fields 2026-03-16 11:59:10 +01:00
Björn Fromme 9eeed7f992 wip: backport form handing system from create flow to edit flow 2026-03-16 11:59:10 +01:00
Björn Fromme ba0a86cbea fix: ignore past travels in list view when patching data 2026-03-16 11:59:10 +01:00
Björn Fromme 41d8d65d82 feat: inform user about automatic reassignments or reset selections 2026-03-16 11:59:10 +01:00
Björn Fromme 57843b8a6f feat: insurance info urls in tooltips 2026-03-16 11:59:10 +01:00
Björn Fromme d6258d0ca1 feat: customizable label for unavailable services 2026-03-16 11:59:10 +01:00
Björn Fromme 66ccebb02b feat: make room selection fields read-only for single room type 2026-03-16 11:59:10 +01:00
Björn Fromme e3081e56f8 feat: extended insurance parsing, pass info urls to view 2026-03-16 11:59:10 +01:00
Björn Fromme 201b223813 fix: filter rentals by skipass duration 2026-03-16 11:59:10 +01:00
Björn Fromme 08d534e39b feat: auto-assign rooms 2026-03-16 11:59:10 +01:00
Björn Fromme 4489169553 wip: improved insurance selection 2026-03-16 11:59:10 +01:00
Björn Fromme 16c239716b wip: check eligibility based on ski pass availability 2026-03-16 11:59:10 +01:00
Björn Fromme f5913eb947 chore: update docs 2026-03-16 11:59:10 +01:00
Björn Fromme f2681af9ee feat: bulk insurance booking by applicant 2026-03-16 11:59:10 +01:00
Björn Fromme 66dd51d75a feat: improved form layout 2026-03-16 11:59:10 +01:00
Björn Fromme 5f78361533 chore: remove debugging statements 2026-03-16 11:59:10 +01:00
Björn Fromme 3c1192298b feat: show room pricing details 2026-03-16 11:59:10 +01:00
Björn Fromme 0bd9d79bbe fix: layout improvements 2026-03-16 11:59:10 +01:00
Björn Fromme a2e055f313 fix: consider participant's age at travel date 2026-03-16 11:59:10 +01:00
Björn Fromme ca1d5c4303 fix: ensure mandatory services are selected 2026-03-16 11:59:10 +01:00
Björn Fromme e6eebc00a3 wip: insurance booking 2026-03-16 11:59:10 +01:00
Björn Fromme 29bdf794f3 wip: insurance booking 2026-03-16 11:59:10 +01:00
Björn Fromme 4ba81b8f03 wip: insurance booking 2026-03-16 11:59:10 +01:00
Björn Fromme 8af7f0e797 wip: insurance booking phase 5 2026-03-16 11:59:10 +01:00
Björn Fromme c67fa18ad3 wip: insurance booking phase 4 2026-03-16 11:59:10 +01:00
Björn Fromme 6c9da6537e wip: insurance booking phase 3 2026-03-16 11:59:10 +01:00
Björn Fromme 241785b428 wip: insurance booking phases 1 and 2 2026-03-16 11:59:10 +01:00
Björn Fromme 411166ffba feat: correct calculation and display of individual pricing 2026-03-16 11:59:10 +01:00
Björn Fromme 203c9ebbca chore: update project dependencies 2026-03-16 11:59:10 +01:00
Björn Fromme ede37d5d0f feat: improved error handling in controllers, cleanup 2026-03-16 11:59:10 +01:00
Björn Fromme 4f02529b15 feat: improved error handling of xml parsers and loaders 2026-03-16 11:59:10 +01:00
Björn Fromme 0f6b73340e feat: parser and loader for insurance data 2026-03-16 11:59:10 +01:00
Björn Fromme 96c53cc173 feat: functionality to determine family status of a booking 2026-03-16 11:59:10 +01:00
Björn Fromme 7ce3bc18b2 feat: prevent booking flow without available rooms 2026-03-16 11:59:10 +01:00
Björn Fromme 82b47e314b feat: validate room selection 2026-03-16 11:59:10 +01:00
Björn Fromme 9d2474c1e3 feat: render tooltips 2026-03-16 11:59:10 +01:00
Björn Fromme 787f69fc46 feat: streamlined tooltip data attributes 2026-03-16 11:59:10 +01:00
Björn Fromme 054d4e52b2 chore: update project dependencies 2026-03-16 11:59:10 +01:00
Björn Fromme 0d1ef6d40e feat: mark unavailable services as read-only and add tooltip 2026-03-16 11:59:10 +01:00
Björn Fromme ead448b8d4 feat: simplify validation 2026-03-16 11:59:10 +01:00
Björn Fromme 7ff10e6792 feat: simplify handling of ski pass service 2026-03-16 11:59:10 +01:00
Björn Fromme 3d6c94e7c5 feat: cached api results for availabilities 2026-03-16 11:59:10 +01:00
Björn Fromme 7673e64738 chore: streamline property naming 2026-03-16 11:59:10 +01:00
Björn Fromme 4230c53812 feat: enrich travel data with live availabilities 2026-03-16 11:59:10 +01:00
Björn Fromme 3198e03cc4 feat: replace xss extension with symfony component 2026-03-16 11:59:10 +01:00
Björn Fromme 1e48e107fc wip: skipass-duration based rentals filtering 2026-03-16 11:59:10 +01:00
Björn Fromme ed7c889c4f wip: transportation services with discount 2026-03-16 11:59:10 +01:00
Björn Fromme 84f4481ef0 wip: service descriptions and car license plate field 2026-03-16 11:59:10 +01:00
Björn Fromme b84997d058 wip: rentals insurance field 2026-03-16 11:59:10 +01:00
Björn Fromme 3063a7c05f wip: improved refresh logic 2026-03-16 11:59:10 +01:00
Björn Fromme 36fe4c9e9a wip: transportation services in summary 2026-03-16 11:59:10 +01:00
Björn Fromme 5c5134b69f wip: update documentation 2026-03-16 11:59:10 +01:00
Björn Fromme e7fb764158 wip: dynamic availability of services 2026-03-16 11:59:10 +01:00
Björn Fromme fe624cfd1c wip: implement transportation, pickups and parking 2026-03-16 11:59:10 +01:00
Björn Fromme 81b8237570 wip: transportation services 2026-03-16 11:59:10 +01:00
Björn Fromme a019c7dae0 wip: prepare transportation services 2026-03-16 11:59:10 +01:00
Björn Fromme 552dd029fa wip: update docs 2026-03-16 11:59:10 +01:00
Björn Fromme bd5c6359fe wip: show pricing 2026-03-16 11:59:10 +01:00
Björn Fromme 6bd483d768 wip: dynamic services fields 2026-03-16 11:59:09 +01:00
Björn Fromme 7003c0d81b wip: age based filtering of options 2026-03-16 11:59:09 +01:00
Björn Fromme b038d9a41f wip: age based filtering of options 2026-03-16 11:59:09 +01:00
Björn Fromme 89c42cf7e4 wip: age based filtering of options 2026-03-16 11:59:09 +01:00
Björn Fromme cd1e5ad3ad chore: update project dependencies 2026-03-16 11:59:09 +01:00
Björn Fromme f36c761c28 wip: conditional mandatory body dimensions 2026-03-16 11:59:09 +01:00
Björn Fromme 0f7d95d31b wip: additional services with constraints 2026-03-16 11:59:09 +01:00
Björn Fromme 4b92f56ed7 wip: courses 2026-03-16 11:59:09 +01:00
Björn Fromme b54fb07e84 wip: booking process 2026-03-16 11:59:09 +01:00
Björn Fromme 11825191cf wip: major refactoring 2026-03-16 11:59:09 +01:00
Björn Fromme d719b17aec wip: form refactoring 2026-03-16 11:59:09 +01:00
Björn Fromme 65a33922cf wip: improved booking summary 2026-03-16 11:59:09 +01:00
Björn Fromme 727ee9b014 wip: refactor 2026-03-16 11:59:09 +01:00
Björn Fromme 4d51f0334f wip: booking summary for step 1 2026-03-16 11:59:09 +01:00
Björn Fromme 86e4866d6a wip: refactor 2026-03-16 11:59:09 +01:00
Björn Fromme e75276ed88 wip: refactor 2026-03-16 11:59:09 +01:00
Björn Fromme bfdf4c0453 fix: correct handling of readonly checkboxes with tooltips 2026-03-16 11:59:09 +01:00
Björn Fromme f90902c5e3 chore: update browserslist 2026-03-16 11:59:09 +01:00
Björn Fromme d0d6844fbd wip: field states and dependencies 2026-03-16 11:59:09 +01:00
Björn Fromme cd7a724e62 wip: refactor forms 2026-03-16 11:59:09 +01:00
Björn Fromme 1f5877460b wip: refactor forms 2026-03-16 11:59:09 +01:00
Björn Fromme 8da77ee13b wip: collapsible forms 2026-03-16 11:59:09 +01:00
Björn Fromme d205cd09ef wip: refactor forms 2026-03-16 11:59:09 +01:00
Björn Fromme b44d8505b2 wip: feedback about booked and assigned rooms 2026-03-16 11:59:09 +01:00
Björn Fromme 9d99fe9272 wip: refactoring 2026-03-16 11:59:09 +01:00
Björn Fromme 431839d36d wip: refactoring 2026-03-16 11:59:09 +01:00
Björn Fromme cce1f688b9 wip: refactoring 2026-03-16 11:59:09 +01:00
920 changed files with 123285 additions and 13225 deletions
@@ -1,11 +0,0 @@
name: opencode
repository: /Users/fromme/Development/Misc/ddev-opencode
version: ""
install_date: "2026-01-05T17:21:57+01:00"
project_files:
- web-build/Dockerfile.opencode
- commands/web/opencode
- config.opencode.yaml
- opencode/.gitignore
global_files: []
removal_actions: []
-11
View File
@@ -1,11 +0,0 @@
#!/bin/bash
#ddev-generated
## Description: OpenCode AI coding assistant
## Usage: opencode
## Example: ddev opencode [...]
set -e
opencode $@
-6
View File
@@ -1,6 +0,0 @@
#ddev-generated
webimage_extra_packages:
- xdg-utils
hooks:
post-start:
- exec: "mkdir -p /var/www/html/.ddev/opencode/.opencode && ln -sf /var/www/html/.ddev/opencode/.opencode ~/.opencode"
+70 -41
View File
@@ -1,44 +1,62 @@
name: myep
type: php
docroot: public
php_version: "8.2"
php_version: "8.4"
webserver_type: apache-fpm
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
additional_hostnames:
- mysnz
- mysbw
- myser
additional_fqdns: [ ]
database:
type: mariadb
version: "10.11"
version: "11.8"
webimage_extra_packages: [ ripgrep, bubblewrap, socat ]
use_dns_when_possible: true
timezone: Europe/Berlin
composer_version: "2"
web_environment: []
web_environment: [ ]
nodejs_version: "22"
corepack_enable: false
# Key features of DDEV's config.yaml:
# name: <projectname> # Name of the project, automatically provides
# http://projectname.ddev.site and https://projectname.ddev.site
# If the name is omitted, the project will take the name of the enclosing directory,
# which is useful if you want to have a copy of the project side by side with this one.
# type: <projecttype> # backdrop, craftcms, django4, drupal, drupal6, drupal7, laravel, magento, magento2, php, python, shopware6, silverstripe, typo3, wordpress
# See https://ddev.readthedocs.io/en/stable/users/quickstart/ for more
# type: <projecttype> # asterios, backdrop, cakephp, codeigniter, craftcms, drupal, drupal6, drupal7, drupal8, drupal9, drupal10, drupal11, drupal12, generic, joomla, laravel, magento, magento2, maho, modx, php, shopware6, silverstripe, symfony, typo3, wordpress, wp-bedrock
# See https://docs.ddev.com/en/stable/users/quickstart/ for more
# information on the different project types
# "drupal" covers recent Drupal 8+
# docroot: <relative_path> # Relative path to the directory containing index.php.
# php_version: "8.2" # PHP version to use, "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"
# php_version: "8.4" # PHP version to use, "5.6" through "8.5"
# You can explicitly specify the webimage but this
# is not recommended, as the images are often closely tied to DDEV's' behavior,
# is not recommended, as the images are often closely tied to DDEV's behavior,
# so this can break upgrades.
# webimage: <docker_image> # nginx/php docker image.
# webimage: <docker_image>
# Its unusual to change this option, and we dont recommend it without Docker experience and a good reason.
# Typically, this means additions to the existing web image using a .ddev/web-build/Dockerfile.*
# database:
# type: <dbtype> # mysql, mariadb, postgres
# version: <version> # database version, like "10.11" or "8.0"
# MariaDB versions can be 5.5-10.8, 10.11, and 11.4.
# MySQL versions can be 5.5-8.0.
# PostgreSQL versions can be 9-17.
# MariaDB versions can be 5.5-10.8, 10.11, 11.4, 11.8, 12.3
# MySQL versions can be 5.5-8.0, 8.4, 9.7
# PostgreSQL versions can be 9-18
# You can explicitly specify the dbimage but this
# is not recommended, as the images are often closely tied to DDEV's behavior,
# so this can break upgrades.
# dbimage: <docker_image>
# Its unusual to change this option, and we dont recommend it without Docker experience and a good reason.
# Typically, this means additions to the existing db image using a .ddev/db-build/Dockerfile.*
# router_http_port: <port> # Port to be used for http (defaults to global configuration, usually 80)
# router_https_port: <port> # Port for https (defaults to global configuration, usually 443)
@@ -48,12 +66,20 @@ corepack_enable: false
# "ddev xdebug" to enable Xdebug and "ddev xdebug off" to disable it work better,
# as leaving Xdebug enabled all the time is a big performance hit.
# xhprof_enabled: false # Set to true to enable Xhprof and "ddev start" or "ddev restart"
# Note that for most people the commands
# "ddev xhprof" to enable Xhprof and "ddev xhprof off" to disable it work better,
# as leaving Xhprof enabled all the time is a big performance hit.
# xhgui_http_port: "8143"
# xhgui_https_port: "8142"
# The XHGui ports can be changed from the default 8143 and 8142
# Very rarely used
# webserver_type: nginx-fpm, apache-fpm, or nginx-gunicorn
# host_xhgui_port: "8142"
# Can be used to change the host binding port of the XHGui
# application. Rarely used; only when port conflict and
# bind_all_ports is used (normally with router disabled)
# xhprof_mode: [prepend|xhgui|global]
# Default is "xhgui"
# webserver_type: nginx-fpm, apache-fpm, generic
# timezone: Europe/Berlin
# If timezone is unset, DDEV will attempt to derive it from the host system timezone
@@ -69,22 +95,24 @@ corepack_enable: false
# commands are executed.
# composer_version: "2"
# You can set it to "" or "2" (default) for Composer v2 or "1" for Composer v1
# You can set it to "" or "2" (default) for Composer v2
# to use the latest major version available at the time your container is built.
# It is also possible to use each other Composer version channel. This includes:
# It is also possible to use any other Composer version channel. This includes:
# - 2.2 (latest Composer LTS version)
# - stable
# - preview
# - snapshot
# Alternatively, an explicit Composer version may be specified, for example "2.2.18".
# To reinstall Composer after the image was built, run "ddev debug rebuild".
# To reinstall Composer after the image was built, run "ddev utility rebuild".
# nodejs_version: "20"
# nodejs_root: <relative_path>
# Relative path to the directory containing the Node.js version file from the
# project root. Only used with "nodejs_version: auto" or "nodejs_version: engine".
# nodejs_version: "24"
# change from the default system Node.js version to any other version.
# See https://ddev.readthedocs.io/en/stable/users/configuration/config/#nodejs_version for more information
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation,
# Note that using of 'ddev nvm' is discouraged because "nodejs_version" is much easier to use,
# can specify any version, and is more robust than using 'nvm'.
# See https://docs.ddev.com/en/stable/users/configuration/config/#nodejs_version for more information
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation.
# corepack_enable: false
# Change to 'true' to 'corepack enable' and gain access to latest versions of yarn/pnpm
@@ -117,7 +145,7 @@ corepack_enable: false
# ddev_version_constraint: ""
# Example:
# ddev_version_constraint: ">= 1.22.4"
# ddev_version_constraint: ">= 1.24.8"
# This will enforce that the running ddev version is within this constraint.
# See https://github.com/Masterminds/semver#checking-version-constraints for
# supported constraint formats
@@ -144,10 +172,8 @@ corepack_enable: false
# - "global": uses the value from the global config.
# - "none": disables performance optimization for this project.
# - "mutagen": enables Mutagen for this project.
# - "nfs": enables NFS for this project.
#
# See https://ddev.readthedocs.io/en/stable/users/install/performance/#nfs
# See https://ddev.readthedocs.io/en/stable/users/install/performance/#mutagen
# See https://docs.ddev.com/en/stable/users/install/performance/#mutagen
# fail_on_hook_fail: False
# Decide whether 'ddev start' should be interrupted by a failing hook
@@ -176,10 +202,10 @@ corepack_enable: false
# The mailpit port is not normally bound on the host at all, instead being routed
# through ddev-router, but it can be bound directly to localhost if specified here.
# webimage_extra_packages: [php7.4-tidy, php-bcmath]
# webimage_extra_packages: ['php${DDEV_PHP_VERSION}-tidy', 'php${DDEV_PHP_VERSION}-yac']
# Extra Debian packages that are needed in the webimage can be added here
# dbimage_extra_packages: [telnet,netcat]
# dbimage_extra_packages: [netcat, telnet, sudo]
# Extra Debian packages that are needed in the dbimage can be added here
# use_dns_when_possible: true
@@ -191,12 +217,15 @@ corepack_enable: false
# project_tld: ddev.site
# The top-level domain used for project URLs
# The default "ddev.site" allows DNS lookup via a wildcard
# If you prefer you can change this to "ddev.local" to preserve
# pre-v1.9 behavior.
# ngrok_args: --basic-auth username:pass1234
# Provide extra flags to the "ngrok http" command, see
# https://ngrok.com/docs/ngrok-agent/config or run "ngrok http -h"
# share_default_provider: ngrok
# The default share provider to use for "ddev share"
# Defaults to global configuration, usually "ngrok"
# Can be "ngrok" or "cloudflared" or the name of a custom provider from .ddev/share-providers/
# share_provider_args: --basic-auth username:pass1234
# Provide extra flags to the share provider script
# See https://docs.ddev.com/en/stable/users/configuration/config/#share_provider_args
# disable_settings_management: false
# If true, DDEV will not create CMS-specific settings files like
@@ -258,7 +287,7 @@ corepack_enable: false
# override_config: false
# By default, config.*.yaml files are *merged* into the configuration
# But this means that some things can't be overridden
# For example, if you have 'use_dns_when_possible: true'' you can't override it with a merge
# For example, if you have 'use_dns_when_possible: true' you can't override it with a merge
# and you can't erase existing hooks or all environment variables.
# However, with "override_config: true" in a particular config.*.yaml file,
# 'use_dns_when_possible: false' can override the existing values, and
@@ -268,13 +297,13 @@ corepack_enable: false
# web_environment: []
# or
# additional_hostnames: []
# can have their intended affect. 'override_config' affects only behavior of the
# can have their intended effect. 'override_config' affects only behavior of the
# config.*.yaml file it exists in.
# Many DDEV commands can be extended to run tasks before or after the
# DDEV command is executed, for example "post-start", "post-import-db",
# "pre-composer", "post-composer"
# See https://ddev.readthedocs.io/en/stable/users/extend/custom-commands/ for more
# See https://docs.ddev.com/en/stable/users/extend/custom-commands/ for more
# information on the commands that can be extended and the tasks you can define
# for them. Example:
#hooks:
-5
View File
@@ -1,5 +0,0 @@
#ddev-generated
# OpenCode internal config
/.opencode/
-4
View File
@@ -1,4 +0,0 @@
#ddev-generated
RUN npm install -g opencode-ai
+65 -9
View File
@@ -25,7 +25,7 @@ APP_SECRET=642ead390b8a38f0a017ec84d5362129
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=8.0.32&charset=utf8mb4"
DATABASE_URL="mysql://db:db@db:3306/db?serverVersion=10.11.11-MariaDB&charset=utf8mb4"
DATABASE_URL="mysql://db:db@db:3306/db?serverVersion=mariadb-11.8.9&charset=utf8mb4"
# DATABASE_URL="postgresql://app:[email protected]:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
@@ -40,32 +40,83 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
MAILER_DSN=null://null
###< symfony/mailer ###
MAILJET_API_KEY=
MAILJET_API_SECRET=
MAILJET_API_BASE_URL=https://api.mailjet.com/v3/REST
MAILJET_DEFAULT_LIST_ID=
# Development default for HTTP Basic Auth password; override in production secrets.
MAILJET_WEBHOOK_BASIC_PASSWORD=secret
APP_NEWSLETTER_CONFIRMATION_TTL_HOURS=1
# Dedicated signing secret for accommodation booking customer access links (kept separate
# from APP_SECRET so it can be rotated independently). Unlike lazily-used API keys, UriSigner
# validates this is non-empty at construction time, so a real dev value is required here
# (override in .env.local/production secrets as usual).
ACCOMMODATION_OFFER_LINK_SECRET=abf8ec28cc2162d9121d35d6f8cbf7c29728cdacce0303e22e1bac854501728a
ACCOMMODATION_TERMS_AT=
ACCOMMODATION_TERMS_CH=
ACCOMMODATION_TERMS_IT=
BPN_CONNECT_BASE_URL=https://bpn-connect.ep-reisen.app
BPN_CONNECT_API_KEY=
# ClickUp task created when an accommodation booking is confirmed. Token/ids are secrets and
# stay empty here — set them in .env.local. Without them the handler skips with a warning.
CLICKUP_API_TOKEN=
CLICKUP_LIST_ID=
CLICKUP_TEMPLATE_ID=
CLICKUP_API_BASE_URL=https://api.clickup.com/api/v2
APP_BPN_USER=
APP_BPN_PASSWORD=
APP_BPN_IP=
APP_BPN_PORT=
APP_BPN_PORTS=
APP_BPN_DEBUG=false
APP_BPN_CONNECTION_TIMEOUT=5
APP_BPN_STREAM_TIMEOUT=30
APP_BPN_TOTAL_TIMEOUT=45
APP_TRAVEL_INFO_BASE_URL="https://www.ep-reisen.de/reiseinformationen/"
APP_LEGAL_NOTICE_URL="https://www.ep-reisen.de/unternehmen/impressum-skireiseveranstalter/"
APP_TERMS_AND_CONDITIONS_URL="https://www.ep-reisen.de/skireisen/infos/allgemeine-infos/agb/"
APP_PRIVACY_POLICY_URL="https://www.ep-reisen.de/unternehmen/impressum-skireiseveranstalter/datenschutz-winterreisen/"
APP_CMS_API_BASE_URL="https://www.ep-reisen.de/"
APP_WEBSITE_BASE_URL="https://www.ep-reisen.de/"
APP_BASE_URL="https://my.ep-reisen.de"
APP_CUSTOMER_SERVICE_EMAIL="[email protected]"
APP_INSURANCE_REVOCATION_URL="https://www.hmrv.de/daten-aendern/vertrag-beenden/widerruf"
# Travel Data Service Configuration
APP_TRAVEL_PREFER_REMOTE=false
APP_TRAVEL_ENABLE_FALLBACK=true
APP_TRAVEL_SNAPSHOT_RETENTION_BUFFER_DAYS=14
API_KEYS=
# Emails
APP_DEFAULT_EMAIL_FROM=[email protected]
APP_DEFAULT_EMAIL_TO=[email protected]
ACCOMMODATION_INQUIRY_EMAIL=[email protected]
XML_EXPORT_PATH="%kernel.project_dir%/var/xmlexport"
JSON_EXPORT_PATH="%kernel.project_dir%/var/jsonexport"
# Global common defaults
APP_SEASON_WINTER_FROM=2026-10-01
APP_SEASON_SUMMER_FROM=2026-05-01
APP_RUNNING_COSTS_FACTOR_EUR=2.75
APP_RUNNING_COSTS_FACTOR_CHF=3.2
APP_UNDERSUBSCRIPTION_SURCHARGE_30_EUR=5.0
APP_UNDERSUBSCRIPTION_SURCHARGE_30_CHF=5.0
APP_UNDERSUBSCRIPTION_SURCHARGE_40_EUR=2.5
APP_UNDERSUBSCRIPTION_SURCHARGE_40_CHF=2.5
SFTP_XML_EXPORT_HOST=
SFTP_XML_EXPORT_PORT=
SFTP_XML_EXPORT_USER=
SFTP_XML_EXPORT_PASSWORD=
# Booking Configuration
# Status for new bookings: 'F' (Fixed/Final), 'O' (Option - requires agency confirmation)
# Use 'O' during beta phase, switch to 'F' for production
DEFAULT_BOOKING_STATUS=F
SFTP_XML_SOURCE_HOST=
SFTP_XML_SOURCE_PORT=
SFTP_XML_SOURCE_USER=
SFTP_XML_SOURCE_PASSWORD=
SFTP_XML_SOURCE_ROOT=
###> league/oauth2-server-bundle ###
OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/secret/private.key
@@ -78,3 +129,8 @@ OAUTH_ENCRYPTION_KEY=580084fd179e67399467f59ee96658ac
# postgresql+advisory://db_user:db_password@localhost/db_name
LOCK_DSN=flock
###< symfony/lock ###
MAINTENANCE_MODE_ENABLED=false
MAINTENANCE_MODE_IP_WHITELIST=188.245.62.21
MAINTENANCE_MODE_ROUTE_WHITELIST=
MAINTENANCE_MODE_PATH_WHITELIST=/api,/token
+1
View File
@@ -4,3 +4,4 @@ APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999
PANTHER_APP_ENV=panther
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots
MAILJET_WEBHOOK_BASIC_PASSWORD=secret
+11 -5
View File
@@ -8,13 +8,9 @@
/vendor/
###< symfony/framework-bundle ###
###> phpunit/phpunit ###
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###
###> symfony/phpunit-bridge ###
.phpunit.result.cache
.phpunit.cache
/phpunit.xml
###< symfony/phpunit-bridge ###
@@ -31,3 +27,13 @@ yarn-error.log
/.php-cs-fixer.php
/.php-cs-fixer.cache
###< friendsofphp/php-cs-fixer ###
/ray.php
###> phpstan/phpstan ###
phpstan.neon
###< phpstan/phpstan ###
###> config reference ###
/config/reference.php
###< config reference ###
+51 -10
View File
@@ -60,7 +60,7 @@ Authorization: Bearer {{$auth.token("oauth2_api")}}
### API travel
# @no-cookie-jar
GET {{base_url}}/api/travels/SBW131225
GET {{base_url}}/api/travels/DPWMP140326
Accept: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
@@ -72,7 +72,7 @@ Authorization: Bearer {{$auth.token("oauth2_api")}}
### API hotel availability remote
# @no-cookie-jar
GET {{base_url}}/api/travels/11603/152546/2026-01-03/availability
GET {{base_url}}/api/travels/11606/152546/2026-01-24/availability
Accept: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
@@ -90,16 +90,50 @@ Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
{
"lastName": "Duschen",
"firstName": "Isolde",
"gender": "f",
"street": "Fooroad 1",
"zipCode": "12345",
"city": "Bartown",
"email": "[email protected]",
"phone": "12345"
"lastName": "{{$random.name.lastName}}",
"firstName": "{{$random.name.firstName}}",
"gender": "d",
"street": "{{$random.address.streetAddress}}",
"zipCode": "{{$random.address.zipCode}}",
"city": "{{$random.address.city}}",
"email": "{{$random.email}}",
"phone": "{{$random.phoneNumber.cellPhone}}"
}
### API newsletter lists map
# @no-cookie-jar
GET {{base_url}}/api/newsletters
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_newsletter")}}
### API newsletter subscriptions
# @no-cookie-jar
POST {{base_url}}/api/newsletter-subscriptions
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_newsletter")}}
{
"email": "{{$random.email}}",
"firstName": "{{$random.address.firstName}}",
"lastName": "{{$random.address.lastName}}",
"listIds": [10321569,10321382,10321383]
}
### API contingent calendar
# @no-cookie-jar
GET {{base_url}}/api/contingents/calendar?hotelCode=DGS&dateFrom=2026-06-01&dateTo=2026-06-30
Accept: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
### API contintent prices
# @no-cookie-jar
GET {{base_url}}/api/contingents/prices?hotelCode=DGS&year=2026
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
### API pickups planning webhook
# @no-cookie-jar
POST {{base_url}}/api/pickups-planning
@@ -115,3 +149,10 @@ GET {{base_url}}/api/pickups-planning/DPWWTS191125
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
### API accommodation booking
# @no-cookie-jar
GET {{base_url}}/api/accommodation-bookings/e4591076-eb65-41e8-a115-09d18d15604a
Accept: application/json
Content-Type: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}}
+8
View File
@@ -0,0 +1,8 @@
import htmx from 'htmx.org'
htmx.config.includeIndicatorStyles = false
htmx.config.historyCacheSize = 0
htmx.config.allowScriptTags = false
import './bootstrap.js'
import './styles/admin.css'
+9
View File
@@ -13,3 +13,12 @@ htmx.config.allowScriptTags = false
htmx.config.withCredentials = true
htmx.config.selfRequestsOnly = false
htmx.config.timeout = 50000 // 50 seconds - slightly higher than backend timeout (45s)
document.body.addEventListener('htmx:beforeSwap', (event) => {
// Symfony renders invalid forms with 422; let HTMX swap those responses so inline
// validation errors are actually shown to the user.
if (event.detail?.xhr?.status === 422) {
event.detail.shouldSwap = true
event.detail.isError = false
}
})
@@ -0,0 +1,84 @@
import { Controller } from '@hotwired/stimulus'
import { useFetch } from '../mixins/use_fetch'
import Autocomplete from '@trevoreyre/autocomplete-js'
export default class extends Controller {
static targets = [ 'input', 'field', 'resetButton', 'searchIcon' ]
static values = { url: String, choices: Array, selected: Boolean }
initialize() {
useFetch(this)
}
connect() {
const searchHandler = input => {
return new Promise(resolve => {
// Check input minimum length
if (input.length < 2) {
return resolve([])
}
// Search choices if provided
if (this.choicesValue.length > 0) {
return resolve(this.choicesValue.filter(choice => {
return -1 !== choice.text.toLowerCase().search(input.toLowerCase())
}))
}
// Use API otherwise
let data = { search: input }
fetch(this.urlValue, { method: 'POST', body: JSON.stringify(data), credentials: 'include' })
.then(this.checkStatus)
.then(this.parseJSON)
.then(data => {
resolve(data)
})
})
}
const submitHandler = result => {
this.fieldTarget.value = result.value
this.selectedValue = true
this.element.dispatchEvent(new CustomEvent('select', {
detail: { result }
}))
}
this.autocomplete = new Autocomplete(this.element, {
search: searchHandler,
getResultValue: result => result.text,
submitOnEnter: true,
onSubmit: submitHandler,
debounceTime: 250,
})
if (this.fieldTarget.value) {
this.selectedValue = true
}
// prevent form submission when selecting entry in autocomplete list with enter key
this.element.addEventListener('keypress', e => {
if (e.key === 'Enter') {
e.preventDefault()
}
})
}
reset() {
this.inputTarget.value = null
this.fieldTarget.value = null
this.selectedValue = false
this.element.dispatchEvent(new CustomEvent('reset'))
}
selectedValueChanged() {
this.resetButtonTarget.classList.toggle('hidden', false === this.selectedValue)
this.searchIconTarget.classList.toggle('hidden', this.selectedValue)
}
disconnect() {
this.autocomplete.destroy()
}
}
+59
View File
@@ -0,0 +1,59 @@
import { Controller } from '@hotwired/stimulus'
/**
* Monitors birthday input fields (day, month, year) and dispatches a custom event
* only when all three fields are filled with valid values.
*
* This prevents premature HTMX refreshes when users are still entering the date,
* improving UX by waiting until the complete date is entered.
*/
export default class extends Controller {
static targets = ['day', 'month', 'year']
/**
* Checks if all birthday fields are filled and dispatches a completion event.
*
* Called on input/change events from the day, month, and year fields.
* Only dispatches the 'birthday:complete' event when all three fields
* contain valid values that could form a complete date.
*/
check() {
const day = this.dayTarget.value.trim()
const month = this.monthTarget.value.trim()
const year = this.yearTarget.value.trim()
if (false === this.isComplete(day, month, year)) {
return
}
this.element.dispatchEvent(new CustomEvent('birthday:complete', { bubbles: true }))
}
/**
* Validates that all date components are filled with plausible values.
*
* @param {string} day The day value
* @param {string} month The month value
* @param {string} year The year value
*
* @returns {boolean} True if all fields contain complete values
*/
isComplete(day, month, year) {
// Day: 1-2 digits
if (0 === day.length || day.length > 2) {
return false
}
// Month: 1-2 digits
if (0 === month.length || month.length > 2) {
return false
}
// Year: exactly 4 digits for a complete year
if (4 !== year.length) {
return false
}
return true
}
}
@@ -0,0 +1,37 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = {
content: String,
label: String,
}
connect() {
this.originalLabel = this.element.innerText
}
disconnect() {
clearTimeout(this.resetTimer)
}
copy() {
navigator.clipboard.writeText(this.contentValue).then(() => {
this.dispatch('copied', {
detail: {
content: this.contentValue,
}
})
}).catch((error) => {
console.error('Failed to copy to clipboard:', error)
})
if (this.hasLabelValue) {
this.element.innerText = this.labelValue
clearTimeout(this.resetTimer)
this.resetTimer = setTimeout(() => {
this.element.innerText = this.originalLabel
}, 3000)
}
}
}
@@ -0,0 +1,13 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static values = {
payload: Object
};
connect() {
if (typeof window.dataLayer !== 'undefined') {
window.dataLayer.push(this.payloadValue);
}
}
}
@@ -0,0 +1,70 @@
import { Controller } from '@hotwired/stimulus'
import { Calendar } from 'vanilla-calendar-pro'
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = ['field', 'hiddenField']
static values = {
minDate: String,
maxDate: String,
disableWeekends: Boolean,
disabledDates: Array,
}
connect() {
const options = {
inputMode: true,
locale: 'de-DE',
selectedTheme: 'light',
selectedDates: this.hiddenFieldTarget.value ? [this.hiddenFieldTarget.value] : [],
onClickDate: (self) => {
const iso = self.context.selectedDates[0] ?? null
this.hiddenFieldTarget.value = iso ?? ''
if (iso) {
const [year, month, day] = iso.split('-')
this.fieldTarget.value = `${day}.${month}.${year}`
} else {
this.fieldTarget.value = ''
}
this.element.dispatchEvent(new CustomEvent('datepicker:picked', {
detail: { date: this.fieldTarget.value }
}))
},
onHide: () => {
this.element.dispatchEvent(new CustomEvent('datepicker:closed'))
},
}
if (this.minDateValue) options.dateMin = this.minDateValue
if (this.maxDateValue) options.dateMax = this.maxDateValue
if (this.disableWeekendsValue) options.disableWeekdays = [0, 6]
if (this.disabledDatesValue.length) options.disableDates = this.disabledDatesValue
this.picker = new Calendar(this.fieldTarget, options)
this.picker.init()
this.handleManualInput = () => {
const value = this.fieldTarget.value.trim()
if (!value) {
this.hiddenFieldTarget.value = ''
this.picker.set({ selectedDates: [] }, { dates: true })
} else {
const match = value.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/)
if (match) {
const [, day, month, year] = match
const iso = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
this.hiddenFieldTarget.value = iso
this.picker.set({ selectedDates: [iso] }, { dates: true })
}
}
this.element.dispatchEvent(new CustomEvent('datepicker:closed'))
}
this.fieldTarget.addEventListener('change', this.handleManualInput)
}
disconnect() {
this.fieldTarget.removeEventListener('change', this.handleManualInput)
this.picker.destroy()
}
}
+29
View File
@@ -0,0 +1,29 @@
import { Controller } from '@hotwired/stimulus'
import GLightbox from 'glightbox'
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = ['item']
connect() {
this.lightbox = GLightbox({
elements: this.itemTargets.map((el) => ({
href: el.dataset.galleryHref,
type: 'image',
alt: el.dataset.galleryAlt ?? '',
})),
})
this.itemTargets.forEach((el, index) => {
el.addEventListener('click', (e) => {
e.preventDefault()
this.lightbox.openAt(index)
})
})
}
disconnect() {
this.lightbox.destroy()
}
}
@@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static outlets = [ 'mobilenav' ]
static classes = [ 'closed' ]
trigger({ params: { mode } }) {
this.mobilenavOutlet.toggle(mode)
}
toggle(mode) {
// Add animation classes only now to avoid fouc
this.element.classList.add('transition-transform', 'duration-300')
this.element.classList.toggle(this.closedClass, 'close' === mode)
}
}
@@ -0,0 +1,36 @@
import { Controller } from '@hotwired/stimulus'
import { useClickOutside } from 'stimulus-use'
export default class extends Controller {
static targets = [ 'label', 'dropdown', 'choice' ]
static values = { placeholder: String }
connect() {
this.update()
useClickOutside(this)
}
toggle() {
this.dropdownTarget.classList.toggle('hidden')
}
update() {
let labels = []
this.choiceTargets.forEach((choice) => {
if (choice.checked) {
labels.push(choice.dataset.label)
}
this.labelTarget.innerText = labels.join(', ')
})
if (0 === labels.length) {
this.labelTarget.innerText = this.placeholderValue
}
}
clickOutside(e) {
this.dropdownTarget.classList.toggle('hidden', true)
}
}
@@ -0,0 +1,11 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = [ 'field' ]
toggle() {
let type = this.fieldTarget.getAttribute('type') === 'password' ? 'text' : 'password'
this.fieldTarget.setAttribute('type', type)
}
}
@@ -0,0 +1,166 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static targets = ['mount', 'error', 'message', 'resetButton', 'day', 'dateFrom', 'dateTo', 'submit']
static values = {
hotelCode: String,
selectedFrom: String,
selectedTo: String,
calendarRefreshUrl: String,
}
connect() {
this.startDate = null
this.endDate = null
this.sessionRestored = false
// Re-apply highlights after every HTMX month swap (navigation or initial load).
this.mountTarget.addEventListener('htmx:afterSwap', () => requestAnimationFrame(() => this.initAfterLoad()))
this.mountTarget.addEventListener('htmx:responseError', () => this.showError())
}
initAfterLoad() {
// Restore from session values exactly once on the first swap.
if (!this.sessionRestored) {
this.sessionRestored = true
const from = this.selectedFromValue
const to = this.selectedToValue
if (from && to) {
this.startDate = from
this.endDate = to
if (this.hasResetButtonTarget) this.resetButtonTarget.classList.remove('hidden')
}
}
this.updateDisplay()
}
selectDate(event) {
const btn = event.currentTarget
btn.blur()
const date = btn.dataset.date
const status = btn.dataset.status
if (!status || status === 'blocked' || status === 'past') return
if (this.startDate && this.endDate) {
this.resetSelection()
}
if (!this.startDate) {
if (status === 'checkout-only') {
this.showMessage('Bitte wähle einen Anreisetag.')
return
}
this.startDate = date
this.endDate = null
this.updateDisplay()
this.showMessage('Bitte wähle das Abreisedatum.')
return
}
if (date === this.startDate) {
this.resetSelection()
return
}
const [from, to] = date < this.startDate ? [date, this.startDate] : [this.startDate, date]
if (this.hasBlockedInRange(from, to)) {
this.resetSelection()
this.showMessage('Dieser Zeitraum enthält nicht verfügbare Daten.')
return
}
const startBtn = this.dayTargets.find(b => b.dataset.date === from)
const minNights = parseInt(startBtn?.dataset.minNights) || 0
const nights = (new Date(to) - new Date(from)) / 86400000
if (minNights > 0 && nights < minNights) {
this.showMessage(`Weniger als ${minNights} Nächte nur auf Anfrage.`)
} else {
this.hideMessage()
}
this.startDate = from
this.endDate = to
this.updateDisplay()
this.activateSubmit(from, to)
this.saveAndRefreshSummary(from, to)
this.dispatch('range-select', { detail: { dateFrom: from, dateTo: to } })
}
hasBlockedInRange(from, to) {
for (const btn of this.dayTargets) {
const d = btn.dataset.date
const s = btn.dataset.status
if (d >= from && d < to && (s === 'blocked' || s === 'past' || s === 'checkout-only')) return true
}
return false
}
updateDisplay() {
for (const btn of this.dayTargets) {
const d = btn.dataset.date
btn.classList.remove('pc-day--pending-start', 'pc-day--selected-start', 'pc-day--selected-end', 'pc-day--in-range')
if (!this.startDate) continue
if (d === this.startDate) {
btn.classList.add(this.endDate ? 'pc-day--selected-start' : 'pc-day--pending-start')
} else if (this.endDate) {
if (d === this.endDate) btn.classList.add('pc-day--selected-end')
else if (d > this.startDate && d < this.endDate) btn.classList.add('pc-day--in-range')
}
}
}
activateSubmit(dateFrom, dateTo) {
if (this.hasDateFromTarget) this.dateFromTarget.value = dateFrom
if (this.hasDateToTarget) this.dateToTarget.value = dateTo
if (this.hasSubmitTarget) {
this.submitTarget.disabled = false
this.submitTarget.classList.remove('opacity-50', 'cursor-not-allowed', 'pointer-events-none')
}
if (this.hasResetButtonTarget) this.resetButtonTarget.classList.remove('hidden')
}
resetSelection() {
this.startDate = null
this.endDate = null
this.updateDisplay()
this.hideMessage()
if (this.hasDateFromTarget) this.dateFromTarget.value = ''
if (this.hasDateToTarget) this.dateToTarget.value = ''
if (this.hasSubmitTarget) {
this.submitTarget.disabled = true
this.submitTarget.classList.add('opacity-50', 'cursor-not-allowed', 'pointer-events-none')
}
if (this.hasResetButtonTarget) this.resetButtonTarget.classList.add('hidden')
this.saveAndRefreshSummary()
}
reset() {
this.resetSelection()
}
saveAndRefreshSummary(dateFrom = '', dateTo = '') {
if (!this.hasCalendarRefreshUrlValue) return
htmx.ajax('POST', this.calendarRefreshUrlValue, {
values: { date_from: dateFrom, date_to: dateTo },
swap: 'none',
target: this.element,
})
}
showMessage(text) {
if (this.hasMessageTarget) this.messageTarget.textContent = text
}
hideMessage() {
if (this.hasMessageTarget) this.messageTarget.textContent = ''
}
showError() {
if (this.hasErrorTarget) this.errorTarget.classList.remove('hidden')
}
}
@@ -0,0 +1,33 @@
import { Controller } from '@hotwired/stimulus'
/**
* Unchecks conflicting additional services as soon as one is selected, so the user sees the
* result immediately instead of waiting for the debounced htmx refresh. The server resolves
* the same conflicts again and stays the source of truth.
*/
export default class extends Controller {
static targets = [ 'input' ]
select(event) {
const input = event.target
if (!input.checked) {
return
}
const group = input.dataset.exclusionGroup
if (!group) {
return
}
const exclusive = '1' === input.dataset.exclusive
this.inputTargets
.filter(other => other !== input)
.filter(other => other.dataset.exclusionGroup === group)
.filter(other => exclusive || '1' === other.dataset.exclusive)
.forEach(other => { other.checked = false })
}
}
@@ -0,0 +1,30 @@
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
static classes = ['closed', 'iconClosed', 'iconExpanded']
static targets = ['submenu', 'button', 'icon']
static values = { expanded: Boolean }
toggleSubmenu() {
this.expandedValue = !this.expandedValue
}
expandedValueChanged(expanded) {
this.submenuTarget.classList.toggle(this.closedClass, false === expanded)
if (false === this.hasButtonTarget) {
return
}
this.buttonTarget.setAttribute('aria-expanded', expanded)
if (false === this.hasIconTarget) {
return
}
if (true === expanded) {
this.iconTarget.classList.add(...this.iconExpandedClasses)
this.iconTarget.classList.remove(...this.iconClosedClasses)
} else {
this.iconTarget.classList.add(...this.iconClosedClasses)
this.iconTarget.classList.remove(...this.iconExpandedClasses)
}
}
}
+90
View File
@@ -0,0 +1,90 @@
import { Controller } from '@hotwired/stimulus'
import Sortable from 'sortablejs'
export default class extends Controller {
static targets = [ 'list', 'item', 'handle', 'positionField', 'positionLabel', 'status' ]
static values = {
url: String,
}
connect() {
this.abortController = null
// The sortable container may be nested (e.g. a tbody) when the controller element also
// has to wrap elements that must not be dragged, like the status message.
new Sortable(this.hasListTarget ? this.listTarget : this.element, {
draggable: '[data-sortable-target="item"]',
handle: '[data-sortable-target="handle"]',
sort: true,
fallbackOnBody: true,
onEnd: e => {
this.updateOrdering()
this.persist()
}
})
}
disconnect() {
this.abortController?.abort()
}
updateOrdering() {
this.positionFieldTargets.forEach((field, index) => {
field.value = index + 1
})
this.positionLabelTargets.forEach((label, index) => {
label.innerText = index + 1
})
}
/**
* Sends the new order to the server. Only active when a url value is present, so the
* controller stays usable for plain form ordering.
*/
persist() {
if (!this.hasUrlValue || this.urlValue === '') {
return
}
// A drag while the previous request is still running makes that request obsolete.
this.abortController?.abort()
this.abortController = new AbortController()
const ids = this.itemTargets
.map(item => Number(item.dataset.sortableId))
.filter(id => Number.isInteger(id) && id > 0)
this.setStatus('speichert …')
fetch(this.urlValue, {
method: 'POST',
credentials: 'include',
signal: this.abortController.signal,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids }),
})
.then(response => {
if (!response.ok) {
throw new Error(`Unexpected response ${response.status}`)
}
this.setStatus('Reihenfolge gespeichert')
})
.catch(error => {
if (error.name === 'AbortError') {
return
}
console.error('Failed to persist ordering', error)
this.setStatus('Speichern fehlgeschlagen')
})
}
setStatus(message) {
this.statusTargets.forEach(status => {
status.innerText = message
})
}
}
-9
View File
@@ -24,24 +24,15 @@ export default class extends Controller {
}
handleNotifications(event) {
console.log('[VOUCHER DEBUG] showNotifications event received:', event)
console.log('[VOUCHER DEBUG] event.detail:', event.detail)
// HTMX wraps the trigger value in an object with 'value' and 'elt' properties
// event.detail.value contains the actual array from the HX-Trigger header
const notifications = event.detail?.value || event.detail || []
console.log('[VOUCHER DEBUG] notifications array:', notifications)
console.log('[VOUCHER DEBUG] notifications count:', Array.isArray(notifications) ? notifications.length : 'not an array')
if (Array.isArray(notifications)) {
notifications.forEach((notification, index) => {
console.log(`[VOUCHER DEBUG] Processing notification ${index}:`, notification)
const className = this.getClassForType(notification.type)
this.showToast(notification.message, className)
})
} else {
console.error('[VOUCHER DEBUG] Notifications is not an array:', notifications)
}
}
+5 -1
View File
@@ -2,7 +2,7 @@ import {Controller} from '@hotwired/stimulus'
export default class extends Controller {
static classes = ['closed', 'open', 'iconOpen']
static targets = ['content', 'icon', 'container']
static targets = ['content', 'icon', 'container', 'trigger']
static values = {
open: {
type: Boolean,
@@ -43,6 +43,10 @@ export default class extends Controller {
this.iconTarget.classList.toggle(iconClass, true === open)
}
if (this.hasTriggerTarget) {
this.triggerTarget.setAttribute('aria-expanded', String(open))
}
// Toggle class on container element (or controller element) if specified
if (this.hasOpenClass) {
const container = this.hasContainerTarget ? this.containerTarget : this.element
+2 -1
View File
@@ -1,5 +1,5 @@
import { Controller } from '@hotwired/stimulus'
import tippy from 'tippy.js'
import tippy, { hideAll } from 'tippy.js'
export default class extends Controller {
static targets = ['trigger', 'template']
@@ -27,6 +27,7 @@ export default class extends Controller {
allowHTML: true,
interactive: true,
appendTo: document.body,
onShow(instance) { hideAll({ exclude: instance }) },
}
}
if (this.hasTriggerTarget) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 130 130" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(3, 28)">
<path d="M107,0.3c-36.4,5.5 -81.6,19.1 -81.6,38.2c0,17.7 41.8,13.2 41.8,13.2c0,0 -67,22.3 -67,-7c0,-33.2 84.5,-44.4 106.8,-44.4Z" fill="#0084d4"/>
<path d="M17,73.5c36.4,-5.4 81.6,-19.1 81.6,-38.2c0,-17.7 -41.8,-13.2 -41.8,-13.2c0,0 67,-22.3 67,7c0,33.3 -84.5,44.4 -106.8,44.4Z" fill="#f8c62f"/>
<path d="M60.7,34.3l-12.8,4l12.2,0.8l-0.4,-2.4l1,-2.4Z" fill="#0084d4"/>
<path d="M75.9,35.2l-9.2,2.9l-3.5,9.7l-1.7,-11.3l4,-10.7l1.7,7.9l8.7,1.5Z" fill="#f8c62f"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 KiB

+95
View File
@@ -0,0 +1,95 @@
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-table" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.375 19.5h17.25m-17.25 0a1.125 1.125 0 0 1-1.125-1.125M3.375 19.5h7.5c.621 0 1.125-.504 1.125-1.125m-9.75 0V5.625m0 12.75v-1.5c0-.621.504-1.125 1.125-1.125m18.375 2.625V5.625m0 12.75c0 .621-.504 1.125-1.125 1.125m1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125m0 3.75h-7.5A1.125 1.125 0 0 1 12 18.375m9.75-12.75c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125m19.5 0v1.5c0 .621-.504 1.125-1.125 1.125M2.25 5.625v1.5c0 .621.504 1.125 1.125 1.125m0 0h17.25m-17.25 0h7.5c.621 0 1.125.504 1.125 1.125M3.375 8.25c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125m17.25-3.75h-7.5c-.621 0-1.125.504-1.125 1.125m8.625-1.125c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125M12 10.875v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 10.875c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125M13.125 12h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125M20.625 12c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5M12 14.625v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 14.625c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125m0 1.5v-1.5m0 0c0-.621.504-1.125 1.125-1.125m0 0h7.5" /></symbol>
<symbol id="icon-dots" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 12.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 18.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z" /></symbol>
<symbol id="icon-feedback" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z" /></symbol>
<symbol id="icon-login" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" /></symbol>
<symbol id="icon-logout" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75" /></symbol>
<symbol id="icon-alert" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" /></symbol>
<symbol id="icon-close" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /></symbol>
<symbol id="icon-back" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" /></symbol>
<symbol id="icon-list" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" /></symbol>
<symbol id="icon-menu" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /></symbol>
<symbol id="icon-edit" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /></symbol>
<symbol id="icon-plus" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></symbol>
<symbol id="icon-minus" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15" /></symbol>
<symbol id="icon-search" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" /></symbol>
<symbol id="icon-user" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" /></symbol>
<symbol id="icon-users" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" /></symbol>
<symbol id="icon-delete" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /></symbol>
<symbol id="icon-check" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /></symbol>
<symbol id="icon-upload" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor"><path d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/></symbol>
<symbol id="icon-download" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" /></symbol>
<symbol id="icon-sort" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" /></symbol>
<symbol id="icon-arrow-left" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15m0 0l6.75 6.75M4.5 12l6.75-6.75" /></symbol>
<symbol id="icon-chevron-down" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" /></symbol>
<symbol id="icon-arrow-right" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" /></symbol>
<symbol id="icon-document" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /></symbol>
<symbol id="icon-filter" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z" /></symbol>
<symbol id="icon-refresh" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" /></symbol>
<symbol id="icon-settings" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></symbol>
<symbol id="icon-at" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" d="M16.5 12a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zm0 0c0 1.657 1.007 3 2.25 3S21 13.657 21 12a9 9 0 10-2.636 6.364M16.5 12V8.25" /></symbol>
<symbol id="icon-mail" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /></symbol>
<symbol id="icon-house" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 21h7.5V10.75M2.25 21h1.5m18 0h-18M2.25 9l4.5-1.636M18.75 3l-1.5.545m0 6.205l3 1m1.5.5l-1.5-.5M6.75 7.364V3h-3v18m3-13.636l10.5-3.819" /></symbol>
<symbol id="icon-phone" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z" /></symbol>
<symbol id="icon-mobile" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" /></symbol>
<symbol id="icon-calendar" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z" /></symbol>
<symbol id="icon-hand" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M10.05 4.575a1.575 1.575 0 10-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 013.15 0v1.5m-3.15 0l.075 5.925m3.075.75V4.575m0 0a1.575 1.575 0 013.15 0V15M6.9 7.575a1.575 1.575 0 10-3.15 0v8.175a6.75 6.75 0 006.75 6.75h2.018a5.25 5.25 0 003.712-1.538l1.732-1.732a5.25 5.25 0 001.538-3.712l.003-2.024a.668.668 0 01.198-.471 1.575 1.575 0 10-2.228-2.228 3.818 3.818 0 00-1.12 2.687M6.9 7.575V12m6.27 4.318A4.49 4.49 0 0116.35 15m.002 0h-.002" /></symbol>
<symbol id="icon-copy" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6" /></symbol>
<symbol id="icon-photo" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" /></symbol>
<symbol id="icon-print" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M6.72 13.829c-.24.03-.48.062-.72.096m.72-.096a42.415 42.415 0 0110.56 0m-10.56 0L6.34 18m10.94-4.171c.24.03.48.062.72.096m-.72-.096L17.66 18m0 0l.229 2.523a1.125 1.125 0 01-1.12 1.227H7.231c-.662 0-1.18-.568-1.12-1.227L6.34 18m11.318 0h1.091A2.25 2.25 0 0021 15.75V9.456c0-1.081-.768-2.015-1.837-2.175a48.055 48.055 0 00-1.913-.247M6.34 18H5.25A2.25 2.25 0 013 15.75V9.456c0-1.081.768-2.015 1.837-2.175a48.041 48.041 0 011.913-.247m10.5 0a48.536 48.536 0 00-10.5 0m10.5 0V3.375c0-.621-.504-1.125-1.125-1.125h-8.25c-.621 0-1.125.504-1.125 1.125v3.659M18 10.5h.008v.008H18V10.5zm-3 0h.008v.008H15V10.5z" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="icon-locked" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z" /></symbol>
<symbol id="icon-unlocked" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 10.5V6.75a4.5 4.5 0 119 0v3.75M3.75 21.75h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H3.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z" /></symbol>
<symbol id="icon-external-link" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M10 6V8H5V19H16V14H18V20C18 20.5523 17.5523 21 17 21H4C3.44772 21 3 20.5523 3 20V7C3 6.44772 3.44772 6 4 6H10ZM21 3V11H19L18.9999 6.413L11.2071 14.2071L9.79289 12.7929L17.5849 5H13V3H21Z"/></symbol>
<symbol id="icon-cookie" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M21.1634 10.9711C21.5132 10.8204 21.9579 11.0073 21.9811 11.3875C22.1494 14.1467 21.1794 16.9625 19.071 19.0709C15.1657 22.976 8.83405 22.9761 4.92886 19.0709C1.02367 15.1657 1.02377 8.83405 4.92885 4.9288C7.03704 2.82061 9.8525 1.85015 12.6115 2.01806C12.9916 2.04119 13.1787 2.48598 13.028 2.83576C12.4774 4.11367 12.7239 5.65275 13.7677 6.69657C14.3307 7.25963 15.038 7.58971 15.7706 7.68848C16.0483 7.72594 16.2738 7.95144 16.3113 8.2292C16.4101 8.96178 16.7402 9.66905 17.3032 10.2321C18.347 11.2759 19.8857 11.5218 21.1634 10.9711ZM19.7845 13.8397C19.8558 13.5362 19.6123 13.2603 19.3017 13.2337C18.0569 13.1271 16.8417 12.599 15.889 11.6463C15.3166 11.0739 14.8979 10.4061 14.6309 9.69455C14.5744 9.54422 14.4556 9.42534 14.3052 9.36892C13.5936 9.10186 12.9259 8.68322 12.3535 8.11078C11.4005 7.15778 10.8715 5.94208 10.7648 4.69683C10.7381 4.38618 10.4621 4.14264 10.1586 4.2141C8.76039 4.54327 7.43341 5.25267 6.34306 6.34301C3.21903 9.46721 3.21893 14.5326 6.34307 17.6567C9.46721 20.7809 14.5326 20.7808 17.6568 17.6567C18.7474 16.566 19.4557 15.2384 19.7845 13.8397ZM9.8786 14.1212C10.4644 14.707 10.4644 15.6567 9.8786 16.2425C9.29281 16.8283 8.34307 16.8283 7.75728 16.2425C7.17149 15.6567 7.17149 14.707 7.75728 14.1212C8.34306 13.5354 9.29281 13.5354 9.8786 14.1212ZM10.2321 8.11078C10.8179 8.69657 10.8179 9.64631 10.2321 10.2321C9.64636 10.8179 8.69661 10.8179 8.11083 10.2321C7.52504 9.64631 7.52504 8.69656 8.11083 8.11078C8.69661 7.52499 9.64636 7.52499 10.2321 8.11078ZM15.889 13.7676C16.4748 14.3534 16.4748 15.3032 15.889 15.889C15.3032 16.4747 14.3535 16.4747 13.7677 15.889C13.1819 15.3032 13.1819 14.3534 13.7677 13.7676C14.3535 13.1818 15.3032 13.1818 15.889 13.7676Z"/></symbol>
<symbol id="icon-mask" fill="currentColor" stroke="none" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M288 64C39.52 64 0 182.1 0 273.5C0 379.5 78.8 448 176 448c27.33 0 51.21-6.516 66.11-36.79l19.93-40.5C268.3 358.6 278.1 352.4 288 352.1c9.9 .3711 19.7 6.501 25.97 18.63l19.93 40.5C348.8 441.5 372.7 448 400 448c97.2 0 176-68.51 176-174.5C576 182.1 536.5 64 288 64zM400 400c-18.12 0-19.56-2.924-23.04-9.986l-20.35-41.33c-13.87-26.86-38.85-43.53-66.82-44.57L288 304L286.2 304.1c-27.96 1.049-52.94 17.71-67.24 45.41l-19.93 40.49C195.6 397.1 194.1 400 176 400c-75.36 0-128-52.04-128-126.5C48 229.3 48 112 288 112s240 117.3 240 161.5C528 347.1 475.4 400 400 400zM160 192C124.7 192 96 220.7 96 256s28.65 64 64 64c35.35 0 64-28.65 64-64S195.3 192 160 192zM416 192c-35.35 0-64 28.65-64 64s28.65 64 64 64c35.35 0 64-28.65 64-64S451.3 192 416 192z"/></symbol>
<symbol id="icon-excel" fill="currentColor" stroke="none" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M365.3 93.38l-74.63-74.64C278.6 6.742 262.3 0 245.4 0H64C28.65 0 0 28.65 0 64l.0065 384c0 35.34 28.65 64 64 64H320c35.2 0 64-28.8 64-64V138.6C384 121.7 377.3 105.4 365.3 93.38zM336 448c0 8.836-7.164 16-16 16H64.02c-8.838 0-16-7.164-16-16L48 64.13c0-8.836 7.164-16 16-16h160L224 128c0 17.67 14.33 32 32 32h79.1V448zM229.1 233.3L192 280.9L154.9 233.3C146.8 222.8 131.8 220.9 121.3 229.1C110.8 237.2 108.9 252.3 117.1 262.8L161.6 320l-44.53 57.25c-8.156 10.47-6.25 25.56 4.188 33.69C125.7 414.3 130.8 416 135.1 416c7.156 0 14.25-3.188 18.97-9.25L192 359.1l37.06 47.65C233.8 412.8 240.9 416 248 416c5.125 0 10.31-1.656 14.72-5.062c10.44-8.125 12.34-23.22 4.188-33.69L222.4 320l44.53-57.25c8.156-10.47 6.25-25.56-4.188-33.69C252.2 220.9 237.2 222.8 229.1 233.3z"/></symbol>
<symbol id="icon-pdf" fill="currentColor" stroke="none" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M365.3 93.38l-74.63-74.64C278.6 6.742 262.3 0 245.4 0H64C28.65 0 0 28.65 0 64l.0065 384c0 35.34 28.65 64 64 64H320c35.2 0 64-28.8 64-64V138.6C384 121.7 377.3 105.4 365.3 93.38zM336 448c0 8.836-7.164 16-16 16H64.02c-8.838 0-16-7.164-16-16L48 64.13c0-8.836 7.164-16 16-16h160L224 128c0 17.67 14.33 32 32 32h79.1V448zM202 286.1c.877-2.688 1.74-5.398 2.582-8.145c1.434-5.762 7.488-31.54 7.488-52.47C212.1 207 197.1 192 178.6 192C160.1 192 145.1 207 145.1 225.5c0 .2969 .1641 28.81 13.85 62.3c-7.035 19.36-15.57 38.8-25.41 57.93c-21.49 10.11-39.24 22.23-52.8 36.07c-6.234 6.438-9.367 14.74-9.367 24.72c0 18.45 15.01 33.46 33.46 33.46c10.8 0 20.98-5.227 27.22-13.98c7.322-10.28 18.38-26.9 30.47-48.95c15.8-6.352 33.88-11.72 53.88-16c13.55 9.578 28.9 17.29 45.71 22.95c4.527 1.551 9.402 2.348 14.43 2.348c20.26 0 36.13-16.19 36.13-36.86c0-20.33-16.54-36.87-36.87-36.87h-3.705c-2.727 .125-20.51 1.141-45.37 5.367C216.9 308.9 208.6 298.3 202 286.1zM110.2 410.4c-3.273 4.688-12.03 2.777-12.03-5.312c0-1.754 .6289-3.43 1.729-4.555c9.02-9.219 19.94-17.05 31.85-23.72C122.3 393.1 114.3 404.7 110.2 410.4zM178.6 218.8c3.693 0 6.703 3.008 6.703 6.703c0 15.21-4.109 34.84-5.746 42.1C172.1 245 171.9 227.2 171.9 225.5C171.9 221.8 174.9 218.8 178.6 218.8zM162.3 348.3c6.611-13.48 13.22-28.46 19.38-44.7c6.389 10.92 14.56 21.86 24.96 31.97C192.6 338.8 177.4 342.9 162.3 348.3zM272.4 339.5h3.352c5.539 0 10.05 4.5 10.05 10.79c0 5.129-4.176 9.32-9.32 9.32c-2.029 0-4.059-.3164-5.852-.9414c-12.33-4.137-23.11-9.32-32.54-15.19C258.3 340.3 272.1 339.5 272.4 339.5z"/></symbol>
<symbol id="icon-file" fill="currentColor" stroke="none" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M365.3 93.38l-74.63-74.64C278.6 6.743 262.3 0 245.4 0L64-.0001c-35.35 0-64 28.65-64 64l.0065 384c0 35.35 28.65 64 64 64H320c35.2 0 64-28.8 64-64V138.6C384 121.7 377.3 105.4 365.3 93.38zM320 464H64.02c-8.836 0-15.1-7.163-16-15.1L48 64.13c-.0004-8.837 7.163-16 16-16h160L224 128c0 17.67 14.33 32 32 32h79.1v288C336 456.8 328.8 464 320 464z"/></symbol>
<symbol id="icon-sigma" fill="currentColor" stroke="none" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M335.1 136l.0005-56H83.59l165 158.7C253.3 243.2 255.1 249.5 255.1 256s-2.656 12.78-7.375 17.31L83.59 432h252.4l-.0005-56c0-13.25 10.75-24 24-24C373.2 352 384 362.8 384 376v80c0 13.25-10.75 24-24 24H23.99c-9.782 0-18.59-5.938-22.25-15.03s-1.438-19.47 5.625-26.28L197.4 256L7.364 73.31C.3015 66.5-1.917 56.13 1.739 47.03S14.21 32 23.99 32h336C373.2 32 384 42.75 384 56v80C384 149.3 373.2 160 359.1 160C346.7 160 335.1 149.3 335.1 136z"/></symbol>
<symbol id="icon-percent" fill="currentColor" stroke="none" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M376.1 71.03c-9.375-9.375-24.56-9.375-33.94 0l-336 336c-9.375 9.375-9.375 24.56 0 33.94C11.72 445.7 17.84 448 24 448s12.28-2.344 16.97-7.031l336-336C386.3 95.59 386.3 80.41 376.1 71.03zM64 176c26.51 0 48-21.49 48-48S90.51 80 64 80C37.49 80 16 101.5 16 128S37.49 176 64 176zM320 336c-26.51 0-48 21.49-48 48s21.49 48 48 48c26.51 0 48-21.49 48-48S346.5 336 320 336z"/></symbol>
<symbol id="icon-chair" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M288 16c26.5 0 48 21.5 48 48V256h16V64c0-35.3-28.7-64-64-64H160C124.7 0 96 28.7 96 64V256h16V64c0-26.5 21.5-48 48-48H288zM48 168c0-4.4-3.6-8-8-8s-8 3.6-8 8v80c0 4.4 3.6 8 8 8s8-3.6 8-8V168zm368 0c0-4.4-3.6-8-8-8s-8 3.6-8 8v80c0 4.4 3.6 8 8 8s8-3.6 8-8V168zM80 304H368c6.1 0 11.6 3.4 14.3 8.8l16 32c2.5 5 2.2 10.9-.7 15.6s-8.1 7.6-13.6 7.6H224 64c-5.5 0-10.7-2.9-13.6-7.6s-3.2-10.6-.7-15.6l16-32c2.7-5.4 8.3-8.8 14.3-8.8zm152 80H384c11.1 0 21.4-5.7 27.2-15.2s6.4-21.2 1.4-31.1l-16-32C391.2 294.8 380.1 288 368 288H80c-12.1 0-23.2 6.8-28.6 17.7l-16 32c-5 9.9-4.4 21.7 1.4 31.1S52.9 384 64 384H216v64H184c-30.9 0-56 25.1-56 56c0 4.4 3.6 8 8 8s8-3.6 8-8c0-22.1 17.9-40 40-40h32v40c0 4.4 3.6 8 8 8s8-3.6 8-8V464h32c22.1 0 40 17.9 40 40c0 4.4 3.6 8 8 8s8-3.6 8-8c0-30.9-25.1-56-56-56H232V384z"/></symbol>
<symbol id="icon-eye" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></symbol>
<symbol id="icon-profile" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M7.864 4.243A7.5 7.5 0 0119.5 10.5c0 2.92-.556 5.709-1.568 8.268M5.742 6.364A7.465 7.465 0 004.5 10.5a7.464 7.464 0 01-1.15 3.993m1.989 3.559A11.209 11.209 0 008.25 10.5a3.75 3.75 0 117.5 0c0 .527-.021 1.049-.064 1.565M12 10.5a14.94 14.94 0 01-3.6 9.75m6.633-4.596a18.666 18.666 0 01-2.485 5.33" /></symbol>
<symbol id="icon-chart" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3v11.25A2.25 2.25 0 006 16.5h2.25M3.75 3h-1.5m1.5 0h16.5m0 0h1.5m-1.5 0v11.25A2.25 2.25 0 0118 16.5h-2.25m-7.5 0h7.5m-7.5 0l-1 3m8.5-3l1 3m0 0l.5 1.5m-.5-1.5h-9.5m0 0l-.5 1.5M9 11.25v1.5M12 9v3.75m3-6v6" /></symbol>
<symbol id="icon-info" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /></symbol>
<symbol id="icon-star" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" /></symbol>
<symbol id="icon-cancel" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></symbol>
<symbol id="icon-bell" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" /></symbol>
<symbol id="icon-folder" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="icon-power" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M5.636 5.636a9 9 0 1 0 12.728 0M12 3v9" /></symbol>
<symbol id="icon-no-symbol" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M18.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636" /></symbol>
<symbol id="icon-draggable" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M8.5 7C9.32843 7 10 6.32843 10 5.5C10 4.67157 9.32843 4 8.5 4C7.67157 4 7 4.67157 7 5.5C7 6.32843 7.67157 7 8.5 7ZM8.5 13.5C9.32843 13.5 10 12.8284 10 12C10 11.1716 9.32843 10.5 8.5 10.5C7.67157 10.5 7 11.1716 7 12C7 12.8284 7.67157 13.5 8.5 13.5ZM10 18.5C10 19.3284 9.32843 20 8.5 20C7.67157 20 7 19.3284 7 18.5C7 17.6716 7.67157 17 8.5 17C9.32843 17 10 17.6716 10 18.5ZM15.5 7C16.3284 7 17 6.32843 17 5.5C17 4.67157 16.3284 4 15.5 4C14.6716 4 14 4.67157 14 5.5C14 6.32843 14.6716 7 15.5 7ZM17 12C17 12.8284 16.3284 13.5 15.5 13.5C14.6716 13.5 14 12.8284 14 12C14 11.1716 14.6716 10.5 15.5 10.5C16.3284 10.5 17 11.1716 17 12ZM15.5 20C16.3284 20 17 19.3284 17 18.5C17 17.6716 16.3284 17 15.5 17C14.6716 17 14 17.6716 14 18.5C14 19.3284 14.6716 20 15.5 20Z"/></symbol>
<symbol id="icon-discount" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M10.0544 2.0941C11.1756 1.13856 12.8248 1.13855 13.9461 2.09411L15.2941 3.24286C15.4542 3.37935 15.6533 3.46182 15.8631 3.47856L17.6286 3.61945C19.0971 3.73663 20.2633 4.9028 20.3805 6.37131L20.5214 8.13679C20.5381 8.34654 20.6205 8.54568 20.757 8.70585L21.9058 10.0539C22.8614 11.1751 22.8614 12.8243 21.9058 13.9456L20.757 15.2935C20.6206 15.4537 20.538 15.6529 20.5213 15.8627L20.3805 17.6281C20.2633 19.0967 19.0971 20.2628 17.6286 20.3799L15.8631 20.5208C15.6533 20.5376 15.4542 20.6201 15.2941 20.7566L13.9461 21.9053C12.8248 22.8609 11.1756 22.8608 10.0543 21.9053L8.70631 20.7566C8.54615 20.6201 8.34705 20.5376 8.1373 20.5209L6.37184 20.3799C4.9033 20.2627 3.73716 19.0966 3.61997 17.6281L3.47906 15.8627C3.46232 15.6529 3.37983 15.4538 3.24336 15.2936L2.0946 13.9455C1.13905 12.8243 1.13904 11.1752 2.09458 10.0539L3.24334 8.70589C3.37983 8.54573 3.46234 8.34654 3.47907 8.13678L3.61996 6.3713C3.73714 4.90278 4.90327 3.73665 6.3718 3.61946L8.13729 3.47857C8.34705 3.46183 8.54619 3.37935 8.70636 3.24286L10.0544 2.0941ZM12.6488 3.61632C12.2751 3.29782 11.7253 3.29781 11.3516 3.61632L10.0036 4.76509C9.5231 5.17456 8.92568 5.42201 8.29637 5.47223L6.5309 5.61312C6.04139 5.65219 5.65268 6.04089 5.61362 6.53041L5.47272 8.29593C5.4225 8.92521 5.17505 9.52259 4.76559 10.0031L3.61683 11.3511C3.29832 11.7248 3.29831 12.2746 3.61683 12.6483L4.76559 13.9963C5.17506 14.4768 5.4225 15.0743 5.47275 15.7035L5.61363 17.469C5.65268 17.9585 6.04139 18.3473 6.53092 18.3863L8.29636 18.5272C8.92563 18.5774 9.5231 18.8249 10.0036 19.2344L11.3516 20.3831C11.7254 20.7016 12.2751 20.7016 12.6488 20.3831L13.9969 19.2343C14.4773 18.8249 15.0747 18.5774 15.704 18.5272L17.4695 18.3863C17.959 18.3472 18.3478 17.9585 18.3868 17.469L18.5277 15.7035C18.5779 15.0742 18.8253 14.4768 19.2349 13.9964L20.3836 12.6483C20.7022 12.2746 20.7021 11.7249 20.3836 11.3511L19.2348 10.0031C18.8253 9.52259 18.5779 8.92519 18.5277 8.2959L18.3868 6.53041C18.3478 6.0409 17.959 5.65219 17.4695 5.61312L15.704 5.47224C15.0748 5.42203 14.4773 5.17455 13.9968 4.76508L12.6488 3.61632ZM14.8284 7.75718L16.2426 9.1714L9.17154 16.2425L7.75733 14.8282L14.8284 7.75718ZM10.2322 10.232C9.64641 10.8178 8.69667 10.8178 8.11088 10.232C7.52509 9.6463 7.52509 8.69652 8.11088 8.11073C8.69667 7.52494 9.64641 7.52494 10.2322 8.11073C10.818 8.69652 10.818 9.6463 10.2322 10.232ZM13.7677 15.8889C14.3535 16.4747 15.3032 16.4747 15.889 15.8889C16.4748 15.3031 16.4748 14.3534 15.889 13.7676C15.3032 13.1818 14.3535 13.1818 13.7677 13.7676C13.1819 14.3534 13.1819 15.3031 13.7677 15.8889Z"/></symbol>
<symbol id="icon-stack" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M20.0833 15.1999L21.2854 15.9212C21.5221 16.0633 21.5989 16.3704 21.4569 16.6072C21.4146 16.6776 21.3557 16.7365 21.2854 16.7787L12.5144 22.0412C12.1977 22.2313 11.8021 22.2313 11.4854 22.0412L2.71451 16.7787C2.47772 16.6366 2.40093 16.3295 2.54301 16.0927C2.58523 16.0223 2.64413 15.9634 2.71451 15.9212L3.9166 15.1999L11.9999 20.0499L20.0833 15.1999ZM20.0833 10.4999L21.2854 11.2212C21.5221 11.3633 21.5989 11.6704 21.4569 11.9072C21.4146 11.9776 21.3557 12.0365 21.2854 12.0787L11.9999 17.6499L2.71451 12.0787C2.47772 11.9366 2.40093 11.6295 2.54301 11.3927C2.58523 11.3223 2.64413 11.2634 2.71451 11.2212L3.9166 10.4999L11.9999 15.3499L20.0833 10.4999ZM12.5144 1.30864L21.2854 6.5712C21.5221 6.71327 21.5989 7.0204 21.4569 7.25719C21.4146 7.32757 21.3557 7.38647 21.2854 7.42869L11.9999 12.9999L2.71451 7.42869C2.47772 7.28662 2.40093 6.97949 2.54301 6.7427C2.58523 6.67232 2.64413 6.61343 2.71451 6.5712L11.4854 1.30864C11.8021 1.11864 12.1977 1.11864 12.5144 1.30864ZM11.9999 3.33233L5.88723 6.99995L11.9999 10.6676L18.1126 6.99995L11.9999 3.33233Z"/></symbol>
<symbol id="icon-bus" xmlns="http://www.w3.org/2000/svg" stroke-width="1.5" viewBox="0 0 24 24" stroke="currentColor" fill="none"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M6 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /><path d="M18 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /><path d="M4 17h-2v-11a1 1 0 0 1 1 -1h14a5 7 0 0 1 5 7v5h-2m-4 0h-8" /><path d="M16 5l1.5 7l4.5 0" /><path d="M2 10l15 0" /><path d="M7 5l0 5" /><path d="M12 5l0 5" /></symbol>
<symbol id="icon-ski" fill="currentColor" stroke="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M380.7 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zM2.7 268.9c6.1-11.8 20.6-16.3 32.4-10.2L239.8 365l49.6-74.5-82.7-87.9c-9.5-10.1-14.4-22.4-15.1-34.9l87.7 42 49.4 52.5c12.8 13.6 14.5 34.1 4.2 49.6l-50.2 75.4 135.8 70.5c13.6 7.1 29.8 7.2 43.6 .3l15.2-7.6c11.9-5.9 26.3-1.1 32.2 10.7s1.1 26.3-10.7 32.2l-15.2 7.6c-27.5 13.7-59.9 13.5-87.2-.7L12.9 301.3C1.2 295.2-3.4 280.7 2.7 268.9zM118.9 65.6L137 74.2l8.7-17.4c4-7.9 13.6-11.1 21.5-7.2s11.1 13.6 7.2 21.5l-8.5 16.9 55.5 26.6c1.7-.9 3.5-1.7 5.4-2.5l80.9-32.4c32.4-13 68.6 6.5 75.6 40.7l12.3 59.7 62.9 30.1c12 5.7 17 20 11.3 32s-20 17-32 11.3l-54.2-25.9c-1-.3-1.9-.6-2.8-1l-229.1-110-9.2 18.4c-4 7.9-13.6 11.1-21.5 7.2s-11.1-13.6-7.2-21.5l9-18-17.6-8.4c-8-3.8-11.3-13.4-7.5-21.3s13.4-11.3 21.3-7.5zm217.3 64.7c-1-4.9-6.2-7.7-10.8-5.8l-45.7 18.3 65.5 31.5-9-43.9z"/></symbol>
<symbol id="icon-snowboard" fill="currentColor" stroke="nonw" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M204.3 3c11.6-6.4 26.2-2.3 32.6 9.3l31.9 57.4c1.3 2.3 3.6 3.8 6.2 4.1l33.8 3.4c24.1 2.4 46.9 12 65.4 27.6L503.5 213.6c10.1 8.5 11.4 23.7 2.9 33.8s-23.7 11.4-33.8 2.9l-68.2-57.5-82.3 43.9 24.7 18.9c24.9 19 34.6 51.9 24.1 81.4l-28.2 79c-1.4 3.8-3.6 7-6.3 9.6l93.3 35.7c4.6 1.8 9.4 2.6 14.3 2.6H472c13.3 0 24 10.7 24 24s-10.7 24-24 24H443.8c-10.8 0-21.4-2-31.5-5.8L60.1 371.3c-11.5-4.4-22-11.2-30.8-20L7 329c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l22.4 22.4c4 4 8.7 7.1 14 9.1l19.4 7.4c-2.9-11.4 2.9-23.4 14-28.1L192 272l0-68.2c0-21.2 12-40.6 31-50.1L284.4 123l-14.1-1.4c-18.3-1.8-34.5-12.5-43.4-28.5L195 35.7c-6.4-11.6-2.3-26.2 9.3-32.6zm91.8 407.2c-.3-3.4 .1-6.9 1.3-10.3l28.2-79c3.5-9.8 .3-20.8-8-27.1L240 234.4l0 42.9c0 16.1-9.7 30.7-24.6 36.9L134 348.2l162.1 62.1zM259.6 189l20.5 15.7 84.6-45.1-17.2-14.5L259.6 189zM384 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0z"/></symbol>
<symbol id="icon-hourglass" fill="currentColor" stroke="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M24 0C10.7 0 0 10.7 0 24S10.7 48 24 48h8V67c0 40.3 16 79 44.5 107.5L158.1 256 76.5 337.5C48 366 32 404.7 32 445v19H24c-13.3 0-24 10.7-24 24s10.7 24 24 24H360c13.3 0 24-10.7 24-24s-10.7-24-24-24h-8V445c0-40.3-16-79-44.5-107.5L225.9 256l81.5-81.5C336 146 352 107.3 352 67V48h8c13.3 0 24-10.7 24-24s-10.7-24-24-24H24zM192 289.9l81.5 81.5C293 391 304 417.4 304 445v19H80V445c0-27.6 11-54 30.5-73.5L192 289.9zm0-67.9l-81.5-81.5C91 121 80 94.6 80 67V48H304V67c0 27.6-11 54-30.5 73.5L192 222.1z"/></symbol>
<symbol id="icon-car" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><circle cx="64" cy="176" r="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><circle cx="192" cy="176" r="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="88" y1="176" x2="168" y2="176" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M216,176h24a8,8,0,0,0,8-8V128a8,8,0,0,0-8-8H208L162.34,74.34A8,8,0,0,0,156.69,72H44.28a8,8,0,0,0-6.65,3.56L8,120v48a8,8,0,0,0,8,8H40" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="208" y1="120" x2="8" y2="120" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-flag-a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><g fill-rule="evenodd"><path fill="#fff" d="M640 480H0V0h640z"/><path fill="#ed2939" d="M640 480H0V320h640zm0-319.9H0V.1h640z"/></g></symbol>
<symbol id="icon-flag-ch" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><g fill-rule="evenodd" stroke-width="1pt"><path fill="#d52b1e" d="M0 0h640v480H0z"/><g fill="#fff"><path d="M170 195h300v90H170z"/><path d="M275 90h90v300h-90z"/></g></g></symbol>
<symbol id="icon-flag-d" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><path fill="#ffce00" d="M0 320h640v160H0z"/><path d="M0 0h640v160H0z"/><path fill="#d00" d="M0 160h640v160H0z"/></symbol>
<symbol id="icon-flag-f" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><g fill-rule="evenodd" stroke-width="1pt"><path fill="#fff" d="M0 0h640v480H0z"/><path fill="#00267f" d="M0 0h213.3v480H0z"/><path fill="#f31830" d="M426.7 0H640v480H426.7z"/></g></symbol>
<symbol id="icon-flag-i" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><g fill-rule="evenodd" stroke-width="1pt"><path fill="#fff" d="M0 0h640v480H0z"/><path fill="#009246" d="M0 0h213.3v480H0z"/><path fill="#ce2b37" d="M426.7 0H640v480H426.7z"/></g></symbol>
<symbol id="icon-flag-nl" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480"><g fill-rule="evenodd"><path fill="#21468b" d="M0 320h640v160H0z"/><path fill="#fff" d="M0 160h640v160H0z"/><path fill="#ae1c28" d="M0 0h640v160H0z"/></g></symbol>
<symbol id="icon-backpack" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M96,48h64a48,48,0,0,1,48,48V216a8,8,0,0,1-8,8H56a8,8,0,0,1-8-8V96A48,48,0,0,1,96,48Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M80,224V152a16,16,0,0,1,16-16h64a16,16,0,0,1,16,16v72" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M96,48V32a16,16,0,0,1,16-16h32a16,16,0,0,1,16,16V48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="112" y1="88" x2="144" y2="88" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="80" y1="168" x2="176" y2="168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="144" y1="168" x2="144" y2="184" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-barricade" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><rect x="24" y="72" width="208" height="88" rx="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="84" y1="72" x2="172" y2="160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="156" y1="72" x2="232" y2="148" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="24" y1="84" x2="100" y2="160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="192" y1="160" x2="192" y2="200" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="64" y1="160" x2="64" y2="200" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-bed" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M112,168V80H216a32,32,0,0,1,32,32v56" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="24" y1="208" x2="24" y2="48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><polyline points="24 168 248 168 248 208" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="112" y1="80" x2="24" y2="80" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-boot" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="152" y1="120" x2="112" y2="120" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="152" y1="88" x2="112" y2="88" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M240,168v32a8,8,0,0,1-8,8H205.89a8.08,8.08,0,0,1-3.58-.84l-12.62-6.32a8.08,8.08,0,0,0-3.58-.84H169.89a8.08,8.08,0,0,0-3.58.84l-12.62,6.32a8.08,8.08,0,0,1-3.58.84H121.89a8.08,8.08,0,0,1-3.58-.84l-12.62-6.32a8.08,8.08,0,0,0-3.58-.84H85.89a8.08,8.08,0,0,0-3.58.84l-12.62,6.32a8.08,8.08,0,0,1-3.58.84H40a8,8,0,0,1-8-8V168c9.22-32.06,12-88.65,0-120H144a8,8,0,0,1,8,8v64h40A48,48,0,0,1,240,168Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="32" y1="168" x2="240" y2="168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-lift" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="16" y1="72" x2="240" y2="32" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><rect x="40" y="104" width="176" height="112" rx="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="40" y1="168" x2="216" y2="168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="128" y1="52" x2="128" y2="104" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="160" y1="104" x2="160" y2="168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="96" y1="104" x2="96" y2="168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-chat" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M71.58,144,32,176V48a8,8,0,0,1,8-8H168a8,8,0,0,1,8,8v88a8,8,0,0,1-8,8Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M80,144v40a8,8,0,0,0,8,8h96.42L224,224V96a8,8,0,0,0-8-8H176" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-weather" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="87.66" y1="56.73" x2="83.5" y2="33.09" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="56.69" y1="76.46" x2="37.03" y2="62.69" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="48.73" y1="112.31" x2="25.09" y2="116.48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="123.52" y1="64.69" x2="137.28" y2="45.03" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M96,144a68.06,68.06,0,1,1,68,72H84a44,44,0,1,1,14.2-85.66" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M59.65,135.35a48,48,0,1,1,80.19-50.94" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-party" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M40.49,205.52,93,61.14a7.79,7.79,0,0,1,12.84-2.85l91.88,91.88A7.79,7.79,0,0,1,194.86,163L50.48,215.51A7.79,7.79,0,0,1,40.49,205.52Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M168,72s0-24,24-24,24-24,24-24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="144" y1="16" x2="144" y2="40" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="216" y1="112" x2="232" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="216" y1="80" x2="240" y2="72" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="78.09" y1="102.09" x2="153.91" y2="177.91" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="101.11" y1="197.11" x2="58.89" y2="154.89" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-dice" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><rect width="256" height="256" fill="none"/><rect x="40" y="40" width="176" height="176" rx="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><circle cx="92" cy="84" r="12"/><circle cx="164" cy="84" r="12"/><circle cx="92" cy="128" r="12"/><circle cx="164" cy="128" r="12"/><circle cx="92" cy="172" r="12"/><circle cx="164" cy="172" r="12"/></symbol>
<symbol id="icon-flag" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="48" y1="224" x2="48" y2="56" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M48,176c64-55.43,112,55.43,176,0V56C160,111.43,112,.57,48,56" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-burger" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M48.07,96a8,8,0,0,1-7.89-9.72C46.68,55.55,83.52,32,128,32s81.32,23.55,87.82,54.28A8,8,0,0,1,207.93,96Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><polyline points="24 176 68 160 108 176 148 160 188 176 232 160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="24" y1="128" x2="232" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M208,168.73V184a32,32,0,0,1-32,32H80a32,32,0,0,1-32-32V167.27" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-handshake" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><polyline points="200 152 160 192 96 176 40 136" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><polyline points="72.68 70.63 128 56 183.32 70.63" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M34.37,60.42,8.85,111.48a8,8,0,0,0,3.57,10.73L40,136,72.68,70.63,45.11,56.85A8,8,0,0,0,34.37,60.42Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M216,136l27.58-13.79a8,8,0,0,0,3.57-10.73L221.63,60.42a8,8,0,0,0-10.74-3.57L183.32,70.63Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M184,72H144L98.34,116.29a8,8,0,0,0,1.38,12.42C117.23,139.9,141,139.13,160,120l40,32,16-16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><polyline points="124.06 216 82.34 205.57 56 186.75" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-badge" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><line x1="152" y1="112" x2="192" y2="112" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="152" y1="144" x2="192" y2="144" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><rect x="32" y="48" width="192" height="160" rx="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><circle cx="96" cy="120" r="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M64,168c3.55-13.8,17.09-24,32-24s28.46,10.19,32,24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-parking" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><circle cx="128" cy="128" r="96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M104,144h32a28,28,0,0,0,0-56H104v80" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-drinks" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M56,32H200L176.85,225A8,8,0,0,1,168.9,232H87.1A8,8,0,0,1,79.15,225Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="60.8" y1="72" x2="195.2" y2="72" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-sauna" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path d="M153.599 76.8c-35.285 0-64 28.706-64 64s28.715 64 64 64 64-28.715 64-64-28.706-64-64-64Zm0 102.4c-21.205 0-38.4-17.195-38.4-38.4s17.195-38.4 38.4-38.4 38.4 17.195 38.4 38.4-17.194 38.4-38.4 38.4Zm152.824 315.623-51.2-140.8c-1.835-5.06-6.639-8.422-12.023-8.422h-89.6V230.4c0-7.074-5.726-12.8-12.8-12.8S128 223.326 128 230.4v128c0 7.074 5.726 12.8 12.8 12.8h93.44l48.137 132.378C284.263 508.775 289.178 512 294.4 512c1.451 0 2.927-.247 4.378-.776 6.638-2.415 10.077-9.754 7.645-16.401ZM209.919 396.8h-107.52c-7.074 0-12.8 5.726-12.8 12.8s5.726 12.8 12.8 12.8h107.52c7.074 0 12.8-5.726 12.8-12.8s-5.726-12.8-12.8-12.8ZM340.36 7.074c-3.157-6.323-10.863-8.875-17.169-5.726-6.323 3.166-8.892 10.846-5.726 17.178 22.886 45.79 12.228 85.726-.111 131.959-7.603 28.424-15.454 57.839-15.991 90.914-.111 7.074 5.521 12.902 12.587 13.013h.213c6.972 0 12.689-5.598 12.8-12.587.486-29.935 7.927-57.796 15.113-84.736 12.552-46.975 25.514-95.547-1.716-150.015Zm65.98 0c-3.174-6.323-10.837-8.875-17.178-5.726-6.323 3.166-8.892 10.846-5.726 17.178 22.903 45.79 12.237 85.726-.111 131.977-13.141 49.203-28.041 104.977-.324 174.251 1.997 5.009 6.81 8.047 11.887 8.047 1.587 0 3.2-.29 4.753-.913 6.562-2.628 9.762-10.078 7.134-16.64-24.559-61.389-11.426-110.575 1.271-158.148C420.599 110.123 433.578 61.551 406.34 7.074Z"/></symbol>
<symbol id="icon-shower" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M64,236a12,12,0,1,1-12-12A12,12,0,0,1,64,236Zm20-44a12,12,0,1,0,12,12A12,12,0,0,0,84,192Zm-64,0a12,12,0,1,0,12,12A12,12,0,0,0,20,192Zm32-32a12,12,0,1,0,12,12A12,12,0,0,0,52,160ZM256,40a8,8,0,0,1-8,8H219.31L191.46,75.86,169.8,202.65a16,16,0,0,1-27.09,8.66l-98-98a16,16,0,0,1,8.69-27.1L180.14,64.54l30.2-30.2A8,8,0,0,1,216,32h32A8,8,0,0,1,256,40ZM174.21,81.79,56,102l98,98Z"/></symbol>
<symbol id="icon-wifi" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><rect width="256" height="256" fill="none"/><circle cx="128" cy="204" r="12"/><path d="M232,93.19a164,164,0,0,0-208,0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M200,129a116,116,0,0,0-144,0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M168,165a68,68,0,0,0-80,0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-mountain" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><circle cx="164" cy="52" r="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M8,200,81.1,75.94a8,8,0,0,1,13.8,0L168,200Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="50.35" y1="128" x2="125.65" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path d="M146.61,163.71l33.06-55.79a8,8,0,0,1,13.76,0L248,200H168" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></symbol>
<symbol id="icon-spinner" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="currentColor"><!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL --><g fill="none" fill-rule="evenodd" stroke-width="2"><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /><animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /></circle><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /><animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /></circle></g></symbol>
</svg>

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.2 KiB

File diff suppressed because one or more lines are too long
+44 -6
View File
@@ -5,6 +5,8 @@ const DEBOUNCE_MS = 200
let debounceTimeout = null
let historyRestoreGracePeriod = false
let savedScrollPosition = null
let activeRequests = 0
function getIndicator() {
return document.getElementById(INDICATOR_ID)
@@ -28,12 +30,20 @@ function hide() {
}
}
function handleBeforeRequest() {
function handleBeforeRequest(event) {
// Ignore requests triggered during history restore grace period
if (true === historyRestoreGracePeriod) {
return
}
activeRequests++
// Save scroll position of the target container before HTMX request
const target = event.detail?.target || document.getElementById('main-content')
if (target && typeof target.scrollTop === 'number') {
savedScrollPosition = { element: target, top: target.scrollTop }
}
// Don't start a new debounce if already pending
if (debounceTimeout) {
return
@@ -45,7 +55,29 @@ function handleBeforeRequest() {
}, DEBOUNCE_MS)
}
function handleRequestEnd() {
// Counter may already be 0 if a force-reset (history save, page show) fired
// before this afterRequest — ignore the stale completion in that case
if (0 === activeRequests) {
return
}
activeRequests--
if (0 === activeRequests) {
hide()
}
}
function handleAfterSwap() {
// Restore scroll position after HTMX swaps content
if (savedScrollPosition !== null && savedScrollPosition.element) {
savedScrollPosition.element.scrollTop = savedScrollPosition.top
savedScrollPosition = null
}
}
function handleHistoryRestore() {
activeRequests = 0
hide()
// Set grace period to ignore change events triggered by history restore
@@ -56,23 +88,29 @@ function handleHistoryRestore() {
}
function handleTimeout() {
hide()
// Don't decrement here — htmx:afterRequest always fires alongside htmx:timeout
// and handles the counter. This handler only shows the alert.
alert('Die Anfrage hat zu lange gedauert. Bitte versuchen Sie es erneut. Falls das Problem weiterhin besteht, kontaktieren Sie bitte unseren Support.')
}
function handleBeforeHistorySave() {
// Hide indicator before HTMX saves the page to history cache
activeRequests = 0
hide()
}
function handlePageShow() {
activeRequests = 0
hide()
}
// Initialize event listeners
document.body.addEventListener('htmx:beforeRequest', handleBeforeRequest)
document.body.addEventListener('htmx:afterRequest', hide)
document.body.addEventListener('htmx:afterRequest', handleRequestEnd)
document.body.addEventListener('htmx:afterSwap', handleAfterSwap)
document.body.addEventListener('htmx:timeout', handleTimeout)
document.body.addEventListener('htmx:historyRestore', handleHistoryRestore)
document.body.addEventListener('htmx:sendError', hide)
document.body.addEventListener('htmx:responseError', hide)
document.body.addEventListener('htmx:beforeHistorySave', handleBeforeHistorySave)
window.addEventListener('pageshow', hide)
window.addEventListener('pageshow', handlePageShow)
window.addEventListener('popstate', handleHistoryRestore)
+29
View File
@@ -0,0 +1,29 @@
export const useFetch = controller => {
Object.assign(controller, {
checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response
} else {
const error = new Error(response.statusText)
error.response = response
throw error
}
},
parseJSON(response) {
return response.json()
},
parseHTML(response) {
return response.text()
},
getInitObject(method = 'get', body = null) {
return {
method,
body,
credentials: 'include',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
}
}
})
}
+4
View File
@@ -53,6 +53,10 @@
background-image: url('../images/bg_5.jpg'), linear-gradient(190deg, rgba(24, 82, 123, 1) 0%, rgba(22, 88, 131, 1) 62%, rgba(0, 112, 224, 1) 100%);;
}
.bg-outer--summer {
background-image: url('../images/bg_summer.jpg'), linear-gradient(190deg, rgba(24, 82, 123, 1) 0%, rgba(22, 88, 131, 1) 62%, rgba(0, 112, 224, 1) 100%);;
}
.sbw .bg-outer--2 {
background-image: url('../images/bg_7.jpg'), linear-gradient(190deg, rgba(24, 82, 123, 1) 0%, rgba(22, 88, 131, 1) 62%, rgba(0, 112, 224, 1) 100%);;
}
+7 -4
View File
@@ -1,6 +1,9 @@
@import "components/typography.css";
@import "components/forms.css";
@import "components/button.css";
@import "components/tooltip.css";
@import "components/toast.css";
@import "components/forms.css";
@import "components/gallery.css";
@import "components/pagination.css";
@import "components/price_calendar.css";
@import "components/toast.css";
@import "components/tooltip.css";
@import "components/typography.css";
@import "components/rte-content.css";
+10
View File
@@ -0,0 +1,10 @@
@import "components/autocomplete.css";
@import "components/badge.css";
@import "components/button.css";
@import "components/datatable.css";
@import "components/datepicker.css";
@import "components/forms.css";
@import "components/pagination.css";
@import "components/toast.css";
@import "components/tooltip.css";
@import "components/typography.css";
+7
View File
@@ -0,0 +1,7 @@
@layer utilities {
/* Reserve the scrollbar gutter so content does not shift width when a
scrollbar appears (e.g. when a collapsible section is opened). */
.scroll-stable {
scrollbar-gutter: stable;
}
}
+7
View File
@@ -0,0 +1,7 @@
@import "tailwindcss/base";
@import "_base.css";
@import "tailwindcss/components";
@import "_components_admin.css";
@import "tailwindcss/utilities";
+1
View File
@@ -5,3 +5,4 @@
@import "_components.css";
@import "tailwindcss/utilities";
@import "_utilities.css";
+33
View File
@@ -0,0 +1,33 @@
.autocomplete {
@apply relative w-full;
}
.autocomplete[data-loading="true"]:after {
@apply block absolute top-0 right-0;
@apply absolute w-4 h-4 rounded-full right-0 mr-4;
content: "";
border: 3px solid rgba(0, 0, 0, 0.12);
border-right: 3px solid rgba(0, 0, 0, 0.48);
top: 50%;
transform: translateY(-50%);
animation: rotate 1s infinite linear;
}
.autocomplete-icon {
@apply absolute top-1/2 right-0 transform -translate-y-1/2 mr-4;
}
.autocomplete[data-loading="true"] .autocomplete-icon {
@apply hidden;
}
.autocomplete-result-list {
@apply bg-white shadow-md max-h-64 overflow-y-auto;
}
.autocomplete-result {
@apply p-2;
}
.autocomplete-result:hover,
.autocomplete-result[aria-selected="true"] {
@apply bg-gray-200;
}
+3
View File
@@ -0,0 +1,3 @@
.badge {
@apply inline-flex items-center rounded-md px-1.5 py-0.5 text-xs font-medium whitespace-nowrap;
}
+21 -11
View File
@@ -1,7 +1,7 @@
.button {
@apply inline-flex items-center justify-center space-x-2 h-10 leading-10 px-4 md:px-8 cursor-pointer;
@apply uppercase leading-none text-center;
@apply transition-colors outline-none focus:outline-2 focus:outline-offset-2 focus:outline-primary-light;
@apply inline-flex items-center justify-center space-x-2 h-8 leading-8 md:h-10 md:leading-10 px-4 md:px-8 cursor-pointer;
@apply uppercase leading-none text-center text-sm md:text-base;
@apply transition-colors outline-none focus:outline-2 focus:outline-offset-2 focus:outline-primary-dark;
@apply rounded-md;
}
@@ -20,42 +20,52 @@
}
.button--secondary {
@apply bg-none bg-primary-dark text-white;
@apply hover:bg-primary-light/80;
@apply bg-none bg-primary-light text-white;
@apply hover:bg-primary-light/50;
}
.button--neutral {
@apply bg-none bg-gray-200;
@apply hover:bg-gray-200/50;
}
.button--warning {
@apply bg-none bg-red-500 text-white;
@apply hover:bg-red-500/50;
}
.sbw {
.button--primary {
@apply bg-none bg-sbw-secondary text-white;
@apply hover:bg-none hover:bg-sbw-primary/80;
@apply hover:bg-none hover:bg-sbw-primary/50;
}
.button--secondary {
@apply bg-none bg-sbw-primary-dark text-white;
@apply hover:bg-none hover:bg-sbw-primary/80;
@apply hover:bg-none hover:bg-sbw-primary/50;
}
}
.snz {
.button--primary {
@apply bg-none bg-snz-secondary text-white;
@apply hover:bg-none hover:bg-snz-primary/80;
@apply hover:bg-none hover:bg-snz-primary/50;
}
.button--secondary {
@apply bg-none bg-snz-primary-dark text-white;
@apply hover:bg-none hover:bg-snz-primary/80;
@apply hover:bg-none hover:bg-snz-primary/50;
}
}
.ser {
.button--primary {
@apply bg-none bg-ser-secondary text-white;
@apply hover:bg-none hover:bg-ser-primary/80;
@apply hover:bg-none hover:bg-ser-primary/50;
}
.button--secondary {
@apply bg-none bg-ser-primary text-white;
@apply hover:bg-none hover:bg-ser-primary/80;
@apply hover:bg-none hover:bg-ser-primary/50;
}
}
+31
View File
@@ -0,0 +1,31 @@
.data-table-wrapper {
@apply overflow-x-auto lg:overflow-x-visible mb-8;
}
.data-table-wrapper__inner {
@apply align-middle inline-block min-w-full overflow-hidden lg:overflow-visible;
}
.data-table {
@apply min-w-full;
}
.data-table tbody {
@apply bg-white;
}
.data-table tr {
@apply border border-gray-300;
}
.data-table th {
@apply px-4 py-2 bg-gray-200 text-left leading-4 font-bold text-primary align-top;
}
.data-table td {
@apply px-4 py-2 leading-5 align-top;
}
.data-table tbody tr {
@apply hover:bg-gray-100;
}
+7
View File
@@ -0,0 +1,7 @@
@import "vanilla-calendar-pro/styles/index.css";
@import "vanilla-calendar-pro/styles/themes/light.css";
[data-vc-theme=light] .vc-date[data-vc-date-selected] .vc-date__btn,
[data-vc-theme=light] .vc-date[data-vc-date-selected] .vc-date__btn:hover {
background-color: theme('colors.secondary');
}
+1
View File
@@ -0,0 +1 @@
@import "glightbox/dist/css/glightbox.min.css";
@@ -0,0 +1,41 @@
.pc-day {
@apply relative w-full text-center py-1 px-0.5 text-sm leading-tight rounded text-white cursor-pointer;
}
.pc-day--out-of-month {
@apply pointer-events-none opacity-0;
}
.pc-day[data-status="ok"] {
@apply bg-emerald-500;
}
.pc-day[data-status="blocked-to-ok"] {
background: linear-gradient(to bottom right, theme('colors.gray.400') 50%, theme('colors.emerald.500') 50%);
}
.pc-day[data-status="checkout-only"] {
background: linear-gradient(to bottom right, theme('colors.emerald.500') 50%, theme('colors.gray.400') 50%);
}
.pc-day[data-status="past"] {
@apply bg-transparent text-gray-400 cursor-default;
}
.pc-day[data-status="blocked"] {
@apply bg-gray-400 cursor-default;
}
.pc-day[data-status=""], .pc-day:not([data-status]) {
@apply text-gray-400 cursor-default;
}
.pc-day.pc-day--pending-start,
.pc-day.pc-day--selected-start,
.pc-day.pc-day--selected-end {
@apply bg-none outline-none bg-secondary text-gray-700;
}
.pc-day.pc-day--in-range {
@apply bg-none bg-secondary text-gray-700 opacity-55;
}
+13
View File
@@ -0,0 +1,13 @@
.rte-content {
p {
@apply pb-4;
}
ul {
@apply list-disc p-4;
}
ol {
@apply list-decimal p-4;
}
}
+4
View File
@@ -0,0 +1,4 @@
### list custom fields
GET {{clickup_baseurl}}/list/{{clickup_list_id}}/field?include_applied_objects=true
Authorization: {{clickup_api_token}}
+52 -40
View File
@@ -4,7 +4,7 @@
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=8.1",
"php": ">=8.4",
"ext-ctype": "*",
"ext-dom": "*",
"ext-iconv": "*",
@@ -14,50 +14,58 @@
"doctrine/doctrine-bundle": "^2.13",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.3",
"dompdf/dompdf": "^3.1",
"fakerphp/faker": "^1.24",
"flagception/flagception-bundle": "^6.1",
"knplabs/knp-menu-bundle": "^3.7",
"knplabs/knp-paginator-bundle": "^6.10",
"league/flysystem-bundle": "^3.4",
"league/flysystem-sftp-v3": "^3.29",
"league/oauth2-server-bundle": "^1.0",
"nelexa/zip": "^4.0",
"nesbot/carbon": "^3.8",
"phpdocumentor/reflection-docblock": "^5.6",
"phpoffice/phpspreadsheet": "^5.4",
"phpstan/phpdoc-parser": "^2.0",
"spatie/crypto": "^2.1",
"symfony/apache-pack": "^1.0",
"symfony/asset": "6.4.*",
"symfony/console": "6.4.*",
"symfony/doctrine-messenger": "6.4.*",
"symfony/dom-crawler": "6.4.*",
"symfony/dotenv": "6.4.*",
"symfony/expression-language": "6.4.*",
"symfony/asset": "7.4.*",
"symfony/console": "7.4.*",
"symfony/doctrine-messenger": "7.4.*",
"symfony/dom-crawler": "7.4.*",
"symfony/dotenv": "7.4.*",
"symfony/expression-language": "7.4.*",
"symfony/flex": "^2",
"symfony/form": "6.4.*",
"symfony/framework-bundle": "6.4.*",
"symfony/html-sanitizer": "6.4.*",
"symfony/http-client": "6.4.*",
"symfony/intl": "6.4.*",
"symfony/lock": "6.4.*",
"symfony/mailer": "6.4.*",
"symfony/mime": "6.4.*",
"symfony/form": "7.4.*",
"symfony/framework-bundle": "7.4.*",
"symfony/html-sanitizer": "7.4.*",
"symfony/http-client": "7.4.*",
"symfony/intl": "7.4.*",
"symfony/lock": "7.4.*",
"symfony/mailer": "7.4.*",
"symfony/mime": "7.4.*",
"symfony/monolog-bundle": "^3.0",
"symfony/notifier": "6.4.*",
"symfony/process": "6.4.*",
"symfony/property-access": "6.4.*",
"symfony/property-info": "6.4.*",
"symfony/runtime": "6.4.*",
"symfony/security-bundle": "6.4.*",
"symfony/serializer": "6.4.*",
"symfony/notifier": "7.4.*",
"symfony/process": "7.4.*",
"symfony/property-access": "7.4.*",
"symfony/property-info": "7.4.*",
"symfony/runtime": "7.4.*",
"symfony/security-bundle": "7.4.*",
"symfony/serializer": "7.4.*",
"symfony/stimulus-bundle": "^2.21",
"symfony/string": "6.4.*",
"symfony/translation": "6.4.*",
"symfony/twig-bundle": "6.4.*",
"symfony/uid": "6.4.*",
"symfony/validator": "6.4.*",
"symfony/web-link": "6.4.*",
"symfony/string": "7.4.*",
"symfony/translation": "7.4.*",
"symfony/twig-bundle": "7.4.*",
"symfony/uid": "7.4.*",
"symfony/ux-twig-component": "^2.36",
"symfony/validator": "7.4.*",
"symfony/web-link": "7.4.*",
"symfony/webpack-encore-bundle": "^2.2",
"symfony/yaml": "6.4.*",
"symfony/yaml": "7.4.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/html-extra": "^3.15",
"twig/intl-extra": "*",
"twig/string-extra": "^3.24",
"twig/twig": "^2.12|^3.0",
"zenstruck/schedule-bundle": "^1.8"
},
@@ -69,7 +77,7 @@
},
"sort-packages": true,
"platform": {
"php": "8.2.28"
"php": "8.4.24"
}
},
"autoload": {
@@ -92,6 +100,8 @@
"symfony/polyfill-php81": "*"
},
"scripts": {
"rector": "vendor/bin/rector process",
"rector:dry-run": "vendor/bin/rector process --dry-run",
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
@@ -109,22 +119,24 @@
"extra": {
"symfony": {
"allow-contrib": true,
"require": "6.4.*",
"require": "7.4.*",
"docker": true
}
},
"require-dev": {
"deployer/deployer": "^7.5",
"friendsofphp/php-cs-fixer": "^3.75",
"phpunit/phpunit": "^9.5",
"spatie/ray": "^1.43",
"spatie/x-ray": "^1.2",
"symfony/browser-kit": "6.4.*",
"symfony/css-selector": "6.4.*",
"symfony/debug-bundle": "6.4.*",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-doctrine": "^2.0",
"phpstan/phpstan-symfony": "^2.0",
"phpunit/phpunit": "^12",
"rector/rector": "^2.4",
"symfony/browser-kit": "7.4.*",
"symfony/css-selector": "7.4.*",
"symfony/debug-bundle": "7.4.*",
"symfony/maker-bundle": "^1.0",
"symfony/phpunit-bridge": "^7.1",
"symfony/stopwatch": "6.4.*",
"symfony/web-profiler-bundle": "6.4.*"
"symfony/phpunit-bridge": "^7.4",
"symfony/stopwatch": "7.4.*",
"symfony/web-profiler-bundle": "7.4.*"
}
}
Generated
+3898 -2565
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -16,4 +16,8 @@ return [
League\FlysystemBundle\FlysystemBundle::class => ['all' => true],
League\Bundle\OAuth2ServerBundle\LeagueOAuth2ServerBundle::class => ['all' => true],
Zenstruck\ScheduleBundle\ZenstruckScheduleBundle::class => ['all' => true],
Flagception\Bundle\FlagceptionBundle\FlagceptionBundle::class => ['all' => true],
Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
];
+4 -2
View File
@@ -15,5 +15,7 @@ framework:
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null
pools:
bpn.cache:
adapter: cache.adapter.filesystem
tags: true
+1 -4
View File
@@ -9,8 +9,7 @@ doctrine:
profiling_collect_backtrace: '%kernel.debug%'
use_savepoints: true
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
enable_native_lazy_objects: true
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
@@ -33,8 +32,6 @@ when@test:
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
+2
View File
@@ -0,0 +1,2 @@
flagception:
features: {}
+11 -14
View File
@@ -1,21 +1,18 @@
flysystem:
storages:
xml_export.storage:
adapter: 'local'
options:
directory: '%env(resolve:XML_EXPORT_PATH)%'
local:
directory: '%kernel.project_dir%/var/xmlexport'
xml_source.storage:
adapter: 'sftp'
options:
host: '%env(SFTP_XML_EXPORT_HOST)%'
port: '%env(int:SFTP_XML_EXPORT_PORT)%'
username: '%env(SFTP_XML_EXPORT_USER)%'
password: '%env(SFTP_XML_EXPORT_PASSWORD)%'
sftp:
host: '%env(SFTP_XML_SOURCE_HOST)%'
port: '%env(int:SFTP_XML_SOURCE_PORT)%'
username: '%env(SFTP_XML_SOURCE_USER)%'
password: '%env(SFTP_XML_SOURCE_PASSWORD)%'
root: '%env(SFTP_XML_SOURCE_ROOT)%'
xml_dump.storage:
adapter: 'local'
options:
local:
directory: '%kernel.project_dir%/var/bpn'
json_export.storage:
adapter: 'local'
options:
directory: '%env(resolve:JSON_EXPORT_PATH)%'
local:
directory: '%kernel.project_dir%/var/jsonexport'
+2 -4
View File
@@ -1,7 +1,6 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
annotations: false
http_method_override: false
handle_all_throwables: true
@@ -9,9 +8,8 @@ framework:
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
# cookie_samesite: lax
cookie_samesite: none # this is to make login work in staging environment. to be removed when going live!
cookie_secure: true
cookie_samesite: lax
#esi: true
#fragments: true
+3
View File
@@ -0,0 +1,3 @@
knp_menu:
twig:
template: _partials/_menu.html.twig
+11
View File
@@ -0,0 +1,11 @@
knp_paginator:
default_options:
page_name: page
sort_field_name: sort
sort_direction_name: direction
distinct: true
filter_field_name: filterField
filter_value_name: filterValue
template:
pagination: '_partials/_paginator_sliding.html.twig'
sortable: '_partials/_paginator_sortable_link.html.twig'
+5 -1
View File
@@ -3,10 +3,12 @@ league_oauth2_server:
private_key: '%env(resolve:OAUTH_PRIVATE_KEY)%'
private_key_passphrase: null
encryption_key: '%env(resolve:OAUTH_ENCRYPTION_KEY)%'
require_code_challenge_for_public_clients: true
enable_client_credentials_grant: true
enable_auth_code_grant: true
enable_refresh_token_grant: false
enable_refresh_token_grant: true
enable_password_grant: false
enable_implicit_grant: false
access_token_ttl: PT10M
resource_server:
public_key: '%env(resolve:OAUTH_PUBLIC_KEY)%'
@@ -15,6 +17,8 @@ league_oauth2_server:
default: ['email']
persistence:
doctrine: null
client:
allow_plaintext_secrets: false
when@test:
league_oauth2_server:
+5 -2
View File
@@ -13,7 +13,7 @@ framework:
max_retries: 3
multiplier: 2
failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
sync: 'sync://'
default_bus: messenger.bus.default
@@ -21,9 +21,12 @@ framework:
messenger.bus.default: []
routing:
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
Symfony\Component\Mailer\Messenger\SendEmailMessage: sync
Symfony\Component\Notifier\Message\ChatMessage: async
Symfony\Component\Notifier\Message\SmsMessage: async
App\Message\MailjetNewsletterEventMessage: async
App\Message\CreateClickUpBookingTaskMessage: async
App\Message\RoleNominationMessage: async
# Route your messages to the transports
# 'App\Message\YourMessage': async
+17 -3
View File
@@ -4,6 +4,7 @@ monolog:
- bpn
- core
- auth
- admin
when@dev:
monolog:
@@ -27,11 +28,16 @@ when@dev:
path: "%kernel.logs_dir%/%kernel.environment%.core.log"
level: debug
channels: ["core"]
admin:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.admin.log"
level: debug
channels: ["admin"]
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event", "!bpn", "!core", "!auth"]
channels: ["!event", "!bpn", "!core", "!auth", "!admin"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
@@ -59,7 +65,7 @@ when@test:
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
when@prod:
when@prod: &prod_config
monolog:
handlers:
database:
@@ -84,13 +90,19 @@ when@prod:
path: "%kernel.logs_dir%/%kernel.environment%.core.log"
level: info
channels: ["core"]
admin:
type: rotating_file
max_files: 7
path: "%kernel.logs_dir%/%kernel.environment%.admin.log"
level: info
channels: ["admin"]
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
channels: ["!bpn", "!core", "!auth"]
channels: ["!bpn", "!core", "!auth", "!admin"]
nested:
type: rotating_file
path: "%kernel.logs_dir%/%kernel.environment%.framework.log"
@@ -105,3 +117,5 @@ when@prod:
channels: [deprecation]
path: php://stderr
formatter: monolog.formatter.json
when@staging: *prod_config
+3
View File
@@ -0,0 +1,3 @@
framework:
property_info:
with_constructor_extractor: true
+6 -3
View File
@@ -2,9 +2,12 @@ framework:
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
# How URLs are generated where there is no request to take the host from: scheduled
# commands and, notably, the Messenger workers that send mail off the request path.
# Without it those links would point at http://localhost. Only ever consulted in a
# non-HTTP context, so web requests keep using their own host — which matters here,
# since one codebase serves four brands.
default_uri: '%env(APP_BASE_URL)%'
when@prod:
framework:
+24 -1
View File
@@ -1,6 +1,7 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\InMemoryUser: 'plaintext'
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
@@ -8,6 +9,18 @@ security:
entity:
class: App\Entity\User
property: email
mailjet_webhook_provider:
memory:
users:
mailjet:
password: '%env(MAILJET_WEBHOOK_BASIC_PASSWORD)%'
roles: [ ROLE_MAILJET_WEBHOOK ]
role_hierarchy:
ROLE_ADMIN:
- ROLE_GROUPS_ADMIN
ROLE_GROUPS_ADMIN:
- ROLE_GROUPS_MANAGER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
@@ -19,7 +32,15 @@ security:
pattern: ^/api
security: true
stateless: true
provider: app_user_provider
oauth2: true
mailjet_webhook:
pattern: ^/webhooks/mailjet/newsletter$
security: true
stateless: true
provider: mailjet_webhook_provider
http_basic:
realm: 'Mailjet Webhook'
main:
lazy: true
provider: app_user_provider
@@ -32,8 +53,9 @@ security:
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/webhooks/mailjet/newsletter$, roles: ROLE_MAILJET_WEBHOOK, requires_channel: https }
- { path: ^/authorize, roles: IS_AUTHENTICATED_REMEMBERED, requires_channel: https }
- { path: '^/', roles: PUBLIC_ACCESS, requires_channel: https }
- { path: ^/, roles: PUBLIC_ACCESS, requires_channel: https }
when@test:
security:
@@ -42,6 +64,7 @@ when@test:
# important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\InMemoryUser: 'plaintext'
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
+7
View File
@@ -1,9 +1,16 @@
twig:
file_name_pattern: '*.twig'
form_themes: ['forms.html.twig']
paths:
'%kernel.project_dir%/assets/images': images
globals:
htmx_change_trigger: 'change delay:100ms'
website_base_url: '%env(APP_WEBSITE_BASE_URL)%'
customer_service_email: '%env(APP_CUSTOMER_SERVICE_EMAIL)%'
legal_notice_url: '%env(APP_LEGAL_NOTICE_URL)%'
terms_and_conditions_url: '%env(APP_TERMS_AND_CONDITIONS_URL)%'
privacy_policy_url: '%env(APP_PRIVACY_POLICY_URL)%'
insurance_revocation_url: '%env(APP_INSURANCE_REVOCATION_URL)%'
when@test:
twig:
+5
View File
@@ -0,0 +1,5 @@
twig_component:
anonymous_template_directory: 'components/'
defaults:
# Namespace & directory for components
App\Twig\Components\: 'components/'
+3 -1
View File
@@ -14,4 +14,6 @@ when@test:
intercept_redirects: false
framework:
profiler: { collect: false }
profiler:
collect: false
collect_serializer_data: true
+48 -8
View File
@@ -3,27 +3,67 @@ zenstruck_schedule:
mailer:
service: mailer
default_to: [email protected]
default_from: info@ep-reisen.de
default_to: [email protected]
default_from: noreply@ep-reisen.de
subject_prefix: "[MyE&P]"
schedule_extensions:
email_on_failure:
to: [email protected]
enabled: true
to: [email protected]
tasks:
- task: app:cleanup:xml-dumps
frequency: "0 1 * * *"
description: "Removes outdated XML dumps of requests/responses to BPN API for debugging"
- task: app:cleanup:log-entries
frequency: "15 1 * * *"
description: "Removes outdated log entries with a retention period of 6 months"
- task: app:draft:cleanup
frequency: "30 1 * * *"
description: "Removes expired drafts"
- task: app:cleanup:newsletter-opt-in-requests
frequency: "45 1 * * *"
description: "Removes expired pending newsletter double opt-in requests"
- task: league:oauth2-server:clear-expired-tokens
frequency: "0 * * * *"
description: "Removes expired oauth2 tokens hourly"
- task: app:bpn:refresh-travel-snapshot --refresh-after 60
frequency: "10 8-19 * * *"
description: "Syncs travel data snapshots with BusPro XML data hourly during peak hours"
- task: app:bpn:refresh-travel-snapshot --refresh-after 180
frequency: "10 20-23,0-7 * * *"
description: "Syncs travel data snapshots with BusPro XML data every 3 hours outside peak hours"
when@staging:
zenstruck_schedule:
mailer:
subject_prefix: "[MyE&P STAGING]"
when@prod:
zenstruck_schedule:
mailer:
subject_prefix: "[MyE&P PROD]"
tasks:
- task: app:bpn:xml-sync
frequency: "*/15 8-19 * * *"
description: "Sync BusPro XML data every 15 min. during peak hours"
description: "Syncs BusPro XML data every 15 min. during peak hours"
- task: app:bpn:xml-sync
frequency: "0 20-23,0-7 * * *"
description: "Sync BusPro XML data hourly outside peak hours"
description: "Syncs BusPro XML data hourly outside peak hours"
- task: app:cleanup:log-entries
frequency: "30 1 * * *"
description: "Removes outdated log entries with a retention period of 6 months"
- task: app:bpn:sync-contingents
frequency: "5-59/15 8-19 * * *"
description: "Syncs the full contingent horizon every 15 min. during peak hours"
- task: app:bpn:sync-contingents
frequency: "5 20-23,0-7 * * *"
description: "Syncs the full contingent horizon hourly outside peak hours"
+275 -25
View File
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=../vendor/symfony/dependency-injection/Loader/schema/services.schema.json
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
@@ -5,28 +6,101 @@
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
travel_info_base_url: '%env(APP_TRAVEL_INFO_BASE_URL)%'
terms_and_conditions_url: '%env(APP_TERMS_AND_CONDITIONS_URL)%'
path_to_keys: '%kernel.project_dir%/config/secret'
bpn_debug: '%env(APP_BPN_DEBUG)%'
default_booking_status: '%env(DEFAULT_BOOKING_STATUS)%'
newsletter_confirmation_ttl_hours: '%env(int:APP_NEWSLETTER_CONFIRMATION_TTL_HOURS)%'
travel_snapshot_retention_buffer_days: '%env(int:APP_TRAVEL_SNAPSHOT_RETENTION_BUFFER_DAYS)%'
default_email_from: '%env(APP_DEFAULT_EMAIL_FROM)%'
default_email_to: '%env(APP_DEFAULT_EMAIL_TO)%'
accommodation_inquiry_email: '%env(ACCOMMODATION_INQUIRY_EMAIL)%'
# Body dimensions choices for BodyDimensionsType
body_dimensions.height_choices:
'bis 148cm': '-148'
'149 - 157cm': '149-157'
'158 - 166cm': '158-166'
'167 - 178cm': '167-178'
'179 - 185cm': '179-185'
'186 - 194cm': '186-194'
'195cm oder mehr': '195cm+'
body_dimensions.shoe_size_min: 36
body_dimensions.shoe_size_max: 48
body_dimensions.weight_choices:
'42 - 48kg': '42-48'
'49 - 57kg': '49-57'
'58 - 66kg': '58-66'
'67 - 78kg': '67-78'
'79 - 85kg': '79-85'
'86 - 94kg': '86-94'
'95kg oder mehr': '95k+'
# MailJet list ids and their labels
mailjet_lists:
10321569: 'E&P Newsletter'
10321382: 'Reisen-Alert Ahrntal'
10321383: 'Reisen-Alert Davos'
10321391: 'Reisen-Alert Familienreisen'
10321384: 'Reisen-Alert Arosa-Lenzerheide'
10321385: 'Reisen-Alert Les Deux Alpes'
10321386: 'Reisen-Alert Montafon'
10321387: 'Reisen-Alert Portes du Soleil'
10321388: 'Reisen-Alert Saalbach-Hinterglemm'
10538809: 'Reisen-Alert Scuol'
10321389: 'Reisen-Alert Stubaital'
10554990: 'Reisen-Alert Ski & Boarderweek'
# Email domains whose accounts are members of staff. BusPro has no CRM selection expressing
# "works here", so ROLE_EMPLOYEE is derived from the address instead. Matched exactly on the
# domain part, never as a suffix.
employee_email_domains:
- 'ep-reisen.de'
# BusProNet "Hausleitung {CODE}" CRM selections, by selection id.
# DEPLOYMENT-CRITICAL: roles and hotel codes are synced on every login, so an id missing
# here does not merely fail to nominate a Hausleitung — it revokes the role and the hotel
# code from everyone holding it, one login at a time, with manual re-approval per user.
# Entries for houses that are not in use yet stay commented out.
bpn_crm_house_manager_ids:
1299: 'SSL'
1300: 'SST'
1301: 'MVK'
# 1302: 'ASB'
1303: 'LPJ'
1304: 'DKS'
1305: 'DGS'
1306: 'DPW'
1307: 'DKI'
1308: 'DWW'
1309: 'PMV'
# 1352: 'ASG'
1371: 'ASC'
1373: 'PCJ'
1374: 'SBW'
# 1375: 'UCH'
# 1376: 'SZO'
1377: 'KHH'
1459: 'SVS'
1461: 'SHM'
1462: 'AGR'
# MailJet contact metadata names for name synchronization
mailjet_contact_metadata_fields:
firstName: 'vorname'
lastName: 'nachname'
# Body dimensions ranges for BodyDimensionsType and ParticipantValidator
body_dimension_ranges:
height_min: 145
height_max: 210
weight_min: 40
weight_max: 120
shoe_size_min: 35
shoe_size_max: 50
# Season data
season_winter_from: '%env(APP_SEASON_WINTER_FROM)%'
season_summer_from: '%env(APP_SEASON_SUMMER_FROM)%'
# domain mapping for theme, gtm id and cmp url
domain_config:
ep-reisen.de:
theme: base
gtm_id: GTM-56LWRF
cmp_url: https://consent.cookiefirst.com/sites/my.ep-reisen.de-28eabc35-7085-4d8f-b450-522bd1a5247c/consent.js
ski-boarderweek.de:
theme: sbw
gtm_id: GTM-MS2C8CH
cmp_url: https://consent.cookiefirst.com/sites/my.ski-boarderweek.de-d3641c34-8183-4b8d-b56e-c052e7a9223e/consent.js
semesterende-skireisen.de:
theme: ser
gtm_id: GTM-MNKDKL9
cmp_url: https://consent.cookiefirst.com/sites/my.semesterende-skireisen.de-c9b3422d-eb62-4ce4-b8f7-91e9b509e26f/consent.js
snowzone.net:
theme: snz
gtm_id: GTM-M96CKL
cmp_url: https://consent.cookiefirst.com/sites/my.snowzone.net-8e6aea0c-7d93-42a0-a822-29fff2aa5613/consent.js
services:
# default configuration for services in *this* file
@@ -39,6 +113,7 @@ services:
$xmlDump: '@xml_dump.storage'
$jsonExport: '@json_export.storage'
$travelInfoBaseUrl: '%env(APP_TRAVEL_INFO_BASE_URL)%'
$termsAndConditionsUrl: '%terms_and_conditions_url%'
$logger: '@monolog.logger.core'
$environment: '%kernel.environment%'
@@ -59,7 +134,7 @@ services:
bpn_username: '%env(APP_BPN_USER)%'
bpn_password: '%env(APP_BPN_PASSWORD)%'
bpn_api_ip: '%env(APP_BPN_IP)%'
bpn_api_port: '%env(APP_BPN_PORT)%'
bpn_api_ports: '%env(csv:APP_BPN_PORTS)%'
debug: '%env(bool:APP_BPN_DEBUG)%'
connection_timeout: '%env(int:APP_BPN_CONNECTION_TIMEOUT)%'
stream_timeout: '%env(int:APP_BPN_STREAM_TIMEOUT)%'
@@ -73,17 +148,73 @@ services:
arguments:
$path: '%path_to_keys%'
App\Menu\AdminMenuBuilder:
arguments:
$factory: '@knp_menu.factory'
tags:
- name: knp_menu.menu_builder
method: createMainMenu
alias: admin_main
App\Menu\GroupsMenuBuilder:
arguments:
$factory: '@knp_menu.factory'
tags:
- name: knp_menu.menu_builder
method: createMainMenu
alias: groups_main
App\Service\BpnXmlSyncManager:
arguments:
$xmlSource: '@xml_source.storage'
$xmlExport: '@xml_export.storage'
$bpnCache: '@bpn.cache'
App\Command\BpnXmlCacheInvalidateCommand:
arguments:
$xmlExport: '@xml_export.storage'
$bpnCache: '@bpn.cache'
$cache: '@cache.app'
App\Security\Crypt:
arguments:
$path: '%path_to_keys%'
App\Service\TravelDataService:
App\Service\TravelSnapshotManager:
arguments:
$retentionBufferDays: '%travel_snapshot_retention_buffer_days%'
App\Service\TravelDataProvider:
arguments:
$logger: '@monolog.logger.core'
$preferRemote: '%env(bool:APP_TRAVEL_PREFER_REMOTE)%'
$enableFallback: '%env(bool:APP_TRAVEL_ENABLE_FALLBACK)%'
App\Service\VoucherValidationService:
App\Service\ParticipantFormSupport:
arguments:
$bodyDimensionRanges: '%body_dimension_ranges%'
App\Service\BookingEditDataLoader:
arguments:
$bpnCache: '@bpn.cache'
App\BusProNet\XmlLoader\TravelLoader:
arguments:
$cache: '@bpn.cache'
App\BusProNet\XmlLoader\HotelLoader:
arguments:
$cache: '@bpn.cache'
App\BusProNet\XmlLoader\PickupLoader:
arguments:
$cache: '@bpn.cache'
App\BusProNet\XmlLoader\InsuranceLoader:
arguments:
$cache: '@bpn.cache'
App\Service\VoucherValidator:
arguments:
$cache: '@cache.app'
$logger: '@monolog.logger.bpn'
@@ -100,28 +231,147 @@ services:
arguments:
$handlers:
# Simple handlers with no external dependencies - instantiated directly
- 'App\Form\Service\ParticipantDateOfBirthFieldHandler'
- 'App\Form\Service\ParticipantAssignedRoomFieldHandler'
- 'App\Form\Service\ParticipantRemarksRoomFieldHandler'
- 'App\Form\Service\ParticipantAdditionalServicesFieldHandler'
- 'App\Form\Service\ParticipantCoursesFieldHandler'
- 'App\Form\Service\ParticipantBoardFieldHandler'
- 'App\Form\Service\ParticipantVegFieldHandler'
- 'App\Form\Service\ParticipantRentalsFieldHandler'
- 'App\Form\Service\ParticipantSkiPassFieldHandler'
- 'App\Form\Service\ParticipantTransportationOutboundFieldHandler'
- 'App\Form\Service\ParticipantTransportationInboundFieldHandler'
- 'App\Form\Service\ParticipantPickupFieldHandler'
- 'App\Form\Service\ParticipantParkingFieldHandler'
- 'App\Form\Service\ParticipantDropOffFieldHandler'
- 'App\Form\Service\ParticipantRentalInsuranceFieldHandler'
- 'App\Form\Service\ParticipantLicensePlateFieldHandler'
# Complex handlers with dependencies - use service references
- '@App\Form\Service\ParticipantDateOfBirthFieldHandler'
- '@App\Form\Service\ParticipantTransportationDiscountReplacementFieldHandler'
- '@App\Form\Service\ParticipantBulkInsuranceFieldHandler'
- '@App\Form\Service\ParticipantInsuranceFieldHandler'
- '@App\Form\Service\ParticipantPurchaseVoucherFieldHandler'
- '@App\Form\Service\ParticipantPromoVoucherFieldHandler'
- '@App\Form\Service\ParticipantParkingFieldHandler'
App\Service\CmsDataService:
# Booking Status Rules
App\BusProNet\Service\StatusRule\Selection1473StatusRule: ~
App\BusProNet\Service\StatusRule\ChaperonServiceStatusRule: ~
# Booking Status Rule Registry
App\BusProNet\Service\BookingStatusRuleRegistry:
arguments:
$rules:
- '@App\BusProNet\Service\StatusRule\Selection1473StatusRule'
- '@App\BusProNet\Service\StatusRule\ChaperonServiceStatusRule'
# Dashboard Widgets
App\Dashboard\Widget\OpenGroupBookingsWidgetProvider: ~
App\Dashboard\Widget\PendingRoleApprovalsWidgetProvider: ~
App\Dashboard\Widget\RecentLogEntriesWidgetProvider: ~
# Dashboard Widget Registry
App\Dashboard\DashboardWidgetRegistry:
arguments:
$providers:
- '@App\Dashboard\Widget\OpenGroupBookingsWidgetProvider'
- '@App\Dashboard\Widget\PendingRoleApprovalsWidgetProvider'
- '@App\Dashboard\Widget\RecentLogEntriesWidgetProvider'
App\Service\CmsDataProvider:
arguments:
$httpClient: '@typo3.client'
$apiKey: 'AbcAbc123'# dummy key, not yet implemented
App\Logger\RequestIdProcessor:
tags:
- { name: monolog.processor }
App\Service\NewsletterManager:
arguments:
$newsletterConfirmationTtlHours: '%newsletter_confirmation_ttl_hours%'
$mailjetLists: '%mailjet_lists%'
$defaultMailjetListId: '%env(default::MAILJET_DEFAULT_LIST_ID)%'
App\Controller\Api\NewsletterSubscriptionController:
arguments:
$mailjetLists: '%mailjet_lists%'
App\Controller\Webhook\MailjetNewsletterWebhookController:
arguments:
$mailjetLists: '%mailjet_lists%'
App\BusProNet\XmlParser\CrmAttributesResponseParser:
arguments:
$houseManagerIds: '%bpn_crm_house_manager_ids%'
App\Security\EmployeeDomainMatcher:
arguments:
$domains: '%employee_email_domains%'
App\Service\DomainConfigProvider:
arguments:
$domainConfig: '%domain_config%'
App\Email\Mailer:
arguments:
$defaults:
from: '%default_email_from%'
to: '%default_email_to%'
App\Service\AccommodationBookingService:
arguments:
$accommodationEmail: '%accommodation_inquiry_email%'
App\Service\AccommodationTermsUrlProvider:
arguments:
$config:
AT: '%env(ACCOMMODATION_TERMS_AT)%'
CH: '%env(ACCOMMODATION_TERMS_CH)%'
IT: '%env(ACCOMMODATION_TERMS_IT)%'
App\Service\GroupsPriceCalculator:
arguments:
$config:
runningCostsEur: '%env(float:APP_RUNNING_COSTS_FACTOR_EUR)%'
runningCostsChf: '%env(float:APP_RUNNING_COSTS_FACTOR_CHF)%'
undersubscription30Eur: '%env(float:APP_UNDERSUBSCRIPTION_SURCHARGE_30_EUR)%'
undersubscription30Chf: '%env(float:APP_UNDERSUBSCRIPTION_SURCHARGE_30_CHF)%'
undersubscription40Eur: '%env(float:APP_UNDERSUBSCRIPTION_SURCHARGE_40_EUR)%'
undersubscription40Chf: '%env(float:APP_UNDERSUBSCRIPTION_SURCHARGE_40_CHF)%'
App\Validator\Constraints\ParticipantValidator:
arguments:
$bodyDimensionRanges: '%body_dimension_ranges%'
App\BpnConnect\AbstractApiClient:
abstract: true
arguments:
$baseUrl: '%env(default::BPN_CONNECT_BASE_URL)%'
$apiKey: '%env(default::BPN_CONNECT_API_KEY)%'
App\BpnConnect\ContingentsClient:
parent: App\BpnConnect\AbstractApiClient
App\ClickUp\ApiClient:
arguments:
$apiToken: '%env(default::CLICKUP_API_TOKEN)%'
$listId: '%env(default::CLICKUP_LIST_ID)%'
$templateId: '%env(default::CLICKUP_TEMPLATE_ID)%'
$baseUrl: '%env(default::CLICKUP_API_BASE_URL)%'
App\Mailjet\ApiClient:
arguments:
$apiKey: '%env(default::MAILJET_API_KEY)%'
$apiSecret: '%env(default::MAILJET_API_SECRET)%'
$apiBaseUrl: '%env(default::MAILJET_API_BASE_URL)%'
$defaultListId: '%env(default::MAILJET_DEFAULT_LIST_ID)%'
$contactMetadataFields: '%mailjet_contact_metadata_fields%'
App\EventListener\MaintenanceModeListener:
arguments:
$options:
enabled: '%env(bool:MAINTENANCE_MODE_ENABLED)%'
whitelisted_ips: '%env(csv:MAINTENANCE_MODE_IP_WHITELIST)%'
whitelisted_routes: '%env(csv:MAINTENANCE_MODE_ROUTE_WHITELIST)%'
whitelisted_paths: '%env(csv:MAINTENANCE_MODE_PATH_WHITELIST)%'
+19
View File
@@ -0,0 +1,19 @@
parameters:
# domain mapping for theme, gtm id and cmp url
domain_config:
myep.ddev.site:
theme: base
gtm_id: GTM-56LWRF
cmp_url: https://consent.cookiefirst.com/sites/my.ep-reisen.de-28eabc35-7085-4d8f-b450-522bd1a5247c/consent.js
myswb.ddev.site:
theme: sbw
gtm_id: GTM-MS2C8CH
cmp_url: https://consent.cookiefirst.com/sites/my.ski-boarderweek.de-d3641c34-8183-4b8d-b56e-c052e7a9223e/consent.js
myser.ddev.site:
theme: ser
gtm_id: GTM-MNKDKL9
cmp_url: https://consent.cookiefirst.com/sites/my.semesterende-skireisen.de-c9b3422d-eb62-4ce4-b8f7-91e9b509e26f/consent.js
mysnz.ddev.site:
theme: snz
gtm_id: GTM-M96CKL
cmp_url: https://consent.cookiefirst.com/sites/my.snowzone.net-8e6aea0c-7d93-42a0-a822-29fff2aa5613/consent.js
+1 -1
View File
@@ -2,7 +2,7 @@ const {defineConfig} = require("cypress");
module.exports = defineConfig({
e2e: {
baseUrl: 'https://myep-next-booking.ddev.site',
baseUrl: 'https://myep.ddev.site',
supportFile: false,
},
});
+18 -25
View File
@@ -17,7 +17,6 @@ add('shared_dirs', [
add('shared_files', [
'public/.htaccess',
'.env.local.php',
]);
set('keep_releases', 3);
@@ -33,6 +32,7 @@ $rsyncOptions = [
'.ddev',
'.git',
'.github',
'.jj',
'node_modules',
'.editorconfig',
'.env.dev.local',
@@ -46,14 +46,17 @@ $rsyncOptions = [
'.phpunit.result.cache',
'config/secret/',
'CLAUDE.md',
'cypress*',
'deploy.php',
'docs',
'package.json',
'package-lock.json',
'*.http',
'http-client.private.env.json',
'http-client*.json',
'postcss.config.js',
'phpunit.xml.dist',
'public/.htaccess',
'ray.php',
'tailwind.config.js',
'webpack.config.js',
'bin/.phpunit',
@@ -74,31 +77,19 @@ $rsyncOptions = [
];
host('prod')
->setHostname('92.205.212.39')
->setRemoteUser('ssh-53857-root')
->setHostname('dedi10193.your-server.de')
->setRemoteUser('myepsf')
->setForwardAgent(true)
->setSshMultiplexing(true)
->setDeployPath('/kunden/tiefschnee.de/myep')
->set('writable_mode', 'chmod')
->set('http_user', 'ssh-53857-root')
->set('bin/php', '/usr/bin/php82')
->setDeployPath('/usr/home/myepsf/public_html/prod')
->set('bin/php', '/usr/bin/php')
->set('http_user', 'myepsf')
->set('rsync_src', __DIR__)
->set('rsync', $rsyncOptions)
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{release_or_current_path}}/public/ --web-url=https://my.ep-reisen.de')
;
host('staging')
->setHostname('185.243.132.170')
->setRemoteUser('p546473')
->setForwardAgent(true)
->setSshMultiplexing(true)
->setDeployPath('/home/www/p546473/html/myep')
->set('writable_mode', 'chmod')
->set('bin/php', '/usr/local/bin/php')
->set('rsync_src', __DIR__)
->set('rsync', $rsyncOptions)
->set('keep_releases', 5)
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{release_or_current_path}}/public/ --web-url=https://myep.dreipunktnull.net')
->set('cachetool_args', '--web=SymfonyHttpClient --web-path={{current_path}}/public/ --web-url=https://my.ep-reisen.de')
->add('shared_files', [
'public/.htpasswd',
])
;
task('deploy', [
@@ -110,14 +101,16 @@ task('deploy', [
'rsync',
'deploy:shared',
'deploy:writable',
'deploy:cache:clear',
'database:migrate',
'deploy:publish',
'cachetool:clear:opcache',
'deploy:publish',
'deploy:stop-workers',
]);
task('deploy:assets', function () {
runLocally('npm i && npm run build');
runLocally('ddev exec npm ci');
runLocally('ddev exec npm run build');
});
task('deploy:stop-workers', function () {
-475
View File
@@ -1,475 +0,0 @@
# Symfony 7.4 Upgrade Plan
**Project:** MyEP Next Booking
**Current Version:** Symfony 6.4.31
**Target Version:** Symfony 7.4 (LTS)
**Date:** 2026-01-05
**Status:** Ready for Upgrade
---
## Executive Summary
**Estimated Effort: LOW**
**Risk Level: LOW**
**Status: READY FOR UPGRADE**
The MyEP Next Booking application is well-positioned for a Symfony 7.4 upgrade. The codebase follows modern Symfony best practices, uses PHP 8 features extensively, and avoids most deprecated patterns. All pre-upgrade fixes have been completed.
**Key Facts:**
- Symfony 7.4 was released on November 27, 2025
- Requires PHP 8.2.0+ (current: PHP 8.2.29)
- LTS version with bug fixes until November 2028, security fixes until November 2029
- Symfony 8.0 = Symfony 7.4 minus deprecations (same features, PHP 8.4 required)
**Pre-Upgrade Status:**
- PHP version: 8.2.29 (compatible)
- OAuth2 Server Bundle: 1.1.0 (compatible)
- Stimulus Bundle: 2.32.0 (compatible)
- KnpMenuBundle: Removed (no longer in use)
- Doctrine ORM: 3.6.0 (compatible)
- All 312 tests passing
- Email validation mode: Configured (html5)
- 18 test-only deprecation warnings (cosmetic, do not affect runtime)
---
## Previous Plan Status
The previous upgrade plan (dated 2025-12-06) has been updated. All pre-upgrade tasks are now complete.
### Completed Items
| Item | Previous Status | Current Status |
|------|----------------|----------------|
| OAuth2 Server Bundle | 1.0.0 | **1.1.0 installed** |
| Stimulus Bundle | 2.31.0 | **2.32.0 installed** |
| PHP 8.2 deprecations (ParticipantDto::$touched) | Planned | **Completed** |
| Doctrine config (controller_resolver) | Planned | **Completed** |
| SecurityController null safety | Needs verification | **Completed** (uses `?->` and `??`) |
| Email validator "loose" mode deprecation | Needs fix | **Completed** (validator.yaml configured) |
| Failing test in BookingDataProcessorTest | Unrelated to upgrade | **Resolved** (test now passes) |
### Items No Longer Relevant
| Item | Reason |
|------|--------|
| KnpMenuBundle upgrade | **Bundle removed from project** |
---
## Current State Analysis
### PHP Version Compatibility
- **Current Runtime:** PHP 8.2.29
- **Composer Platform:** PHP 8.2.28
- **Symfony 7.4 Required:** PHP 8.2.0+
- **Status:** Compatible
### Installed Dependencies
#### Core Symfony Packages (6.4.x)
All 33 Symfony packages currently at 6.4.x need version constraint updates to 7.4.*
#### Third-Party Bundles - Compatible
| Package | Installed | Symfony 7.4 Compatible |
|---------|-----------|------------------------|
| `doctrine/orm` | 3.6.0 | Yes |
| `doctrine/doctrine-bundle` | 2.18.1 | Yes |
| `doctrine/doctrine-migrations-bundle` | 3.7.0 | Yes |
| `league/oauth2-server-bundle` | 1.1.0 | Yes |
| `symfony/stimulus-bundle` | 2.32.0 | Yes |
| `symfony/webpack-encore-bundle` | 2.4.0 | Yes |
| `symfony/monolog-bundle` | 3.11.0 | Yes |
| `zenstruck/schedule-bundle` | 1.9.0 | Yes |
### Code Quality Assessment
The codebase implements modern Symfony/PHP patterns:
- All controllers use PHP 8 attributes (`#[Route]`)
- Constructor property promotion used throughout
- Strict types enforced on all files
- Typed properties and return type declarations
- Entities use PHP 8 attributes for ORM mapping
- Modern security system (AbstractLoginFormAuthenticator)
- No deprecated annotation usage
---
## Pre-Upgrade Fixes - COMPLETED
### 1. Email Validator "loose" Mode Deprecation - DONE
**Issue:** The default mode for `#[Assert\Email]` is "loose", which is deprecated in Symfony 6.2+ and removed in Symfony 7.0.
**Resolution:** Framework default configured in `config/packages/validator.yaml`:
```yaml
framework:
validation:
email_validation_mode: html5
```
All Email constraints in the codebase also explicitly use `mode: 'strict'`:
- `src/Form/Model/ParticipantDto.php` - Has `mode: 'strict'`
- `src/Form/Model/RegistrationDto.php` - Has `mode: 'strict'`
- `src/BusProNet/Model/Communication.php` - Has `mode: 'strict'`
- `src/Controller/ResetPasswordController.php` - Has `mode: 'strict'`
### 2. Test Deprecation Warnings - COSMETIC ONLY
**Issue:** 18 deprecation warnings appear during test runs.
**Cause:** `ParticipantEditDtoTest` creates a standalone validator using `Validation::createValidatorBuilder()` which bypasses the framework's `validator.yaml` configuration.
**Impact:** These warnings are cosmetic and do not affect:
- Runtime behavior (all Email constraints use explicit `mode: 'strict'`)
- Symfony 7.4 compatibility (no code changes needed)
- Test results (all 312 tests pass)
**Note:** Warnings can be silenced with `SYMFONY_DEPRECATIONS_HELPER=disabled` if desired.
---
## Required Changes
### 1. Update Composer Version Constraints
**File:** `composer.json`
#### Symfony Core Packages
Update all packages from `6.4.*` to `7.4.*`:
```json
{
"require": {
"symfony/asset": "7.4.*",
"symfony/console": "7.4.*",
"symfony/doctrine-messenger": "7.4.*",
"symfony/dom-crawler": "7.4.*",
"symfony/dotenv": "7.4.*",
"symfony/expression-language": "7.4.*",
"symfony/form": "7.4.*",
"symfony/framework-bundle": "7.4.*",
"symfony/html-sanitizer": "7.4.*",
"symfony/http-client": "7.4.*",
"symfony/intl": "7.4.*",
"symfony/lock": "7.4.*",
"symfony/mailer": "7.4.*",
"symfony/mime": "7.4.*",
"symfony/notifier": "7.4.*",
"symfony/process": "7.4.*",
"symfony/property-access": "7.4.*",
"symfony/property-info": "7.4.*",
"symfony/runtime": "7.4.*",
"symfony/security-bundle": "7.4.*",
"symfony/serializer": "7.4.*",
"symfony/string": "7.4.*",
"symfony/translation": "7.4.*",
"symfony/twig-bundle": "7.4.*",
"symfony/uid": "7.4.*",
"symfony/validator": "7.4.*",
"symfony/web-link": "7.4.*",
"symfony/yaml": "7.4.*"
}
}
```
#### Development Packages
```json
{
"require-dev": {
"symfony/browser-kit": "7.4.*",
"symfony/css-selector": "7.4.*",
"symfony/debug-bundle": "7.4.*",
"symfony/stopwatch": "7.4.*",
"symfony/web-profiler-bundle": "7.4.*"
}
}
```
### 2. Update Symfony Flex Configuration
**File:** `composer.json`
```json
{
"extra": {
"symfony": {
"allow-contrib": true,
"require": "7.4.*",
"docker": true
}
}
}
```
---
## Potential Breaking Changes
### 1. Symfony Core Changes (Symfony 7.0 -> 7.4)
Symfony 7.0 removed all deprecated features from 6.4. Our codebase is fully compliant:
- **Native Return Types:** Already implemented
- **Attribute-based Configuration:** Already implemented
- **Security System:** Modern authenticator pattern in use
- **Form System:** Modern approach in use
- **No Annotation Usage:** All using PHP 8 attributes
### 2. Email Validation Mode
**Breaking Change:** The default `mode` for `Email` constraint changes from `loose` to `html5` in Symfony 7.0.
**Status:** Already handled - all constraints use explicit `mode: 'strict'` and framework default is set to `html5`.
### 3. Deprecation Cleanup
Deprecations accumulated in Symfony 7.1-7.4 will need review:
- Check Symfony Profiler after upgrade for any new deprecation warnings
- Review [UPGRADE-7.0.md](https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md)
- Review [UPGRADE-7.4.md](https://github.com/symfony/symfony/blob/7.4/UPGRADE-7.4.md)
---
## Upgrade Procedure
### Phase 1: Preparation (15 minutes)
1. **Create Feature Branch**
```bash
git checkout -b feature/symfony-7.4-upgrade
```
2. **Backup Current State**
```bash
git tag before-symfony-7.4-upgrade
```
### Phase 2: Dependency Updates (30 minutes - 1 hour)
1. **Update composer.json**
- Update all Symfony package constraints to `7.4.*`
- Update `extra.symfony.require` to `"7.4.*"`
2. **Run Composer Update**
```bash
ddev composer update
```
3. **Review Recipe Updates**
```bash
ddev composer recipes
```
Review any recipe updates from Symfony Flex and apply as needed.
4. **Clear All Caches**
```bash
ddev exec bin/console cache:clear
ddev exec bin/console cache:warmup
ddev exec "php -r 'opcache_reset();'"
```
### Phase 3: Testing & Validation (1-2 hours)
1. **Run PHPUnit Test Suite**
```bash
ddev exec ./vendor/bin/phpunit
```
Check for:
- Test failures
- Deprecation warnings
- Fatal errors
2. **Run PHP-CS-Fixer**
```bash
ddev php vendor/bin/php-cs-fixer fix --dry-run --diff
```
3. **Manual Testing - Critical Paths**
- [ ] User authentication (BPN API login)
- [ ] OAuth2 token generation (`/token` endpoint)
- [ ] OAuth2 authorization flow (`/authorize` endpoint)
- [ ] API endpoints (all `/api/*` routes)
- [ ] Booking creation flow (Steps 1-4)
- [ ] Participant form rendering and submission
- [ ] Dynamic field updates (HTMX)
- [ ] Real-time pricing calculations
- [ ] Insurance selection and filtering
- [ ] Transportation service selection
- [ ] Payment method selection
- [ ] Final booking submission to BPN API
- [ ] Booking edit functionality
- [ ] PDF/XML download functionality
- [ ] User registration
- [ ] Password reset
- [ ] Personal data management
4. **Check Symfony Profiler**
- Review deprecation warnings (should be minimal)
- Check performance metrics
- Verify no errors in logs
5. **Test Frontend Assets**
```bash
npm run build
```
- Verify Stimulus controllers load correctly
- Test HTMX interactions
- Verify Toastify notifications
- Check TailwindCSS compilation
### Phase 4: Bug Fixes (0-2 hours)
Address any issues discovered during testing:
1. **Review Error Logs**
```bash
ddev logs
```
2. **Fix Any Remaining Deprecations**
- Use Symfony Profiler to identify deprecations
- Update code to use modern alternatives
### Phase 5: Deployment (1 hour)
1. **Deploy to Staging**
```bash
ddev exec vendor/bin/dep deploy staging
```
2. **Staging Validation**
- Full regression testing
- Performance testing
3. **Production Deployment**
- Schedule maintenance window
- Deploy during low-traffic period
- Monitor error logs closely
---
## Rollback Plan
### Immediate Rollback
If critical issues are discovered:
1. **Git Revert**
```bash
git checkout master
git reset --hard before-symfony-7.4-upgrade
```
2. **Restore Dependencies**
```bash
ddev composer install
```
3. **Clear Caches**
```bash
ddev exec bin/console cache:clear
```
### Production Rollback
If issues occur in production:
```bash
ddev exec vendor/bin/dep rollback production
```
---
## Testing Checklist
### Unit Tests
- [ ] All PHPUnit tests pass (312 tests)
- [ ] No new deprecation warnings
- [ ] Code coverage maintained
### Integration Tests
- [ ] BusProNet API integration
- [ ] XML parsing and data processing
- [ ] Booking price calculations
- [ ] Insurance assignment logic
- [ ] Field handler system
### Functional Tests
- [ ] User authentication flow
- [ ] OAuth2 token generation
- [ ] API endpoints respond correctly
- [ ] Booking creation (all steps)
- [ ] Form validation
- [ ] HTMX partial updates
- [ ] Dynamic field state changes
- [ ] Real-time pricing updates
- [ ] Toast notifications
### Browser Testing
- [ ] Chrome (latest)
- [ ] Firefox (latest)
- [ ] Safari (latest)
- [ ] Mobile browsers
---
## Timeline Estimate
| Phase | Estimated Time | Notes |
|-------|---------------|-------|
| **Phase 1:** Preparation | 15 min | Branch creation |
| **Phase 2:** Dependency Updates | 30 min - 1 hour | composer.json updates, composer update |
| **Phase 3:** Testing & Validation | 1-2 hours | Automated + manual testing |
| **Phase 4:** Bug Fixes | 0-2 hours | Address any issues |
| **Phase 5:** Deployment | 1 hour | Staging deployment |
| **Total** | **2.5-6 hours** | Average: **3.5 hours** |
---
## Future Considerations: Symfony 8.0
Symfony 8.0 was released alongside 7.4 (November 2025) with identical features but:
- Requires PHP 8.4
- No deprecation layers (all deprecated code removed)
- Shorter support window (8 months)
**Recommendation:** Stay on Symfony 7.4 LTS for stability. Plan PHP 8.4 upgrade separately, then consider Symfony 8.x path.
---
## Success Criteria
- [ ] All PHPUnit tests pass (312 tests)
- [ ] No deprecation warnings in Symfony Profiler
- [ ] All critical user flows functional
- [ ] OAuth2 authentication working
- [ ] BPN API integration operational
- [ ] Booking creation flow complete
- [ ] Frontend assets compile and load
- [ ] Performance metrics comparable or better
- [ ] No errors in production logs after 24 hours
---
## Additional Resources
### Official Symfony Documentation
- [Upgrade Major Version Guide](https://symfony.com/doc/current/setup/upgrade_major.html)
- [UPGRADE-7.0.md](https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md)
- [UPGRADE-7.4.md](https://github.com/symfony/symfony/blob/7.4/UPGRADE-7.4.md)
- [Symfony 7.4 Release Notes](https://symfony.com/releases/7.4)
- [Preparing for Symfony 7.4 and 8.0](https://symfony.com/blog/preparing-for-symfony-7-4-and-symfony-8-0)
### Bundle-Specific Documentation
- [OAuth2 Server Bundle](https://github.com/thephpleague/oauth2-server-bundle)
- [Doctrine ORM 3.x Documentation](https://www.doctrine-project.org/projects/orm.html)
---
**Document Version:** 5.0
**Previous Version:** 4.0 (dated 2025-12-06)
**Last Updated:** 2026-01-05
**Status:** Ready for Symfony 7.4 Upgrade
+414
View File
@@ -0,0 +1,414 @@
# API Consumer Guide
This document describes the public JSON API exposed under `/api`, written for developers implementing a **client** in another application. It is self-contained: no access to this codebase is required to use it.
## Overview
A Symfony application exposing a read-mostly JSON API under the `/api` prefix. All `/api/*` requests are stateless and authenticated via OAuth2 Bearer tokens (League OAuth2 Server, JWT access tokens). Responses are `application/json`. HTTPS is enforced on all routes.
## Authentication
- Token endpoint: `POST /token` (unauthenticated).
- Enabled grants: **client_credentials**, **authorization_code** (PKCE required for public clients), **refresh_token**. Password and implicit grants are disabled.
- Access token TTL: **10 minutes** — clients must refresh/re-request frequently.
- Available scopes: `email`, `id`, `profile`, `roles`, `api`. Default scope if none requested: `email`.
- Each granted scope maps to a role `ROLE_OAUTH2_<SCOPE_UPPERCASE>` (e.g. scope `api``ROLE_OAUTH2_API`).
- Send the token as `Authorization: Bearer <access_token>`.
Scope required per endpoint:
| Scope needed | Endpoints |
|---|---|
| `api` | everything except the two below |
| `profile` | `GET /api/crm-attributes` |
| `email` | `GET /api/userinfo` (optional extra scopes `id`, `profile`, `roles` widen the response) |
`/api/userinfo` and `/api/crm-attributes` act on the **authenticated end user**, so they require an authorization_code token issued for a user. All other endpoints are machine-to-machine and work with client_credentials.
### Machine-to-machine example
```
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=...&client_secret=...&scope=api
```
```
GET /api/hotels
Authorization: Bearer eyJ0eXAi...
```
## Error conventions
There is no single error envelope; three shapes occur:
- `{"message": "..."}` — commonly with 404 / 400.
- `{"error": "...", "type": "api_error"}` — upstream failures on some endpoints. **Caution:** on `/api/products` and `/api/travels/{dateId}/{hotelId}/{dateTo}/availability` this shape is returned with HTTP **200**, so clients must check for the presence of an `error` key, not only the status code.
- `{"success": false, "message": "..."}` — the write endpoints (contact form, newsletter).
Validation failures on endpoints using mapped query strings / payloads (`/api/contingents/*`, `/api/newsletter-subscriptions`) return **400** with Symfony's constraint-violation body. Missing/invalid token yields **401**; insufficient scope yields **403**.
The HTTP methods listed below are the intended ones. Several read routes do not restrict methods server-side; clients should still use `GET` for them.
---
## Endpoints
### Reference data (BusProNet master data)
#### `GET /api/hotels` — scope `api`
List of hotels. Array of objects: `id` (int), `code` (string), `name`, `city`, `street`, `phone`, `country`.
#### `GET /api/hotels/{id}` — scope `api`
Single hotel by numeric id, same field set as the list. `404 {"message":"Not found"}` if unknown.
#### `GET /api/countries` — scope `api`
Array of `{id, name, token, nationality}`.
#### `GET /api/products` — scope `api`
Product master data from the upstream BusProNet system, cached server-side for 1 hour. On upstream failure returns `{"error": "...", "type": "api_error"}` **with status 200**.
#### `GET /api/last-update` — scope `api`
Timestamp of the last upstream data export: `{"timestamp": "YYYY-MM-DD HH:MM:SS"}`. Note: if no export marker file exists the current implementation errors (500) rather than returning null — treat a non-JSON/500 response as "unknown".
---
### Pickups (bus boarding points)
#### `GET /api/pickups` — scope `api`
Array of `{id, code, city, postalCode, street}`.
#### `GET /api/pickups/{id}` — scope `api`
Single pickup by numeric id, same fields as the list.
#### `GET /api/pickups-planning/{travelCode}` — scope `api`
Planned outbound (HIN) boarding stops for one travel code. Returns an array, chronologically sorted:
```json
[{"city": "...", "location": "...", "datetime": "YYYY-MM-DD HH:MM", "busNumber": "..."}]
```
`404 {"error":"Planning data not available"}` if no planning has been uploaded yet, `404 {"error":"Travel code not found"}` for an unknown code, `500 {"error":"Failed to read planning data"}` on storage errors.
#### `POST /api/pickups-planning` — scope `api`
Bulk-replaces the planning dataset. Body: a JSON **array** of raw planning rows using the upstream German keys:
```json
[
{
"PlanungsArt": "HIN",
"Reisecode": "ABC123",
"Zustieg/Ausstieg Ort": "Köln",
"Zustieg/Ausstieg Strasse": "Hauptbahnhof",
"Zeit": "24.12.2026 07:30",
"BusNummer": "1"
}
]
```
Rows without `PlanungsArt === "HIN"` or without `Reisecode` are dropped; duplicates (same city + location + datetime + bus) are de-duplicated; results are grouped by `Reisecode` and sorted by time. Response `{"status":"ok"}` (200). `400 {"error":"Invalid JSON payload"}`, `500 {"error":"Failed to write pickups planning data"}`.
This is a full overwrite, not a merge.
---
### Travels
#### `GET /api/travels` — scope `api`
Index/mapping of all known travel dates. Object keyed by numeric travel id, each value `{id, code, label, dateFrom, dateTo, hotels: [...]}`.
#### `GET /api/travels/{dateId}/{hotelId}` — scope `api`
Single travel by **numeric** ids (`hotelId` optional). Route matches only when both segments are digits.
#### `GET /api/travels/{dateCode}/{hotelCode}` — scope `api`
Same, addressed by **string** codes (`hotelCode` optional). The date code is sanitized (separators stripped) before lookup. `404 {"message":"Not found"}` if the date code is unknown, `404 {"message":"Travel not found"}` if no data exists.
Both variants accept optional query parameters:
- `source=local` — force the local XML/snapshot data.
- `source=remote` — force a live upstream call.
- `prefer_remote=1` — used only when `source` is absent; prefers upstream with local fallback.
Response fields: `id`, `code`, `productCode`, `productId`, `label`, `hotelId`, `hotel` (hotel object), `dateFrom`, `dateTo`, `type`, `status`, `allowedBookingStatus[]`, `priceFrom`, `selectionGroups[]`, `additionalServices[]`, `transportationServices[]`, `pickups[]`, `dropOffs[]`, `rooms[]`, `guide`, `insurances[]`.
#### `GET /api/travels/{dateId}/{hotelId}/{dateTo}/availability` — scope `api`
Live hotel availability from the upstream system. `dateTo` must be `Y-m-d`. On upstream failure returns `{"error":"...","type":"api_error"}` **with status 200**.
---
### Contingents & accommodation prices
#### `GET /api/contingents/prices?hotelCode=…&year=…` — scope `api`
Price timeline for one accommodation and calendar year, collapsed into contiguous segments (adjacent days with the same effective price are merged into one row). The timeline never starts before today; if the requested year is entirely in the past the response is `[]`.
- `hotelCode`: required, max 16 chars, `[A-Za-z0-9_-]+` (matches the accommodation's calendar code).
- `year`: required int, 10009999.
Each row:
```json
{
"dateFrom": "2026-06-01",
"dateTo": "2026-06-14",
"season": "high|low|...|null",
"includedPax": 2,
"pricePerNight": 89.5,
"priceAdditionalPerson": 25.0,
"defaultPricePerNight": 99.0,
"defaultPriceAdditionalPerson": 30.0,
"currency": "EUR",
"type": "discount|null"
}
```
Prices are **decimal major units** (converted from integer minor units server-side). `default*` fields are non-null only when the winning price is a discount, and then carry the undiscounted price. `400 {"error":"Hotel not found for hotelCode."}` for an unknown code; `400` with violations for invalid parameters.
#### `GET /api/contingents/calendar?hotelCode=…&dateFrom=…&dateTo=…` — scope `api`
Per-day availability enriched with prices.
`dateFrom` and `dateTo` are **optional, and must be supplied together** — one without the other is a `400`. Both are `Y-m-d` and **inclusive** (`dateTo` is the last night, not the checkout day); when supplied, the range may not exceed 366 days and `dateTo` must not precede `dateFrom`.
**Omit both to get the full priced span.** The range is then derived from the accommodation's persisted prices, `MIN(dateFrom)` to `MAX(dateTo)`, and never starts before today. This is the way to fetch everything a hotel sells in one call, and it is not subject to the 366-day cap — a hotel priced over two seasons returns well over a year of entries.
Full-span responses are contiguous, exactly like ranged ones: every day between the derived bounds gets an entry, including days no price covers. Those come back `BLOCKED` with `null` price fields — a hotel closed over winter reports the whole closure day by day rather than skipping it, so a consumer keying off `status` always finds one.
The response is `[]` — a `200`, not a `502` — when the hotel has no prices at all, or when every priced period has already ended.
Availability is served from a **local snapshot** refreshed over a 24-month horizon — every 15 minutes during the day, hourly overnight — not fetched from the upstream contingent service per request. The endpoint therefore responds in single-digit milliseconds and stays available during an upstream outage, at the cost of being at most one sync interval stale.
The response format is unchanged from the previous upstream-backed implementation: same fields, same order, same types, same `status` values. One behavioural note — the endpoint returns **one entry per day of the range**, whether that range came from `dateFrom`/`dateTo` or was derived from the prices. Previously days the upstream service did not mention were simply absent, so a response may contain days it would not have contained before. It is a superset, never a different shape.
Two kinds of day resolve to `BLOCKED` regardless of the underlying contingent:
- **days in the past** — the snapshot is maintained from today forward only (`prices` likewise refuses past ranges)
- **days beyond the synced horizon** — currently 24 months out. Prices are often maintained further ahead than the contingent is synced, so a full-span response can end in a run of `BLOCKED` days that simply have no availability data yet.
Each entry:
```json
{
"date": "2026-06-01",
"status": "Free|Blocked|...",
"type": "discount|null",
"pricePerNight": 89.5,
"defaultPricePerNight": 99.0,
"priceAdditionalPerson": 25.0,
"defaultPriceAdditionalPerson": 30.0,
"currency": "EUR",
"includedPax": 2,
"minNights": 2
}
```
Important rule: **a day with no maintained price is forced to `Blocked`** regardless of what the upstream contingent says. Price fields may be `null` in that case. This applies to both modes.
Errors: `400 {"error":"Hotel not found for hotelCode."}`, `400` with violations for invalid parameters.
`502 {"error":"Failed to fetch contingent data."}` is still returned — with the same body as before — but it now means **"no usable local snapshot for this hotel"** rather than "the upstream call failed": either the hotel has never synced successfully, or its last successful sync is more than 6 hours old. Treat it as before: the data is unavailable, not empty. This matters because the alternative would be a `200` reporting every day as `BLOCKED`, which is indistinguishable from a genuinely fully-booked hotel.
---
### Operating the snapshot (deployment)
The snapshot is a new table populated by the scheduler, so it is **empty immediately after a deploy that runs the migration**. Until the first successful sync every hotel returns `502` — deliberately, so no consumer caches a fully-blocked calendar as if it were real availability.
Rollout order:
1. **Confirm `BPN_CONNECT_API_KEY` is valid for the target environment before deploying.** If it is rejected the sync cannot populate anything and the endpoint stays at `502`.
2. Deploy; `database:migrate` creates the empty tables.
3. Run `bin/console app:bpn:sync-contingents` on the host, promptly and ideally off-peak — a consumer that page-caches whatever it renders from a `502` may hold that for the length of its own cache period.
4. Verify: `contingent_sync_state.synced_at` populated and `failure_count` at 0 for every hotel, then spot-check one calendar response.
Thereafter the scheduler keeps it current; a sync failing for one hotel puts only that hotel into `502` and leaves the rest serving normally.
### Freshness and propagation
There is deliberately **no change-notification endpoint**. Availability changes slowly, and the measured cost of simply refetching on a TTL is low enough that a polling/revision mechanism was not worth the extra moving parts on either side.
That leaves two levers, and consumers should know both:
- **Their own cache TTL** bounds how stale a rendered calendar can be. A one-hour TTL is the current agreed budget.
- **Direct cache invalidation** is the only fast path when something must propagate sooner — a hotel closing, or bad availability that got cached. Consumers should keep this targeted rather than flushing everything; the TYPO3 site, for example, tags its cached calendar and price entries per hotel, so a single hotel can be flushed and re-warmed on its own.
On this side, staleness is bounded by the sync cadence and hard-capped by the 6-hour guard: past that, the endpoint returns `502` rather than presenting stale availability as current.
---
### Accommodation bookings (group bookings)
#### `GET /api/accommodation-bookings/{uuid}` — scope `api`
Single booking by UUID. `404 {"message":"Not found"}` if unknown.
```json
{
"uuid": "...",
"status": "...",
"type": "...",
"dateFrom": "2026-06-01",
"dateTo": "2026-06-08",
"nights": 7,
"paxCount": 40,
"minorsCount": 12,
"childrenCount": 3,
"groupName": "...",
"acceptedAt": "2026-05-01T10:00:00+00:00",
"personalData": {},
"accommodation": {},
"boardService": {},
"additionalServices": [],
"accommodationDiscount": null,
"boardServiceDiscount": null,
"additionalServicesDiscount": null,
"totalDiscountAmount": null,
"totalDiscountLabel": null,
"totalPrice": 123456,
"pricingCurrency": "EUR",
"pricingVersion": 3,
"priceBreakdown": {}
}
```
`totalPrice` and `totalDiscountAmount` are integer **minor units** (cents) — unlike the contingent endpoints. The three `*Discount` fields are whole **percentages** (1100) or `null`, not amounts. `dateFrom`/`dateTo` are `Y-m-d`; `acceptedAt` is a full ISO-8601 datetime and is `null` until accepted. `priceBreakdown` is a computed nested structure.
The first three discounts each apply to one section of the breakdown: `accommodationDiscount` to `basePrice + additionalPersonsPrice`, `boardServiceDiscount` to `boardPrice`, `additionalServicesDiscount` to `servicesPrice`. Surcharges and running costs sit in `total` but in no section, so they are never discounted.
`totalDiscountAmount` is a freely named discount on the whole price, labelled by `totalDiscountLabel`. It is a fixed sum, not a percentage, and is subtracted **after** the three section discounts have reduced `total`. It is capped at what is left of that subtotal, so `discountedTotal` is never negative and the amount shown in the breakdown may be smaller than `totalDiscountAmount` itself. The section discounts are each rounded to the nearest cent as they are applied.
`priceBreakdown` carries the resulting rows, all in minor units:
| field | meaning |
| --- | --- |
| `discounts` | list of `{label, percent, amount}` for the section discounts; entries rounding to `0` are omitted, and `label` already includes its `Rabatt ` prefix |
| `discountSubtotal` | `total` minus the section discounts — present only when `totalDiscountAmount` applies *and* at least one section discount did, otherwise `null` |
| `totalDiscountDetails` | `{label, amount}` for the total discount, or `null`; `amount` is the capped figure actually subtracted |
| `discountedTotal` | the final price, equal to the booking's `totalPrice` |
#### `POST /api/accommodation-bookings/{uuid}/accept` — scope `api`
Marks the booking as accepted (server-side side effects: status change, `acceptedAt`, notifications). No request body. Returns the same booking representation as the GET. `404` if unknown. Not idempotent in terms of side effects — call once.
---
### Contact form
#### `POST /api/contactform` — scope `api`
Creates or matches an address record in the upstream CRM.
Request body (all fields optional strings; the upstream system decides what is required):
```json
{
"lastName": "...", "firstName": "...", "gender": "...",
"street": "...", "zipCode": "...", "city": "...",
"email": "...", "phone": "..."
}
```
- `201``{"success": true, "addressId": 123, "personId": 456, "isNewRecord": true}`
- `409``{"success": false, "message": "<upstream notification>"}` (upstream rejected/conflicted)
- `400``{"success": false, "message": "<error>"}` (upstream call failed)
- `422` — malformed payload
---
### Newsletter
#### `GET /api/newsletters` — scope `api`
The configured newsletter lists as an array of `{id, name, ...}` mapping objects. Use the returned `id` values as `listIds` below.
#### `POST /api/newsletter-subscriptions` — scope `api`
Request:
```json
{
"email": "[email protected]",
"firstName": "Ada",
"lastName": "Lovelace",
"listIds": [1, 2]
}
```
- `email`: required, strict email validation.
- `firstName` / `lastName`: optional, max 255 chars.
- `listIds`: required, at least one positive integer; every id must be one of the configured lists.
Responses:
- `200` — subscription completed, `state: "subscribed"`.
- `202` — a double-opt-in confirmation mail was requested, `state: "confirmation_requested"`.
- Body in both cases:
```json
{
"success": true,
"email": "[email protected]",
"lists": [{"id": 1, "name": "...", "state": "success|pending|already_registered"}],
"state": "subscribed|pending_confirmation|confirmation_requested",
"confirmationRequested": true
}
```
- `400` — unknown or disallowed list ids: `{"success": false, "message": "...", "listIds": [...], "unknownListIds": [...]}`, or validation violations.
- `503``{"success": false, "email": "...", "listIds": [...], "message": "Newsletter subscription request could not be processed."}` when the newsletter provider is unavailable. Safe to retry.
---
### End-user endpoints (require a user-bound token)
#### `GET /api/userinfo` — scope `email` (+ optional `id`, `profile`, `roles`)
OIDC-style claims for the authenticated user. The response contains only the claims covered by the granted scopes:
- always: `email`
- scope `id`: `person_id`, `address_id`
- scope `roles`: `roles` (array; only the roles that actually grant something are exported — the implicit baseline role is stripped, and so are the `*_PENDING` markers of roles the BusPro CRM claims but nobody has approved yet, see `docs/user-roles.md`)
- scope `profile`: `profile` object:
```json
{
"first_name": "...", "last_name": "...", "title": "...", "salutation": "...",
"gender": "...", "date_of_birth": "1990-01-01", "nationality": "...",
"address": {"street": "...", "postcode": "...", "city": "...", "district": "...", "country": "..."},
"communication": {"email": "...", "mobile": "...", "phone": "...", "newsletter": true},
"hotel_codes": ["..."], "height": null, "weight": null, "shoe_size": null, "remarks": "..."
}
```
Note: `profile.communication.email` comes from the CRM address record and is **not necessarily** the login email — a single address can hold several contacts. Use the top-level `email` claim for identity.
`400 {"message": "...", "code": "..."}` when the upstream lookup fails or rejects the credentials.
#### `GET /api/crm-attributes` — scope `profile`
CRM selection attributes/segments for the authenticated user. `400 {"message": "...", "code": "..."}` on upstream failure.
---
## Client implementation notes
1. **Token lifetime is 10 minutes** — implement refresh/re-fetch with a safety margin and retry once on 401.
2. **Check for an `error` key even on 200 responses** for `/api/products` and the travel availability endpoint.
3. **Money units are inconsistent across endpoints**: contingent endpoints return decimal major units; accommodation-booking fields return integer cents. Normalize at the client boundary.
4. **Dates**: `Y-m-d` everywhere except `acceptedAt` (ISO-8601 datetime) and pickup planning (`Y-m-d H:i`). Contingent `dateFrom`/`dateTo` are inclusive night boundaries.
5. **Server-side caching** (1 h on products) means upstream changes may not be visible immediately. The contingent calendar is snapshot-backed instead: it is at most one sync interval behind upstream. There is no change-notification endpoint — clients are expected to cache on their own TTL and, when something must propagate sooner, invalidate their cache directly.
6. **Route ambiguity**: `/api/travels/{a}/{b}` resolves to the id-based route when both segments are numeric, otherwise to the code-based route. Non-numeric codes are safe; purely numeric *codes* will hit the id route.
+898
View File
@@ -0,0 +1,898 @@
# bpn-connect Query Reference
> **Scope: endpoint design and the XML→SQL migration plan for the `bpn-connect` Go proxy.**
> For schema semantics, conventions and confidence marks see
> [`docs/buspro-database-reference.md`](buspro-database-reference.md), which is authoritative
> and wins on any conflict. The table descriptions below are kept for endpoint context.
This document summarizes the BusProNet schema exports in
`docs/buspronet-schema` for future `bpn-connect` endpoint/query development.
Generated from:
- `docs/buspronet-schema/BusPronet_20260601-1517.csv`: table columns
- `docs/buspronet-schema/BusPronet_20260601-1518.csv`: foreign keys
Current limitation: the visible exports do not include primary-key or index
catalog data, even though those were expected. Identity flags are not a reliable
primary-key substitute in this database because many `ID...` columns are not
marked as identity. Add PK/index exports before finalizing performance-sensitive
queries.
## Naming Conventions
- Primary identifiers usually follow `ID<TableName>`, for example
`Buchung.IDBuchung`, `Adresse.IDAdresse`, `AdressePerson.IDAdressePerson`.
- Foreign key columns usually include `_FS`, for example
`BuchungTN.IDBuchung_FS`.
- Address data is split into:
- `Adresse`: address/customer account root.
- `AdressePerson`: person attached to an address.
- `AdresseAnschrift`: postal address.
- `AdresseKommunikation`: communication values such as email/phone.
- Booking data is split into:
- `Buchung`: booking header.
- `BuchungTN`: booking participants.
- `BuchungTNFerienziel`, `BuchungTNLeistung`: participant travel/service rows.
- Public booking number appears to be `Buchung.Vorgang`.
- Internal booking id is `Buchung.IDBuchung`.
- Many tables have `Status` fields. Based on observed data, `Status = 'L'`
appears to be a soft-delete marker and should be excluded from portal lookup
queries. Other status values still need table-specific business validation.
## Core Tables
### `Buchung`
Booking header. Important columns:
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDBuchung` | `bigint` | no | Internal booking id. |
| `Vorgang` | `nvarchar(100)` | no | Public booking number/reference. |
| `IDReise_FS` | `bigint` | yes | Links to `Reise.IDReise`; no FK was present in the export. |
| `IDAdresse_FS_Anmelder` | `bigint` | yes | Applicant address id; no FK was present in the export. |
| `IDAdresseAnschrift_FS_Anmelder` | `bigint` | yes | Applicant postal address id; no FK was present in the export. |
| `IdAdressePerson_FS_Anmelder` | `bigint` | yes | Applicant person id; FK exists. |
| `IDAdresse_FS_Agentur` | `bigint` | no | Agency address; FK exists. |
| `IDAdresse_FS_Mandant` | `bigint` | no | Tenant/client address; FK exists. |
| `LoginWert1` | `nvarchar(100)` | no | Possible login-related value; semantics unknown. |
| `LoginWert2` | `nvarchar(100)` | no | Possible login-related value; semantics unknown. |
| `LoginWert3` | `nvarchar(100)` | no | Possible login-related value; semantics unknown. |
Known exported foreign keys:
- `Buchung.IdAdressePerson_FS_Anmelder -> AdressePerson.IDAdressePerson`
- `Buchung.IDAdresse_FS_Agentur -> Adresse.IDAdresse`
- `Buchung.IDAdresse_FS_ErsterSachb -> Adresse.IDAdresse`
- `Buchung.IDAdresse_FS_LetzterSachb -> Adresse.IDAdresse`
- `Buchung.IDAdresse_FS_Mandant -> Adresse.IDAdresse`
Notable missing FKs in the export:
- `Buchung.IDAdresse_FS_Anmelder`
- `Buchung.IDAdresseAnschrift_FS_Anmelder`
- `Buchung.IDReise_FS`
Treat those as likely relationships but verify against real data.
### `BuchungTN`
Booking participant.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDBuchungTN` | `bigint` | no | Participant row id. |
| `IDBuchung_FS` | `bigint` | no | Booking header id. |
| `IDAdressePerson_FS` | `bigint` | no | Participant person id. |
| `IDAdresseAnschrift_FS` | `bigint` | yes | Participant postal address id. |
| `Status` | `nvarchar(2)` | no | Participant status; values need business validation. |
| `BuchungsDatum` | `datetime` | no | Booking date. |
| `StornoStatusKV` | `nvarchar(2)` | yes | Cancellation-related status. |
| `StornoDatum` | `datetime` | yes | Cancellation date. |
| `Position` | `smallint` | no | Participant position within booking. |
Known exported foreign keys:
- `BuchungTN.IDBuchung_FS -> Buchung.IDBuchung`
- `BuchungTN.IDAdressePerson_FS -> AdressePerson.IDAdressePerson`
### `Adresse`
Customer/address root.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDAdresse` | `bigint` | no | Address/customer id needed by the local user record. |
| `SuchName` | `nvarchar(402)` | no | Search/display name. |
| `Status` | `nvarchar(2)` | no | Address status; active values need validation. |
| `Art` | `tinyint` | no | Address type; values need validation. |
| `IDAdresseAnschrift_FS_Versandanschrift` | `bigint` | no | Default shipping/postal address. |
| `IDAdressePerson_FS_ReferenzM` | `bigint` | no | Reference person. |
| `DatumLöschungDSGVO` | `datetime` | yes | GDPR deletion marker. Exclude rows where this is not null for portal access. |
### `AdressePerson`
Person attached to an address.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDAdressePerson` | `bigint` | no | Person id needed by the local user record. |
| `IDAdresse_FS` | `bigint` | no | Parent address id. |
| `Name` | `nvarchar(200)` | no | Last name. |
| `Vorname` | `nvarchar(200)` | yes | First name. |
| `Geschlecht` | `nvarchar(2)` | no | Gender/salutation code. |
| `Status` | `nvarchar(2)` | no | Person status; active values need validation. |
| `Passwort` | `nvarchar(200)` | no | Legacy BusProNet password field. Do not use from `bpn-connect`; password migration remains on the BusProNet XML API until the algorithm is known. |
| `Registrierung` | `bit` | no | Registration flag; semantics need validation. |
| `IDFremd` | `nvarchar(100)` | no | External id field. |
Known exported foreign key:
- `AdressePerson.IDAdresse_FS -> Adresse.IDAdresse`
### `AdresseKommunikation`
Communication values for an address/person.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDAdresseKommunikation` | `bigint` | no | Communication row id. |
| `IDAdresse_FS` | `bigint` | no | Address id. |
| `IDAdressePerson_FS` | `bigint` | no | Person id. No FK was present in the export, but the name strongly implies `AdressePerson.IDAdressePerson`. |
| `Wert` | `nvarchar(512)` | no | Communication value, likely email/phone depending on type. |
| `WertTelefonie` | `nvarchar(100)` | yes | Phone-specific normalized value. |
| `IDArtKommunikation_FS` | `bigint` | no | Communication type. |
| `Status` | `nvarchar(2)` | no | Communication status; active values need validation. |
| `Newsletter` | `bit` | no | Newsletter flag. |
| `DoubleOptIn` | `bit` | no | Double opt-in flag. |
Known exported foreign keys:
- `AdresseKommunikation.IDAdresse_FS -> Adresse.IDAdresse`
- `AdresseKommunikation.IDArtKommunikation_FS -> ArtKommunikation.IDArtKommunikation`
Important missing FK:
- `AdresseKommunikation.IDAdressePerson_FS` is not exported as a FK. Join it to
`AdressePerson.IDAdressePerson` only after validating with real data.
### `ArtKommunikation`
Communication type lookup.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDArtKommunikation` | `bigint` | no | Type id. |
| `Langtext` | `nvarchar(200)` | yes | Long label. |
| `Kurztext` | `nvarchar(40)` | yes | Short label. |
| `Code` | `nvarchar(20)` | yes | Type code. Find the email code/id here. |
| `Status` | `nvarchar(2)` | yes | Type status. |
Before relying on email lookup queries, run:
```sql
SELECT IDArtKommunikation, Langtext, Kurztext, Code, Status
FROM dbo.ArtKommunikation
ORDER BY IDArtKommunikation;
```
Then hard-code or configure the email type ids/codes in `bpn-connect`.
### `AdresseAnschrift`
Postal address.
| Column | Type | Nullable | Notes |
| --- | --- | --- | --- |
| `IDAdresseAnschrift` | `bigint` | no | Postal address id. |
| `IDAdresse_FS` | `bigint` | no | Address id. |
| `IDAdressePerson_FS` | `bigint` | yes | Person id. |
| `Anrede` | `nvarchar(100)` | yes | Salutation. |
| `Name` | `nvarchar(400)` | yes | Postal name. |
| `Strasse` | `nvarchar(200)` | no | Street. |
| `PLZ` | `nvarchar(20)` | no | Postal code. |
| `Ort` | `nvarchar(200)` | no | City. |
| `Status` | `nvarchar(2)` | no | Postal address status. |
No direct FK from `AdresseAnschrift` to `Adresse` or `AdressePerson` was present
in the export subset shown by the current FK file. Treat these as likely
relationships and validate them with data.
### `Reise` and `Produkt`
Travel/product metadata.
`Reise` important columns:
- `IDReise`
- `IDProdukt_FS`
- `Bezeichnung`
- `Code`
- `TerminVon`
- `TerminBis`
- `Status`
- `StornoDatum`
`Produkt` important columns:
- `IDProdukt`
- `Bezeichnung`
- `Code`
- `Suchfeld`
- `Status`
Known exported foreign key:
- `Reise.IDProdukt_FS -> Produkt.IDProdukt`
## Relationship Map
Most relevant joins for portal access:
```text
Buchung.IDBuchung
-> BuchungTN.IDBuchung_FS
-> BuchungTN.IDAdressePerson_FS
-> AdressePerson.IDAdressePerson
-> AdressePerson.IDAdresse_FS
-> Adresse.IDAdresse
```
Applicant joins:
```text
Buchung.IdAdressePerson_FS_Anmelder
-> AdressePerson.IDAdressePerson
-> AdressePerson.IDAdresse_FS
-> Adresse.IDAdresse
```
Email joins to validate:
```text
AdresseKommunikation.IDAdressePerson_FS
-> AdressePerson.IDAdressePerson
AdresseKommunikation.IDAdresse_FS
-> Adresse.IDAdresse
AdresseKommunikation.IDArtKommunikation_FS
-> ArtKommunikation.IDArtKommunikation
```
## Required bpn-connect Endpoints
All endpoints are private and authenticated by API key:
```http
X-API-Key: {apiKey}
Accept: application/json
```
Keep responses narrow. `bpn-connect` should return only fields needed by the
Symfony portal and should never return BusProNet passwords, bank data, credit
card data, or broad customer records by default.
Authentication rule: Symfony owns portal passwords after a user has been
bootstrapped locally. The BusProNet legacy password algorithm is currently
unknown, so `bpn-connect` must not verify passwords from the database. Keep the
existing BusProNet XML password check only for first-time legacy migration. Once
the local Symfony password hash exists, all subsequent login/profile refresh
logic should use local authentication plus `bpn-connect` read endpoints.
### `GET /api/bookings/applicant-lookup`
Purpose: resolve an applicant by email and public booking number. This is the
core endpoint for local user creation after a booking and for the portal access
request flow.
Request:
```http
GET /api/bookings/applicant-lookup?email={email}&bookingNumber={vorgang}
```
Response `200`:
```json
{
"bookingNumber": "111386",
"bookingId": 123456,
"addressId": 98765,
"personId": 54321,
"email": "[email protected]",
"firstName": "Example",
"lastName": "Customer"
}
```
Response rules:
- Return `200` when `email` belongs to `Buchung.IdAdressePerson_FS_Anmelder`
for the given `Buchung.Vorgang`.
- Return `404` when there is no matching non-deleted applicant.
- Return `409` if the query returns more than one applicant row after
deduplication. This should be rare and indicates inconsistent BusProNet data.
- Normalize input email by trimming and lowercasing before querying.
SQL:
```sql
DECLARE @Email nvarchar(512) = LOWER(LTRIM(RTRIM(@email)));
DECLARE @Vorgang nvarchar(100) = LTRIM(RTRIM(@bookingNumber));
SELECT TOP (2)
b.Vorgang AS bookingNumber,
b.IDBuchung AS bookingId,
a.IDAdresse AS addressId,
ap.IDAdressePerson AS personId,
@Email AS email,
ap.Vorname AS firstName,
ap.Name AS lastName
FROM dbo.Buchung b
INNER JOIN dbo.AdressePerson ap
ON ap.IDAdressePerson = b.IdAdressePerson_FS_Anmelder
INNER JOIN dbo.Adresse a
ON a.IDAdresse = ap.IDAdresse_FS
WHERE b.Vorgang = @Vorgang
AND a.DatumLöschungDSGVO IS NULL
AND a.Status <> 'L'
AND ap.Status <> 'L'
AND EXISTS (
SELECT 1
FROM dbo.AdresseKommunikation ak
WHERE ak.IDAdresse_FS = ap.IDAdresse_FS
AND ak.IDAdressePerson_FS = ap.IDAdressePerson
AND LOWER(LTRIM(RTRIM(ak.Wert))) = @Email
AND ak.Status <> 'L'
-- TODO: restrict to validated email communication type.
-- AND ak.IDArtKommunikation_FS IN (...)
)
ORDER BY ap.IDAdressePerson;
```
### `GET /api/customers/{addressId}/persons/{personId}`
Purpose: fetch the personal data for a known BusProNet person. Use this after a
local user exists and already stores `addressId` and `personId`. Do not use email
as the identifier because multiple `Adresse` rows can share an email address.
Request:
```http
GET /api/customers/{addressId}/persons/{personId}
```
Response `200`:
```json
{
"addressId": 98765,
"personId": 54321,
"firstName": "Example",
"lastName": "Customer",
"email": "[email protected]",
"genderCode": "F",
"title": null,
"birthDate": "1980-01-01T00:00:00Z",
"nationality": "deutsch",
"nationalityCountryName": "Deutschland",
"street": "Example Street 1",
"postalCode": "12345",
"city": "Example City",
"addressCountryName": "Deutschland"
}
```
Response rules:
- Return `200` for a non-deleted address/person pair.
- Return `404` if the address/person pair does not exist or has `Status = 'L'`.
- Return only portal-editable or portal-visible fields.
SQL:
```sql
DECLARE @AddressId bigint = @addressId;
DECLARE @PersonId bigint = @personId;
SELECT
a.IDAdresse AS addressId,
ap.IDAdressePerson AS personId,
ap.Name AS lastName,
ap.Vorname AS firstName,
ap.Geschlecht AS genderCode,
ap.Titel AS title,
ap.Geburtsdatum AS birthDate,
ap.Briefanrede AS letterSalutation,
ap.Anrede AS salutation,
ap.Newsletter AS newsletter,
email.Wert AS email,
manifest.IDArtNationalitaet_FS AS nationalityId,
person_nat.Langtext AS nationalityCountryName,
person_nat.Kurztext AS nationality,
person_nat.Code AS nationalityCode,
aa.IDAdresseAnschrift AS postalAddressId,
aa.Anrede AS postalSalutation,
aa.Name AS postalName,
aa.Strasse AS street,
aa.PLZ AS postalCode,
aa.Ort AS city,
aa.Ortsteil AS district,
aa.IDArtNationalitaet_FS_Land AS addressCountryId,
address_country.Langtext AS addressCountryName,
address_country.Kurztext AS addressCountryNationality,
address_country.Code AS addressCountryCode,
ad.TelefonOK AS phoneAllowed,
ad.MailOK AS mailAllowed,
ad.PostOK AS postAllowed
FROM dbo.AdressePerson ap
INNER JOIN dbo.Adresse a
ON a.IDAdresse = ap.IDAdresse_FS
OUTER APPLY (
SELECT TOP (1)
ak.Wert
FROM dbo.AdresseKommunikation ak
WHERE ak.IDAdresse_FS = ap.IDAdresse_FS
AND ak.IDAdressePerson_FS = ap.IDAdressePerson
AND ak.Status <> 'L'
-- TODO: restrict to validated email communication type.
-- AND ak.IDArtKommunikation_FS IN (...)
ORDER BY ak.IDAdresseKommunikation DESC
) email
LEFT JOIN dbo.AdresseAnschrift aa
ON aa.IDAdresseAnschrift = ap.IDAdresseAnschrift_FS_Versandanschrift
AND aa.Status <> 'L'
LEFT JOIN dbo.ArtNationalitaet address_country
ON address_country.IDArtNationalitaet = aa.IDArtNationalitaet_FS_Land
AND COALESCE(address_country.Status, '') <> 'L'
OUTER APPLY (
SELECT TOP (1)
m.IDArtNationalitaet_FS
FROM dbo.AdressePersonManifest m
WHERE m.IDAdressePerson_FS = ap.IDAdressePerson
AND m.IDAdresse_FS = ap.IDAdresse_FS
AND COALESCE(m.Status, '') <> 'L'
ORDER BY m.IDAdressePersonManifest DESC
) manifest
LEFT JOIN dbo.ArtNationalitaet person_nat
ON person_nat.IDArtNationalitaet = manifest.IDArtNationalitaet_FS
AND COALESCE(person_nat.Status, '') <> 'L'
LEFT JOIN dbo.AdresseDatenschutz ad
ON ad.IdAdresse_FS = a.IDAdresse
WHERE a.IDAdresse = @AddressId
AND ap.IDAdressePerson = @PersonId
AND a.DatumLöschungDSGVO IS NULL
AND a.Status <> 'L'
AND ap.Status <> 'L';
```
### Optional Debug Endpoint: `GET /api/customers/by-email`
Purpose: manual investigation only. Email is not unique across `Adresse`, so this
endpoint should return a list and should not be used as a local user identifier.
Request:
```http
GET /api/customers/by-email?email={email}
```
Use the same joins as `GET /api/customers/{addressId}/persons/{personId}`, but
start from `AdresseKommunikation` and return all non-deleted matching persons.
Do not use this for account creation unless the user also provides a booking
number or another disambiguating key.
## Symfony Login And Bootstrap Replacement Plan
Current Symfony login behavior:
- Existing local users authenticate against the local Symfony password hash.
- Existing legacy local users may still have an encrypted legacy password in the
local `User.password` column. Symfony validates it locally once, then replaces
it with a Symfony password hash.
- If no local user exists, `BpnAuthenticator::bootstrapUser()` currently calls
the BusProNet XML API with email and password:
- `getPersonalDataWithPassword(email, password)`
- `getCrmAttributesWithPassword(email, password)`
- After any successful local login, `BpnAuthenticator::refreshBpnSnapshot()`
calls the BusProNet XML API by local `addressId` and `personId`:
- `getPersonalData(email, addressId, personId)`
- `getCrmAttributes(email, addressId, personId)`
Replacement rule:
- Keep login password validation local to Symfony.
- Keep the current XML password-based bootstrap for users that exist in
BusProNet but do not yet have a local Symfony user.
- On successful XML legacy verification, Symfony creates a local user with a
Symfony password hash from the submitted password.
- Future logins use only the local hash and must not call XML for password
verification.
- Replace post-login snapshot refresh with `bpn-connect` id-based read endpoints.
### Login Endpoint Usage
No `bpn-connect` endpoint is needed to authenticate a password.
Existing local user login should do:
1. Find local `User` by normalized email.
2. Validate local Symfony password hash.
3. If the local row still has a legacy encrypted local password, migrate it to a
Symfony hash without contacting BusProNet.
4. Call `GET /api/customers/{addressId}/persons/{personId}` to refresh profile
completeness.
5. Call `GET /api/customers/{addressId}/crm-attributes` to refresh roles and
hotel codes.
Missing local user login should do:
1. Call the existing BusProNet XML password-based bootstrap.
2. If valid, create a local `User` with a Symfony hash of the submitted password.
3. Store returned `addressId`, `personId`, `roles`, `hotelCodes`, and
`profileComplete`.
4. Persist and continue login.
5. If invalid, fail with the generic invalid-login message.
Do not add a `bpn-connect` password verification endpoint until the BusProNet
password algorithm is known and validated against real examples. The observed
database values do not currently match simple MD5/SHA/Base64 derivations.
### `GET /api/customers/{addressId}/crm-attributes`
Purpose: replace XML `SelektionCRM` reads used during login refresh and by the
OAuth CRM attributes endpoint.
Request:
```http
GET /api/customers/{addressId}/crm-attributes
```
Minimal response:
```json
{
"roles": ["ROLE_CUSTOMER"],
"hotelCodes": []
}
```
Detailed response may also include selection groups and CRM actions if the
current `/api/crm-attributes` response must remain compatible.
Known role mapping from the XML parser:
- `Selektionsstamm.IDSelektionsstamm = 1292` selected: `ROLE_ADMIN` and
`ROLE_HOUSE_MANAGER`
- `Selektionsstamm.IDSelektionsstamm = 1293` selected: `ROLE_MANAGER`
- `Selektionsstamm.IDSelektionsstamm = 1070` selected: `ROLE_TEAMER`
- selected `Selektionsstamm.Selektion` matching `Hausleitung {CODE}`:
`ROLE_HOUSE_MANAGER` and hotel code `{CODE}`
- admin users also receive default hotel code `SSL`
- no matched role means `ROLE_CUSTOMER`
Candidate SQL for selected customer selections:
```sql
DECLARE @AddressId bigint = @addressId;
SELECT
sg.IDSelektionsgruppenstamm AS groupId,
sg.Selektionsgruppe AS groupLabel,
s.IDSelektionsstamm AS selectionId,
s.Selektion AS selectionLabel,
CAST(1 AS bit) AS selected
FROM dbo.Selektionen sel
INNER JOIN dbo.Selektionsstamm s
ON s.IDSelektionsstamm = sel.IDSelektionsstamm_FS
LEFT JOIN dbo.Selektionsgruppe sg_map
ON sg_map.IDSelektionsstamm_FS = s.IDSelektionsstamm
LEFT JOIN dbo.Selektionsgruppenstamm sg
ON sg.IDSelektionsgruppenstamm = sg_map.IDSelektionsgruppenstamm_FS
WHERE sel.IDAdresse_FS = @AddressId
AND COALESCE(s.Status, '') <> 'L'
AND COALESCE(sg.Status, '') <> 'L'
ORDER BY sg.Position, sg.Selektionsgruppe, sg_map.Position, s.Selektion;
```
The Go service can derive `roles` and `hotelCodes` from this result with the
mapping above. Before shipping, verify whether XML `SelektionCRM` includes
unselected mutable options; if the portal only needs roles/hotel codes, selected
rows are enough.
Candidate SQL for CRM actions if compatibility is required:
```sql
DECLARE @AddressId bigint = @addressId;
SELECT
ca.IDCRMAktion AS id,
ca.Code AS code,
ca.Bezeichnung AS label,
ca.Aktiv AS selected
FROM dbo.CRMZuweisung cz
INNER JOIN dbo.CRMAktion ca
ON ca.IDCRMAktion = cz.IDCRMAktion_FS
WHERE cz.IDAdresse_FS = @AddressId
AND ca.Status <> 'L'
ORDER BY ca.Bezeichnung;
```
This needs data validation against the XML response before compatibility is
guaranteed.
## XML Calls To Replace For Local User Processes
| Current Symfony call | Current XML purpose | Replacement |
| --- | --- | --- |
| `getPersonalData(email, addressId, personId)` | Load profile by known user ids. | `GET /api/customers/{addressId}/persons/{personId}` |
| `updatePersonalData(email, personalData)` | Persist profile edits. | Future `PATCH /api/customers/{addressId}/persons/{personId}` with transaction-safe updates. |
| `getCrmAttributes(email, addressId, personId)` | Refresh roles/hotel codes and expose CRM attributes. | `GET /api/customers/{addressId}/crm-attributes` |
| `getPersonalDataWithPassword(email, password)` | Missing-local-user bootstrap by BPN password. | Keep XML until the local user has been created/migrated. |
| `getCrmAttributesWithPassword(email, password)` | Roles for missing-local-user bootstrap by BPN password. | Keep XML until the local user has been created/migrated. |
| `register(registrationData)` | Create BusProNet address/person and local user. | Future `POST /api/customers` if direct DB writes are allowed; otherwise keep XML until write rules are known. |
| `createAddress(personalData)` | Create BusProNet address/person without mail. | Future `POST /api/customers` if direct DB writes are allowed; otherwise keep XML until write rules are known. |
Recommended migration sequence:
1. Keep XML for legacy password bootstrap only.
2. Replace booking applicant lookup for guest provisioning and portal access.
3. Replace post-login profile/CRM refresh reads.
4. Replace personal-data page reads.
5. Replace OAuth/userinfo and CRM API reads.
6. Replace booking form prefill reads.
7. Defer personal-data writes until update rules are validated.
8. Defer registration/create-address until the insert graph is known.
### Phase 1: Keep XML For Legacy Password Bootstrap
Keep these XML calls temporarily:
- `getPersonalDataWithPassword(email, password)`
- `getCrmAttributesWithPassword(email, password)`
Scope:
- Only used when no local Symfony user exists yet.
- On success, create the local user with a Symfony password hash from the
submitted password.
- Store `addressId`, `personId`, `roles`, `hotelCodes`, and `profileComplete`.
- Future logins for that user use only the local Symfony password hash.
Do not implement a `bpn-connect` password verification endpoint until the
BusProNet password algorithm is known and verified.
### Phase 2: Booking Applicant Lookup
Replace XML/fragile booking lookup plumbing with:
```http
GET /api/bookings/applicant-lookup?email={email}&bookingNumber={vorgang}
```
Symfony integration points:
- `BookingGuestAccountManager::provisionGuestAccountForBooking()`
- `BookingGuestAccountManager::requestPortalAccess()`
- booking-created welcome account provisioning
This endpoint returns only the fields needed for local user creation:
- `bookingNumber`
- `bookingId`
- `addressId`
- `personId`
- `email`
- `firstName`
- `lastName`
### Phase 3: Post-login Snapshot Refresh
Replace XML reads in `BpnAuthenticator::refreshBpnSnapshot()` with:
```http
GET /api/customers/{addressId}/persons/{personId}
GET /api/customers/{addressId}/crm-attributes
```
Symfony keeps local password validation. `bpn-connect` only refreshes ids,
profile completeness, roles, and hotel codes after the password has already been
validated locally.
### Phase 4: Personal-data Page Reads
Replace XML read in `PersonalDataController::loadPersonalData()` with:
```http
GET /api/customers/{addressId}/persons/{personId}
```
Keep `updatePersonalData()` on XML for now. Reads are low-risk; writes require
validated BusProNet update semantics.
### Phase 5: OAuth/Userinfo And CRM Reads
Replace XML reads in:
- `UserinfoController`
- `CrmAttributeController`
with:
```http
GET /api/customers/{addressId}/persons/{personId}
GET /api/customers/{addressId}/crm-attributes
```
### Phase 6: Booking Form Prefill Reads
Replace XML read in `ParticipantDataPrefiller::prefillApplicantFromUser()` with:
```http
GET /api/customers/{addressId}/persons/{personId}
```
### Phase 7: Defer Personal-data Writes
Keep XML call:
- `updatePersonalData(email, personalData)`
Future replacement:
```http
PATCH /api/customers/{addressId}/persons/{personId}
```
Do this only after write rules are validated for:
- `AdressePerson`
- `AdresseAnschrift`
- `AdresseKommunikation`
- `AdressePersonManifest`
- `AdresseZusatzfeld` or other tables holding height, weight, shoe size, and
remarks if those are not in the core person/address tables.
### Phase 8: Defer Registration And Create-address
Keep XML calls:
- `register(registrationData)`
- `createAddress(personalData)`
Future replacement:
```http
POST /api/customers
```
This is higher risk than read replacement because it requires the full BusProNet
insert graph, required defaults, and side effects.
## Candidate SQL: Find Email Communication Type
Run once during `bpn-connect` development:
```sql
SELECT
IDArtKommunikation,
Langtext,
Kurztext,
Code,
Status
FROM dbo.ArtKommunikation
WHERE
LOWER(COALESCE(Langtext, '')) LIKE '%mail%'
OR LOWER(COALESCE(Kurztext, '')) LIKE '%mail%'
OR LOWER(COALESCE(Code, '')) LIKE '%mail%'
ORDER BY IDArtKommunikation;
```
If the data uses German labels, also inspect all rows manually. The schema alone
cannot prove the canonical email type.
## Candidate SQL: Validate Missing Relationships
Use these checks before shipping lookup logic:
```sql
-- Check whether AdresseKommunikation.IDAdressePerson_FS is a real person link.
SELECT TOP (20)
ak.IDAdresseKommunikation,
ak.IDAdresse_FS,
ak.IDAdressePerson_FS,
ap.IDAdressePerson,
ap.IDAdresse_FS AS PersonAddressId,
ak.Wert
FROM dbo.AdresseKommunikation ak
LEFT JOIN dbo.AdressePerson ap
ON ap.IDAdressePerson = ak.IDAdressePerson_FS
WHERE ak.IDAdressePerson_FS <> 0
AND ap.IDAdressePerson IS NULL;
```
```sql
-- Check whether Buchung.IDAdresse_FS_Anmelder matches the applicant person's address.
SELECT TOP (100)
b.IDBuchung,
b.Vorgang,
b.IDAdresse_FS_Anmelder,
b.IdAdressePerson_FS_Anmelder,
ap.IDAdresse_FS AS ApplicantPersonAddressId
FROM dbo.Buchung b
LEFT JOIN dbo.AdressePerson ap
ON ap.IDAdressePerson = b.IdAdressePerson_FS_Anmelder
WHERE b.IDAdresse_FS_Anmelder IS NOT NULL
AND ap.IDAdresse_FS <> b.IDAdresse_FS_Anmelder;
```
```sql
-- Inspect status values before adding active-only predicates.
SELECT 'Adresse' AS table_name, Status, COUNT(*) AS rows
FROM dbo.Adresse
GROUP BY Status
UNION ALL
SELECT 'AdressePerson', Status, COUNT(*)
FROM dbo.AdressePerson
GROUP BY Status
UNION ALL
SELECT 'AdresseKommunikation', Status, COUNT(*)
FROM dbo.AdresseKommunikation
GROUP BY Status
UNION ALL
SELECT 'BuchungTN', Status, COUNT(*)
FROM dbo.BuchungTN
GROUP BY Status
ORDER BY table_name, Status;
```
## Indexes To Confirm Or Add
The current CSV files do not include index definitions. For the lookup endpoint,
confirm whether these access paths already exist:
- `Buchung(Vorgang)` including `IDBuchung`, `IdAdressePerson_FS_Anmelder`
- `BuchungTN(IDBuchung_FS)` including `IDAdressePerson_FS`, `Status`
- `AdressePerson(IDAdressePerson)` including `IDAdresse_FS`, `Vorname`, `Name`,
`Status`
- `AdresseKommunikation(IDAdressePerson_FS, Wert)` including `IDAdresse_FS`,
`IDArtKommunikation_FS`, `Status`
- `AdresseKommunikation(IDAdresse_FS, Wert)` including `IDAdressePerson_FS`,
`IDArtKommunikation_FS`, `Status`
If the database collation is case-sensitive and email lookup must be
case-insensitive, avoid `LOWER(Wert)` on large tables unless a computed
normalized-email column or suitable index exists.
## Future Endpoint Candidates
The XML plumbing can be replaced incrementally by small read endpoints backed by
targeted SQL:
| Endpoint | Purpose | Core tables |
| --- | --- | --- |
| `GET /api/bookings/lookup` | Resolve email + public booking number to booking/person/address ids. | `Buchung`, `BuchungTN`, `AdressePerson`, `AdresseKommunikation`, `Adresse` |
| `GET /api/bookings/{bookingId}` | Fetch booking header/detail by internal id. | `Buchung`, `Reise`, `Produkt`, `BuchungTN` |
| `GET /api/bookings/{bookingId}/participants` | Fetch participants for a booking. | `BuchungTN`, `AdressePerson`, `AdresseAnschrift` |
| `GET /api/customers/{addressId}/persons/{personId}` | Fetch a minimal customer/person profile. | `Adresse`, `AdressePerson`, `AdresseKommunikation`, `AdresseAnschrift` |
Keep endpoint responses narrow. Return only ids and fields needed by the Symfony
portal so the Go service does not become a broad BusProNet data mirror.
## Regeneration Notes
When new catalog exports are added, regenerate this document with:
1. Columns export from `sys.tables`, `sys.schemas`, `sys.columns`, `sys.types`.
2. Foreign key export from `sys.foreign_keys` and related FK columns.
3. Primary-key export from `sys.key_constraints`.
4. Index export from `sys.indexes`, `sys.index_columns`, and `sys.columns`.
Primary keys and indexes should be added to the table sections and the lookup
query should be revisited once the real access paths are known.
+382
View File
@@ -0,0 +1,382 @@
# BusProNet XML API — working reference
Condensed from the vendor PDF `docs/bpn_docs.pdf` (41 pages, German), keeping what this project
uses or plausibly could. The PDF stays authoritative; a few of its sentences are mangled by a
broken font encoding, so anything unclear there is flagged rather than guessed at.
> **The PDF lags the live API.** The vendor has shipped elements since it was written —
> `<ausstiege>` (return boarding points) is one confirmed example. So *absent from the PDF* means
> "not in this snapshot", never "unsupported". Treat the document as a floor on what the API
> accepts, not a ceiling, and prefer a live `buchungsart=Anfrage` probe over an argument from
> silence.
Read this alongside `buspro-database-reference.md` (what BusPro actually stores) — the two answer
different questions, and where they disagree the schema is the record of what happened.
**Use it for:** what an element is called and what it may contain; which codes a failure can
return; which documented capabilities we are not using; and which elements we send that the
vendor never documented — those are the ones that can break without warning.
## Envelope
Every request is `<anfrage>` with `<user>`, `<key>` and `<satz typ="…"/>`.
```
key = md5( user + password + date("YYYYMMDD") + satz-typ )
```
Per satz type and per day. `ApiClient::createKey()` implements it, and `sendRawXml()` regenerates
the key before sending, so a hand-built payload can carry a placeholder.
## Satz types
**Documented:** `ADRESSFELDER`, `ADRESSFELDERGUTSCHEIN`, `ADRESSFELDERKATALOGANFRAGE`,
`AGENTUREN`, `AGENTURKONTO`, `AKTIONSGUTSCHEIN`, `BUCHUNG`, `BUCHUNGAENDERUNG`, `CRM`,
`CRMKATALOGANFRAGE`, `GUTSCHEINBUCHUNG`, `GUTSCHEINDRUCK`, `GUTSCHEINPRUEFUNGEINLOESUNG`,
`GUTSCHEINVORLAGEN`, `GUTSCHEINVORSCHAU`, `GUTSCHEINZAHLUNGSARTEN`, `KATALOGANFRAGE`,
`KUNDENKONTO`, `KUNDENLISTE`, `MOEGLICHEAENDERUNGEN`, `PRODUKTDATEN`, `PRODUKTE`, `SITZPLATZ`,
`STAMMHOTELS`, `STAMMLAENDER`, `STAMMVERSICHERUNGEN`, `STAMMZUSTIEGE`, `VERFUEGBARKEIT`,
`VERFUEGBARKEITHOTEL`, `ZAHLUNG`, `ZAHLUNG2`, `ZAHLUNGSARTEN`, `ZAHLUNGSARTEN2`.
`SITZPLATZAUSWAHL` and `ZAHLUNG4` are named in prose without their own section.
**Used here but undocumented:** `VERFUEGBARKEIT2` (`ApiClient::TYPE_AVAILABILITY_EXTENDED`) — the
extended availability call returning `buchungstatusmoeglich` and per-service `pflicht`/`frei`.
Its contract is observed, not specified.
**Documented but unused here:** `SITZPLATZ`/`SITZPLATZAUSWAHL`, `KUNDENLISTE`, `ZAHLUNG2`,
`ADRESSFELDER`, `STAMMHOTELS`, `STAMMVERSICHERUNGEN`, `STAMMZUSTIEGE`, `KATALOGANFRAGE`.
## BUCHUNG — the create contract
`<buchungsart>` decides what the call does:
| Value | Effect |
|---|---|
| `Anfrage` | Enquiry. Validates and **returns the full price breakdown**. Nothing is stored. |
| `Buchung` | Stores the booking. |
`<status>` at the root: `F` Festbuchung · `O` Optionsbuchung · `A` Anfragebuchung. Gated by
error `962` ("Buchungsstatus #1# kann nicht verarbeitet werden, nur Status #2# möglich"), and by
`982`/`983` when the travel forbids options or enquiries outright.
### Two accommodation models
The base payload books accommodation as an ordinary service:
```xml
<unterbringungen>
<unterbringung idleistung="22341" anzahl="1" zuordnung="1,2"/>
</unterbringungen>
```
For the **Ferienziel** domain — what this app books — `unterbringungen` is *replaced* by
`ferienzielunterbringungen`, **and** a root `<idpartner>` added:
```xml
<ferienzielunterbringungen>
<ferienzielunterbringung idzimmer="2" kategorie="Ik" idverpflegung="2"
anreise="30.01.2018" abreise="06.02.2018"
anzahl="1" zuordnung="1,2"/>
</ferienzielunterbringungen>
<idpartner>78687</idpartner>
```
> `<idpartner>` is introduced as the element you add when switching to the Ferienziel model, and
> `914 Partner-ID fehlt` guards it. Note it is **not** confined to bookings that have a room: a
> teamer booking with zero `BuchungTNFerienziel` rows still returns `<idpartner>222925</idpartner>`
> from `Vorgang_Details`. Where that comes from is **unresolved** — `Buchung` has no partner FK, so
> either it is stored on `Buchung.IDAdresse_FS_ExtraFerienzielPartner`, or it is derived from the
> travel. That booking's product has exactly one hotel, so the response cannot distinguish the two;
> one read-only query settles it.
Accommodation is **mandatory**`913 Unterbringungen fehlen` / `916 Ferienziel-Unterbringungen
fehlen`. Confirmed empirically on the test system 2026-09-02, not just documented: see
"Validation gate order" below. Room dates are cross-checked against the transport legs (`921`,
`923`).
### Full documented request shape
```xml
<anfrage>
<user/><key/><satz typ="BUCHUNG"/>
<buchungsart>Anfrage|Buchung</buchungsart>
<status>F|O|A</status>
<idagentur/> <idcrm/> <idreise/> <idpartner/>
<fremdvorgang/> <!-- your own reference, stored as Buchung.FremdVorgang -->
<datenschutztfmp/> <!-- ad consent, combinable: T Telefon, F Telefax, M EMail, P Post -->
<anmelder>
name, vorname, anrede, titel, geschlecht, nationalitaet, geburtsdatum,
<anschrift>strasse, plz, ort, ortsteil, land</anschrift>
<kommunikation>telefonmobil, email, telefonprivat</kommunikation>
<bemerkung/>
</anmelder>
<teilnehmerliste>
<teilnehmer id="1">
…same personal fields…
<wünsche><unterbringungswunsch/><beförderungswunsch/></wünsche>
<aktionscode/>
</teilnehmer>
</teilnehmerliste>
<beförderungen><beförderung idleistung anzahl zuordnung/></beförderungen>
<ferienzielunterbringungen></ferienzielunterbringungen>
<zusatzleistungen><zusatzleistung idleistung anzahl zuordnung/></zusatzleistungen>
<zustiege><zustieg idzustieg anzahl zuordnung/></zustiege>
<sitzpläne><sitzplan idleistung idsitzplan sitzplätze="1B;1A"/></sitzpläne>
<versicherungen><versicherung idversicherung anzahl zuordnung/></versicherungen>
<gutscheine><gutschein gutscheinnr einloesecode/></gutscheine>
<zuschlaege>
<zuschlag text betrag anzahl zuordnung
provision altersrabatt gruppenrabatt frühbucherrabatt bzberechnung/>
</zuschlaege>
<zahlung idzahlungsart bezeichnung art>
<bankverbindung kreditinstitut bic iban kontoinhaber/>
</zahlung>
</anfrage>
```
`zuordnung` is a comma-joined list of 1-based `teilnehmer/@id` values throughout.
### Responses
`buchungsart=Anfrage``<buchung>möglich</buchung>` plus `<preise>`: one `<preis>` per line with
`position`, `art`, `unterart`, `bezeichnung`, `terminvon`/`terminbis`, `anzahl`, `zuordnung`,
`preis`, `gesamtpreis`, `id`; then `<gesamtpreis>` and `<zahlungsbedingungen>` with `<anzahlung>`
and `<restzahlung>` (each `betrag` + `termin`). `art` values seen: `BEF` transport, `UNT`
accommodation, `SON` other, `ERM` discount, `VER` insurance.
`buchungsart=Buchung``<buchung>erfolgt</buchung>`, `<vorgang>`, `<rechnung>`, `<idbuchung>`,
`<email>`, `<pdfpasswort>`.
### Validation gate order (measured)
Established with `buchungsart=Anfrage` against the test system on 2026-09-02, by mirroring a real
room-less teamer booking (Vorgang 110628) element for element:
1. **Accommodation.** No `ferienzielunterbringungen``916`, regardless of everything else being
valid. Nothing further is evaluated.
2. **Personal data**, once a room is present → `650` with the field list *"Fehlende
Anmelder/Teilnehmer Daten … Nachname, Vorname, Strasse, Plz, Ort, Telefon-Mobil, Mail-Adresse,
Geburtsdatum, Nationalität"*, for the Anmelder **and every participant**.
So **sending `idadresse`/`idadresseperson` alone is not enough on create** — BusPro validates the
personal fields whether or not it could resolve them from the ids. Echoing the record back
(`idadresse` + `idadresseperson` + full data) narrows the complaint to whatever that record is
genuinely missing, which is a useful way to audit an address: the placeholder account 19465:41003
fails on `Telefon-Mobil` and `Nationalität` because its `Vorgang_Details` record has only
`telefonprivat` and no `nationalitaet`.
Note `650` again: both of those are hard rejections delivered under the code
`Notification::isError()` treats as success.
## BUCHUNGAENDERUNG — the edit contract
Structurally identical to `BUCHUNG` plus `<idbuchung>`, and the responses follow `buchungsart`
the same way. Ask `MOEGLICHEAENDERUNGEN` first (`<idreise>`), which answers:
```xml
<änderungen>
<änderung art="anzahl_teilnehmer" möglich="False"/>
<änderung art="beförderung" möglich="False"/>
<änderung art="zustieg" möglich="False"/>
<änderung art="sitztplatz" möglich="False"/> <!-- vendor's typo -->
<änderung art="unterbringung" möglich="False"/>
<änderung art="zusatzleistung" möglich="True" möglichbiszum="23.02.2020"/>
<änderung art="teilnehmerdaten" möglich="False"/>
</änderungen>
```
## How this app maps onto the contract
`BookingPayloadBuilder::buildCreatePayload()` builds create; `buildBasePayload()` + the
`addTo…Payload()` helpers build edit; `ApiClient::createBooking()`/`updateBooking()` wrap them.
| Documented element | Sent on create | Sent on edit | Notes |
|---|---|---|---|
| `buchungsart` | yes | yes | Edit **hardcodes `Buchung`** (`ApiClient.php:233`) |
| `status` | yes | yes | Edit replays the value read back from BusPro — see the caveat below |
| `idreise`, `idpartner`, `idagentur` | yes | yes | `idpartner` sent unconditionally, even with no room |
| `anmelder` | yes | yes | Create builds it from participant[0]; edit uses `PersonalData::toPayload()` |
| `anmelder/bemerkung` | — | yes | Via `PersonalData::toPayload()` |
| `teilnehmerliste` | yes | yes | |
| `wünsche` (`unterbringungswunsch`, `beförderungswunsch`) | yes | yes | |
| `aktionscode` | yes | yes | Promo code, paired with `AKTIONSGUTSCHEIN` |
| `beförderungen`, `zusatzleistungen`, `zustiege` | yes | yes | Built by `ServiceMappingCollector` |
| `ferienzielunterbringungen` | yes | yes | Create omits the node entirely when no room maps; edit always emits the empty skeleton |
| `versicherungen` | yes | yes | |
| `gutscheine` | yes | yes | Paired with `GUTSCHEINPRUEFUNGEINLOESUNG` |
| `zahlung` + `bankverbindung` | yes | yes | |
| `idcrm` | no | no | |
| `fremdvorgang` | no | no | Would give our own bookings a stable external reference |
| `datenschutztfmp` | no | no | Advertising consent — we track newsletter consent locally instead |
| `sitzpläne` | no | no | See Seats |
| `zuschlaege` | no | no | Free-text manual surcharge or discount with its own amount |
### Newer than the PDF
These are absent from the document but work against the live API — vendor additions that
post-date it. Listed so nobody mistakes the PDF's silence for a contract violation, and so the
gaps in this reference are known.
| Element | Where | Note |
|---|---|---|
| `<ausstiege><ausstieg idzustieg …/></ausstiege>` | create and edit | Return boarding points. Confirmed as a recent vendor addition; the PDF documents only `<zustiege>`. |
| `<status>` inside `<teilnehmer>` | create (hardcoded `F`) and edit | Not in the PDF in either direction, though `Vorgang_Details` returns `status_teilnehmer`. |
| `<login>J</login>` on `KUNDENKONTO` | probe command | Passwordless read escape hatch; see `bpn-login-j-passwordless-reads`. |
| `VERFUEGBARKEIT2` | availability path | Whole satz type post-dates the PDF. Returns `buchungstatusmoeglich` and per-service `pflicht`. |
When one of these needs pinning down, the authoritative move is a live `Anfrage` call, not a
reading of this file.
### Caveat: the edit flow replays a derived status
`buildBasePayload()` sends `'status' => $bookingData->status`, and `Booking::$status` is parsed
from the response's root `<status>` (`BookingParser.php:38`). But `Buchung` has **no status
column** — the root value is an aggregate over `BuchungTN.Status`, the only real store
(`<status>F</status>` beside `<status_teilnehmer>F/F/…/F</status_teilnehmer>` in
`tests/Resources/booking_data.xml`). So on a booking whose participants do *not* all share one
status, the edit flow sends an aggregate back as a directive. Worth confirming against a mixed
booking before relying on it.
### Gap: edit never dry-runs
Create is two-phase — `Anfrage` to validate and price, then `Buchung`. Edit sends
`buchungsart=Buchung` directly (`ApiClient.php:233`), even though `BUCHUNGAENDERUNG` supports
`Anfrage` identically. An enquiry pass would surface `913`/`924`/`962` and return the recalculated
price *before* mutating a live booking.
## Seats
`SITZPLATZ` asks BusPro to pick seats:
```xml
<satz typ="SITZPLATZ"/>
<idreise/><idleistung_hin/><idleistung_rueck/><anzahl_personen/>
<wunsch_vornemittehinten>V|M|H</wunsch_vornemittehinten>
<wunsch_linksrechts>L|R</wunsch_linksrechts>
<wunsch_fenstergang>F|G</wunsch_fenstergang>
```
Response: one `<sitzplan>` per direction with `sitzplaetze="0D;1D;1C"`, `idsitzplan`,
`richtung="H|R"`, `bezeichnung`, `idleistung`, and `grafik` (base64 PNG of the seat map). Where
seats carry surcharges the response adds `<zuschläge>` (`id`, `bezeichnung`, `preis`, colours) and
the request must then carry `idzuschlag`. `SITZPLATZAUSWAHL` returns the raw plan structure
instead of a picture.
Chosen seats go back into a booking via `<sitzpläne>`, landing in
`BuchungTNLeistungZusatz.Sitzplatz` / `IDSitzplan_FS`. Guarded by `933 Sitzplan mit ID #1# bei
Leistung #2# nicht freigegeben` and `304 Es konnte nicht für alle Teilnehmer ein Sitzplatz
ermittelt werden`.
## KUNDENKONTO
`<art>`: `Adressdaten`, `Adressdaten_Ändern`, `Adresse_Neu`, `SelektionCRM`,
`SelektionCRM_Ändern`, `Vorgänge`, `Vorgangdruck`, `Voucherdruck`, `Dokumentdruck`,
`Passwort_Anfrage`, `Newsletter`, `Adressdokument`, `Vorgang_Details`, `Prüfung`, `PrüfungEmail`,
`Ausweisdaten_Ändern`, `Stornoanfrage`, `Storno`, `Versicherungspolice`.
`Stornoanfrage` answers `stornierung_moeglich` + `stornopreis`; `Storno` answers `storniert`
the documented way to cancel, including cleaning up a test booking. `Ausweisdaten_Ändern` takes a
`<personen>` list with `<ausweis>` data and answers `änderung`. `Versicherungspolice` returns
per-policy document URLs.
## AGENTURKONTO
`<art>`: `Vorgänge`, `Vorgangdruck`, `Rechnungdruck`, `Hotelgutscheine`, `Hotelgutscheindruck`,
`OptionInFest` — the last converts a held option into a firm booking, answering
`<optioninfestumgewandelt>true</optioninfestumgewandelt>`. `Vorgangdruck` takes `idbuchung`,
`Rechnungdruck` takes `idrechnung`, `Hotelgutscheindruck` takes `idgutschein`; print arts return
base64 PDFs.
## Availability and payment
`VERFUEGBARKEIT` takes `<idreise>` plus a `<leistungen><leistung id="…"/></leistungen>` filter and
answers `<reise id status>` plus per-service `status` ("buchbar"), `frei`, `preis`,
`preisfaellig`. `VERFUEGBARKEIT2`, which we actually use, additionally reports
`buchungstatusmoeglich` and `pflicht` but is undocumented.
`ZAHLUNGSARTEN2` lists payment methods; `ZAHLUNG2` records a payment against a booking
(`vorgang`, `idbuchung`, `datum`, `betrag`, `idzahlungsart`, `zahlungstext` — all mandatory).
`ZAHLUNG` reports a credit-card authorisation after booking; the amount must equal the confirmed
`anzahlung` or errors `1011`-`1018` follow.
## Error codes
Returned as `<satz typ="HINWEIS"><nr>…</nr><text>…</text></satz>`. `#1#`/`#2#` are substituted at
runtime.
> **`650` is not a success code.** Its documented text is a bare `#1#` — a generic message
> carrier whose entire content is substituted. `Notification::isError()`
> (`src/BusProNet/Model/Notification.php:33-36`) treats it as success, which happens to hold on
> the `KUNDENKONTO` paths but not on `BUCHUNG`/`BUCHUNGAENDERUNG`, where the same code delivers
> real rejections such as *"Es wurde nicht jedem Teilnehmer eine Pflichtleistung zugeordnet"*.
> `BookingEditSubmitter.php:81` therefore reports some genuine failures as INFO.
**Envelope / auth** — 100 Anfrageknoten fehlt · 101 Satzknoten fehlt · 102 Ungültiger Satztyp ·
103/104 User fehlt/fehlerhaft · 105/106 Key fehlt/fehlerhaft · 999 Systemfehler
**Lookup** — 200 Keine Einträge · 201/202 Partner · 203 Ungültiger Termin · 300 IDReise fehlt ·
301 Reise nicht gefunden · 302 IDLeistung (Hin & Rück) fehlt · 303 IDLeistung passt nicht zu
IDReise · 304 Kein Sitzplatz für alle Teilnehmer ermittelbar · 305 Anzahl Personen fehlt ·
306/307 Leistungen · 308 Keine Zahlungsarten · 400 IDPartner fehlt · 401 Partner nicht gefunden ·
402 Bis-Termin fehlt · 403 Keine Unterbringungsleistungen gefunden
**Customer / address** — 500 Art fehlt · 502 Keine Kunden · 840-842 Personen · 850 IDAdresse und
EMail fehlen · 851 Passwort fehlt · 852 Art fehlt · 853 ID, EMail oder Passwort falsch · 855 Keine
Daten für Adresse · 860 Adressdaten fehlen · 862-867 Selektionsmerkmale / CRM-Aktionen ·
870-875 Newsletter · 880-882 Dokumente · 885-891 Pflichtfelder (Name, Vorname, Geschlecht, EMail,
PLZ, Straße) · 889 Kunde bereits angelegt (ID #1#)
**Booking (create and edit)** — 900 Buchungsart fehlt · 901 Buchungsart falsch · 902 Status
fehlt · 903 Status falsch · 904/905 Agentur · 906 Reise-ID fehlt · 907 Reise nicht gefunden ·
908 Reise ist storniert · **909 Beförderungen fehlen** · 910 Leistung gehört nicht zur Reise ·
911 Leistung gehört nicht zum Produkt · 912 Beförderungsleistung fehlt · **913 Unterbringungen
fehlen** · **914 Partner-ID fehlt** · 915 Partner nicht gefunden · **916 Ferienziel-Unterbringungen
fehlen** · 917 Zimmer-IDZ fehlt · 918 Kategorie fehlt · 919 Verpflegungs-ID fehlt · 920 Anreise
fehlt · **921 Anreise passt nicht zur Beförderungsleistung (Hinfahrt)** · 922 Abreise fehlt ·
**923 Abreise passt nicht zur Beförderungsleistung (Rückfahrt)** · **924 Ferienziel: Keine Preise
zu den Daten gefunden** · 925 Preis zu den Daten nicht gefunden · 930 Zustiege fehlen ·
931 Zustieg nicht gefunden · 932 Zustieg bei Leistung nicht freigegeben · 933 Sitzplan bei
Leistung nicht freigegeben · 935-938 Versicherungen · 940-942 Zahlungsart · 950 Anmelder fehlt ·
951 Teilnehmerliste fehlt · 952 Teilnehmer-ID fehlt · 953 Keine Teilnehmer übergeben ·
960 Preisfehler · 961 Buchung konnte nicht gespeichert werden · **962 Buchungsstatus #1# kann
nicht verarbeitet werden, nur Status #2# möglich** · 970 CRM-Merkmal nicht gültig · 980 Reise ist
fürs Internet gesperrt · 981 Reise ist nicht mehr buchbar (#1#) · **982 Optionsbuchungen nicht
zugelassen** · 983 Anfragebuchung nicht zugelassen · 984 Leistung nicht fürs Internet buchbar ·
985 Zustieg nicht fürs Internet buchbar · 986/987 Rechnung · 990-994 Agenturkonto ·
995/996 Gutschein · 997/998 Buchung-ID · 1001 Reisedatum fehlerhaft · 1002 Buchungsdatum
fehlerhaft · 1003 Status im Vorgang nicht korrekt · 1011-1018 Zahlungsabgleich
**Vouchers** — 600-608 Gutscheine · 610/611 Buchungsart · 612-621 Gutscheinart / Stamm /
Kapazität · 622 Einlösecode fehlt · 630-632 Aktionsgutschein
## Applying this: the teamer placeholder booking
**Answered 2026-09-02: `BUCHUNG` cannot create it.** A payload mirroring the real teamer booking
(travel 12429, hotel 222925, agency 77876, both bus legs, ski pass, Ortstaxe, Keycard-Pfand,
pickup and drop-off, root and participant status `O`, ids-only identity, no room) returns
`916 Ferienziel-Unterbringungen fehlen`. Adding a room to the identical payload clears that gate
and moves on to `650`, which proves accommodation was the only structural objection.
Two blockers that were *not* the problem:
- **Status `O` is fine here.** Travel 12429 reports `buchungstatusmoeglich="F, O, A"`. The `982`
refusal seen earlier is per travel, not a global setting.
- **`NurFahrt` never came up** — the request never got far enough for it to matter.
What the real booking shows about how the office builds one, worth reproducing if the work moves
to a direct write:
- `<idpartner>` **is** present despite there being no accommodation — 222925 is the ordinary
hotel of the travel (`Adresse.IDAdresse`, "NEU Sportclub Weissfluh Midweeks und Wochenreisen",
the sole hotel of product 1429, with real bookable rooms), not a special no-accommodation
partner. Whether the booking stores it or the response derives it is still open.
- Each teamer seat is its **own `AdressePerson`** (407725, 407726) under the shared address 41003,
with an empty `<anschrift/>`.
- `<wünsche><beförderungswunsch>` carries the role label — "Reiseleitung + Busbegleitung".
- Per participant, `<optionsdatum>` sets the option expiry.
- The total is driven to zero with a **manual `<zuschlag>`**: Ortstaxe 44,00 + Keycard-Pfand 10,80
+ Abfahrtsortzuschlag 25,80 = 80,60, offset by an unnamed 80,60 line. `<zuschlaege>` is part of
the documented `BUCHUNG` payload, so this part *is* expressible over XML.
See `.ddev/plans/teamer-placeholder-booking-plan.md`.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,971 @@
"foreign_key_name";"child_schema";"child_table";"child_column";"parent_schema";"parent_table";"parent_column"
"FK_Tarif_Schulamt";"dbo";"ABOSummeFahrscheine";"IDAdresse_FS_Schulamt";"dbo";"Schulamt";"IDSchulamt"
"FK_Tarif_Schule";"dbo";"ABOSummeFahrscheine";"IDAdresse_FS_Schule";"dbo";"Schule";"IDSchule"
"FK_Tarif_Schuljahr";"dbo";"ABOSummeFahrscheine";"IDABOSchuljahr_FS";"dbo";"ABOSchuljahr";"IDABOSchuljahr"
"FK_AdressAuswertungProtokoll_Adresse";"dbo";"AdressAuswertungProtokoll";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAgenturKatalog_Adresse";"dbo";"AdresseAgenturKatalog";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAgenturKatalog_ArtKatalog";"dbo";"AdresseAgenturKatalog";"IDArtKatalog_FS";"dbo";"ArtKatalog";"IDArtKatalog"
"FK_AdresseAgenturOrganisation_Adresse";"dbo";"AdresseAgenturOrganisation";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAgenturOrganisation_ArtAgenturOrganisation";"dbo";"AdresseAgenturOrganisation";"IDArtAgenturOrganisation_FS";"dbo";"ArtAgenturOrganisation";"IDArtAgenturOrganisation"
"FK_AdresseAgenturProvision_Adresse";"dbo";"AdresseAgenturProvision";"IDArtProvisionsstaffel_FS";"dbo";"ArtProvisionsstaffel";"IDArtProvisionsstaffel"
"FK_AdresseAgenturProvision_Adresse1";"dbo";"AdresseAgenturProvision";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAgenturZusatz_Adresse";"dbo";"AdresseAgenturZusatz";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAgenturZusatz_ArtAgenturPreisgruppe";"dbo";"AdresseAgenturZusatz";"IDArtAgenturPreisgruppe_FS";"dbo";"ArtAgenturPreisgruppe";"IDArtAgenturPreisgruppe"
"FK_AdresseAgenturZusatz_ArtPreisschema";"dbo";"AdresseAgenturZusatz";"IDArtPreisschema_FS";"dbo";"ArtPreisschema";"IDArtPreisschema"
"FK_AdresseAnruf_Adresse";"dbo";"AdresseAnruf";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseAnschriftKoordinate_AdresseAnschrift";"dbo";"AdresseAnschriftKoordinate";"IDAdresseAnschrift_FS";"dbo";"AdresseAnschrift";"IDAdresseAnschrift"
"FK_AdresseAnschriftKoordinate_ArtZustiegKoordinaten";"dbo";"AdresseAnschriftKoordinate";"IDArtZustiegKoordinaten_FS";"dbo";"ArtZustiegKoordinaten";"IDArtZustiegKoordinaten"
"FK_Adresse_Bankverbindung";"dbo";"AdresseBankverbindung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Adresse_Bearbeitung";"dbo";"AdresseBearbeitung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Adresse_Bearbeitung_ErsterSachbearbeiter";"dbo";"AdresseBearbeitung";"IDAdresse_FS_ErsterSachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_Adresse_Bearbeitung_LetzterSachbearbeiter";"dbo";"AdresseBearbeitung";"IDAdresse_FS_LetzterSachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_AdresseCRS_Adresse";"dbo";"AdresseCRS";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseCRS_ArtCRS";"dbo";"AdresseCRS";"IDArtCRS_FS";"dbo";"ArtCRS";"IDArtCRS"
"FK_AdresseDatenschutz_Adresse";"dbo";"AdresseDatenschutz";"IdAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseEmpfehlerKonto_Adresse";"dbo";"AdresseEmpfehlerKonto";"IDAdresse_FS_Empfehler";"dbo";"Adresse";"IDAdresse"
"FK_AdresseEmpfehlerKonto_Adresse1";"dbo";"AdresseEmpfehlerKonto";"IDAdresse_FS_Empfohlener";"dbo";"Adresse";"IDAdresse"
"FK_AdresseHinweis_Adresse";"dbo";"AdresseHinweis";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseHistorie_Adresse";"dbo";"AdresseHistorie";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseHistorieBuchungTN_Adresse";"dbo";"AdresseHistorieBuchungTN";"IDAdresseHistorie_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseHistorieMietbus_Adresse";"dbo";"AdresseHistorieMietbus";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Adresse_Kommunikation";"dbo";"AdresseKommunikation";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseKommunikation_ArtKommunikation";"dbo";"AdresseKommunikation";"IDArtKommunikation_FS";"dbo";"ArtKommunikation";"IDArtKommunikation"
"FK_Adresse_Kreditkarte";"dbo";"AdresseKreditkarte";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLandSteuer_Adresse";"dbo";"AdresseLandSteuer";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLandSteuer_Land";"dbo";"AdresseLandSteuer";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_AdresseLinieAuftraggeber_Adresse";"dbo";"AdresseLinieAuftraggeber";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLinieAuftraggeber_ArtStatistikGruppe";"dbo";"AdresseLinieAuftraggeber";"IDArtStatistikGruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_AdresseLinieAuftraggeberBlock_Adresse";"dbo";"AdresseLinieAuftraggeberBlock";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLinieAuftraggeberBlock_AdresseLinieAuftraggeber";"dbo";"AdresseLinieAuftraggeberBlock";"IDAdresseLinieAuftraggeber_FS";"dbo";"AdresseLinieAuftraggeber";"IDAdresseLinieAuftraggeber"
"FK_AdresseLinieAuftraggeberLinie_Adresse";"dbo";"AdresseLinieAuftraggeberLinie";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLinieAuftraggeberLinie_AdresseLinieAuftraggeber";"dbo";"AdresseLinieAuftraggeberLinie";"IDAdresseLinieAuftraggeber_FS";"dbo";"AdresseLinieAuftraggeber";"IDAdresseLinieAuftraggeber"
"FK_AdresseLinieAuftraggeberTour_Adresse";"dbo";"AdresseLinieAuftraggeberTour";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseLinieAuftraggeberTour_AdresseLinieAuftraggeber";"dbo";"AdresseLinieAuftraggeberTour";"IDAdresseLinieAuftraggeber_FS";"dbo";"AdresseLinieAuftraggeber";"IDAdresseLinieAuftraggeber"
"FK_AdressMandant_Adresse";"dbo";"AdresseMandant";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseMandantDokumentAusgabe_Adresse";"dbo";"AdresseMandantDokumentAusgabe";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseMandantDokumentAusgabe_ArtDokumentAusgabe";"dbo";"AdresseMandantDokumentAusgabe";"IDArtDokumentAusgabe_FS";"dbo";"ArtDokumentAusgabe";"IDArtDokumentAusgabe"
"FK_AdresseMandantERechnung_Adresse";"dbo";"AdresseMandantERechnung";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_AdresseMandantERechnungBV_AdresseBankverbindung";"dbo";"AdresseMandantERechnungBV";"IDAdresseBankverbindung_FS";"dbo";"AdresseBankverbindung";"IDAdresseBankverbindung"
"FK_AdresseMandantERechnungBV_AdresseMandantERechnung";"dbo";"AdresseMandantERechnungBV";"IDAdresseMandantERechnung_FS";"dbo";"AdresseMandantERechnung";"IDAdresseMandantERechnung"
"FK_AdresseMandantNummernkreis_Adresse";"dbo";"AdresseMandantNummernkreis";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseMandantNummernkreis_Nummernkreis";"dbo";"AdresseMandantNummernkreis";"IDNummernkreis_FS";"dbo";"Nummernkreis";"IDNummernkreis"
"FK_Adresse_Person";"dbo";"AdressePerson";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonal_Adresse";"dbo";"AdressePersonal";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonal_ArtBetriebshof";"dbo";"AdressePersonal";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_AdressePersonal_ArtLohnMandant";"dbo";"AdressePersonal";"IDArtLohnMandant_FS";"dbo";"ArtLohnMandant";"IDArtLohnMandant"
"FK_AdressePersonal_ArtPersonalEinsatz";"dbo";"AdressePersonal";"IDArtPersonalEinsatz_FS";"dbo";"ArtPersonalEinsatz";"IDArtPersonalEinsatz"
"FK_AdressePersonal_ArtPersonalGruppeKompetenz";"dbo";"AdressePersonal";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_AdressePersonalArt_Adresse";"dbo";"AdressePersonalArt";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalGruppeProdukt_Adresse";"dbo";"AdressePersonalGruppeProdukt";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalGruppeProdukt_ArtPersonalGruppeProdukt";"dbo";"AdressePersonalGruppeProdukt";"IDArtPersonalGruppeProdukt_FS";"dbo";"ArtPersonalGruppeProdukt";"IDArtPersonalGruppeProdukt"
"FK_AdressePersonalKleidung_Adresse";"dbo";"AdressePersonalKleidung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalKleidung_ArtPersonalKleidung";"dbo";"AdressePersonalKleidung";"IDArtPersonalKleidung_FS";"dbo";"ArtPersonalKleidung";"IDArtPersonalKleidung"
"FK_AdressePersonalNummer_Adresse";"dbo";"AdressePersonalNummer";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalNummer_ArtPersonalNummer";"dbo";"AdressePersonalNummer";"IDArtPersonalNummer_FS";"dbo";"ArtPersonalNummer";"IDArtPersonalNummer"
"FK_AdressePersonalPunkte_Adresse";"dbo";"AdressePersonalPunkte";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalSonstGegenstaende_Adresse";"dbo";"AdressePersonalSonstGegenstaende";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalSonstGegenstaende_ArtPersonalSonstGegenstaende";"dbo";"AdressePersonalSonstGegenstaende";"IDArtPersonalSonstGegenstaende_FS";"dbo";"ArtPersonalSonstGegenstaende";"IDArtPersonalSonstGegenstaende"
"FK_AdressePersonalSperrKasse_Adresse";"dbo";"AdressePersonalSperrKasse";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalSperrKasse_ZahlungStamm";"dbo";"AdressePersonalSperrKasse";"IDZahlungStamm_FS";"dbo";"ZahlungStamm";"IDZahlungStamm"
"FK_AdressePersonalUnfall_Adresse";"dbo";"AdressePersonalUnfall";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalVerwendung_Adresse";"dbo";"AdressePersonalVerwendung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalZusatz_Adresse";"dbo";"AdressePersonalZusatz";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePersonalZusatz_SpracheMaske";"dbo";"AdressePersonalZusatz";"IDSpracheMaske_FS";"dbo";"SpracheMaske";"IDSpracheMaske"
"FK_AdressePunkte_Adresse";"dbo";"AdressePunkte";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdressePunkte_Adresse1";"dbo";"AdressePunkte";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_AdresseSteueraufteilungDetail_Adresse";"dbo";"AdresseSteueraufteilungDetail";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseSteueraufteilungDetail_Steueraufteilung";"dbo";"AdresseSteueraufteilungDetail";"IDSteueraufteilungDetail_FS";"dbo";"SteueraufteilungDetail";"IDSteueraufteilungDetail"
"FK_AdresseZusatz_Adresse";"dbo";"AdresseZusatz";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseZusatzfeld_Adresse";"dbo";"AdresseZusatzfeld";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AdresseZusatzfeld_AdressePerson";"dbo";"AdresseZusatzfeld";"IDAdressePerson_FS";"dbo";"AdressePerson";"IDAdressePerson"
"FK_AdresseZusatzfeld_ArtAdresseZusatzfeld";"dbo";"AdresseZusatzfeld";"IDArtAdresseZusatzfeld_FS";"dbo";"ArtAdresseZusatzfeld";"IDArtAdresseZusatzfeld"
"FK_AdresseMietbusZusatz_Adresse";"dbo";"AdresseZusatzMietbus";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Adresse_AgenturSelektion";"dbo";"AgenturSelektionenKunde";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Selektionsstamm_AgenturSelektion";"dbo";"AgenturSelektionenKunde";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_ArbeitswertMaterial_Arbeitswert";"dbo";"ArbeitswertMaterial";"IDArbeitswert_FS";"dbo";"Arbeitswert";"IDArbeitswert"
"FK_ArbeitswertMaterial_Artikel";"dbo";"ArbeitswertMaterial";"IDArtikel_FS";"dbo";"Artikel";"IDArtikel"
"FK_ArbeitswertPersonal_Arbeitswert";"dbo";"ArbeitswertPersonal";"IDArbeitswert_FS";"dbo";"Arbeitswert";"IDArbeitswert"
"FK_ArbeitswertPersonal_Arbeitszeitwert";"dbo";"ArbeitswertPersonal";"IDArbeitszeitwert_FS";"dbo";"Arbeitszeitwert";"IDArbeitszeitwert"
"FK_ArtArbeitszeitZusatzEinst_ArtArbeitszeitZusatz";"dbo";"ArtArbeitszeitZusatzEinst";"IDArtArbeitszeitZusatz_FS";"dbo";"ArtArbeitszeitzusatz";"IDArtArbeitszeitzusatz"
"FK_ArtikelBewegung_Artikel";"dbo";"ArtikelBewegung";"IDArtikel_FS";"dbo";"Artikel";"IDArtikel"
"FK_ArtikelImport_ArtArtikelImport";"dbo";"ArtikelImport";"IDArtArtikelImport_FS";"dbo";"ArtArtikelImport";"IDArtArtikelImport"
"FK_Artikelzusatz_ArtEinheit";"dbo";"Artikelzusatz";"IDArtEinheit_FS";"dbo";"ArtEinheit";"IDArtEinheit"
"FK_ArtikelZuweisungWarengruppe_Artikel";"dbo";"ArtikelZuweisungWarengruppe";"IDArtikel_FS";"dbo";"Artikel";"IDArtikel"
"FK_ArtikelZuweisungWarengruppe_Warengruppe";"dbo";"ArtikelZuweisungWarengruppe";"IDArtWarengruppe_FS";"dbo";"ArtWarengruppe";"IDArtWarengruppe"
"FK_Auftrag_Adresse3";"dbo";"Auftrag";"IDAdresse_FS_Kunde";"dbo";"Adresse";"IDAdresse"
"FK_Auftrag_Auftragsart";"dbo";"Auftrag";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_AuftragBlock_Auftrag";"dbo";"AuftragBlock";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragFahrer_Auftrag";"dbo";"AuftragFahrer";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragFahrer_AuftragFahrzeug";"dbo";"AuftragFahrer";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragFahrer_AuftragTeilauftrag";"dbo";"AuftragFahrer";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragFahrerArbeitszeit_ArtArbeitszeitzusatz";"dbo";"AuftragFahrerArbeitszeit";"IDArtArbeitszeitzusatz_FS";"dbo";"ArtArbeitszeitzusatz";"IDArtArbeitszeitzusatz"
"FK_AuftragFahrerArbeitszeit_AuftragFahrer";"dbo";"AuftragFahrerArbeitszeit";"IDAuftragFahrer_FS";"dbo";"AuftragFahrer";"IDAuftragFahrer"
"FK_AuftragFahrerArbeitszeitSpesen_AuftragFahrer";"dbo";"AuftragFahrerArbeitszeitSpesen";"IDAuftragFahrer_FS";"dbo";"AuftragFahrer";"IDAuftragFahrer"
"FK_AuftragFahrerTagesStunden_AuftragFahrer";"dbo";"AuftragFahrerTagesStunden";"IDAuftragFahrer_FS";"dbo";"AuftragFahrer";"IDAuftragFahrer"
"FK_AuftragFahrzeug_Auftrag";"dbo";"AuftragFahrzeug";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragFahrzeug_AuftragTeilauftrag";"dbo";"AuftragFahrzeug";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragFahrzeugNavi_AuftragFahrzeug";"dbo";"AuftragFahrzeugNavi";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragFahrzeugNavi_Fahrzeug";"dbo";"AuftragFahrzeugNavi";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_AuftragFahrzeugNaviGrenzuebertritt_AuftragFahrzeug";"dbo";"AuftragFahrzeugNaviGrenzuebertritt";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragFahrzeugTagesKM_AuftragFahrzeug";"dbo";"AuftragFahrzeugTagesKM";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragInkludierteLeistung_Auftrag";"dbo";"AuftragInkludierteLeistung";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragInkludierteLeistung_AuftragTeilauftrag";"dbo";"AuftragInkludierteLeistung";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragNebenleistung_Auftrag";"dbo";"AuftragInkludierteLeistung";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragNebenleistung_AuftragTeilauftrag";"dbo";"AuftragInkludierteLeistung";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragKalkulationswert_Auftrag";"dbo";"AuftragKalkulationswert";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragKalkulationswert_AuftragTeilauftrag";"dbo";"AuftragKalkulationswert";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragKilometer_Auftrag";"dbo";"AuftragKilometer";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragKilometer_AuftragFahrzeug";"dbo";"AuftragKilometer";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragKilometer_AuftragTeilauftrag";"dbo";"AuftragKilometer";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragKilometerLand_Auftrag";"dbo";"AuftragKilometerLand";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragKilometerLand_AuftragFahrzeug";"dbo";"AuftragKilometerLand";"IDAuftragFahrzeug_FS";"dbo";"AuftragFahrzeug";"IDAuftragFahrzeug"
"FK_AuftragKilometerLand_AuftragKilometer";"dbo";"AuftragKilometerLand";"IDAuftragKilometer_FS";"dbo";"AuftragKilometer";"IDAuftragKilometer"
"FK_AuftragKilometerLand_AuftragTeilauftrag";"dbo";"AuftragKilometerLand";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragKilometerLand_Land";"dbo";"AuftragKilometerLand";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_AuftragsartMwst_Auftragsart";"dbo";"AuftragsartMwst";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_AuftragSuche_Adresse1";"dbo";"AuftragSuche";"IDAdresse_FS_Kunde";"dbo";"Adresse";"IDAdresse"
"FK_AuftragSuche_Auftrag";"dbo";"AuftragSuche";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragSuche_Auftragsart";"dbo";"AuftragSuche";"IDAuftragsArt_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_AuftragTAAbholstelle_AuftragTeilauftrag";"dbo";"AuftragTAAbholstelle";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragTARoute_Auftrag";"dbo";"AuftragTARoute";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragTARoute_AuftragTeilauftrag";"dbo";"AuftragTARoute";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragTARoute_Land";"dbo";"AuftragTARoute";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_AuftragTeilauftrag_Auftrag";"dbo";"AuftragTeilauftrag";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragTeilauftragPreis_Auftrag";"dbo";"AuftragTeilauftragPreis";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragTeilauftragPreis_AuftragTeilauftrag";"dbo";"AuftragTeilauftragPreis";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragTeilauftragPreisErweitert_AuftragTeilauftrag";"dbo";"AuftragTeilauftragPreisErweitert";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AuftragTeilauftragPreisErweitert_Ausstattung";"dbo";"AuftragTeilauftragPreisErweitert";"IDAusstattung_FS";"dbo";"Ausstattung";"IDAusstattung"
"FK_AuftragText_ArtAuftragstext";"dbo";"AuftragText";"IDArtAuftragstext_FS";"dbo";"ArtAuftragstext";"IDArtAuftragstext"
"FK_AuftragText_Auftrag";"dbo";"AuftragText";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragZusatz_ArtStornogrund";"dbo";"AuftragZusatz";"IDArtStornogrund_FS";"dbo";"ArtStornogrund";"IDArtStornogrund"
"FK_AuftragZusatz_Auftrag";"dbo";"AuftragZusatz";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragZusatzleistung_Auftrag";"dbo";"AuftragZusatzleistung";"IDAuftrag_FS";"dbo";"Auftrag";"IDAuftrag"
"FK_AuftragZusatzleistung_AuftragTeilauftrag";"dbo";"AuftragZusatzleistung";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_AusstattungFahrzeugAusstattung_ArtFahrzeugAusstattungMerkmal";"dbo";"AusstattungFahrzeugAusstattung";"IDArtFahrzeugAusstattungMerkmal_FS";"dbo";"ArtFahrzeugAusstattungMerkmal";"IDArtFahrzeugAusstattungMerkmal"
"FK_AusstattungFahrzeugAusstattung_Ausstattung";"dbo";"AusstattungFahrzeugAusstattung";"IDAusstattung_FS";"dbo";"Ausstattung";"IDAusstattung"
"FK_AusstattungKalkulationsWert_Ausstattung";"dbo";"AusstattungKalkulationsWert";"IDAusstattung_FS";"dbo";"Ausstattung";"IDAusstattung"
"FK_AusstattungKalkulationsWert_KalkulationswertBezeichnung";"dbo";"AusstattungKalkulationsWert";"IDKalkulationsWertBezeichnung_FS";"dbo";"KalkulationswertBezeichnung";"IDKalkulationswertBezeichnung"
"FK_AusstattungKalkulationswertPersonen_AusstattungKalkulationsWert";"dbo";"AusstattungKalkulationswertPersonen";"IDAusstattungKalkulationswert_FS";"dbo";"AusstattungKalkulationsWert";"IDAusstattungKalkulationsWert"
"FK_AZKImport_Adresse";"dbo";"AZKImport";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_AZKImport_AZKImportEinstellung";"dbo";"AZKImport";"IDAZKImportEinstellung_FS";"dbo";"AZKImportEinstellung";"IDAZKImportEinstellung"
"FK_Befoerderungsvertrag_Adresse";"dbo";"Befoerderungsvertrag";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_Befoerderungsvertrag_AdresseAnschrift";"dbo";"Befoerderungsvertrag";"IDAdresseAnschrift_FS_Partner";"dbo";"AdresseAnschrift";"IDAdresseAnschrift"
"FK_BefoerderungsvertragTeilauftrag_AuftragTeilauftrag";"dbo";"BefoerderungsvertragTeilauftrag";"IDAuftragTeilauftrag_FS";"dbo";"AuftragTeilauftrag";"IDAuftragTeilauftrag"
"FK_BefoerderungsvertragTeilauftrag_Befoerderungsvertrag";"dbo";"BefoerderungsvertragTeilauftrag";"IDBefoerderungsvertrag_FS";"dbo";"Befoerderungsvertrag";"IDBefoerderungsvertrag"
"FK_Block_Adresse";"dbo";"Block";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_Block_ArtBetriebshof";"dbo";"Block";"IDArtBetriebshof_FS_Anfang";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_Block_ArtBetriebshof1";"dbo";"Block";"IDArtBetriebshof_FS_Ende";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_Block_ArtBlockArt";"dbo";"Block";"IDArtBlockart_FS";"dbo";"ArtBlockArt";"IDArtBlockArt"
"FK_Block_ArtFahrplanVersion";"dbo";"Block";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_Block_ArtFremdunternehmen";"dbo";"Block";"IDArtFremdunternehmen_FS";"dbo";"ArtFremdunternehmen";"IDArtFremdunternehmen"
"FK_Block_ArtReichweitentyp";"dbo";"Block";"IDArtReichweitentyp_FS";"dbo";"ArtReichweitentyp";"IDArtReichweitentyp"
"FK_Block_Fahrzeug";"dbo";"Block";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_Block_Ort_AbstellAnfang";"dbo";"Block";"IDOrt_FS_AbstellAnfang";"dbo";"Ort";"IDOrt"
"FK_Block_Ort_AbstellEnde";"dbo";"Block";"IDOrt_FS_AbstellEnde";"dbo";"Ort";"IDOrt"
"FK_BlockFahrzeugtyp_ArtFahrzeugTypen";"dbo";"BlockFahrzeugtyp";"IDArtFahrzeugTypen_FS";"dbo";"ArtFahrzeugTypen";"IDArtFahrzeugTypen"
"FK_BlockFahrzeugtyp_Block";"dbo";"BlockFahrzeugtyp";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_BlockGruppeVerkehrstag_ArtGruppeVerkehrstag";"dbo";"BlockGruppeVerkehrstag";"IDArtGruppeVerkehrstag_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_BlockGruppeVerkehrstag_Block";"dbo";"BlockGruppeVerkehrstag";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_Blockkombination_ArtFahrplanVersion";"dbo";"Blockkombination";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_BlockkombinationBlock_Block";"dbo";"BlockkombinationBlock";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_BlockkombinationBlock_Blockkombination";"dbo";"BlockkombinationBlock";"IDBlockkombination_FS";"dbo";"Blockkombination";"IDBlockkombination"
"FK_BlockkombinationGruppeVerkehrstag_ArtGruppeVerkehrstag";"dbo";"BlockkombinationGruppeVerkehrstag";"IDArtGruppeVerkehrstag_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_BlockkombinationGruppeVerkehrstag_Blockkombination";"dbo";"BlockkombinationGruppeVerkehrstag";"IDBlockkombination_FS";"dbo";"Blockkombination";"IDBlockkombination"
"FK_BlockPause_Block";"dbo";"BlockPause";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_BlockPause_Ort";"dbo";"BlockPause";"IDOrt_FS";"dbo";"Ort";"IDOrt"
"FK_BlockPlanung_Adresse";"dbo";"BlockPlanung";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_BlockPlanung_Adresse2";"dbo";"BlockPlanung";"LoeschenManuellIDAdresse_FS_SB";"dbo";"Adresse";"IDAdresse"
"FK_BlockPlanung_ArtBetriebshof";"dbo";"BlockPlanung";"IDArtBetriebshof_FS_Anfang";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_BlockPlanung_ArtBetriebshof1";"dbo";"BlockPlanung";"IDArtBetriebshof_FS_Ende";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_BlockPlanung_ArtBlockArt";"dbo";"BlockPlanung";"IDArtBlockart_FS";"dbo";"ArtBlockArt";"IDArtBlockArt"
"FK_BlockPlanung_ArtFahrplanVersion";"dbo";"BlockPlanung";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_BlockPlanung_ArtFremdunternehmen";"dbo";"BlockPlanung";"IDArtFremdunternehmen_FS";"dbo";"ArtFremdunternehmen";"IDArtFremdunternehmen"
"FK_BlockPlanung_ArtReichweitentyp";"dbo";"BlockPlanung";"IDArtReichweitentyp_FS";"dbo";"ArtReichweitentyp";"IDArtReichweitentyp"
"FK_BlockPlanung_Block";"dbo";"BlockPlanung";"IDBlock_FS_Basis";"dbo";"Block";"IDBlock"
"FK_BlockPlanung_Fahrzeug";"dbo";"BlockPlanung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_BlockPlanung_Ort_AbstellAnfang";"dbo";"BlockPlanung";"IDOrt_FS_AbstellAnfang";"dbo";"Ort";"IDOrt"
"FK_BlockPlanung_Ort_AbstellEnde";"dbo";"BlockPlanung";"IDOrt_FS_AbstellEnde";"dbo";"Ort";"IDOrt"
"FK_BlockPlanungFahrzeugtyp_ArtFahrzeugTypen";"dbo";"BlockPlanungFahrzeugtyp";"IDArtFahrzeugTypen_FS";"dbo";"ArtFahrzeugTypen";"IDArtFahrzeugTypen"
"FK_BlockPlanungFahrzeugtyp_BlockPlanung";"dbo";"BlockPlanungFahrzeugtyp";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_BlockPlanungPause_BlockPlanung";"dbo";"BlockPlanungPause";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_BlockPlanungPause_Ort";"dbo";"BlockPlanungPause";"IDOrt_FS";"dbo";"Ort";"IDOrt"
"FK_BlockPlanungPreisMehrMinder_TourPlanung";"dbo";"BlockPlanungPreisMehrMinder";"IDTourPlanung_FS";"dbo";"TourPlanung";"IDTourPlanung"
"FK_BlockPlanungZusatz_BlockPlanung";"dbo";"BlockPlanungZusatz";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_BlockSitzenbleiber_Block";"dbo";"BlockSitzenbleiber";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_BlockSitzenbleiber_TourNach";"dbo";"BlockSitzenbleiber";"IdTour_FS_Nach";"dbo";"Tour";"IDTour"
"FK_BlockSitzenbleiber_TourVon";"dbo";"BlockSitzenbleiber";"IdTour_FS_Von";"dbo";"Tour";"IDTour"
"FK_BlockTour_Block";"dbo";"BlockTour";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_BlockTour_Tour";"dbo";"BlockTour";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_BlockZusatz_Block";"dbo";"BlockZusatz";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_Buchung_Adresse";"dbo";"Buchung";"IDAdresse_FS_Agentur";"dbo";"Adresse";"IDAdresse"
"FK_Buchung_Adresse1";"dbo";"Buchung";"IDAdresse_FS_ErsterSachb";"dbo";"Adresse";"IDAdresse"
"FK_Buchung_Adresse2";"dbo";"Buchung";"IDAdresse_FS_LetzterSachb";"dbo";"Adresse";"IDAdresse"
"FK_Buchung_Adresse3";"dbo";"Buchung";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_Buchung_IdAdressePerson";"dbo";"Buchung";"IdAdressePerson_FS_Anmelder";"dbo";"AdressePerson";"IDAdressePerson"
"FK_BuchungBemerkung_Buchung";"dbo";"BuchungBemerkung";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungDokument_Adresse";"dbo";"BuchungDokument";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_BuchungDokument_ArtDokument";"dbo";"BuchungDokument";"IDArtDokument_FS";"dbo";"ArtDokument";"IDArtDokument"
"FK_BuchungDokument_Buchung";"dbo";"BuchungDokument";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungDruck_Buchung";"dbo";"BuchungDruck";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungMeldung_Adresse";"dbo";"BuchungMeldung";"IDAdresse_FS_Mitarbeiter_Eingabe";"dbo";"Adresse";"IDAdresse"
"FK_BuchungMeldung_Adresse1";"dbo";"BuchungMeldung";"IDAdresse_FS_Mitarbeiter_Meldung";"dbo";"Adresse";"IDAdresse"
"FK_BuchungMeldung_ArtMeldungArt";"dbo";"BuchungMeldung";"IDArtMeldungart_FS";"dbo";"ArtMeldungArt";"IDArtMeldungArt"
"FK_BuchungMeldung_Buchung";"dbo";"BuchungMeldung";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungMeldung_BuchungTNFerienziel";"dbo";"BuchungMeldung";"IDBuchungTNFerienziel_FS";"dbo";"BuchungTNFerienziel";"IDBuchungTNFerienziel"
"FK_BuchungMeldung_BuchungTNLeistung";"dbo";"BuchungMeldung";"IDBuchungTNLeistung_FS";"dbo";"BuchungTNLeistung";"IDBuchungTNLeistung"
"FK_BuchungReisebüro_Buchung";"dbo";"BuchungReisebüro";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungReisebüroVersicherungsGruppe_ArtVersicherungsGruppe";"dbo";"BuchungReisebüroVersicherungsGruppe";"IDArtVersicherungsGruppe_FS";"dbo";"ArtVersicherungsGruppe";"IDArtVersicherungsGruppe"
"FK_BuchungReisebüroVersicherungsGruppe_BuchungReisebüro";"dbo";"BuchungReisebüroVersicherungsGruppe";"IDBuchungReisebüro_FS";"dbo";"BuchungReisebüro";"IDBuchungReisebüro"
"FK_BuchungReisebüroVisum_BuchungReisebüro";"dbo";"BuchungReisebüroVisum";"IDBuchungReisebüro_FS";"dbo";"BuchungReisebüro";"IDBuchungReisebüro"
"FK_BuchungTextbaustein_Buchung";"dbo";"BuchungTextbaustein";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungTextbaustein_Textbaustein";"dbo";"BuchungTextbaustein";"IDTextbaustein_FS";"dbo";"Textbaustein";"IDTextbaustein"
"FK_BuchungTN_AdressePerson";"dbo";"BuchungTN";"IDAdressePerson_FS";"dbo";"AdressePerson";"IDAdressePerson"
"FK_BuchungTN_ArtTeilnahmeStornoGrund";"dbo";"BuchungTN";"IDArtTeilnahmeStornoGrund_FS";"dbo";"ArtTeilnahmeStornoGrund";"IDArtTeilnahmeStornoGrund"
"FK_BuchungTN_Buchung";"dbo";"BuchungTN";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungTNFerienziel_Adresse";"dbo";"BuchungTNFerienziel";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_BuchungTNFerienziel_ArtVerpflegung";"dbo";"BuchungTNFerienziel";"IDArtVerpflegung_FS";"dbo";"ArtVerpflegung";"IDArtVerpflegung"
"FK_BuchungTNFerienziel_BuchungTN";"dbo";"BuchungTNFerienziel";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNFerienziel_Zimmerart";"dbo";"BuchungTNFerienziel";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_BuchungTNFerienzielPreis_BuchungTNFerienziel";"dbo";"BuchungTNFerienzielPreis";"IDBuchungTNFerienziel_FS";"dbo";"BuchungTNFerienziel";"IDBuchungTNFerienziel"
"FK_BuchungTNFerienzielPreis_BuchungTNPreis";"dbo";"BuchungTNFerienzielPreis";"IDBuchungTNPreis_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_BuchungTNLeistung_BuchungTN";"dbo";"BuchungTNLeistung";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNLeistung_Leistung";"dbo";"BuchungTNLeistung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_BuchungTNLeistungPreis_BuchungTNLeistung";"dbo";"BuchungTNLeistungPreis";"IDBuchungTNLeistung_FS";"dbo";"BuchungTNLeistung";"IDBuchungTNLeistung"
"FK_BuchungTNLeistungPreis_BuchungTNPreis";"dbo";"BuchungTNLeistungPreis";"IDBuchungTNPreis_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_BuchungTNLeistungZusatz_BuchungTNLeistung";"dbo";"BuchungTNLeistungZusatz";"IDBuchungTNLeistung_FS";"dbo";"BuchungTNLeistung";"IDBuchungTNLeistung"
"FK_BuchungTNPreis_Adresse";"dbo";"BuchungTNPreis";"IDAdresse_FS_Sachb";"dbo";"Adresse";"IDAdresse"
"FK_BuchungTNPreis_ArtPreisschema";"dbo";"BuchungTNPreis";"IDArtPreisschema_FS";"dbo";"ArtPreisschema";"IDArtPreisschema"
"FK_BuchungTNPreis_BuchungTN";"dbo";"BuchungTNPreis";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNPreisErm_BuchungTNPreis";"dbo";"BuchungTNPreisErm";"IDBuchungTNPreis_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_BuchungTNVersicherung_BuchungTN";"dbo";"BuchungTNVersicherung";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNVersicherung_Leistung";"dbo";"BuchungTNVersicherung";"IDLeistung_FS_Versicherung";"dbo";"Leistung";"IDLeistung"
"FK_BuchungTNVersicherungPreis_BuchungTNPreis";"dbo";"BuchungTNVersicherungPreis";"IDBuchungTNPreis_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_BuchungTNVersicherungPreis_BuchungTNVersicherung";"dbo";"BuchungTNVersicherungPreis";"IDBuchungTNVersicherung_FS";"dbo";"BuchungTNVersicherung";"IDBuchungTNVersicherung"
"FK_BuchungTNWunsch_BuchungTN";"dbo";"BuchungTNWunsch";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNZahlung_BuchungTN";"dbo";"BuchungTNZahlung";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNZahlung_Zahlung";"dbo";"BuchungTNZahlung";"IDZahlung_FS";"dbo";"Zahlung";"IDZahlung"
"FK_BuchungTNZuschlag_BuchungTN";"dbo";"BuchungTNZuschlag";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_BuchungTNZuschlagPreis_BuchungTNPreis";"dbo";"BuchungTNZuschlagPreis";"IDBuchungTNPreis_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_BuchungTNZuschlagPreis_BuchungTNZuschlag";"dbo";"BuchungTNZuschlagPreis";"IDBuchungTNZuschlag_FS";"dbo";"BuchungTNZuschlag";"IDBuchungTNZuschlag"
"FK_BuchungTNZuschlagZusatz_BuchungTNZuschlag";"dbo";"BuchungTNZuschlagZusatz";"IDBuchungTNZuschlag_FS";"dbo";"BuchungTNZuschlag";"IDBuchungTNZuschlag"
"FK_BuchungUnterlagenStatus_Adresse";"dbo";"BuchungUnterlagenStatus";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_BuchungUnterlagenStatus_ArtUnterlagenStatus";"dbo";"BuchungUnterlagenStatus";"IDArtUnterlagenStatus_FS";"dbo";"ArtUnterlagenStatus";"IDArtUnterlagenStatus"
"FK_BuchungUnterlagenStatus_Buchung";"dbo";"BuchungUnterlagenStatus";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungVersicherungAngebot_Buchung";"dbo";"BuchungVersicherungAngebot";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BuchungVersicherungAngebot_Leistung";"dbo";"BuchungVersicherungAngebot";"IDLeistung_FS_Versicherung";"dbo";"Leistung";"IDLeistung"
"FK_BuchungZahlung_ArtZahlungsart";"dbo";"BuchungZahlung";"IDArtZahlungsart_FS";"dbo";"ArtZahlungsart";"IDArtZahlungsart"
"FK_BuchungZahlung_Buchung";"dbo";"BuchungZahlung";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_BundeslandPLZOrt_ArtBundesland";"dbo";"BundeslandPLZOrt";"IDArtBundesland_FS";"dbo";"ArtBundesland";"IDArtBundesland"
"FK_ConnectChat_ArtConnectChatKategorie";"dbo";"ConnectChat";"IDArtConnectChatKategorie_FS";"dbo";"ArtConnectChatKategorie";"IDArtConnectChatKategorie"
"FK_ConnectChatKategorieKompetenz_ArtPersonalGruppeKompetenz";"dbo";"ConnectChatKategorieKompetenz";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_ChatNachricht_ChatRaum";"dbo";"ConnectChatNachricht";"IDChat_FS";"dbo";"ConnectChat";"IDChat"
"FK_ChatTeilnehmer_ChatRaum";"dbo";"ConnectChatTeilnehmer";"IDChat_FS";"dbo";"ConnectChat";"IDChat"
"FK_ConnectDokumentReferenzen_ConnectDokument";"dbo";"ConnectDokumentReferenzen";"IDConnectDokument_FS";"dbo";"ConnectDokument";"IDConnectDokument"
"FK_ConnectKompetenz_ArtPersonalGruppeKompetenz";"dbo";"ConnectKompetenz";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_ConnectNotificationsReceiver_ConnectNotifications";"dbo";"ConnectNotificationsReceiver";"IDConnectNotification";"dbo";"ConnectNotifications";"Id"
"FK_ConnectOrdner_ConnectOrdner";"dbo";"ConnectOrdner";"IDConnectOrdner_FS_Parent";"dbo";"ConnectOrdner";"IDConnectOrdner"
"FK_Connect_Planungsabruf_Adresse_Aenderung";"dbo";"ConnectPlanungsabruf";"IDAdresse_FS_Aenderung";"dbo";"Adresse";"IDAdresse"
"FK_Connect_Planungsabruf_Adresse_Fahrer";"dbo";"ConnectPlanungsabruf";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_ConnectPlanungsabrufHistorie_Adresse";"dbo";"ConnectPlanungsabrufHistorie";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_ConnectRueckmeldungMB_AuftragFahrer";"dbo";"ConnectRueckmeldungMB";"IDAuftragFahrer_FS";"dbo";"AuftragFahrer";"IDAuftragFahrer"
"FK_ConnectRueckmeldungMBFoto_ConnectRueckmeldungMB";"dbo";"ConnectRueckmeldungMBFoto";"IDConnectRueckmeldungMB_FS";"dbo";"ConnectRueckmeldungMB";"IDConnectRueckmeldungMB"
"FK_ConnectRueckmeldungMBKilometer_ConnectRueckmeldungMB";"dbo";"ConnectRueckmeldungMBKilometer";"IDConnectRueckmeldungMB_FS";"dbo";"ConnectRueckmeldungMB";"IDConnectRueckmeldungMB"
"FK_ArtConnectRueckmeldungMBText_ConnectRueckmeldungMBText";"dbo";"ConnectRueckmeldungMBText";"IDArtConnectRueckmeldungMBText_FS";"dbo";"ArtConnectRueckmeldungMBText";"IDArtConnectRueckmeldungMBText"
"FK_ConnectRueckmeldungMBText_ConnectRueckmeldungMB";"dbo";"ConnectRueckmeldungMBText";"IDConnectRueckmeldungMB_FS";"dbo";"ConnectRueckmeldungMB";"IDConnectRueckmeldungMB"
"FK_CRMAktionDesignSeite_CRMAktion";"dbo";"CRMAktionDesignSeite";"IDCRMAktion_FS";"dbo";"CRMAktion";"IDCRMAktion"
"FK_CRMAktionDesignSeiteZuweisung_CRMAktionDesignSeite";"dbo";"CRMAktionDesignSeiteZuweisung";"IDCRMAktionDesignSeite_FS";"dbo";"CRMAktionDesignSeite";"IDCRMAktionDesignSeite"
"FK_CRMAktionPLZ_CRMAktion";"dbo";"CRMAktionPLZ";"IDCRMAktion_FS";"dbo";"CRMAktion";"IDCRMAktion"
"FK_CRMAktionZuGruppe_CRMAktion";"dbo";"CRMAktionZuGruppe";"IDCRMAktion_FS";"dbo";"CRMAktion";"IDCRMAktion"
"FK_CRMAktionZuGruppe_CRMAktionZuGruppe";"dbo";"CRMAktionZuGruppe";"IDArtCRMGruppe_FS";"dbo";"ArtCRMGruppe";"IDArtCRMGruppe"
"FK_CRMAktionZuProdukt_CRMAktion";"dbo";"CRMAktionZuProdukt";"IDCRMAktion_FS";"dbo";"CRMAktion";"IDCRMAktion"
"FK_CRMAktionZuProdukt_Produkt";"dbo";"CRMAktionZuProdukt";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_CRMAktionZuReise_CRMAktion";"dbo";"CRMAktionZuReise";"IDCRMAktion_FS";"dbo";"CRMAktion";"IDCRMAktion"
"FK_CRMAktionZuReise_Reise";"dbo";"CRMAktionZuReise";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_CRMDesignSegment_CRMDesign";"dbo";"CRMDesignSegment";"IDCRMDesign_FS";"dbo";"CRMDesign";"IDCRMDesign"
"FK_CRMInternetZuweisung_ArtCRMInternet";"dbo";"CRMInternetZuweisung";"IDArtCRMInternet_FS";"dbo";"ArtCRMInternet";"IDArtCRMInternet"
"FK_CRMInternetZuweisung_Buchung";"dbo";"CRMInternetZuweisung";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_CRMWerbepartner_Adresse";"dbo";"CRMWerbepartner";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_CRMWerbepartnerDesign_CRMDesign";"dbo";"CRMWerbepartnerDesign";"IDCRMDesign_FS";"dbo";"CRMDesign";"IDCRMDesign"
"FK_CRMWerbepartnerDesign_CRMWerbepartner";"dbo";"CRMWerbepartnerDesign";"IDCRMWerbepartner_FS";"dbo";"CRMWerbepartner";"IDCRMWerbepartner"
"FK_CRMWerbepartnerPLZ_CRMWerbepartner";"dbo";"CRMWerbepartnerPLZ";"IDCRMWerbepartner_FS";"dbo";"CRMWerbepartner";"IDCRMWerbepartner"
"FK_CRMZuweisung_Adresse";"dbo";"CRMZuweisung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_CRMZuweisung_Adresse1";"dbo";"CRMZuweisung";"IDAdresse_FS_VonPersonal";"dbo";"Adresse";"IDAdresse"
"FK_DienstplandruckExport_ArtDienstplandruckExport";"dbo";"DienstplandruckExport";"IDArtDienstplandruckExport_FS";"dbo";"ArtDienstplandruckExport";"IDArtDienstplandruckExport"
"FK_DispoAenderung_Adresse";"dbo";"DispoAenderung";"IDAdresse_FS_Disponent";"dbo";"Adresse";"IDAdresse"
"FK_DispoAenderungDisponent_DispoAenderung";"dbo";"DispoAenderungDisponent";"IDDispoAenderung_FS";"dbo";"DispoAenderung";"IDDispoAenderung"
"FK_DispoAenderungDisponent_DispoAnmeldungDisponent";"dbo";"DispoAenderungDisponent";"IDDispoAnmeldungDisponent_FS";"dbo";"DispoAnmeldungDisponent";"IDDispoAnmeldungDisponent"
"FK_DispoAnmeldungDisponent_Adresse";"dbo";"DispoAnmeldungDisponent";"IDAdresse_FS_Disponent";"dbo";"Adresse";"IDAdresse"
"FK_DispoEinstellungKompetenzen_ArtPersonalGruppeKompetenz";"dbo";"DispoEinstellungKompetenz";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_DispoEinstellungKompetenzBetriebshofAnzeige_ArtBetriebshof";"dbo";"DispoEinstellungKompetenzBetriebshofAnzeige";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_DispoEinstellungKompetenzBetriebshofAnzeige_DispoEinstellungKompetenz";"dbo";"DispoEinstellungKompetenzBetriebshofAnzeige";"IDDispoEinstellungKompetenz_FS";"dbo";"DispoEinstellungKompetenz";"IDDispoEinstellungKompetenz"
"FK_DispoEinstellungKompetenzMandantAnzeige_Adresse";"dbo";"DispoEinstellungKompetenzMandantAnzeige";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_DispoEinstellungKompetenzMandantAnzeige_DispoEinstellungKompetenzen";"dbo";"DispoEinstellungKompetenzMandantAnzeige";"IDDispoEinstellungKompetenz_FS";"dbo";"DispoEinstellungKompetenz";"IDDispoEinstellungKompetenz"
"FK_Dokument_Adresse";"dbo";"Dokument";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_Dokument_ArtDokument";"dbo";"Dokument";"IDArtDokument_FS";"dbo";"ArtDokument";"IDArtDokument"
"FK_DruckArchiv_Adresse";"dbo";"DruckArchiv";"IDAdresse_FS_SB";"dbo";"Adresse";"IDAdresse"
"FK_DruckArchivZIP_Adresse";"dbo";"DruckArchivZIP";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_DTAMeldung_RechnungHaupt";"dbo";"DTAMeldung";"IDRechnungHaupt_FS";"dbo";"RechnungHaupt";"IDRechnungHaupt"
"FK_EinreisebestimmungText_Einreisebestimmung";"dbo";"EinreisebestimmungText";"IDEinreisebestimmung_FS";"dbo";"Einreisebestimmung";"IDEinreisebestimmung"
"FK_ExportInternetSpalte_ExportInternet";"dbo";"ExportInternetSpalte";"IDExportInternetZeile_FS";"dbo";"ExportInternetZeile";"IDExportInternetZeile"
"FK_ExportInternetZeile_ExportInternetZeile";"dbo";"ExportInternetZeile";"IDExportInternet_FS";"dbo";"ExportInternet";"IDExportInternet"
"FK_FahrtArt_ArtFahrtArt";"dbo";"FahrtArtKonten";"IdArtFahrtArt_FS";"dbo";"ArtFahrtArt";"IDArtFahrtArt"
"FK_Fahrzeug_ArtFahrzeugBriefOrt";"dbo";"Fahrzeug";"IDArtFahrzeugBriefOrt_FS";"dbo";"ArtFahrzeugBriefOrt";"IDArtFahrzeugBriefOrt"
"FK_Fahrzeug_ArtReichweitentyp";"dbo";"Fahrzeug";"IDArtReichweitentyp_FS";"dbo";"ArtReichweitentyp";"IDArtReichweitentyp"
"FK_Fahrzeug_FahrzeugBetriebshof";"dbo";"Fahrzeug";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_Fahrzeug_FahrzeugEinsatz";"dbo";"Fahrzeug";"IDArtFahrzeugEinsatz_FS";"dbo";"ArtFahrzeugEinsatz";"IDArtFahrzeugEinsatz"
"FK_Fahrzeug_FahrzeugTypen";"dbo";"Fahrzeug";"IDArtFahrzeugTypen_FS";"dbo";"ArtFahrzeugTypen";"IDArtFahrzeugTypen"
"FK_FahrzeugAusstattung_AusstattungsMerkmale";"dbo";"FahrzeugAusstattung";"IDArtFahrzeugAusstattungMerkmal_FS";"dbo";"ArtFahrzeugAusstattungMerkmal";"IDArtFahrzeugAusstattungMerkmal"
"FK_FahrzeugAusstattung_Fahrzeug";"dbo";"FahrzeugAusstattung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugEinbauten_Fahrzeug";"dbo";"FahrzeugEinbauten";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugGerät_ArtFahrzeugGerätTyp";"dbo";"FahrzeugGerät";"IDArtFahrzeugGerätTyp_FS";"dbo";"ArtFahrzeugGerätTyp";"IDArtFahrzeugGerätTyp"
"FK_FahrzeugGerätHistorie_ArtFahrzeugGerätOrt";"dbo";"FahrzeugGerätHistorie";"IDArtFahrzeugGerätOrt_FS";"dbo";"ArtFahrzeugGerätOrt";"IDArtFahrzeugGerätOrt"
"FK_FahrzeugGerätHistorie_Fahrzeug";"dbo";"FahrzeugGerätHistorie";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugGerätHistorie_FahrzeugGerät";"dbo";"FahrzeugGerätHistorie";"IDFahrzeugGerät_FS";"dbo";"FahrzeugGerät";"IDFahrzeugGerät"
"FK_FahrzeugLeasing_Fahrzeug";"dbo";"FahrzeugLeasing";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugNummer_ArtFahrzeugNummer";"dbo";"FahrzeugNummer";"IDArtFahrzeugNummer_FS";"dbo";"ArtFahrzeugNummer";"IDArtFahrzeugNummer"
"FK_FahrzeugNummer_Fahrzeug";"dbo";"FahrzeugNummer";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugStatistikAnmelder_Fahrzeug";"dbo";"FahrzeugStatistikAnmelder";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugTerminKettenAufbau_FahrzeugTermin";"dbo";"FahrzeugTerminKettenAufbau";"IDFahrzeugTermin_FS";"dbo";"FahrzeugTermin";"IDFahrzeugTermin"
"FK_FahrzeugTerminKettenAufbau_FahrzeugTerminHaeufigkeit";"dbo";"FahrzeugTerminKettenAufbau";"IDFahrzeugTerminHaeufigkeit_FS";"dbo";"FahrzeugTerminHaeufigkeit";"IDFahrzeugTerminHaeufigkeit"
"FK_FahrzeugTerminKettenAufbau_FahrzeugTerminkette";"dbo";"FahrzeugTerminKettenAufbau";"IDFahrzeugTerminkette_FS";"dbo";"FahrzeugTerminkette";"IDFahrzeugTerminkette"
"FK_FahrzeugTerminZuweisung_Fahrzeug";"dbo";"FahrzeugTerminZuweisung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugTerminZuweisung_FahrzeugTerminKettenAufbau";"dbo";"FahrzeugTerminZuweisung";"IDFahrzeugTerminKettenAufbau_FS";"dbo";"FahrzeugTerminKettenAufbau";"IDFahrzeugTerminKettenAufbau"
"FK_FahrzeugVermietung_Fahrzeug";"dbo";"FahrzeugVermietung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugVersicherung_Fahrzeug";"dbo";"FahrzeugVersicherung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugVerwendung_Fahrzeug";"dbo";"FahrzeugVerwendung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FahrzeugWerbung_Fahrzeug";"dbo";"FahrzeugWerbung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_FehlerProtokoll_Adresse";"dbo";"FehlerProtokoll";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_FehlerProtokoll_FehlerProtokollTyp";"dbo";"FehlerProtokoll";"IDFehlerProtokollTyp_FS";"dbo";"FehlerProtokollTyp";"IDFehlerProtokollTyp"
"FK_FehlerProtokollTypEinstellung_FehlerProtokollTyp_FS";"dbo";"FehlerProtokollTypEinstellung";"IDFehlerProtokollTyp_FS";"dbo";"FehlerProtokollTyp";"IDFehlerProtokollTyp"
"FK_FehlerProtokollTypEinstellung_Kommunikation_FS";"dbo";"FehlerProtokollTypEinstellung";"IDKommunikation_FS";"dbo";"Kommunikation";"IDKommunikation"
"FK_FerienzielZwischenPartner_Adresse";"dbo";"FerienzielZwischenPartner";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_FerienzielZwischenPartner_FerienzielZwischenZeitraum";"dbo";"FerienzielZwischenPartner";"IDFerienzielZwischenZeitraum_FS";"dbo";"FerienzielZwischenZeitraum";"IDFerienzielZwischenZeitraum"
"FK_FerienzielZwischenZeitraum_Produkt";"dbo";"FerienzielZwischenZeitraum";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_Fibuaufteilung_ArtFibuaufteilung";"dbo";"Fibuaufteilung";"IdArtFibuaufteilung_FS";"dbo";"ArtFibuaufteilung";"IDArtFibuaufteilung"
"FK_Fibuaufteilung_Kontenplan";"dbo";"Fibuaufteilung";"IdKontenplan_FS";"dbo";"Kontenplan";"IDKontenplan"
"FK_FibuAufteilungWerte_Buchung";"dbo";"FibuAufteilungWerte";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_FibuAufteilungWerte_Fibuaufteilung";"dbo";"FibuAufteilungWerte";"IDFibuAufteilung_FS";"dbo";"Fibuaufteilung";"IdFibuaufteilung"
"FK_FPAllgemein_ArtFahrplanVersion";"dbo";"FPAllgemein";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_FPLinie_ArtFahrplanVersion";"dbo";"FPLinie";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_FPLinie_ArtFPLinienTyp";"dbo";"FPLinie";"IDArtFPLinienTyp_FS";"dbo";"ArtFPLinienTyp";"IDArtFPLinienTyp"
"FK_FPLinie_ArtLinieVerbund";"dbo";"FPLinie";"IDArtLinieVerbund_FS";"dbo";"ArtLinieVerbund";"IDArtLinieVerbund"
"FK_FPLinie_ArtLinieVUBereich";"dbo";"FPLinie";"IDArtLinieVUBereich_FS";"dbo";"ArtLinieVUBereich";"IDArtLinieVUBereich"
"FK_FPLinie_ArtStatistikGruppe";"dbo";"FPLinie";"IDArtStatistikgruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_FPLinieAnschluss_FPLinie";"dbo";"FPLinieAnschluss";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieAnschluss_FPLinie_Bringer";"dbo";"FPLinieAnschluss";"IDFPLinie_FS_Bringer";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieAnschluss_FPLinieHaltestelle";"dbo";"FPLinieAnschluss";"IDFPLinieHaltestelle_FS_Position";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieAnschluss_FPLinieHaltestelleZubringer";"dbo";"FPLinieAnschluss";"IDFPLinieHaltestelle_FS_Position_Zubringer";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieAnschluss_FPLinieSymbol";"dbo";"FPLinieAnschluss";"IDFPLinieSymbol_FS";"dbo";"FPLinieSymbol";"IDFPLinieSymbol"
"FK_FPLinieAnschlussDefinition_ArtFahrplanVersion";"dbo";"FPLinieAnschlussDefinition";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_FPLinieAnschlussDefinition_FPLinie_Abbringer";"dbo";"FPLinieAnschlussDefinition";"IDFPLinie_FS_Abbringer";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieAnschlussDefinition_FPLinie_Zubringer";"dbo";"FPLinieAnschlussDefinition";"IDFPLinie_FS_Zubringer";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieAnschlussDefinition_Haltepunkt_Abbringer";"dbo";"FPLinieAnschlussDefinition";"IDHaltepunkt_FS_Abbringer";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPLinieAnschlussDefinition_Haltepunkt_Zubringer";"dbo";"FPLinieAnschlussDefinition";"IDHaltepunkt_FS_Zubringer";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPLinieAnschlussDefinition_Haltestelle_Abbringer";"dbo";"FPLinieAnschlussDefinition";"IDHaltestelle_FS_Abbringer";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FPLinieAnschlussDefinition_Haltestelle_Zubringer";"dbo";"FPLinieAnschlussDefinition";"IDHaltestelle_FS_Zubringer";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FPLinieAnschlussDefinitionUmstieg_FPLinieAnschlussDefinition";"dbo";"FPLinieAnschlussDefinitionUmstieg";"IDFPLinieAnschlussDefinition_FS";"dbo";"FPLinieAnschlussDefinition";"IDFPLinieAnschlussDefinition"
"FK_FPLinieAnschlussDefinitionUmstiegGruppeVT_FPLinieAnschlussDefinitionUmstieg";"dbo";"FPLinieAnschlussDefinitionUmstiegGruppeVT";"IDFPLinieAnschlussDefinitionUmstieg_FS";"dbo";"FPLinieAnschlussDefinitionUmstieg";"IDFPLinieAnschlussDefinitionUmstieg"
"FK_FPLinieBeschraenkung_ArtLaufzeitschema";"dbo";"FPLinieBeschraenkung";"IDArtLaufzeitschema_FS";"dbo";"ArtLaufzeitschema";"IDArtLaufzeitschema"
"FK_FPLinieBeschraenkung_FPSondererklaerung";"dbo";"FPLinieBeschraenkung";"IDFPSondererklaerung_FS";"dbo";"FPSondererklaerung";"IDFPSondererklaerung"
"FK_FPLinieBeschraenkungFerienFeier_FPLinieBeschraenkung";"dbo";"FPLinieBeschraenkungFerienFeier";"IDFPLinieBeschraenkung_FS";"dbo";"FPLinieBeschraenkung";"IDFPLinieBeschraenkung"
"FK_FPLinieBeschraenkungLaufzeit_FPLinieBeschraenkung";"dbo";"FPLinieBeschraenkungLaufzeit";"IDFPLinieBeschraenkung_FS";"dbo";"FPLinieBeschraenkung";"IDFPLinieBeschraenkung"
"FK_FPLinieBeschraenkungWochentyp_ArtWochentyp";"dbo";"FPLinieBeschraenkungWochentyp";"IDArtWochentyp_FS";"dbo";"ArtWochentyp";"IDArtWochentyp"
"FK_FPLinieBeschraenkungWochentyp_FPLinieBeschraenkung";"dbo";"FPLinieBeschraenkungWochentyp";"IDFPLinieBeschraenkung_FS";"dbo";"FPLinieBeschraenkung";"IDFPLinieBeschraenkung"
"FK_FPLinieDruck_FPLinie";"dbo";"FPLinieDruck";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieFahrplanAdresse_FahrplanAdresse";"dbo";"FPLinieFahrplanAdresse";"IDFahrplanAdresse_FS";"dbo";"FahrplanAdresse";"IDFahrplanAdresse"
"FK_FPLinieFahrplanAdresse_FPLinie";"dbo";"FPLinieFahrplanAdresse";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieFahrt_ArtFremdunternehmen";"dbo";"FPLinieFahrt";"IDArtFremdunternehmen_FS";"dbo";"ArtFremdunternehmen";"IDArtFremdunternehmen"
"FK_FPLinieFahrt_FPLinie";"dbo";"FPLinieFahrt";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieFahrt_FPLinieFahrt";"dbo";"FPLinieFahrt";"IDFPLinieFahrt_FS_VerstaerkerVon";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPLinieFahrt_FPLinieFahrt_TeilenOriginal";"dbo";"FPLinieFahrt";"IDFPLinieFahrt_FS_TeilenOriginal";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPLinieFahrt_FPLinieZeitart";"dbo";"FPLinieFahrt";"IDFPLinieZeitart_FS";"dbo";"FPLinieZeitart";"IDFPLinieZeitart"
"FK_FPLinieFahrtAnschluss_FPLinieAnschluss";"dbo";"FPLinieFahrtAnschluss";"IDFPLinieAnschluss_FS";"dbo";"FPLinieAnschluss";"IDFPLinieAnschluss"
"FK_FPLinieFahrtAnschluss_FPLinieFahrt";"dbo";"FPLinieFahrtAnschluss";"IDFPLinieFahrt_FS";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPLinieFahrtAnschluss_FPLinieFahrt_Bringer";"dbo";"FPLinieFahrtAnschluss";"IDFPLinieFahrt_FS_Bringer";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPLinieFahrtAnschluss_FPLinieHaltestelle_Bringer";"dbo";"FPLinieFahrtAnschluss";"IDFPLinieHaltestelle_FS_Bringer";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieFahrtAnschlussBeschraenkung_FPLinieBeschraenkung";"dbo";"FPLinieFahrtAnschlussBeschraenkung";"IDFPLinieBeschraenkung_FS";"dbo";"FPLinieBeschraenkung";"IDFPLinieBeschraenkung"
"FK_FPLinieFahrtAnschlussBeschraenkung_FPLinieFahrtAnschluss";"dbo";"FPLinieFahrtAnschlussBeschraenkung";"IDFPLinieFahrtAnschluss_FS";"dbo";"FPLinieFahrtAnschluss";"IDFPLinieFahrtAnschluss"
"FK_FPLinieFahrtBeschraenkung_FPLinieBeschraenkung";"dbo";"FPLinieFahrtBeschraenkung";"IDFPLinieBeschraenkung_FS";"dbo";"FPLinieBeschraenkung";"IDFPLinieBeschraenkung"
"FK_FPLinieFahrtBeschraenkung_FPLinieFahrt";"dbo";"FPLinieFahrtBeschraenkung";"IDFPLinieFahrt_FS";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPLinieHaltestelle_ArtKreisGebiet";"dbo";"FPLinieHaltestelle";"IDArtKreisGebiet_FS";"dbo";"ArtKreisGebiet";"IDArtKreisGebiet"
"FK_FPLinieHaltestelle_FPLinie";"dbo";"FPLinieHaltestelle";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieHaltestelle_FPLinieHaltestelle";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle_FS_VerschiebenAuf";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieHaltestelle_Haltepunkt";"dbo";"FPLinieHaltestelle";"IDHaltepunkt_FS";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPLinieHaltestelle_Haltestelle";"dbo";"FPLinieHaltestelle";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FPLinieHaltestelleBemerkung_FPLinieHaltestelle";"dbo";"FPLinieHaltestelleBemerkung";"IDFPLinieHaltestelle_FS";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieHaltestelleBemerkung_HaltestelleBemerkung";"dbo";"FPLinieHaltestelleBemerkung";"IDHaltestelleBemerkung_FS";"dbo";"HaltestelleBemerkung";"IDHaltestelleBemerkung"
"FK_FPLinieHaltestelleZeitart_ArtKreisGebiet";"dbo";"FPLinieHaltestelleZeitart";"IDArtKreisGebiet_FS";"dbo";"ArtKreisGebiet";"IDArtKreisGebiet"
"FK_FPLinieHaltestelleZeitart_FPLinieHaltestelle";"dbo";"FPLinieHaltestelleZeitart";"IDFPLinieHaltestelle_FS";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieHaltestelleZeitart_FPLinieZeitart";"dbo";"FPLinieHaltestelleZeitart";"IDFPLinieZeitart_FS";"dbo";"FPLinieZeitart";"IDFPLinieZeitart"
"FK_FPLinieHaltestelleZeitart_HaltestelleBemerkung";"dbo";"FPLinieHaltestelleZeitart";"IDHaltestelleBemerkung_FS";"dbo";"HaltestelleBemerkung";"IDHaltestelleBemerkung"
"FK_FPLinieHaltestelleZeitart_LinieZiel";"dbo";"FPLinieHaltestelleZeitart";"IDLinieZiel_FS";"dbo";"LinieZiel";"IDLinieZiel"
"FK_FPLinieZeitart_ArtStatistikGruppe";"dbo";"FPLinieZeitart";"IDArtStatistikgruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_FPLinieZeitart_FPLinie";"dbo";"FPLinieZeitart";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_FPLinieZeitart_FPLinieHaltestelle_TeilenAbschnittBis";"dbo";"FPLinieZeitart";"IDFPLinieHaltestelle_FS_TeilenAbschnittBis";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieZeitart_FPLinieHaltestelle_TeilenAbschnittVon";"dbo";"FPLinieZeitart";"IDFPLinieHaltestelle_FS_TeilenAbschnittVon";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPLinieZeitart_FPLinieZeitart";"dbo";"FPLinieZeitart";"IDFPLinieZeitart_FS_TeilenOriginal";"dbo";"FPLinieZeitart";"IDFPLinieZeitart"
"FK_FPSchuelerAbsage_Adresse";"dbo";"FPSchuelerAbsage";"IdAdresse_FS_Bearbeitet";"dbo";"Adresse";"IDAdresse"
"FK_FPSchuelerAbsage_FPSchueler";"dbo";"FPSchuelerAbsage";"IDFPSchueler_FS";"dbo";"FPSchueler";"IDFPSchueler"
"FK_FPSchuelerBefoerderung_FPSchueler";"dbo";"FPSchuelerBefoerderung";"IDFPSchueler_FS";"dbo";"FPSchueler";"IDFPSchueler"
"FK_FPSchuelerBefoerderung_FPSchule";"dbo";"FPSchuelerBefoerderung";"IDFPSchule_FS";"dbo";"FPSchule";"IDFPSchule"
"FK_FPSchuelerBefoerderung_FPSchuljahr";"dbo";"FPSchuelerBefoerderung";"IDFPSchuljahr_FS";"dbo";"FPSchuljahr";"IDFPSchuljahr"
"FK_FPSchuelerBefoerderungBewegung_Haltepunkt_Ausstieg";"dbo";"FPSchuelerBefoerderungBewegung";"IDHaltepunkt_FS_Ausstieg";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPSchuelerBefoerderungBewegung_Haltepunkt_Einstieg";"dbo";"FPSchuelerBefoerderungBewegung";"IDHaltepunkt_FS_Einstieg";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPSchuelerBefoerderungBewegung_Haltestelle_Ausstieg";"dbo";"FPSchuelerBefoerderungBewegung";"IDHaltestelle_FS_Ausstieg";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FPSchuelerBefoerderungBewegung_Haltestelle_Einstieg";"dbo";"FPSchuelerBefoerderungBewegung";"IDHaltestelle_FS_Einstieg";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FPSchuelerBefoerderungBewegung_IDFPSchuelerBefoerderung";"dbo";"FPSchuelerBefoerderungBewegung";"IDFPSchuelerBefoerderung_FS";"dbo";"FPSchuelerBefoerderung";"IDFPSchuelerBefoerderung"
"FK_FPSchuelerBefoerderungBewegungAbsage_FPSchuelerAbsage";"dbo";"FPSchuelerBefoerderungBewegungAbsage";"IDFPSchuelerAbsage_FS";"dbo";"FPSchuelerAbsage";"IDFPSchuelerAbsage"
"FK_FPSchuelerBefoerderungBewegungAbsage_FPSchuelerBefoerderungBewegung";"dbo";"FPSchuelerBefoerderungBewegungAbsage";"IDFPSchuelerBefoerderungBewegung_FS";"dbo";"FPSchuelerBefoerderungBewegung";"IDFPSchuelerBefoerderungBewegung"
"FK_FPSchuelerBefoerderungBewegungZuordnung_FPLinieFahrt";"dbo";"FPSchuelerBefoerderungBewegungZuordnung";"IDFPLinieFahrt_FS";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_FPSchuelerBefoerderungBewegungZuordnung_FPLinieHaltestelle";"dbo";"FPSchuelerBefoerderungBewegungZuordnung";"IDFPLinieHaltestelle_FS";"dbo";"FPLinieHaltestelle";"IDFPLinieHaltestelle"
"FK_FPSchuelerBefoerderungBewegungZuordnung_FPSchuelerBefoerderungBewegung";"dbo";"FPSchuelerBefoerderungBewegungZuordnung";"IDFPSchuelerBefoerderungBewegung_FS";"dbo";"FPSchuelerBefoerderungBewegung";"IDFPSchuelerBefoerderungBewegung"
"FK_FPSchuelerBefoerderungBewegungZuordnung_FPZeitart";"dbo";"FPSchuelerBefoerderungBewegungZuordnung";"IDFPLinieZeitart_FS";"dbo";"FPLinieZeitart";"IDFPLinieZeitart"
"FK_FPSchuleHaltestelleHaltepunkt_FPSchule";"dbo";"FPSchuleHaltestelleHaltepunkt";"IDFPSchule_FS";"dbo";"FPSchule";"IDFPSchule"
"FK_FPSchuleHaltestelleHaltepunkt_Haltepunkt";"dbo";"FPSchuleHaltestelleHaltepunkt";"IDHaltepunkt_FS";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_FPSchuleHaltestelleHaltepunkt_Haltestelle";"dbo";"FPSchuleHaltestelleHaltepunkt";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_FreibescheinigungManuelleEingabe_Adresse";"dbo";"FreibescheinigungManuelleEingabe";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_FreibescheinigungRuhetag_Adresse";"dbo";"FreibescheinigungRuhetag";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_GruppeVerkehrstag_ArtGruppeVerkehrstag";"dbo";"GruppeVerkehrstag";"IDArtGruppeVerkehrstag_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_GruppeVerkehrstagFerien_ArtGruppeVerkehrstag";"dbo";"GruppeVerkehrstagFerien";"IDArtGruppeVerkehrstag_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_Gutschein_ArtGutscheinversand";"dbo";"Gutschein";"IDArtGutscheinversand_FS";"dbo";"ArtGutscheinversand";"IDArtGutscheinversand"
"FK_GutscheinlayoutInternet_ArtGutscheinlayout";"dbo";"GutscheinlayoutInternet";"IDArtGutscheinlayout_FS";"dbo";"ArtGutscheinlayout";"IDArtGutscheinlayout"
"FK_Gutscheinzuschlag_Gutschein";"dbo";"GutscheinZuschlag";"IDGutschein_FS";"dbo";"Gutschein";"IDGutschein"
"FK_Gutscheinzuschlag_Kontenplan";"dbo";"GutscheinZuschlag";"IDKontenplan_FS";"dbo";"Kontenplan";"IDKontenplan"
"FK_Haltepunkt_ArtHaltepunktArt";"dbo";"Haltepunkt";"IDArtHaltepunktArt_FS";"dbo";"ArtHaltepunktArt";"IDArtHaltepunktArt"
"FK_Haltepunkt_Haltestelle";"dbo";"Haltepunkt";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_HaltepunktFahrplankasten_ArtHaltepunktFahrplankasten";"dbo";"HaltepunktFahrplankasten";"IDArtHaltepunktFahrplankasten_FS";"dbo";"ArtHaltepunktFahrplankasten";"IDArtHaltepunktFahrplankasten"
"FK_HaltepunktFahrplankasten_HaltestelleHaltepunkt";"dbo";"HaltepunktFahrplankasten";"IDHaltestelleHaltepunkt_FS";"dbo";"HaltestelleHaltepunkt";"IDHaltestelleHaltepunkt"
"FK_Haltestelle_ArtHaltestelleZwischenpunkttyp";"dbo";"Haltestelle";"IDArtHaltestelleZwischenpunkttyp_FS";"dbo";"ArtHaltestelleZwischenpunkttyp";"IDArtHaltestelleZwischenpunkttyp"
"FK_Haltestelle_HaltestelleNach";"dbo";"Haltestelle";"IDHaltestelle_FS_ZwNach";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Haltestelle_HaltestelleVon";"dbo";"Haltestelle";"IDHaltestelle_FS_ZwVon";"dbo";"Haltestelle";"IDHaltestelle"
"FK_HaltestelleDruck_Haltestelle";"dbo";"HaltestelleDruck";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_HaltestelleFahrplanAdresse_FahrplanAdresse";"dbo";"HaltestelleFahrplanAdresse";"IDFahrplanAdresse_FS";"dbo";"FahrplanAdresse";"IDFahrplanAdresse"
"FK_HaltestelleFahrplanAdresse_Haltestelle";"dbo";"HaltestelleFahrplanAdresse";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_HaltestelleHaltepunkt_ArtBetriebshof";"dbo";"HaltestelleHaltepunkt";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_HaltestelleHaltepunkt_ArtHaltepunktAbfallbehaelter";"dbo";"HaltestelleHaltepunkt";"IDArtHaltepunktAbfallbehaelter_FS";"dbo";"ArtHaltepunktAbfallbehaelter";"IDArtHaltepunktAbfallbehaelter"
"FK_HaltestelleHaltepunkt_ArtHaltepunktBlindenleitsystem";"dbo";"HaltestelleHaltepunkt";"IDArtHaltepunktBlindenleitsystem_FS";"dbo";"ArtHaltepunktBlindenleitsystem";"IDArtHaltepunktBlindenleitsystem"
"FK_HaltestelleHaltepunkt_ArtHaltepunktBlinkaufforderung";"dbo";"HaltestelleHaltepunkt";"IDArtHaltepunktBlinkaufforderung_FS";"dbo";"ArtHaltepunktBlinkaufforderung";"IDArtHaltepunktBlinkaufforderung"
"FK_HaltestelleHaltepunkt_ArtHaltepunktBusbordstein";"dbo";"HaltestelleHaltepunkt";"IDArtHaltepunktBusbordstein_FS";"dbo";"ArtHaltepunktBusbordstein";"IDArtHaltepunktBusbordstein"
"FK_HaltestelleHaltepunkt_Haltepunkt";"dbo";"HaltestelleHaltepunkt";"IDHaltepunkt_FS";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_HaltestelleHaltepunkt_Haltestelle";"dbo";"HaltestelleHaltepunkt";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_HaltestelleHaltepunkt_Ort";"dbo";"HaltestelleHaltepunkt";"IDOrt_FS";"dbo";"Ort";"IDOrt"
"FK_ImportAdressen_ArtImportAdressen";"dbo";"ImportAdressen";"IDArtImportAdressen_FS";"dbo";"ArtImportAdressen";"IDArtImportAdressen"
"FK_ImportMatrix_ArtBuchungsImport";"dbo";"ImportMatrix";"IDArtBuchungsImport_FS";"dbo";"ArtBuchungsImport";"IDArtBuchungsImport"
"FK_InternetCRMZuweisung_ArtCRMGruppe";"dbo";"InternetCRMZuweisung";"IDArtCRMGruppe_FS";"dbo";"ArtCRMGruppe";"IDArtCRMGruppe"
"FK_InternetCRMZuweisung_ArtCRMInternet";"dbo";"InternetCRMZuweisung";"IDArtCRMInternet_FS";"dbo";"ArtCRMInternet";"IDArtCRMInternet"
"FK_KalenderFahrplanversion_ArtFahrplanVersion";"dbo";"KalenderFahrplanversion";"IDArtFahrplanversion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_KalenderLaufzeitschema_ArtLaufzeitschema";"dbo";"KalenderLaufzeitschema";"IDArtLaufzeitschema_FS";"dbo";"ArtLaufzeitschema";"IDArtLaufzeitschema"
"FK_KalenderSondergruppen_ArtGruppeVerkehrstag";"dbo";"KalenderSondergruppen";"IDArtSondergruppen_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_KalenderWochentypen_ArtWochentyp";"dbo";"KalenderWochentypen";"IDArtWochentyp_FS";"dbo";"ArtWochentyp";"IDArtWochentyp"
"FK_KalkulationBeförderung_Kalkulation";"dbo";"KalkulationBeförderung";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationBeförderungLand_KalkulationBeförderung";"dbo";"KalkulationBeförderungLand";"IDKalkulationBeförderung_FS";"dbo";"KalkulationBeförderung";"IDKalkulationBeförderung"
"FK_KalkulationBusleistung_Kalkulation";"dbo";"KalkulationBusleistung";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationBusleistungPreis_KalkulationBusleistung";"dbo";"KalkulationBusleistungPreis";"IDKalkulationBusleistung_FS";"dbo";"KalkulationBusleistung";"IDKalkulationBusleistung"
"FK_KalkulationBusleistungPreis_Kalkulationswertbezeichnung";"dbo";"KalkulationBusleistungPreis";"IDKalkulationswertbezeichnung_FS";"dbo";"KalkulationswertBezeichnung";"IDKalkulationswertBezeichnung"
"FK_KalkulationErgebnis_Kalkulation";"dbo";"KalkulationErgebnis";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationErgebnisM_Kalkulation";"dbo";"KalkulationErgebnisM";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationErgebnisZimmerPreis_KalkulationErgebnis";"dbo";"KalkulationErgebnisZimmerPreis";"IDKalkulationErgebnis_FS";"dbo";"KalkulationErgebnis";"IDKalkulationErgebnis"
"FK_KalkulationErgebnisZimmerPreis_Zimmerart";"dbo";"KalkulationErgebnisZimmerPreis";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_KalkulationFZAusgrenzung_KalkulationFZ";"dbo";"KalkulationFZAusgrenzung";"IDKalkulationFZ_FS";"dbo";"KalkulationFZ";"IDKalkulationFZ"
"FK_KalkulationFZBeförderung_KalkulationFZ";"dbo";"KalkulationFZBeförderung";"IDKalkulationFZ_FS";"dbo";"KalkulationFZ";"IDKalkulationFZ"
"FK_KalkulationFZErgebnis_ArtPartnerPreisCode";"dbo";"KalkulationFZErgebnis";"IdArtPartnerPreisCode_FS";"dbo";"ArtPartnerPreisCode";"IDArtPartnerPreisCode"
"FK_KalkulationFZErgebnis_ArtVerpflegung";"dbo";"KalkulationFZErgebnis";"IDArtVerpflegung_FS";"dbo";"ArtVerpflegung";"IDArtVerpflegung"
"FK_KalkulationFZErgebnis_KalkulationFZ";"dbo";"KalkulationFZErgebnis";"IDKalkulationFZ_FS";"dbo";"KalkulationFZ";"IDKalkulationFZ"
"FK_KalkulationFZTag_KalkulationFZ";"dbo";"KalkulationFZTag";"IDKalkulationFZ_FS";"dbo";"KalkulationFZ";"IDKalkulationFZ"
"FK_KalkulationPax_Kalkulation";"dbo";"KalkulationPax";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationReise_Kalkulation";"dbo";"KalkulationReise";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationReise_Reise";"dbo";"KalkulationReise";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_KalkulationSonstiges_Kalkulation";"dbo";"KalkulationSonstiges";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationSonstigesPreis_KalkulationSonstiges";"dbo";"KalkulationSonstigesPreis";"IDKalkulationSonstiges_FS";"dbo";"KalkulationSonstiges";"IDKalkulationSonstiges"
"FK_KalkulationUnterbringung_Kalkulation";"dbo";"KalkulationUnterbringung";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationUnterbringungM_Kalkulation";"dbo";"KalkulationUnterbringungM";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationUnterbringungMPreis_KalkulationUnterbringungM";"dbo";"KalkulationUnterbringungMPreis";"IDKalkulationUnterbringungM_FS";"dbo";"KalkulationUnterbringungM";"IDKalkulationUnterbringungM"
"FK_KalkulationUnterbringungPartner_Adresse";"dbo";"KalkulationUnterbringungPartner";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_KalkulationUnterbringungPartner_KalkulationUnterbringung";"dbo";"KalkulationUnterbringungPartner";"IDKalkulationUnterbringung_FS";"dbo";"KalkulationUnterbringung";"IDKalkulationUnterbringung"
"FK_KalkulationUnterbringungPreis_KalkulationUnterbringung";"dbo";"KalkulationUnterbringungPreis";"IDKalkulationUnterbringung_FS";"dbo";"KalkulationUnterbringung";"IDKalkulationUnterbringung"
"FK_KalkulationUnterbringungPreis_KalkulationUnterbringungPartner";"dbo";"KalkulationUnterbringungPreis";"IDKalkulationUnterbringungPartner_FS";"dbo";"KalkulationUnterbringungPartner";"IDKalkulationUnterbringungPartner"
"FK_KalkulationUnterbringungPreis_KalkulationUnterbringungZimmer";"dbo";"KalkulationUnterbringungPreis";"IDKalkulationUnterbringungZimmer_FS";"dbo";"KalkulationUnterbringungZimmer";"IDKalkulationUnterbringungZimmer"
"FK_KalkulationUnterbringungZimmer_KalkulationUnterbringung";"dbo";"KalkulationUnterbringungZimmer";"IDKalkulationUnterbringung_FS";"dbo";"KalkulationUnterbringung";"IDKalkulationUnterbringung"
"FK_KalkulationUnterbringungZimmer_Zimmerart";"dbo";"KalkulationUnterbringungZimmer";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_KalkulationUnterbringungZimmerPreis_KalkulationUnterbringung";"dbo";"KalkulationUnterbringungZimmerPreis";"IDKalkulationUnterbringung_FS";"dbo";"KalkulationUnterbringung";"IDKalkulationUnterbringung"
"FK_KalkulationUnterbringungZimmerPreis_KalkulationUnterbringungZimmer";"dbo";"KalkulationUnterbringungZimmerPreis";"IDKalkulationUnterbringungZimmerPreis";"dbo";"KalkulationUnterbringungZimmer";"IDKalkulationUnterbringungZimmer"
"FK_KalkulationZuschlag_Kalkulation";"dbo";"KalkulationZuschlag";"IDKalkulation_FS";"dbo";"Kalkulation";"IDKalkulation"
"FK_KalkulationZuschlagPosten_KalkulationZuschlag";"dbo";"KalkulationZuschlagPosten";"IDKalkulationZuschlag_FS";"dbo";"KalkulationZuschlag";"IDKalkulationZuschlag"
"FK_KommunikationEinstellung_Kommunikation";"dbo";"KommunikationEinstellung";"IDKommunikation_FS";"dbo";"Kommunikation";"IDKommunikation"
"FK_KonstantenErmäßigungProdukt_KonstantenErmäßigung";"dbo";"KonstantenErmäßigungProdukt";"IDKonstantenErmäßigungStaffel_FS";"dbo";"KonstantenErmäßigungStaffel";"IDKonstantenErmäßigungStaffel"
"FK_KonstantenErmäßigungProdukt_Produkt";"dbo";"KonstantenErmäßigungProdukt";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_KonstantenErmäßigungStaffel_KonstantenErmäßigung";"dbo";"KonstantenErmäßigungStaffel";"IDKonstantenErmäßigung_FS";"dbo";"KonstantenErmäßigung";"IDKonstantenErmäßigung"
"FK_KonstantenErmäßigungZimmer_KonstantenErmäßigung";"dbo";"KonstantenErmäßigungZimmer";"IDKonstantenErmäßigungStaffel_FS";"dbo";"KonstantenErmäßigungStaffel";"IDKonstantenErmäßigungStaffel"
"FK_KonstantenErmäßigungZimmer_Zimmerart";"dbo";"KonstantenErmäßigungZimmer";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_KonstantenErmäßigungZustieg_KonstantenErmäßigung";"dbo";"KonstantenErmäßigungZustieg";"IDKonstantenErmäßigungStaffel_FS";"dbo";"KonstantenErmäßigungStaffel";"IDKonstantenErmäßigungStaffel"
"FK_KonstantenErmäßigungZustieg_Zustieg";"dbo";"KonstantenErmäßigungZustieg";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_KonstantenFlexTarifStaffel_KonstantenFlexTarif";"dbo";"KonstantenFlexTarifStaffel";"IDKonstantenFlexTarif_FS";"dbo";"KonstantenFlexTarif";"IDKonstantenFlexTarif"
"FK_KonstantenFlexTarifStaffel_Leistung";"dbo";"KonstantenFlexTarifStaffel";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_KonstantenGruppenermStaffel_KonstantenGruppenerm";"dbo";"KonstantenGruppenermStaffel";"IDKonstantenGruppenerm_FS";"dbo";"KonstantenGruppenerm";"IDKonstantenGruppenerm"
"FK_KonstantenRabattStaffelEingabe_KonstantenRabattStaffel";"dbo";"KonstantenRabattStaffelEingabe";"IDKonstantenRabattStaffel_FS";"dbo";"KonstantenRabattStaffel";"IDKonstantenRabattStaffel"
"FK_KonstantenStAuftZuschlag_Land";"dbo";"KonstantenStAuftZuschlag";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_KonstantenSteueraufteilung_SteueraufteilungArt";"dbo";"KonstantenSteueraufteilung";"IDSteueraufteilungArt_FS";"dbo";"SteueraufteilungArt";"IDSteueraufteilungArt"
"FK_KonstantenSteueraufteilungDetail_KonstantenSteueraufteilung";"dbo";"KonstantenSteueraufteilungDetail";"IDKonstantenSteueraufteilung_FS";"dbo";"KonstantenSteueraufteilung";"IDKonstantenSteueraufteilung"
"FK_KonstantenSteueraufteilungDetail_Steueraufteilung";"dbo";"KonstantenSteueraufteilungDetail";"IDSteueraufteilungDetail_FS";"dbo";"SteueraufteilungDetail";"IDSteueraufteilungDetail"
"FK_KonstantenStornoStaffelTage_KonstantenStornoStaffel";"dbo";"KonstantenStornoStaffelTage";"IDKonstantenStornoStaffel_FS";"dbo";"KonstantenStornoStaffel";"IDKonstantenStornoStaffel"
"FK_ArtikelLagerort_Artikel";"dbo";"LagerRegal";"IDLager_FS";"dbo";"Lager";"IDLager"
"FK_LandFiskal_Land";"dbo";"LandFiskal";"IDLand_Fs";"dbo";"Land";"IDLand"
"FK_LandHinweis_Land";"dbo";"LandHinweis";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_LandKonto_Land";"dbo";"LandKonto";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_LandMwst_Land";"dbo";"LandMwst";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_LandVerpflegungSpesen_ArtSpesenLand";"dbo";"LandVerpflegungSpesen";"IDArtSpesenLand_FS";"dbo";"ArtSpesenLand";"IDArtSpesenLand"
"FK_LandVerpflegungSpesen_ArtSpesenVerpflegung";"dbo";"LandVerpflegungSpesen";"IDArtSpesenVerpflegung_FS";"dbo";"ArtSpesenVerpflegung";"IDArtSpesenVerpflegung"
"FK_Leistung_ArtLeistungSonstigesUnterart";"dbo";"Leistung";"IDArtLeistungSonstigesUnterart_FS";"dbo";"ArtLeistungSonstigesUnterart";"IDArtLeistungSonstigesUnterart"
"FK_Leistung_LeistungBefoerderung";"dbo";"LeistungBefoerderung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_Leistung_LeistungExternSystem";"dbo";"LeistungExternSystem";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungHotelMoeglich_Adresse";"dbo";"LeistungHotelGesperrt";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_LeistungHotelMoeglich_LeistungBefoerderung";"dbo";"LeistungHotelGesperrt";"IDLeistungBefoerderung_FS";"dbo";"LeistungBefoerderung";"IDLeistungBefoerderung"
"FK_Adresse_LeistungMandantMoeglich";"dbo";"LeistungMandantMoeglich";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Leistung_LeistungMandantMoeglich";"dbo";"LeistungMandantMoeglich";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_Adresse_LeistungPartnerMoeglich";"dbo";"LeistungPartnerMoeglich";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Leistung_LeistungPartnerMoeglich";"dbo";"LeistungPartnerMoeglich";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungPreis_ArtPreisschema";"dbo";"LeistungPreis";"IDArtPreisSchema_FS";"dbo";"ArtPreisschema";"IDArtPreisschema"
"FK_LeistungPreis_Leistung";"dbo";"LeistungPreis";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungProdukt_Leistung";"dbo";"LeistungProdukt";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungProdukt_Produkt";"dbo";"LeistungProdukt";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_Leistung_LeistungSelektion";"dbo";"LeistungSelektionenKunde";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_Selektionsstamm_LeistungSelektion";"dbo";"LeistungSelektionenKunde";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_LeistungSitzplan_Leistung";"dbo";"LeistungSitzplan";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungSitzplan_Sitzplan";"dbo";"LeistungSitzplan";"IDSitzplan_FS";"dbo";"Sitzplan";"IDSitzplan"
"FK_Leistung_LeistungText";"dbo";"LeistungText";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_Leistung_LeistungTicket";"dbo";"LeistungTicket";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungTicketZusatz_LeistungTicket";"dbo";"LeistungTicketZusatz";"IDLeistungTicket_FS";"dbo";"LeistungTicket";"IDLeistungTicket"
"FK_LeistungVersicherung_Leistung";"dbo";"LeistungVersicherung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungVersicherung_Versicherungsbedingung_Leistung";"dbo";"LeistungVersicherung_Versicherungsbedingung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungVersicherung_Versicherungsbedingung_Versicherungsbedingung";"dbo";"LeistungVersicherung_Versicherungsbedingung";"IDVersicherungsbedingung_FS";"dbo";"Versicherungsbedingung";"IDVersicherungsbedingung"
"FK_LeistungVersicherungsGruppe_ArtVersicherungsGruppe";"dbo";"LeistungVersicherungsGruppe";"IDArtVersicherungsGruppe_FS";"dbo";"ArtVersicherungsGruppe";"IDArtVersicherungsGruppe"
"FK_LeistungVersicherungsGruppe_LeistungVersicherung";"dbo";"LeistungVersicherungsGruppe";"IDLeistungVersicherung_FS";"dbo";"LeistungVersicherung";"IDLeistungVersicherung"
"FK_Leistung_LeistungVoucher";"dbo";"LeistungVoucher";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungZusatz_ArtAgenturPreisgruppe";"dbo";"LeistungZusatz";"IDArtAgenturPreisgruppe_FS";"dbo";"ArtAgenturPreisgruppe";"IDArtAgenturPreisgruppe"
"FK_LeistungZusatz_KonstantenSteueraufteilung";"dbo";"LeistungZusatz";"IDKonstantenSteueraufteilung_FS";"dbo";"KonstantenSteueraufteilung";"IDKonstantenSteueraufteilung"
"FK_LeistungZusatz_Leistung";"dbo";"LeistungZusatz";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_LeistungZustiegMoeglich_LeistungBefoerderung";"dbo";"LeistungZustiegMoeglichGesperrt";"IDLeistungBefoerderung_FS";"dbo";"LeistungBefoerderung";"IDLeistungBefoerderung"
"FK_Zustieg_LeistungZustiegMoeglich";"dbo";"LeistungZustiegMoeglichGesperrt";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_LiniePlanungEinstellung_Adresse";"dbo";"LiniePlanungEinstellung";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_LiniePlanungEinstellung_ArtPersonalGruppeKompetenz";"dbo";"LiniePlanungEinstellung";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_LinieStatistikAufteilungSpalteZuordnung_ArtStatistikGruppe";"dbo";"LinieStatistikAufteilungSpalteZuordnung";"IDArtStatistikGruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_LinieStatistikAufteilungSpalteZuordnung_Auftragsart";"dbo";"LinieStatistikAufteilungSpalteZuordnung";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_LinieStatistikAufteilungSpalteZuordnung_LinieStatistikAufteilungSpalte";"dbo";"LinieStatistikAufteilungSpalteZuordnung";"IDLinieStatistikAufteilungSpalte_FS";"dbo";"LinieStatistikAufteilungSpalte";"IDLinieStatistikAufteilungSpalte"
"FK_LinieStatistikSummeSpalte_ArtLinieStatistikSumme";"dbo";"LinieStatistikSummeSpalte";"IDArtLinieStatistikSumme_FS";"dbo";"ArtLinieStatistikSumme";"IDArtLinieStatistikSumme"
"FK_LinieStatistikSummeSpalteZuordnung_ArtStatistikGruppe";"dbo";"LinieStatistikSummeSpalteZuordnung";"IDArtStatistikGruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_LinieStatistikSummeSpalteZuordnung_Auftragsart";"dbo";"LinieStatistikSummeSpalteZuordnung";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_LinieStatistikSummeSpalteZuordnung_LinieStatistikSummeSpalte";"dbo";"LinieStatistikSummeSpalteZuordnung";"IDLinieStatistikSummeSpalte_FS";"dbo";"LinieStatistikSummeSpalte";"IDLinieStatistikSummeSpalte"
"FK_LinieWegPunkteGM_Haltestelle";"dbo";"LinieWegPunkteGM";"IDHaltestelle_FS_von";"dbo";"Haltestelle";"IDHaltestelle"
"FK_LinieWegPunkteGM_Haltestelle1";"dbo";"LinieWegPunkteGM";"IDHaltestelle_FS_nach";"dbo";"Haltestelle";"IDHaltestelle"
"FK_LinieZiel_ArtLinieZielSonderzeichen";"dbo";"LinieZiel";"IDArtLinieZielSonderzeichen_FS";"dbo";"ArtLinieZielSonderzeichen";"IDArtLinieZielSonderzeichen"
"FK_LinieZusatzKilometer_ArtStatistikGruppe";"dbo";"LinieZusatzKilometer";"IDArtStatistikgruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_LinieZusatzKilometer_Auftragsart";"dbo";"LinieZusatzKilometer";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_LinieZusatzKilometer_Fahrzeug";"dbo";"LinieZusatzKilometer";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_ListenterminalEinstellung_Adresse";"dbo";"ListenterminalEinstellung";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ListenterminalEinstellung_ArtPersonalGruppeKompetenz";"dbo";"ListenterminalEinstellung";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_Lohnart_ArtLohnsystem";"dbo";"Lohnart";"IDArtLohnsystem_FS";"dbo";"ArtLohnsystem";"IDArtLohnsystem"
"FK_LohnartPersonalSperrung_Adresse";"dbo";"LohnartPersonalSperrung";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_LohnartPersonalSperrung_Lohnart";"dbo";"LohnartPersonalSperrung";"IDLohnart_FS";"dbo";"Lohnart";"IDLohnart"
"FK_LohnartTag_Lohnart";"dbo";"LohnartTag";"IDLohnart_FS";"dbo";"Lohnart";"IDLohnart"
"FK_LohnDruckLobuPersonalSperrung_Adresse";"dbo";"LohnDruckLobuPersonalSperrung";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_LohnDruckLobuPersonalSperrung_ArtLohnDruckLobu";"dbo";"LohnDruckLobuPersonalSperrung";"IDArtLohnDruckLobu_FS";"dbo";"ArtLohnDruckLobu";"IDArtLohnDruckLobu"
"FK_Lohnextra_Adresse";"dbo";"Lohnextra";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_Lohnextra_ArtLohnextra";"dbo";"Lohnextra";"IDArtLohnextra_FS";"dbo";"ArtLohnextra";"IDArtLohnextra"
"FK_LohnParameter_Adresse";"dbo";"LohnParameter";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_LohnParameter_ArtLohnsystem";"dbo";"LohnParameter";"IDArtLohnsystem_FS";"dbo";"ArtLohnsystem";"IDArtLohnsystem"
"FK_LohnStundenkonto_Adresse";"dbo";"LohnStundenkonto";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_LohnStundenkonto_ArtLohnStundenkonto";"dbo";"LohnStundenkonto";"IDArtLohnStundenkonto_FS";"dbo";"ArtLohnStundenkonto";"IDArtLohnStundenkonto"
"FK_LohnsystemPersonalSperrung_Adresse";"dbo";"LohnsystemPersonalSperrung";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_LohnsystemPersonalSperrung_ArtLohnsystem";"dbo";"LohnsystemPersonalSperrung";"IDArtLohnsystem_FS";"dbo";"ArtLohnsystem";"IDArtLohnsystem"
"FK_LohnTagesdaten_Adresse";"dbo";"LohnTagesdaten";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_LohnUebergabe_Adresse";"dbo";"LohnUebergabe";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_LohnUebergabe_ArtLohnsystem";"dbo";"LohnUebergabe";"IDArtLohnsystem_FS";"dbo";"ArtLohnsystem";"IDArtLohnsystem"
"FK_MandantZuordnungZahlung_Adresse";"dbo";"MandantZuordnungKontenplan";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_MandantZuordnungZahlung_ZahlungCode";"dbo";"MandantZuordnungKontenplan";"IDMandantZuordnung_FS";"dbo";"Kontenplan";"IDKontenplan"
"FK_MandantZuordnungReise_Adresse";"dbo";"MandantZuordnungReise";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_MandantZuordnungReise_Reise";"dbo";"MandantZuordnungReise";"IDMandantZuordnung_FS";"dbo";"Reise";"IDReise"
"FK_MandantZuordnungZustieg_Adresse";"dbo";"MandantZuordnungZustieg";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_MandantZuordnungZustieg_Zustieg";"dbo";"MandantZuordnungZustieg";"IDMandantZuordnung_FS";"dbo";"Zustieg";"IDZustieg"
"FK_MitgliedAdresse_ArtMitgliedsstufen";"dbo";"MitgliedsstufeAdresse";"IDArtMitgliedsstufe_FS";"dbo";"ArtMitgliedsstufe";"IDArtMitgliedsstufe"
"FK_MitgliedAdresse_ArtZahlungsart";"dbo";"MitgliedsstufeAdresse";"IDArtZahlungsart_FS";"dbo";"ArtZahlungsart";"IDArtZahlungsart"
"FK_MitgliedsstufeAdresse_Adresse";"dbo";"MitgliedsstufeAdresse";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_MitgliedsEinstellungBetrag_ArtMitgliedsstufen";"dbo";"MitgliedsstufeBetrag";"IDArtMitgliedsstufe_FS";"dbo";"ArtMitgliedsstufe";"IDArtMitgliedsstufe"
"FK_MitgliedVorteilBezeichnungArtMitgliedsstufe_ArtMitgliedsstufe";"dbo";"MitgliedsVorteilBezeichnungArtMitgliedsstufe";"IDArtMitgliedsstufe_FS";"dbo";"ArtMitgliedsstufe";"IDArtMitgliedsstufe"
"FK_Newsletter_Adresse";"dbo";"Newsletter";"IDAdresse_FS_ErsterSB";"dbo";"Adresse";"IDAdresse"
"FK_Newsletter_Adresse1";"dbo";"Newsletter";"IDAdresse_FS_LetzterSB";"dbo";"Adresse";"IDAdresse"
"FK_NewsletterAdressat_Adresse";"dbo";"NewsletterAdressat";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_NewsletterAdressat_Newsletter";"dbo";"NewsletterAdressat";"IDNewsletter_FS";"dbo";"Newsletter";"IDNewsletter"
"FK_NewsletterAdressat_NewsletterVersand";"dbo";"NewsletterAdressat";"IDNewsletterVersand_FS";"dbo";"NewsletterVersand";"IDNewsletterVersand"
"FK_NewsletterBlock_Newsletter";"dbo";"NewsletterBlock";"IDNewsletter_FS";"dbo";"Newsletter";"IDNewsletter"
"FK_NewsletterVersand_Adresse";"dbo";"NewsletterVersand";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_NewsletterVersand_Newsletter";"dbo";"NewsletterVersand";"IDNewsletter_FS";"dbo";"Newsletter";"IDNewsletter"
"FK_NotizFahrerFahrzeug_ArtNotizart";"dbo";"NotizFahrerFahrzeug";"IDArtNotizart_FS";"dbo";"ArtNotizart";"IDArtNotizart"
"FK_NummernVerwaltung_Nummernkreis";"dbo";"NummernVerwaltung";"IDNummernkreis_FS";"dbo";"Nummernkreis";"IDNummernkreis"
"FK_OrtBeziehung_Ort";"dbo";"OrtBeziehung";"IDOrt_FS_Ort1";"dbo";"Ort";"IDOrt"
"FK_OrtBeziehung_Ort1";"dbo";"OrtBeziehung";"IDOrt_FS_Ort2";"dbo";"Ort";"IDOrt"
"FK_PartnerBefoederungsvertragspreis_Adresse";"dbo";"PartnerBefoederungsvertragspreis";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_PartnerDokument_Adresse";"dbo";"PartnerDokument";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerGebiet_Land";"dbo";"PartnerGebiet";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_PartnerGebietPreis_PartnerGebiet";"dbo";"PartnerGebietPreis";"IDPartnergebiet_FS";"dbo";"PartnerGebiet";"IDPartnergebiet"
"FK_PartnerKontingent_Adresse";"dbo";"PartnerKontingent";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerLeistung_Adresse";"dbo";"PartnerLeistung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerLeistungPreis_PartnerLeistung";"dbo";"PartnerLeistungPreis";"IDPartnerLeistung_FS";"dbo";"PartnerLeistung";"IDPartnerLeistung"
"FK_PartnerLeistungPreis_PartnerSaisontafel";"dbo";"PartnerLeistungPreis";"IDPartnerSaisontafel_FS";"dbo";"PartnerSaisontafel";"IDPartnerSaisontafel"
"FK_PartnerPreis_ArtPreisschema";"dbo";"PartnerPreis";"IDPartnerSaisonTafel_FS";"dbo";"PartnerSaisontafel";"IDPartnerSaisontafel"
"FK_PartnerPreis_PartnerPreisKategorie";"dbo";"PartnerPreis";"IDPartnerPreisKategorie_FS";"dbo";"PartnerPreisKategorie";"IDPartnerPreisKategorie"
"FK_PartnerPreisKategorie_Adresse";"dbo";"PartnerPreisKategorie";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerPreisKategorie_ArtPartnerPreisCode";"dbo";"PartnerPreisKategorie";"IDArtPartnerPreisCode_FS";"dbo";"ArtPartnerPreisCode";"IDArtPartnerPreisCode"
"FK_PartnerPreisKategorie_ArtVerpflegung";"dbo";"PartnerPreisKategorie";"IDArtVerpflegung_FS";"dbo";"ArtVerpflegung";"IDArtVerpflegung"
"FK_PartnerProdukt_Adresse";"dbo";"PartnerProdukt";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerProdukt_Produkt";"dbo";"PartnerProdukt";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_PartnerSaisontafel_Adresse";"dbo";"PartnerSaisontafel";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerSaisonzeit_Adresse";"dbo";"PartnerSaisonzeit";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerSaisonzeit_PartnerSaisontafel";"dbo";"PartnerSaisonzeit";"IDPartnerSaisonTafel_FS";"dbo";"PartnerSaisontafel";"IDPartnerSaisontafel"
"FK_Adresse_PartnerSelektion";"dbo";"PartnerSelektionenKunde";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Selektionsstamm_PartnerSelektion";"dbo";"PartnerSelektionenKunde";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_PartnerZimmer_Adresse";"dbo";"PartnerZimmer";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerZimmer_ArtPartnerPreisCode";"dbo";"PartnerZimmer";"IDArtPartnerPreisCode_FS";"dbo";"ArtPartnerPreisCode";"IDArtPartnerPreisCode"
"FK_PartnerZimmer_Zimmerart";"dbo";"PartnerZimmer";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_PartnerZusatz_Adresse";"dbo";"PartnerZusatz";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_PartnerZusatz_ArtAgenturPreisgruppe";"dbo";"PartnerZusatz";"IDArtAgenturPreisgruppe_FS";"dbo";"ArtAgenturPreisgruppe";"IDArtAgenturPreisgruppe"
"FK_PartnerZusatz_KonstantenSteueraufteilung";"dbo";"PartnerZusatz";"IDKonstantenSteueraufteilung_FS";"dbo";"KonstantenSteueraufteilung";"IDKonstantenSteueraufteilung"
"FK_PersonalGruppeDatenschutz_ArtPersonalGruppeKompetenz";"dbo";"PersonalGruppeDatenschutz";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_PersonalGruppeDatenschutzDarstellung_ArtPersonalGruppeKompetenz";"dbo";"PersonalGruppeDatenschutzDarstellung";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_PersonalGruppeDatenschutzLöschung_ArtPersonalGruppeKompetenz";"dbo";"PersonalGruppeDatenschutzLöschung";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_PersonalGruppeKompetenz_ArtPersonalGruppeKompetenz";"dbo";"PersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz_FS";"dbo";"ArtPersonalGruppeKompetenz";"IDArtPersonalGruppeKompetenz"
"FK_Personalkapazitaet_Adresse";"dbo";"Personalkapazitaet";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_Personalkapazitaet_ArtPersonalkapazitaet";"dbo";"Personalkapazitaet";"IDArtPersonalkapazitaet_FS";"dbo";"ArtPersonalkapazitaet";"IDArtPersonalkapazitaet"
"FK_PersonalkapazitaetArbeitszeit_ArtPersonalkapazitaet";"dbo";"PersonalkapazitaetArbeitszeit";"IDArtPersonalkapazitaet_FS";"dbo";"ArtPersonalkapazitaet";"IDArtPersonalkapazitaet"
"FK_PersonalkapazitaetEingabe_Adresse";"dbo";"PersonalkapazitaetEingabe";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_PersonalkapazitaetMindestbesetzung_ArtBetriebshof";"dbo";"PersonalkapazitaetMindestbesetzung";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_PersonalkapazitaetMindestbesetzung_ArtMindestbesetzungZeitraum";"dbo";"PersonalkapazitaetMindestbesetzung";"IDArtMindestbesetzungZeitraum_FS";"dbo";"ArtMindestbesetzungZeitraum";"IDArtMindestbesetzungZeitraum"
"FK_PersonalkapazitaetMindestbesetzungZeitraum_ArtMindestbesetzungZeitraum";"dbo";"PersonalkapazitaetMindestbesetzungZeitraum";"IDArtMindestbesetzungZeitraum_FS";"dbo";"ArtMindestbesetzungZeitraum";"IDArtMindestbesetzungZeitraum"
"FK_PlanungSoll_Adresse";"dbo";"PlanungSoll";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_PlanungSoll_ArtPersonalkapazitaet";"dbo";"PlanungSoll";"IDArtPersonalkapazitaet_FS_Schema";"dbo";"ArtPersonalkapazitaet";"IDArtPersonalkapazitaet"
"FK_PlanungSollBlock_BlockPlanung";"dbo";"PlanungSollBlock";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_PlanungSollBlock_PlanungSoll";"dbo";"PlanungSollBlock";"IDPlanungSoll_FS";"dbo";"PlanungSoll";"IDPlanungSoll"
"FK_PlanungSollLohnarten_Lohnart";"dbo";"PlanungSollLohnart";"IDLohnart_FS";"dbo";"Lohnart";"IDLohnart"
"FK_PlanungSollLohnarten_PlanungSoll";"dbo";"PlanungSollLohnart";"IDPlanungSoll_FS";"dbo";"PlanungSoll";"IDPlanungSoll"
"FK_PortalBemerkung_PortalBuchung";"dbo";"PortalBemerkung";"IDPortalBuchung_FS";"dbo";"PortalBuchung";"IDPortalBuchung"
"FK_PortalLeistung_PortalBuchung";"dbo";"PortalLeistung";"IDPortalBuchung_FS";"dbo";"PortalBuchung";"IDPortalBuchung"
"FK_PortalLeistungTN_PortalLeistung";"dbo";"PortalLeistungTN";"IDPortalLeistung_FS";"dbo";"PortalLeistung";"IDPortalLeistung"
"FK_PortalLeistungTN_PortalTN";"dbo";"PortalLeistungTN";"IDPortalTN_FS";"dbo";"PortalTN";"IDPortalTN"
"FK_PortalLeistungZusatz_PortalBuchung";"dbo";"PortalLeistungZusatz";"IDPortalBuchung_FS";"dbo";"PortalBuchung";"IDPortalBuchung"
"FK_PortalTN_PortalBuchung";"dbo";"PortalTN";"IDPortalBuchung_FS";"dbo";"PortalBuchung";"IDPortalBuchung"
"FK_Produkt_KonstantenSteueraufteilung";"dbo";"Produkt";"IDKonstantenSteueraufteilung_FS";"dbo";"KonstantenSteueraufteilung";"IDKonstantenSteueraufteilung"
"FK_ProduktArtPersonalGruppe_ArtPersonalGruppeProdukt";"dbo";"ProduktArtPersonalGruppe";"IDArtPersonalGruppeProdukt_FS";"dbo";"ArtPersonalGruppeProdukt";"IDArtPersonalGruppeProdukt"
"FK_ProduktArtPersonalGruppe_Produkt";"dbo";"ProduktArtPersonalGruppe";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_ProduktBeschreibungInhalt_ProduktBeschreibung";"dbo";"ProduktBeschreibungInhalt";"IDProduktBeschreibung_FS";"dbo";"ProduktBeschreibung";"IDProduktBeschreibung"
"FK_ProduktbeschreibungKategorie_ProduktBeschreibung";"dbo";"ProduktbeschreibungKategorie";"IDProduktbeschreibung_FS";"dbo";"ProduktBeschreibung";"IDProduktBeschreibung"
"FK_ProduktbeschreibungKategorie_WWSuchKategorie";"dbo";"ProduktbeschreibungKategorie";"IDWWSuchKategorie_FS";"dbo";"WWSuchKategorie";"IDWWSuchKategorie"
"FK_ProduktbeschreibungKategorie_WWSuchKategorieEintrag";"dbo";"ProduktbeschreibungKategorie";"IDWWSuchKategorieEintrag_FS";"dbo";"WWSuchKategorieEintrag";"IDWWSuchKategorieEintrag"
"FK_ProduktBeschreibungZusatz_ProduktBeschreibung";"dbo";"ProduktBeschreibungZusatz";"IDProduktBeschreibung_FS";"dbo";"ProduktBeschreibung";"IDProduktBeschreibung"
"FK_ProduktDokument_Produkt";"dbo";"ProduktDokument";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_ProduktSachbearbeiter_Adresse";"dbo";"ProduktSachbearbeiter";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ProduktSachbearbeiter_Produkt";"dbo";"ProduktSachbearbeiter";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_Produkt_ProduktText";"dbo";"ProduktText";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_Qualitaet_ArtFahrplanVersion";"dbo";"Qualitaet";"IDArtFahrplanversion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_QualitaetDefinition_ArtBlockArt";"dbo";"QualitaetDefinition";"IDArtBlockArt_FS";"dbo";"ArtBlockArt";"IDArtBlockArt"
"FK_QualitaetDefinition_ArtGruppeVerkehrstag";"dbo";"QualitaetDefinition";"IDArtGruppeVerkehrstag_FS";"dbo";"ArtGruppeVerkehrstag";"IDArtGruppeVerkehrstag"
"FK_QualitaetDefinition_Qualitaet";"dbo";"QualitaetDefinition";"IDQualitaet_FS";"dbo";"Qualitaet";"IDQualitaet"
"FK_QualitaetDefinitionAuftragsart_Auftragsart";"dbo";"QualitaetDefinitionAuftragsart";"IDAuftragsart_FS";"dbo";"Auftragsart";"IDAuftragsart"
"FK_QualitaetDefinitionAuftragsart_Qualitaet";"dbo";"QualitaetDefinitionAuftragsart";"IDQualitaet_FS";"dbo";"Qualitaet";"IDQualitaet"
"FK_QualitaetDefinitionFahrzeug_Fahrzeug";"dbo";"QualitaetDefinitionFahrzeug";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_QualitaetDefinitionFahrzeug_Qualitaet";"dbo";"QualitaetDefinitionFahrzeug";"IDQualitaet_FS";"dbo";"Qualitaet";"IDQualitaet"
"FK_QualitaetDefinitionLinie_Qualitaet";"dbo";"QualitaetDefinitionLinie";"IDQualitaet_FS";"dbo";"Qualitaet";"IDQualitaet"
"FK_QualitaetZuordnung_Qualitaet";"dbo";"QualitaetZuordnung";"IDQualitaet_FS";"dbo";"Qualitaet";"IDQualitaet"
"FK_QuittierungAusfahrt_AuftragFahrer";"dbo";"QuittierungAusfahrt";"IDAuftragFahrer_FS";"dbo";"AuftragFahrer";"IDAuftragFahrer"
"FK_QuittierungAusfahrt_BlockPlanung";"dbo";"QuittierungAusfahrt";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_Rechnung_AdresseAnschrift";"dbo";"Rechnung";"IDAdresseAnschrift_FS";"dbo";"AdresseAnschrift";"IDAdresseAnschrift"
"FK_Rechnung_ArtZahlungsart";"dbo";"Rechnung";"IDArtZahlungsart_FS";"dbo";"ArtZahlungsart";"IDArtZahlungsart"
"FK_Rechnung_RechnungHaupt";"dbo";"Rechnung";"IDRechnungHaupt_FS";"dbo";"RechnungHaupt";"IDRechnungHaupt"
"FK_RechnungBetrag_Rechnung";"dbo";"RechnungBetrag";"IDRechnung_FS";"dbo";"Rechnung";"IDRechnung"
"FK_RechnungBetragMahnung_RechnungBetrag";"dbo";"RechnungBetragMahnung";"IdRechnungBetrag_FS";"dbo";"RechnungBetrag";"IDRechnungBetrag"
"FK_RechnungBuchung_Buchung";"dbo";"RechnungBuchung";"IDBuchung_FS";"dbo";"Buchung";"IDBuchung"
"FK_RechnungBuchung_RechnungHaupt";"dbo";"RechnungBuchung";"IDRechnungHaupt_FS";"dbo";"RechnungHaupt";"IDRechnungHaupt"
"FK_RechnungHaupt_Adresse";"dbo";"RechnungHaupt";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_RechnungHaupt_Adresse1";"dbo";"RechnungHaupt";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_RechnungPosten_Rechnung";"dbo";"RechnungPosten";"IDRechnung_FS";"dbo";"Rechnung";"IDRechnung"
"FK_RechnungPosten_Teilnehmer_BuchungTNPreis";"dbo";"RechnungPosten_Teilnehmer";"IDBuchungTN_FS";"dbo";"BuchungTNPreis";"IDBuchungTNPreis"
"FK_RechnungPosten_Teilnehmer_RechnungPostenBetragTOU";"dbo";"RechnungPosten_Teilnehmer";"IDRechnungPostenBetragTOU_FS";"dbo";"RechnungPostenBetragTOU";"IDRechnungPostenBetragTOU"
"FK_RechnungPostenBetragALL_RechnungPosten";"dbo";"RechnungPostenBetragALL";"IDRechnungPosten_FS";"dbo";"RechnungPosten";"IDRechnungPosten"
"FK_RechnungPostenBetragTOU_RechnungPosten";"dbo";"RechnungPostenBetragTOU";"IDRechnungPosten_FS";"dbo";"RechnungPosten";"IDRechnungPosten"
"FK_RechnungPostenLinieAufteilungTour_RechnungPostenLinieAufteilung";"dbo";"RechnungPostenLinieAufteilungTour";"IDRechnungPostenLinieAufteilung_FS";"dbo";"RechnungPostenLinieAufteilung";"IDRechnungPostenLinieAufteilung"
"FK_RechnungPostenMietbusAufteilung_RechnungPostenBetragALL";"dbo";"RechnungPostenMietbusAufteilung";"IDRechnungPostenBetragAll_FS";"dbo";"RechnungPostenBetragALL";"IDRechnungPostenBetragALL"
"FK_RechnungSteueraufteilung_Rechnung";"dbo";"RechnungSteueraufteilung";"IDRechnung_FS";"dbo";"Rechnung";"IDRechnung"
"FK_ReisabBefoerderung_Reisab";"dbo";"ReisabBefoerderung";"IdReisab_FS";"dbo";"Reisab";"IdReisab"
"FK_ReisabLand_Land";"dbo";"ReisabLand";"IdLand_FS";"dbo";"Land";"IDLand"
"FK_ReisabLand_Reisab";"dbo";"ReisabLand";"IDReisab_FS";"dbo";"Reisab";"IdReisab"
"FK_ReisabLeistung_ArtReiseKosten";"dbo";"ReisabLeistung";"IdArtReiseKosten_FS";"dbo";"ArtReiseKosten";"IDArtReiseKosten"
"FK_ReisabLeistung_Reisab";"dbo";"ReisabLeistung";"IdReisab_FS";"dbo";"Reisab";"IdReisab"
"FK_ReisabReise_Reisab";"dbo";"ReisabReise";"IDReisab_FS";"dbo";"Reisab";"IdReisab"
"FK_ReisabReise_Reise";"dbo";"ReisabReise";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReisabUmsatz_Reisab";"dbo";"ReisabUmsatz";"IdReisab_FS";"dbo";"Reisab";"IdReisab"
"FK_Reise_Produkt";"dbo";"Reise";"IDProdukt_FS";"dbo";"Produkt";"IDProdukt"
"FK_ReiseBeleg_Reise";"dbo";"ReiseBeleg";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseBelegDokument_ReiseBeleg";"dbo";"ReiseBelegDokument";"IDReiseBeleg_FS";"dbo";"ReiseBeleg";"IDReiseBeleg"
"FK_ReiseBelegPosten_ReiseBeleg";"dbo";"ReiseBelegPosten";"IDReiseBeleg_FS";"dbo";"ReiseBeleg";"IDReiseBeleg"
"FK_ReiseDevise_ArtWaehrung";"dbo";"ReiseDevise";"IDArtWaehrung_FS";"dbo";"ArtWaehrung";"IDArtWaehrung"
"FK_ReiseDevise_Reise";"dbo";"ReiseDevise";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseDokument_Reise";"dbo";"ReiseDokument";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseFlexTarif_KonstantenFlexTarif";"dbo";"ReiseFlexTarif";"IDKonstantenFlexTarif_FS";"dbo";"KonstantenFlexTarif";"IDKonstantenFlexTarif"
"FK_ReiseFlexTarif_Reise";"dbo";"ReiseFlexTarif";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseGuides_ArtReiseGuides";"dbo";"ReiseGuides";"IDArtReiseGuides_FS";"dbo";"ArtReiseGuides";"IDArtReiseGuides"
"FK_ReiseKosten_Reise";"dbo";"ReiseKosten";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseLand_Land";"dbo";"ReiseLand";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_ReiseLand_Reise";"dbo";"ReiseLand";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseLeistung_Leistung";"dbo";"ReiseLeistung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_ReiseLeistung_Reise";"dbo";"ReiseLeistung";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseLeistungGruppe_Reise";"dbo";"ReiseLeistungGruppe";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseLeistungGruppeZuweisung_Leistung";"dbo";"ReiseLeistungGruppeZuweisung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_ReiseLeistungGruppeZuweisung_ReiseLeistungGruppe";"dbo";"ReiseLeistungGruppeZuweisung";"IDReiseLeistungGruppe_FS";"dbo";"ReiseLeistungGruppe";"IDReiseLeistungGruppe"
"FK_ReiseleiterAbrechnung_Adresse";"dbo";"ReiseleiterAbrechnung";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterAbrechnung_Reise";"dbo";"ReiseleiterAbrechnung";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseleiterAbrechnung_ReiseleiterZuordnungStamm";"dbo";"ReiseleiterAbrechnung";"IDReiseleiterZuordnungStamm_FS";"dbo";"ReiseleiterZuordnungStamm";"IDReiseleiterZuordnungStamm"
"FK_ReiseleiterAbrechnungPosten_ReiseleiterAbrechnung";"dbo";"ReiseleiterAbrechnungPosten";"IDReiseleiterAbrechnung_FS";"dbo";"ReiseleiterAbrechnung";"IDReiseleiterAbrechnung"
"FK_ReiseleiterAbrechnungPosten_ReiseleiterPosten";"dbo";"ReiseleiterAbrechnungPosten";"IDReiseleiterPosten_FS";"dbo";"ReiseleiterPosten";"IDReiseleiterPosten"
"FK_ReiseleiterAbrechnungSpesen_ArtSpesenVerpflegung";"dbo";"ReiseleiterAbrechnungSpesen";"IDArtSpesenVerpflegung_FS";"dbo";"ArtSpesenVerpflegung";"IDArtSpesenVerpflegung"
"FK_ReiseleiterAbrechnungSpesen_ReiseleiterAbrechnung";"dbo";"ReiseleiterAbrechnungSpesen";"IDReiseleiterAbrechnung_FS";"dbo";"ReiseleiterAbrechnung";"IDReiseleiterAbrechnung"
"FK_ReiseleiterAbrechnungZuAbschlag_ReiseleiterAbrechnung";"dbo";"ReiseleiterAbrechnungZuAbschlag";"IDReiseleiterAbrechnung_FS";"dbo";"ReiseleiterAbrechnung";"IDReiseleiterAbrechnung"
"FK_ReiseleiterAbrVergütungStaffel_ReiseleiterAbrVergütungStamm1";"dbo";"ReiseleiterAbrVergütungStaffel";"IDReiseleiterAbrVergütungStamm_FS";"dbo";"ReiseleiterAbrVergütungStamm";"IDReiseleiterAbrVergütungStamm"
"FK_ReiseleiterAbrVergütungStaffelAnAbreise_ReiseleiterAbrVergütungStamm";"dbo";"ReiseleiterAbrVergütungStaffelAnAbreise";"IDReiseleiterAbrVergütungStamm_FS";"dbo";"ReiseleiterAbrVergütungStamm";"IDReiseleiterAbrVergütungStamm"
"FK_ReiseleiterArbeitszeit_ReiseleiterZuordnungReiseleiter";"dbo";"ReiseleiterArbeitszeit";"IDReiseleiterZuordnungReiseleiter_FS";"dbo";"ReiseleiterZuordnungReiseleiter";"IDReiseleiterZuordnungReiseleiter"
"FK_ReiseleiterHonorarStaffel_Adresse";"dbo";"ReiseleiterHonorarStaffel";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterHonorarStaffel_ArtReiseleiterHonorar";"dbo";"ReiseleiterHonorarStaffel";"IDArtReiseleiterHonorar_FS";"dbo";"ArtReiseleiterHonorar";"IDArtReiseleiterHonorar"
"FK_ReiseleiterSelektionen_Adresse";"dbo";"ReiseleiterSelektionen";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterSelektionen_Selektionsstamm";"dbo";"ReiseleiterSelektionen";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_ReiseleiterSpesenBetrag_ArtSpesenLand";"dbo";"ReiseleiterSpesenBetrag";"IDArtSpesenLand_FS";"dbo";"ArtSpesenLand";"IDArtSpesenLand"
"FK_ReiseleiterSpesenBetrag_ReiseleiterSpesenStaffel";"dbo";"ReiseleiterSpesenBetrag";"IDReiseleiterSpesenStaffel_FS";"dbo";"ReiseleiterSpesenStaffel";"IDReiseleiterSpesenStaffel"
"FK_ReiseleiterStamm_Adresse";"dbo";"ReiseleiterStamm";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterWunschReise_Adresse";"dbo";"ReiseleiterWunschReise";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterWunschReise_Reise";"dbo";"ReiseleiterWunschReise";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseleiterZuordnungReiseleiter_Adresse1";"dbo";"ReiseleiterZuordnungReiseleiter";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_ReiseleiterZuordnungReiseleiter_ReiseleiterZuordnungStamm";"dbo";"ReiseleiterZuordnungReiseleiter";"IDReiseleiterZuordnungStamm_FS";"dbo";"ReiseleiterZuordnungStamm";"IDReiseleiterZuordnungStamm"
"FK_ReiseleiterZuordnungZusatzleistung_Leistung";"dbo";"ReiseleiterZuordnungZusatzleistung";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_ReiseleiterZuordnungZusatzleistung_ReiseleiterZuordnungReiseleiter";"dbo";"ReiseleiterZuordnungZusatzleistung";"IDReiseleiterZuordnungReiseleiter_FS";"dbo";"ReiseleiterZuordnungReiseleiter";"IDReiseleiterZuordnungReiseleiter"
"FK_ReiseListenVersand_ArtListenart";"dbo";"ReiseListenVersand";"IdArtListenart_FS";"dbo";"ArtListenart";"IDArtListenArt"
"FK_ReiseListenVersand_ArtListenart1";"dbo";"ReiseListenVersand";"IdArtListenart_FS";"dbo";"ArtListenart";"IDArtListenArt"
"FK_ReiseListenVersand_DruckEinstellungEMail";"dbo";"ReiseListenVersand";"IdDruckeinstellungEmail_FS";"dbo";"DruckEinstellungEMail";"IDDruckEinstellungEMail"
"FK_ReiseListenVersand_Reise";"dbo";"ReiseListenVersand";"IdReise_FS";"dbo";"Reise";"IDReise"
"FK_ReisePartner_Adresse";"dbo";"ReisePartner";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_ReisePartner_ArtVerpflegung";"dbo";"ReisePartner";"IDArtVerpflegung_FS";"dbo";"ArtVerpflegung";"IDArtVerpflegung"
"FK_ReisePartner_Reise";"dbo";"ReisePartner";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReisePersonalZimmer_Reise";"dbo";"ReisePersonalZimmer";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReisePersonalZimmer_Zimmerart";"dbo";"ReisePersonalZimmer";"IDZimmerart_FS";"dbo";"Zimmerart";"IDZimmerart"
"FK_ReiseSelektionen_Reise";"dbo";"ReiseSelektionen";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseSelektionen_Selektionsstamm";"dbo";"ReiseSelektionen";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_ReiseSitzplan_Reise";"dbo";"ReiseSitzplan";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseSitzplan_Sitzplan";"dbo";"ReiseSitzplan";"IDSitzplan_FS";"dbo";"Sitzplan";"IDSitzplan"
"FK_ReiseSitzplatzPreis_ArtSitzplatzKategorie";"dbo";"ReiseSitzplatzPreis";"IDArtSitzplatzKategorie_FS";"dbo";"ArtSitzplatzKategorie";"IDArtSitzplatzKategorie"
"FK_ReiseSitzplatzPreis_Reise";"dbo";"ReiseSitzplatzPreis";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseStatistik_Reise";"dbo";"ReiseStatistik";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseStatistikVertrieb_ReiseStatistik";"dbo";"ReiseStatistikVertrieb";"IDReiseStatistik_FS";"dbo";"ReiseStatistik";"IDReiseStatistik"
"FK_ReiseStatus_Reise";"dbo";"ReiseStatus";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseStatusBuchhaltung_ArtReiseStatusBuchhaltung";"dbo";"ReiseStatusBuchhaltung";"IDArtReiseStatusBuchhaltung_FS";"dbo";"ArtReiseStatusBuchhaltung";"IDArtReiseStatusBuchhaltung"
"FK_ReiseStatusBuchhaltung_Reise";"dbo";"ReiseStatusBuchhaltung";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_Reise_ReiseText";"dbo";"ReiseText";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseTextbaustein_Reise";"dbo";"ReiseTextbaustein";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseTextbaustein_Textbaustein";"dbo";"ReiseTextbaustein";"IDTextbaustein_FS";"dbo";"Textbaustein";"IDTextbaustein"
"FK_ReiseTextbausteinAbwJeMandant_Mandant";"dbo";"ReiseTextbausteinAbwJeMandant";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_ReiseTextbausteinAbwJeMandant_Reise";"dbo";"ReiseTextbausteinAbwJeMandant";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseTextbausteinAbwJeMandant_Textbaustein";"dbo";"ReiseTextbausteinAbwJeMandant";"IDTextbaustein_FS";"dbo";"Textbaustein";"IDTextbaustein"
"FK_Reiseunterlage_Reise";"dbo";"Reiseunterlage";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_Reiseunterlage_ReiseunterlagenBaustein";"dbo";"Reiseunterlage";"IDReiseunterlagenBaustein_FS";"dbo";"ReiseunterlagenBaustein";"IDReiseunterlagenBaustein"
"FK_ReiseunterlageInhalt_Reiseunterlage";"dbo";"ReiseunterlageInhalt";"IDReiseunterlage_FS";"dbo";"Reiseunterlage";"IDReiseunterlage"
"FK_ReiseunterlagenBaustein_ReiseunterlagenBausteinTyp";"dbo";"ReiseunterlagenBaustein";"IDReiseunterlagenBausteinTyp_FS";"dbo";"ReiseunterlagenBausteinTyp";"IDReiseunterlagenBausteinTyp"
"FK_ReiseunterlagenBausteinBedingung_ReiseunterlagenBaustein";"dbo";"ReiseunterlagenBausteinBedingung";"IDReiseunterlagenBaustein_FS";"dbo";"ReiseunterlagenBaustein";"IDReiseunterlagenBaustein"
"FK_ReiseunterlagenBausteinBedingung_ReiseunterlagenBedingung";"dbo";"ReiseunterlagenBausteinBedingung";"IDReiseunterlagenBedingung_FS";"dbo";"ReiseunterlagenBedingung";"IDReiseunterlagenBedingung"
"FK_ReiseunterlagenBausteinInhalt_ReiseunterlagenBaustein";"dbo";"ReiseunterlagenBausteinInhalt";"IDReiseunterlagenBaustein_FS";"dbo";"ReiseunterlagenBaustein";"IDReiseunterlagenBaustein"
"FK_ReiseunterlagenVorlageBaustein_ReiseunterlagenBaustein";"dbo";"ReiseunterlagenVorlageBaustein";"IDReiseUnterlagenBaustein_FS";"dbo";"ReiseunterlagenBaustein";"IDReiseunterlagenBaustein"
"FK_ReiseunterlagenVorlageBaustein_ReiseunterlagenVorlage";"dbo";"ReiseunterlagenVorlageBaustein";"IDReiseUnterlagenVorlage_FS";"dbo";"ReiseunterlagenVorlage";"IDReiseUnterlagenVorlage"
"FK_ReiseunterlagenVorlageInhalt_ReiseunterlagenVorlage";"dbo";"ReiseunterlagenVorlageInhalt";"IDReiseunterlagenVorlage_FS";"dbo";"ReiseunterlagenVorlage";"IDReiseUnterlagenVorlage"
"FK_ReiseVersicherungsGruppe_ArtVersicherungsGruppe";"dbo";"ReiseVersicherungsGruppe";"IDArtVersicherungsGruppe_FS";"dbo";"ArtVersicherungsGruppe";"IDArtVersicherungsGruppe"
"FK_ReiseVersicherungsGruppe_Reise";"dbo";"ReiseVersicherungsGruppe";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseVerwendung_Reise";"dbo";"ReiseVerwendung";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseVplDokument_Dokument";"dbo";"ReiseVplDokument";"IdDokument_FS";"dbo";"Dokument";"IDDokument"
"FK_ReiseVplDokument_ReiseVpl";"dbo";"ReiseVplDokument";"IdReiseVpl_FS";"dbo";"ReiseVpl";"IdReiseVpl"
"FK_ReiseVplKdVormerkung_ReiseVpl";"dbo";"ReiseVplKdVormerkung";"IdReiseVpl_FS";"dbo";"ReiseVpl";"IdReiseVpl"
"FK_ReiseVplPartner_ReiseVpl";"dbo";"ReiseVplPartner";"IdReiseVpl_FS";"dbo";"ReiseVpl";"IdReiseVpl"
"FK_ReiseVplPartnerDokument_Dokument";"dbo";"ReiseVplPartnerDokument";"IdDokument_FS";"dbo";"Dokument";"IDDokument"
"FK_ReiseVplPartnerDokument_ReiseVplPartner";"dbo";"ReiseVplPartnerDokument";"IdReiseVplPartner_FS";"dbo";"ReiseVplPartner";"IdReiseVplPartner"
"FK_ReiseVplPartnerStatus_ArtReiseVplPartnerStatus";"dbo";"ReiseVplPartnerStatus";"IDArtReiseVplPartnerStatus_FS";"dbo";"ArtReiseVplPartnerStatus";"IDArtReiseVplPartnerStatus"
"FK_ReiseVplPartnerStatus_ReiseVplPartner";"dbo";"ReiseVplPartnerStatus";"IDReiseVplPartner_FS";"dbo";"ReiseVplPartner";"IdReiseVplPartner"
"FK_ReiseVplStatus_ArtReiseVplStatus";"dbo";"ReiseVplStatus";"IDArtReiseVplStatus_FS";"dbo";"ArtReiseVplStatus";"IDArtReiseVplStatus"
"FK_ReiseVplStatus_ReiseVpl";"dbo";"ReiseVplStatus";"IDReiseVpl_FS";"dbo";"ReiseVpl";"IdReiseVpl"
"FK_ReiseVplVerwendung_ReiseVpl";"dbo";"ReiseVplVerwendung";"IDReiseVpl_FS";"dbo";"ReiseVpl";"IdReiseVpl"
"FK_ReiseWerbeplanung_Reise";"dbo";"ReiseWerbeplanung";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReisezielSelektionsstamm_Reiseziel";"dbo";"ReisezielSelektionsstamm";"IDReiseziel_FS";"dbo";"Reiseziel";"IDReiseziel"
"FK_ReisezielSelektionsstamm_Selektionsstamm";"dbo";"ReisezielSelektionsstamm";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_ReiseZusatz_ArtAgenturPreisgruppe";"dbo";"ReiseZusatz";"IDArtAgenturPreisgruppe_FS";"dbo";"ArtAgenturPreisgruppe";"IDArtAgenturPreisgruppe"
"FK_ReiseZusatz_Reise";"dbo";"ReiseZusatz";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReiseZusatzAbwJeMandant_Adresse";"dbo";"ReiseZusatzAbwJeMandant";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_ReiseZusatzAbwJeMandant_Reise";"dbo";"ReiseZusatzAbwJeMandant";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ReparaturAuftragZusatz_ReparaturAuftrag";"dbo";"ReparaturAuftragZusatz";"IDReparaturAuftrag_FS";"dbo";"Reparaturauftrag";"IDReparaturauftrag"
"FK_Rollsystem_ArtFahrplanVersion";"dbo";"Rollsystem";"IDArtFahrplanversion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_RollsystemBlock_Block";"dbo";"RollsystemBlock";"IDBlock_FS";"dbo";"Block";"IDBlock"
"FK_RollsystemBlock_RollsystemFahrerFahrzeug";"dbo";"RollsystemBlock";"IDRollsystemFahrerFahrzeug_FS";"dbo";"RollsystemFahrerFahrzeug";"IDRollsystemFahrerFahrzeug"
"FK_RollsystemFahrerFahrzeug_Rollsystem";"dbo";"RollsystemFahrerFahrzeug";"IDRollsystem_FS";"dbo";"Rollsystem";"IDRollsystem"
"FK_RollsystemFerien_Rollsystem";"dbo";"RollsystemFerien";"IDRollsystem_FS";"dbo";"Rollsystem";"IDRollsystem"
"FK_RollsystemPerkap_ArtPersonalkapazitaet";"dbo";"RollsystemPerkap";"IDArtPersonalkapazitaet_FS";"dbo";"ArtPersonalkapazitaet";"IDArtPersonalkapazitaet"
"FK_RollsystemPerkap_RollsystemFahrerFahrzeug";"dbo";"RollsystemPerkap";"IDRollsystemFahrerFahrzeug_FS";"dbo";"RollsystemFahrerFahrzeug";"IDRollsystemFahrerFahrzeug"
"FK_RsbVeransAnzahlung_RsbVerans";"dbo";"RsbVeransAnzahlung";"IDRsbVerans_FS";"dbo";"RsbVerans";"IDRsbVeranstalter"
"FK_RsbVeransZusatz_RsbVerans";"dbo";"RsbVeransZusatz";"IDRsbVerans_FS";"dbo";"RsbVerans";"IDRsbVeranstalter"
"FK_Rufbus_FPLinieFahrt";"dbo";"Rufbus";"IDFPLinieFahrt_FS";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_Rufbus_FPLinieHaltestelleZeitartNach";"dbo";"Rufbus";"FPLinieHaltestelleZeitart_FS_Nach";"dbo";"FPLinieHaltestelleZeitart";"IDFPLinieHaltestelleZeitart"
"FK_Rufbus_FPLinieHaltestelleZeitartVon";"dbo";"Rufbus";"FPLinieHaltestelleZeitart_FS_Von";"dbo";"FPLinieHaltestelleZeitart";"IDFPLinieHaltestelleZeitart"
"FK_Rufbus_Haltepunkt_Nach";"dbo";"Rufbus";"IDHaltepunkt_FS_Nach";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Rufbus_Haltepunkt_Von";"dbo";"Rufbus";"IDHaltepunkt_FS_Von";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Rufbus_Haltestelle_Nach";"dbo";"Rufbus";"IDHaltestelle_FS_Nach";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Rufbus_Haltestelle_Von";"dbo";"Rufbus";"IDHaltestelle_FS_Von";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Rufbus_Linie";"dbo";"Rufbus";"IDFPLinie_FS";"dbo";"FPLinie";"IDFPLinie"
"FK_SaisonZeit_SaisonBezeichnung";"dbo";"SaisonZeit";"IDSaisonBezeichnung_FS";"dbo";"SaisonBezeichnung";"IDSaisonBezeichnung"
"FK_SchiffsDeck_Schiff";"dbo";"SchiffsDeck";"IDSchiff_FS";"dbo";"Schiff";"IDSchiff"
"FK_SchiffsKabine_SchiffsDeck";"dbo";"SchiffsKabine";"IDSchiffsDeck_FS";"dbo";"SchiffsDeck";"IDSchiffsDeck"
"FK_Schule_Schulamt";"dbo";"Schule";"IDSchulamt_FS";"dbo";"Schulamt";"IDSchulamt"
"FK_Adresse_Selektion";"dbo";"Selektionen";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Selektionsstamm_Selektion";"dbo";"Selektionen";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_Selektionsgruppenstamm_Selektionsgruppe";"dbo";"Selektionsgruppe";"IDSelektionsgruppenstamm_FS";"dbo";"Selektionsgruppenstamm";"IDSelektionsgruppenstamm"
"FK_Selektionsstamm_Selektionsgruppe";"dbo";"Selektionsgruppe";"IDSelektionsstamm_FS";"dbo";"Selektionsstamm";"IDSelektionsstamm"
"FK_Sitzplan_Sitzplanobjekt";"dbo";"Sitzplanobjekt";"IDSitzplan_FS";"dbo";"Sitzplan";"IDSitzplan"
"FK_Sperrung_Adresse";"dbo";"Sperrung";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_Sperrung_ArtSperrartFahrer";"dbo";"Sperrung";"IDArtSperrartFahrer_FS";"dbo";"ArtSperrartFahrer";"IDArtSperrartFahrer"
"FK_Sperrung_ArtSperrartFahrzeug";"dbo";"Sperrung";"IDArtSperrartFahrzeug_FS";"dbo";"ArtSperrartFahrzeug";"IDArtSperrartFahrzeug"
"FK_Sperrung_ArtSperrKategorie";"dbo";"Sperrung";"IDArtSperrKategorie_FS";"dbo";"ArtSperrKategorie";"IDArtSperrKategorie"
"FK_Sperrung_Fahrzeug";"dbo";"Sperrung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_SperrungSperrStatus_ArtSperrStatus";"dbo";"SperrungSperrStatus";"IDArtSperrStatus_FS";"dbo";"ArtSperrStatus";"IDArtSperrStatus"
"FK_SperrungSperrStatus_Sperrung";"dbo";"SperrungSperrStatus";"IDSperrung_FS";"dbo";"Sperrung";"IDSperrung"
"FK_Spesen_Adresse";"dbo";"Spesen";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_Spesen_ArtSpesen";"dbo";"Spesen";"IDArtSpesen_FS";"dbo";"ArtSpesen";"IDArtSpesen"
"FK_SpracheMaskeModul_Programmmodul";"dbo";"SpracheMaskeModul";"IDProgrammmodul_FS";"dbo";"Programmmodul";"IDProgrammmodul"
"FK_SpracheMaskeText_SpracheMaske";"dbo";"SpracheMaskeText";"IDSpracheMaske_FS";"dbo";"SpracheMaske";"IDSpracheMaske"
"FK_SteueraufteilungDetail_Land";"dbo";"SteueraufteilungDetail";"IDLand_FS";"dbo";"Land";"IDLand"
"FK_SteueraufteilungDetail_SteueraufteilungArt";"dbo";"SteueraufteilungDetail";"IDSteueraufteilungArt_FS";"dbo";"SteueraufteilungArt";"IDSteueraufteilungArt"
"FK_SteueraufteilungDetail_SteueraufteilungUnterart";"dbo";"SteueraufteilungDetail";"IDSteueraufteilungUnterart_FS";"dbo";"SteueraufteilungUnterart";"IDSteueraufteilungUnterart"
"FK_SteueraufteilungDetailArtVerpflegung_ArtVerpflegung";"dbo";"SteueraufteilungDetailArtVerpflegung";"IDArtVerpflegung_FS";"dbo";"ArtVerpflegung";"IDArtVerpflegung"
"FK_SteueraufteilungDetailArtVerpflegung_SteueraufteilungDetail";"dbo";"SteueraufteilungDetailArtVerpflegung";"IDSteueraufteilungDetail_FS";"dbo";"SteueraufteilungDetail";"IDSteueraufteilungDetail"
"FK_SteueraufteilungUnterart_SteueraufteilungArt";"dbo";"SteueraufteilungUnterart";"IDSteueraufteilungArt_FS";"dbo";"SteueraufteilungArt";"IDSteueraufteilungArt"
"FK_Tachostand_Fahrzeug";"dbo";"Tachostand";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_Tachostand_TachostandImportEinstellung";"dbo";"Tachostand";"IDTachostandImportEinstellung_FS";"dbo";"TachostandImportEinstellung";"IDTachostandImportEinstellung"
"FK_Tankerfassung_ArtBetankung";"dbo";"Tankerfassung";"IDArtBetankung_FS";"dbo";"ArtBetankung";"IDArtBetankung"
"FK_Tankerfassung_ArtKarftstoffart";"dbo";"Tankerfassung";"IDArtKraftstoffart_FS";"dbo";"ArtKraftstoffart";"IDArtKraftstoffart"
"FK_Tankerfassung_Fahrzeug";"dbo";"Tankerfassung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_Tankerfassung_TankimportEinstellung";"dbo";"Tankerfassung";"IDTankimportEinstellung_FS";"dbo";"TankimportEinstellung";"IDTankimportEinstellung"
"FK_TankimportEinstellung_ArtBetankung";"dbo";"TankimportEinstellung";"IDArtBetankung_FS";"dbo";"ArtBetankung";"IDArtBetankung"
"FK_TankimportEinstellungArtBetankung_ArtBetankung";"dbo";"TankimportEinstellungArtBetankung";"IDArtBetankung_FS";"dbo";"ArtBetankung";"IDArtBetankung"
"FK_TankimportEinstellungArtBetankung_TankimportEinstellung";"dbo";"TankimportEinstellungArtBetankung";"IDTankimportEinstellung_FS";"dbo";"TankimportEinstellung";"IDTankimportEinstellung"
"FK_TankimportEinstellungKraftstoff_ArtKraftstoffart";"dbo";"TankimportEinstellungKraftstoff";"IDArtKraftstoffart_FS";"dbo";"ArtKraftstoffart";"IDArtKraftstoffart"
"FK_TankimportEinstellungKraftstoff_TankimportEinstellung";"dbo";"TankimportEinstellungKraftstoff";"IDTankimportEinstellung_FS";"dbo";"TankimportEinstellung";"IDTankimportEinstellung"
"FK_TaxiPartner_Adresse";"dbo";"TaxiPartner";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_TaxiPartnerKosten_TaxiPartner";"dbo";"TaxiPartnerKosten";"IDTaxiPartner_FS";"dbo";"TaxiPartner";"IDTaxiPartner"
"FK_TaxiPartnerMapGuide_TaxiPartner";"dbo";"TaxiPartnerMapGuide";"IDTaxiPartner_FS";"dbo";"TaxiPartner";"IDTaxiPartner"
"FK_TaxiPartnerZustieg_Adresse";"dbo";"TaxiPartnerZustieg";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_TaxiPartnerZustieg_Zustieg";"dbo";"TaxiPartnerZustieg";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_TerminalFreigabe_ArtTerminalFreigabe";"dbo";"TerminalFreigabe";"IDArtTerminalFreigabe_FS";"dbo";"ArtTerminalFreigabe";"IDArtTerminalFreigabe"
"FK_TerminalFreigabeArtBetriebshof_ArtBetriebshof";"dbo";"TerminalFreigabeArtBetriebshof";"IDArtBetriebshof_FS";"dbo";"ArtBetriebshof";"IDArtBetriebshof"
"FK_TerminalProtokoll_Adresse";"dbo";"TerminalProtokoll";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_TerminArtSachbearbeiter_Adresse";"dbo";"TerminArtSachbearbeiter";"IDAdresse_FS_Personal";"dbo";"Adresse";"IDAdresse"
"FK_TerminArtSachbearbeiter_TerminArt";"dbo";"TerminArtSachbearbeiter";"IDTerminArt_FS";"dbo";"TerminArt";"IDTerminArt"
"FK_TerminKetteAbfolge_TerminKette";"dbo";"TerminKetteAbfolge";"IDTerminArt_FS";"dbo";"TerminArt";"IDTerminArt"
"FK_TerminKetteAbfolge_TerminKette1";"dbo";"TerminKetteAbfolge";"IDTerminKette_FS";"dbo";"TerminKette";"IDTerminKette"
"FK_TerminSachbearbeiter_Termin";"dbo";"TerminSachbearbeiter";"IDTermin_FS";"dbo";"Termin";"IDTermin"
"FK_Tour_ArtFahrplanVersion";"dbo";"Tour";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_Tour_ArtStatistikGruppe";"dbo";"Tour";"IDArtStatistikgruppe_FS_Haupt";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_Tour_FPLinieFahrt";"dbo";"Tour";"IDFPLinieFahrt_FS";"dbo";"FPLinieFahrt";"IDFPLinieFahrt"
"FK_Tour_Haltepunkt_Anfang";"dbo";"Tour";"IDHaltepunkt_FS_Anfang";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Tour_Haltepunkt_Ende";"dbo";"Tour";"IDHaltepunkt_FS_Ende";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Tour_Haltestelle_Anfang";"dbo";"Tour";"IDHaltestelle_FS_Anfang";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Tour_Haltestelle_Ende";"dbo";"Tour";"IDHaltestelle_FS_Ende";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Tour_Ort_Anfang";"dbo";"Tour";"IDOrt_FS_Anfang";"dbo";"Ort";"IDOrt"
"FK_Tour_Ort_Ende";"dbo";"Tour";"IDOrt_FS_Ende";"dbo";"Ort";"IDOrt"
"FK_TourFahrzeugtyp_ArtFahrzeugTypen";"dbo";"TourFahrzeugtyp";"IDArtFahrzeugTypen_FS";"dbo";"ArtFahrzeugTypen";"IDArtFahrzeugTypen"
"FK_TourFahrzeugtyp_Tour";"dbo";"TourFahrzeugtyp";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourFerienFeier_Tour";"dbo";"TourFerienFeier";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourHaltestelleHaltepunkt_Haltepunkt";"dbo";"TourHaltestelleHaltepunkt";"IDHaltepunkt_FS";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_TourHaltestelleHaltepunkt_Haltestelle";"dbo";"TourHaltestelleHaltepunkt";"IDHaltestelle_FS";"dbo";"Haltestelle";"IDHaltestelle"
"FK_TourHaltestelleHaltepunkt_Tour";"dbo";"TourHaltestelleHaltepunkt";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourKreisGebiet_ArtKreisGebiet";"dbo";"TourKreisGebiet";"IDArtKreisGebiet_FS";"dbo";"ArtKreisGebiet";"IDArtKreisGebiet"
"FK_TourKreisGebiet_Tour";"dbo";"TourKreisGebiet";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourLaufzeit_TourLaufzeit";"dbo";"TourLaufzeit";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourPlanung_Adresse";"dbo";"TourPlanung";"IDAdresse_FS_Fahrer";"dbo";"Adresse";"IDAdresse"
"FK_TourPlanung_Adresse2";"dbo";"TourPlanung";"LoeschenManuellIDAdresse_FS_SB";"dbo";"Adresse";"IDAdresse"
"FK_TourPlanung_ArtFahrplanVersion";"dbo";"TourPlanung";"IDArtFahrplanVersion_FS";"dbo";"ArtFahrplanVersion";"IDArtFahrplanVersion"
"FK_TourPlanung_ArtStatistikGruppe";"dbo";"TourPlanung";"IDArtStatistikgruppe_FS_Haupt";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_TourPlanung_BlockPlanung";"dbo";"TourPlanung";"IDBlockPlanung_FS";"dbo";"BlockPlanung";"IDBlockPlanung"
"FK_TourPlanung_Fahrzeug";"dbo";"TourPlanung";"IDFahrzeug_FS";"dbo";"Fahrzeug";"IDFahrzeug"
"FK_Tourplanung_Haltepunkt_Anfang";"dbo";"TourPlanung";"IDHaltepunkt_FS_Anfang";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Tourplanung_Haltepunkt_Ende";"dbo";"TourPlanung";"IDHaltepunkt_FS_Ende";"dbo";"Haltepunkt";"IDHaltepunkt"
"FK_Tourplanung_Haltestelle_Anfang";"dbo";"TourPlanung";"IDHaltestelle_FS_Anfang";"dbo";"Haltestelle";"IDHaltestelle"
"FK_Tourplanung_Haltestelle_Ende";"dbo";"TourPlanung";"IDHaltestelle_FS_Ende";"dbo";"Haltestelle";"IDHaltestelle"
"FK_TourPlanung_Ort_Anfang";"dbo";"TourPlanung";"IDOrt_FS_Anfang";"dbo";"Ort";"IDOrt"
"FK_TourPlanung_Ort_Ende";"dbo";"TourPlanung";"IDOrt_FS_Ende";"dbo";"Ort";"IDOrt"
"FK_TourPlanung_Tour";"dbo";"TourPlanung";"IDTour_FS_Basis";"dbo";"Tour";"IDTour"
"FK_TourPlanungFahrzeugtyp_ArtFahrzeugTypen";"dbo";"TourPlanungFahrzeugtyp";"IDArtFahrzeugTypen_FS";"dbo";"ArtFahrzeugTypen";"IDArtFahrzeugTypen"
"FK_TourPlanungFahrzeugtyp_TourPlanung";"dbo";"TourPlanungFahrzeugtyp";"IDTourPlanung_FS";"dbo";"TourPlanung";"IDTourPlanung"
"FK_TourPlanungKreisGebiet_ArtKreisGebiet";"dbo";"TourPlanungKreisGebiet";"IDArtKreisGebiet_FS";"dbo";"ArtKreisGebiet";"IDArtKreisGebiet"
"FK_TourPlanungKreisGebiet_TourPlanung";"dbo";"TourPlanungKreisGebiet";"IDTourPlanung_FS";"dbo";"TourPlanung";"IDTourPlanung"
"FK_TourPlanungStatistik_ArtStatistikGruppe";"dbo";"TourPlanungStatistik";"IDArtStatistikGruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_TourPlanungStatistik_TourPlanung";"dbo";"TourPlanungStatistik";"IDTourPlanung_FS";"dbo";"TourPlanung";"IDTourPlanung"
"FK_TourPlanungZusatz_TourPlanung";"dbo";"TourPlanungZusatz";"IDTourPlanung_FS";"dbo";"TourPlanung";"IDTourPlanung"
"FK_TourStatistik_ArtStatistikGruppe";"dbo";"TourStatistik";"IDArtStatistikGruppe_FS";"dbo";"ArtStatistikGruppe";"IDArtStatistikGruppe"
"FK_TourStatistik_Tour";"dbo";"TourStatistik";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourWochentyp_ArtWochentyp";"dbo";"TourWochentyp";"IDArtWochentyp_FS";"dbo";"ArtWochentyp";"IDArtWochentyp"
"FK_TourWochentyp_Tour";"dbo";"TourWochentyp";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourZeitraum_ArtLaufzeitschema";"dbo";"TourZeitraum";"IDArtLaufzeitschema_FS";"dbo";"ArtLaufzeitschema";"IDArtLaufzeitschema"
"FK_TourZeitraum_Tour";"dbo";"TourZeitraum";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_TourZusatz_Tour";"dbo";"TourZusatz";"IDTour_FS";"dbo";"Tour";"IDTour"
"FK_UserStartmenue_Adresse";"dbo";"UserStartmenue";"IDAdresse_FS";"dbo";"Adresse";"IDAdresse"
"FK_UserStartmenue_Programmmodul";"dbo";"UserStartmenue";"IDProgrammmodul_FS";"dbo";"Programmmodul";"IDProgrammmodul"
"FK_VorplanungRasterAblauf_VorplanungRaster";"dbo";"VorplanungRasterAblauf";"IDVorplanungRaster_FS";"dbo";"VorplanungRaster";"IDVorplanungRaster"
"FK_VorplanungRasterAblaufAbwPartner_Adresse";"dbo";"VorplanungRasterAblaufAbwPartner";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_VorplanungRasterAblaufAbwPartner_VorplanungRasterAblauf";"dbo";"VorplanungRasterAblaufAbwPartner";"IDVorplanungRasterAblauf_FS";"dbo";"VorplanungRasterAblauf";"IDVorplanungRasterAblauf"
"FK_VorplanungRasterAblaufAbwPartner_VorplanungRasterTermin";"dbo";"VorplanungRasterAblaufAbwPartner";"IDVorplanungRasterTermin_FS";"dbo";"VorplanungRasterTermin";"IDVorplanungRasterTermin"
"FK_VorplanungRasterAblaufStatus_Adresse";"dbo";"VorplanungRasterAblaufStatus";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_VorplanungRasterAblaufStatus_ArtReiseVplPartnerStatus";"dbo";"VorplanungRasterAblaufStatus";"IDArtReiseVplPartnerStatus_FS";"dbo";"ArtReiseVplPartnerStatus";"IDArtReiseVplPartnerStatus"
"FK_VorplanungRasterAblaufStatus_VorplanungRasterAblauf";"dbo";"VorplanungRasterAblaufStatus";"IDVorplanungRasterAblauf_FS";"dbo";"VorplanungRasterAblauf";"IDVorplanungRasterAblauf"
"FK_VorplanungRasterAblaufStatus_VorplanungRasterTermin";"dbo";"VorplanungRasterAblaufStatus";"IDVorplanungRasterTermin_FS";"dbo";"VorplanungRasterTermin";"IDVorplanungRasterTermin"
"FK_VorplanungRasterAblaufZusatz_VorplanungRasterAblauf";"dbo";"VorplanungRasterAblaufZusatz";"IDVorplanungRasterAblauf_FS";"dbo";"VorplanungRasterAblauf";"IDVorplanungRasterAblauf"
"FK_VorplanungRasterBemerkung_VorplanungRaster";"dbo";"VorplanungRasterBemerkung";"IDVorplanungRaster_FS";"dbo";"VorplanungRaster";"IDVorplanungRaster"
"FK_VorplanungRasterDokument_Adresse";"dbo";"VorplanungRasterDokument";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_VorplanungRasterDokument_ArtDokument";"dbo";"VorplanungRasterDokument";"IDArtDokument_FS";"dbo";"ArtDokument";"IDArtDokument"
"FK_VorplanungRasterDokument_VorplanungRaster";"dbo";"VorplanungRasterDokument";"IDVorplanungRaster_FS";"dbo";"VorplanungRaster";"IDVorplanungRaster"
"FK_VorplanungRasterKalkulationÜbernahme_VorplanungRasterKalkulation";"dbo";"VorplanungRasterKalkulationÜbernahme";"IDVorplanungRasterKalkulation_FS";"dbo";"VorplanungRasterKalkulation";"IDVorplanungRasterKalkulation"
"FK_VorplanungRasterTermin_VorplanungRaster";"dbo";"VorplanungRasterTermin";"IDVorplanungRaster_FS";"dbo";"VorplanungRaster";"IDVorplanungRaster"
"FK_WaehrungsKurse_ArtWaehrung";"dbo";"WaehrungsKurse";"IDArtWaehrung_FS";"dbo";"ArtWaehrung";"IDArtWaehrung"
"FK_WerbeplanungPunkte_ArtWerbeplanungReiseart";"dbo";"WerbeplanungPunkte";"IDArtWerbeplanungReiseart_FS";"dbo";"ArtWerbeplanungReiseart";"IDArtWerbeplanungReiseart"
"FK_WWKategorieEintrag_WWSuchKategorie";"dbo";"WWSuchKategorieEintrag";"IDWWSuchKategorie_FS";"dbo";"WWSuchKategorie";"IDWWSuchKategorie"
"FK_Zahlung_Adresse";"dbo";"Zahlung";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_Zahlung_ArtWaehrung";"dbo";"Zahlung";"IDWaehrung_FS";"dbo";"ArtWaehrung";"IDArtWaehrung"
"FK_Zahlung_ArtZahlungsart";"dbo";"Zahlung";"IDArtZahlungart_FS";"dbo";"ArtZahlungsart";"IDArtZahlungsart"
"FK_Zahlung_ZahlungCode";"dbo";"Zahlung";"IDKontenplan_FS";"dbo";"Kontenplan";"IDKontenplan"
"FK_Zahlung_ZahlungStamm";"dbo";"Zahlung";"IDZahlungStamm_FS";"dbo";"ZahlungStamm";"IDZahlungStamm"
"FK_ZahlungDokument_Adresse";"dbo";"ZahlungDokument";"IDAdresse_FS_Sachbearbeiter";"dbo";"Adresse";"IDAdresse"
"FK_ZahlungDokument_ArtDokument";"dbo";"ZahlungDokument";"IDArtDokument_FS";"dbo";"ArtDokument";"IDArtDokument"
"FK_ZahlungDokument_Zahlung";"dbo";"ZahlungDokument";"IDZahlung_FS";"dbo";"Zahlung";"IDZahlung"
"FK_ZahlungStamm_Adresse";"dbo";"ZahlungStamm";"IDAdresse_FS_Mandant";"dbo";"Adresse";"IDAdresse"
"FK_ZahlungStamm_ArtWaehrung";"dbo";"ZahlungStamm";"IDWaehrung_FS";"dbo";"ArtWaehrung";"IDArtWaehrung"
"FK_ZahlungStamm_Nummernkreis";"dbo";"ZahlungStamm";"IDNummernkreis_FS";"dbo";"Nummernkreis";"IDNummernkreis"
"FK_ZiellandRoute_Land";"dbo";"ZiellandRoute";"IDLand_FS_Route";"dbo";"Land";"IDLand"
"FK_ZiellandRoute_Land1";"dbo";"ZiellandRoute";"IDLand_FS_Zielland";"dbo";"Land";"IDLand"
"FK_Zusatzinformation_Adresse";"dbo";"Zusatzinformation";"IDAdresse_FS_Partner";"dbo";"Adresse";"IDAdresse"
"FK_Zusatzinformation_ArtZusatzinfoStamm";"dbo";"Zusatzinformation";"IDArtZusatzinfoStamm_FS";"dbo";"ArtZusatzinfoStamm";"IDArtZusatzinfoStamm"
"FK_Zusatzinformation_Reise";"dbo";"Zusatzinformation";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ZusatzZimmer_ArtBuchungsStatus";"dbo";"ZusatzZimmer";"IDArtBuchungsstatus_FS";"dbo";"ArtBuchungsStatus";"IDArtBuchungsStatus"
"FK_ZusatzZimmer_Reise";"dbo";"ZusatzZimmer";"IDReise_FS";"dbo";"Reise";"IDReise"
"FK_ZustiegHinweis_Zustieg";"dbo";"ZustiegHinweis";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_Zustiegkoordinate_Zustieg";"dbo";"Zustiegkoordinate";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_ZustiegKoordinate_ZustiegKoordinatenArt";"dbo";"Zustiegkoordinate";"IDArtKoordinaten_FS";"dbo";"ArtZustiegKoordinaten";"IDArtZustiegKoordinaten"
"FK_ZustiegPLZ_Zustieg1";"dbo";"ZustiegPLZ";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_ZustiegPreis_ArtZustiegPreis1";"dbo";"ZustiegPreis";"IDArtZustiegPreis_FS";"dbo";"ArtZustiegPreis";"IDArtZustiegPreis"
"FK_ZustiegPreis_Zustieg1";"dbo";"ZustiegPreis";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_ZustiegRoute_ArtZustiegRoutenbeschreibung";"dbo";"ZustiegRoute";"IDArtZustiegRoutenbeschreibung_FS";"dbo";"ArtZustiegRoutenbeschreibung";"IDArtZustiegRoutenbeschreibung"
"FK_ZustiegRoute_Zustieg";"dbo";"ZustiegRoute";"IDZustieg_FS";"dbo";"Zustieg";"IDZustieg"
"FK_ZustiegsPlanungBesonders_ZustiegsPlanungPerson";"dbo";"ZustiegsPlanungBesonders";"IDZustiegsPlanungPerson_FS";"dbo";"ZustiegsPlanungPerson";"IDZustiegsPlanungPerson"
"FK_ZustiegsPlanungBus_ZustiegsPlanung";"dbo";"ZustiegsPlanungBus";"IDZustiegsPlanung_FS";"dbo";"ZustiegsPlanung";"IDZustiegsPlanung"
"FK_ZustiegsPlanungBusStelle_ZustiegsPlanungBus";"dbo";"ZustiegsPlanungBusStelle";"IDZustiegsPlanungBus_FS";"dbo";"ZustiegsPlanungBus";"IDZustiegsPlanungBus"
"FK_ZustiegsPlanungLeistung_ZustiegsPlanung";"dbo";"ZustiegsPlanungLeistung";"IDZustiegsPlanung_FS";"dbo";"ZustiegsPlanung";"IDZustiegsPlanung"
"FK_ZustiegsPlanungPerson_BuchungTN";"dbo";"ZustiegsPlanungPerson";"IDBuchungTN_FS";"dbo";"BuchungTN";"IDBuchungTN"
"FK_ZustiegsPlanungPerson_Leistung";"dbo";"ZustiegsPlanungPerson";"IDLeistung_FS";"dbo";"Leistung";"IDLeistung"
"FK_ZustiegsPlanungPerson_ZustiegsPlanung";"dbo";"ZustiegsPlanungPerson";"IDZustiegsPlanung_FS";"dbo";"ZustiegsPlanung";"IDZustiegsPlanung"
"FK_ZustiegsPlanungPersonStelle_ZustiegsPlanungBusStelle";"dbo";"ZustiegsPlanungPersonStelle";"IDZustiegsPlanungBusStelle_FS";"dbo";"ZustiegsPlanungBusStelle";"IDZustiegsPlanungBusStelle"
"FK_ZustiegsPlanungPersonStelle_ZustiegsPlanungPerson";"dbo";"ZustiegsPlanungPersonStelle";"IDZustiegsPlanungPerson_FS";"dbo";"ZustiegsPlanungPerson";"IDZustiegsPlanungPerson"
"FK_ZustiegZeitplan_ArtZustiegZeitplan";"dbo";"ZustiegZeitplan";"IDArtZustiegZeitplan_FS";"dbo";"ArtZustiegZeitplan";"IDArtZustiegZeitplan"
1 foreign_key_name child_schema child_table child_column parent_schema parent_table parent_column
2 FK_Tarif_Schulamt dbo ABOSummeFahrscheine IDAdresse_FS_Schulamt dbo Schulamt IDSchulamt
3 FK_Tarif_Schule dbo ABOSummeFahrscheine IDAdresse_FS_Schule dbo Schule IDSchule
4 FK_Tarif_Schuljahr dbo ABOSummeFahrscheine IDABOSchuljahr_FS dbo ABOSchuljahr IDABOSchuljahr
5 FK_AdressAuswertungProtokoll_Adresse dbo AdressAuswertungProtokoll IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
6 FK_AdresseAgenturKatalog_Adresse dbo AdresseAgenturKatalog IDAdresse_FS dbo Adresse IDAdresse
7 FK_AdresseAgenturKatalog_ArtKatalog dbo AdresseAgenturKatalog IDArtKatalog_FS dbo ArtKatalog IDArtKatalog
8 FK_AdresseAgenturOrganisation_Adresse dbo AdresseAgenturOrganisation IDAdresse_FS dbo Adresse IDAdresse
9 FK_AdresseAgenturOrganisation_ArtAgenturOrganisation dbo AdresseAgenturOrganisation IDArtAgenturOrganisation_FS dbo ArtAgenturOrganisation IDArtAgenturOrganisation
10 FK_AdresseAgenturProvision_Adresse dbo AdresseAgenturProvision IDArtProvisionsstaffel_FS dbo ArtProvisionsstaffel IDArtProvisionsstaffel
11 FK_AdresseAgenturProvision_Adresse1 dbo AdresseAgenturProvision IDAdresse_FS dbo Adresse IDAdresse
12 FK_AdresseAgenturZusatz_Adresse dbo AdresseAgenturZusatz IDAdresse_FS dbo Adresse IDAdresse
13 FK_AdresseAgenturZusatz_ArtAgenturPreisgruppe dbo AdresseAgenturZusatz IDArtAgenturPreisgruppe_FS dbo ArtAgenturPreisgruppe IDArtAgenturPreisgruppe
14 FK_AdresseAgenturZusatz_ArtPreisschema dbo AdresseAgenturZusatz IDArtPreisschema_FS dbo ArtPreisschema IDArtPreisschema
15 FK_AdresseAnruf_Adresse dbo AdresseAnruf IDAdresse_FS dbo Adresse IDAdresse
16 FK_AdresseAnschriftKoordinate_AdresseAnschrift dbo AdresseAnschriftKoordinate IDAdresseAnschrift_FS dbo AdresseAnschrift IDAdresseAnschrift
17 FK_AdresseAnschriftKoordinate_ArtZustiegKoordinaten dbo AdresseAnschriftKoordinate IDArtZustiegKoordinaten_FS dbo ArtZustiegKoordinaten IDArtZustiegKoordinaten
18 FK_Adresse_Bankverbindung dbo AdresseBankverbindung IDAdresse_FS dbo Adresse IDAdresse
19 FK_Adresse_Bearbeitung dbo AdresseBearbeitung IDAdresse_FS dbo Adresse IDAdresse
20 FK_Adresse_Bearbeitung_ErsterSachbearbeiter dbo AdresseBearbeitung IDAdresse_FS_ErsterSachbearbeiter dbo Adresse IDAdresse
21 FK_Adresse_Bearbeitung_LetzterSachbearbeiter dbo AdresseBearbeitung IDAdresse_FS_LetzterSachbearbeiter dbo Adresse IDAdresse
22 FK_AdresseCRS_Adresse dbo AdresseCRS IDAdresse_FS dbo Adresse IDAdresse
23 FK_AdresseCRS_ArtCRS dbo AdresseCRS IDArtCRS_FS dbo ArtCRS IDArtCRS
24 FK_AdresseDatenschutz_Adresse dbo AdresseDatenschutz IdAdresse_FS dbo Adresse IDAdresse
25 FK_AdresseEmpfehlerKonto_Adresse dbo AdresseEmpfehlerKonto IDAdresse_FS_Empfehler dbo Adresse IDAdresse
26 FK_AdresseEmpfehlerKonto_Adresse1 dbo AdresseEmpfehlerKonto IDAdresse_FS_Empfohlener dbo Adresse IDAdresse
27 FK_AdresseHinweis_Adresse dbo AdresseHinweis IDAdresse_FS dbo Adresse IDAdresse
28 FK_AdresseHistorie_Adresse dbo AdresseHistorie IDAdresse_FS dbo Adresse IDAdresse
29 FK_AdresseHistorieBuchungTN_Adresse dbo AdresseHistorieBuchungTN IDAdresseHistorie_FS dbo Adresse IDAdresse
30 FK_AdresseHistorieMietbus_Adresse dbo AdresseHistorieMietbus IDAdresse_FS dbo Adresse IDAdresse
31 FK_Adresse_Kommunikation dbo AdresseKommunikation IDAdresse_FS dbo Adresse IDAdresse
32 FK_AdresseKommunikation_ArtKommunikation dbo AdresseKommunikation IDArtKommunikation_FS dbo ArtKommunikation IDArtKommunikation
33 FK_Adresse_Kreditkarte dbo AdresseKreditkarte IDAdresse_FS dbo Adresse IDAdresse
34 FK_AdresseLandSteuer_Adresse dbo AdresseLandSteuer IDAdresse_FS dbo Adresse IDAdresse
35 FK_AdresseLandSteuer_Land dbo AdresseLandSteuer IDLand_FS dbo Land IDLand
36 FK_AdresseLinieAuftraggeber_Adresse dbo AdresseLinieAuftraggeber IDAdresse_FS dbo Adresse IDAdresse
37 FK_AdresseLinieAuftraggeber_ArtStatistikGruppe dbo AdresseLinieAuftraggeber IDArtStatistikGruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
38 FK_AdresseLinieAuftraggeberBlock_Adresse dbo AdresseLinieAuftraggeberBlock IDAdresse_FS dbo Adresse IDAdresse
39 FK_AdresseLinieAuftraggeberBlock_AdresseLinieAuftraggeber dbo AdresseLinieAuftraggeberBlock IDAdresseLinieAuftraggeber_FS dbo AdresseLinieAuftraggeber IDAdresseLinieAuftraggeber
40 FK_AdresseLinieAuftraggeberLinie_Adresse dbo AdresseLinieAuftraggeberLinie IDAdresse_FS dbo Adresse IDAdresse
41 FK_AdresseLinieAuftraggeberLinie_AdresseLinieAuftraggeber dbo AdresseLinieAuftraggeberLinie IDAdresseLinieAuftraggeber_FS dbo AdresseLinieAuftraggeber IDAdresseLinieAuftraggeber
42 FK_AdresseLinieAuftraggeberTour_Adresse dbo AdresseLinieAuftraggeberTour IDAdresse_FS dbo Adresse IDAdresse
43 FK_AdresseLinieAuftraggeberTour_AdresseLinieAuftraggeber dbo AdresseLinieAuftraggeberTour IDAdresseLinieAuftraggeber_FS dbo AdresseLinieAuftraggeber IDAdresseLinieAuftraggeber
44 FK_AdressMandant_Adresse dbo AdresseMandant IDAdresse_FS dbo Adresse IDAdresse
45 FK_AdresseMandantDokumentAusgabe_Adresse dbo AdresseMandantDokumentAusgabe IDAdresse_FS dbo Adresse IDAdresse
46 FK_AdresseMandantDokumentAusgabe_ArtDokumentAusgabe dbo AdresseMandantDokumentAusgabe IDArtDokumentAusgabe_FS dbo ArtDokumentAusgabe IDArtDokumentAusgabe
47 FK_AdresseMandantERechnung_Adresse dbo AdresseMandantERechnung IDAdresse_FS_Mandant dbo Adresse IDAdresse
48 FK_AdresseMandantERechnungBV_AdresseBankverbindung dbo AdresseMandantERechnungBV IDAdresseBankverbindung_FS dbo AdresseBankverbindung IDAdresseBankverbindung
49 FK_AdresseMandantERechnungBV_AdresseMandantERechnung dbo AdresseMandantERechnungBV IDAdresseMandantERechnung_FS dbo AdresseMandantERechnung IDAdresseMandantERechnung
50 FK_AdresseMandantNummernkreis_Adresse dbo AdresseMandantNummernkreis IDAdresse_FS dbo Adresse IDAdresse
51 FK_AdresseMandantNummernkreis_Nummernkreis dbo AdresseMandantNummernkreis IDNummernkreis_FS dbo Nummernkreis IDNummernkreis
52 FK_Adresse_Person dbo AdressePerson IDAdresse_FS dbo Adresse IDAdresse
53 FK_AdressePersonal_Adresse dbo AdressePersonal IDAdresse_FS dbo Adresse IDAdresse
54 FK_AdressePersonal_ArtBetriebshof dbo AdressePersonal IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
55 FK_AdressePersonal_ArtLohnMandant dbo AdressePersonal IDArtLohnMandant_FS dbo ArtLohnMandant IDArtLohnMandant
56 FK_AdressePersonal_ArtPersonalEinsatz dbo AdressePersonal IDArtPersonalEinsatz_FS dbo ArtPersonalEinsatz IDArtPersonalEinsatz
57 FK_AdressePersonal_ArtPersonalGruppeKompetenz dbo AdressePersonal IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
58 FK_AdressePersonalArt_Adresse dbo AdressePersonalArt IDAdresse_FS dbo Adresse IDAdresse
59 FK_AdressePersonalGruppeProdukt_Adresse dbo AdressePersonalGruppeProdukt IDAdresse_FS dbo Adresse IDAdresse
60 FK_AdressePersonalGruppeProdukt_ArtPersonalGruppeProdukt dbo AdressePersonalGruppeProdukt IDArtPersonalGruppeProdukt_FS dbo ArtPersonalGruppeProdukt IDArtPersonalGruppeProdukt
61 FK_AdressePersonalKleidung_Adresse dbo AdressePersonalKleidung IDAdresse_FS dbo Adresse IDAdresse
62 FK_AdressePersonalKleidung_ArtPersonalKleidung dbo AdressePersonalKleidung IDArtPersonalKleidung_FS dbo ArtPersonalKleidung IDArtPersonalKleidung
63 FK_AdressePersonalNummer_Adresse dbo AdressePersonalNummer IDAdresse_FS dbo Adresse IDAdresse
64 FK_AdressePersonalNummer_ArtPersonalNummer dbo AdressePersonalNummer IDArtPersonalNummer_FS dbo ArtPersonalNummer IDArtPersonalNummer
65 FK_AdressePersonalPunkte_Adresse dbo AdressePersonalPunkte IDAdresse_FS dbo Adresse IDAdresse
66 FK_AdressePersonalSonstGegenstaende_Adresse dbo AdressePersonalSonstGegenstaende IDAdresse_FS dbo Adresse IDAdresse
67 FK_AdressePersonalSonstGegenstaende_ArtPersonalSonstGegenstaende dbo AdressePersonalSonstGegenstaende IDArtPersonalSonstGegenstaende_FS dbo ArtPersonalSonstGegenstaende IDArtPersonalSonstGegenstaende
68 FK_AdressePersonalSperrKasse_Adresse dbo AdressePersonalSperrKasse IDAdresse_FS dbo Adresse IDAdresse
69 FK_AdressePersonalSperrKasse_ZahlungStamm dbo AdressePersonalSperrKasse IDZahlungStamm_FS dbo ZahlungStamm IDZahlungStamm
70 FK_AdressePersonalUnfall_Adresse dbo AdressePersonalUnfall IDAdresse_FS dbo Adresse IDAdresse
71 FK_AdressePersonalVerwendung_Adresse dbo AdressePersonalVerwendung IDAdresse_FS dbo Adresse IDAdresse
72 FK_AdressePersonalZusatz_Adresse dbo AdressePersonalZusatz IDAdresse_FS dbo Adresse IDAdresse
73 FK_AdressePersonalZusatz_SpracheMaske dbo AdressePersonalZusatz IDSpracheMaske_FS dbo SpracheMaske IDSpracheMaske
74 FK_AdressePunkte_Adresse dbo AdressePunkte IDAdresse_FS dbo Adresse IDAdresse
75 FK_AdressePunkte_Adresse1 dbo AdressePunkte IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
76 FK_AdresseSteueraufteilungDetail_Adresse dbo AdresseSteueraufteilungDetail IDAdresse_FS dbo Adresse IDAdresse
77 FK_AdresseSteueraufteilungDetail_Steueraufteilung dbo AdresseSteueraufteilungDetail IDSteueraufteilungDetail_FS dbo SteueraufteilungDetail IDSteueraufteilungDetail
78 FK_AdresseZusatz_Adresse dbo AdresseZusatz IDAdresse_FS dbo Adresse IDAdresse
79 FK_AdresseZusatzfeld_Adresse dbo AdresseZusatzfeld IDAdresse_FS dbo Adresse IDAdresse
80 FK_AdresseZusatzfeld_AdressePerson dbo AdresseZusatzfeld IDAdressePerson_FS dbo AdressePerson IDAdressePerson
81 FK_AdresseZusatzfeld_ArtAdresseZusatzfeld dbo AdresseZusatzfeld IDArtAdresseZusatzfeld_FS dbo ArtAdresseZusatzfeld IDArtAdresseZusatzfeld
82 FK_AdresseMietbusZusatz_Adresse dbo AdresseZusatzMietbus IDAdresse_FS dbo Adresse IDAdresse
83 FK_Adresse_AgenturSelektion dbo AgenturSelektionenKunde IDAdresse_FS dbo Adresse IDAdresse
84 FK_Selektionsstamm_AgenturSelektion dbo AgenturSelektionenKunde IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
85 FK_ArbeitswertMaterial_Arbeitswert dbo ArbeitswertMaterial IDArbeitswert_FS dbo Arbeitswert IDArbeitswert
86 FK_ArbeitswertMaterial_Artikel dbo ArbeitswertMaterial IDArtikel_FS dbo Artikel IDArtikel
87 FK_ArbeitswertPersonal_Arbeitswert dbo ArbeitswertPersonal IDArbeitswert_FS dbo Arbeitswert IDArbeitswert
88 FK_ArbeitswertPersonal_Arbeitszeitwert dbo ArbeitswertPersonal IDArbeitszeitwert_FS dbo Arbeitszeitwert IDArbeitszeitwert
89 FK_ArtArbeitszeitZusatzEinst_ArtArbeitszeitZusatz dbo ArtArbeitszeitZusatzEinst IDArtArbeitszeitZusatz_FS dbo ArtArbeitszeitzusatz IDArtArbeitszeitzusatz
90 FK_ArtikelBewegung_Artikel dbo ArtikelBewegung IDArtikel_FS dbo Artikel IDArtikel
91 FK_ArtikelImport_ArtArtikelImport dbo ArtikelImport IDArtArtikelImport_FS dbo ArtArtikelImport IDArtArtikelImport
92 FK_Artikelzusatz_ArtEinheit dbo Artikelzusatz IDArtEinheit_FS dbo ArtEinheit IDArtEinheit
93 FK_ArtikelZuweisungWarengruppe_Artikel dbo ArtikelZuweisungWarengruppe IDArtikel_FS dbo Artikel IDArtikel
94 FK_ArtikelZuweisungWarengruppe_Warengruppe dbo ArtikelZuweisungWarengruppe IDArtWarengruppe_FS dbo ArtWarengruppe IDArtWarengruppe
95 FK_Auftrag_Adresse3 dbo Auftrag IDAdresse_FS_Kunde dbo Adresse IDAdresse
96 FK_Auftrag_Auftragsart dbo Auftrag IDAuftragsart_FS dbo Auftragsart IDAuftragsart
97 FK_AuftragBlock_Auftrag dbo AuftragBlock IDAuftrag_FS dbo Auftrag IDAuftrag
98 FK_AuftragFahrer_Auftrag dbo AuftragFahrer IDAuftrag_FS dbo Auftrag IDAuftrag
99 FK_AuftragFahrer_AuftragFahrzeug dbo AuftragFahrer IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
100 FK_AuftragFahrer_AuftragTeilauftrag dbo AuftragFahrer IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
101 FK_AuftragFahrerArbeitszeit_ArtArbeitszeitzusatz dbo AuftragFahrerArbeitszeit IDArtArbeitszeitzusatz_FS dbo ArtArbeitszeitzusatz IDArtArbeitszeitzusatz
102 FK_AuftragFahrerArbeitszeit_AuftragFahrer dbo AuftragFahrerArbeitszeit IDAuftragFahrer_FS dbo AuftragFahrer IDAuftragFahrer
103 FK_AuftragFahrerArbeitszeitSpesen_AuftragFahrer dbo AuftragFahrerArbeitszeitSpesen IDAuftragFahrer_FS dbo AuftragFahrer IDAuftragFahrer
104 FK_AuftragFahrerTagesStunden_AuftragFahrer dbo AuftragFahrerTagesStunden IDAuftragFahrer_FS dbo AuftragFahrer IDAuftragFahrer
105 FK_AuftragFahrzeug_Auftrag dbo AuftragFahrzeug IDAuftrag_FS dbo Auftrag IDAuftrag
106 FK_AuftragFahrzeug_AuftragTeilauftrag dbo AuftragFahrzeug IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
107 FK_AuftragFahrzeugNavi_AuftragFahrzeug dbo AuftragFahrzeugNavi IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
108 FK_AuftragFahrzeugNavi_Fahrzeug dbo AuftragFahrzeugNavi IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
109 FK_AuftragFahrzeugNaviGrenzuebertritt_AuftragFahrzeug dbo AuftragFahrzeugNaviGrenzuebertritt IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
110 FK_AuftragFahrzeugTagesKM_AuftragFahrzeug dbo AuftragFahrzeugTagesKM IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
111 FK_AuftragInkludierteLeistung_Auftrag dbo AuftragInkludierteLeistung IDAuftrag_FS dbo Auftrag IDAuftrag
112 FK_AuftragInkludierteLeistung_AuftragTeilauftrag dbo AuftragInkludierteLeistung IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
113 FK_AuftragNebenleistung_Auftrag dbo AuftragInkludierteLeistung IDAuftrag_FS dbo Auftrag IDAuftrag
114 FK_AuftragNebenleistung_AuftragTeilauftrag dbo AuftragInkludierteLeistung IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
115 FK_AuftragKalkulationswert_Auftrag dbo AuftragKalkulationswert IDAuftrag_FS dbo Auftrag IDAuftrag
116 FK_AuftragKalkulationswert_AuftragTeilauftrag dbo AuftragKalkulationswert IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
117 FK_AuftragKilometer_Auftrag dbo AuftragKilometer IDAuftrag_FS dbo Auftrag IDAuftrag
118 FK_AuftragKilometer_AuftragFahrzeug dbo AuftragKilometer IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
119 FK_AuftragKilometer_AuftragTeilauftrag dbo AuftragKilometer IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
120 FK_AuftragKilometerLand_Auftrag dbo AuftragKilometerLand IDAuftrag_FS dbo Auftrag IDAuftrag
121 FK_AuftragKilometerLand_AuftragFahrzeug dbo AuftragKilometerLand IDAuftragFahrzeug_FS dbo AuftragFahrzeug IDAuftragFahrzeug
122 FK_AuftragKilometerLand_AuftragKilometer dbo AuftragKilometerLand IDAuftragKilometer_FS dbo AuftragKilometer IDAuftragKilometer
123 FK_AuftragKilometerLand_AuftragTeilauftrag dbo AuftragKilometerLand IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
124 FK_AuftragKilometerLand_Land dbo AuftragKilometerLand IDLand_FS dbo Land IDLand
125 FK_AuftragsartMwst_Auftragsart dbo AuftragsartMwst IDAuftragsart_FS dbo Auftragsart IDAuftragsart
126 FK_AuftragSuche_Adresse1 dbo AuftragSuche IDAdresse_FS_Kunde dbo Adresse IDAdresse
127 FK_AuftragSuche_Auftrag dbo AuftragSuche IDAuftrag_FS dbo Auftrag IDAuftrag
128 FK_AuftragSuche_Auftragsart dbo AuftragSuche IDAuftragsArt_FS dbo Auftragsart IDAuftragsart
129 FK_AuftragTAAbholstelle_AuftragTeilauftrag dbo AuftragTAAbholstelle IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
130 FK_AuftragTARoute_Auftrag dbo AuftragTARoute IDAuftrag_FS dbo Auftrag IDAuftrag
131 FK_AuftragTARoute_AuftragTeilauftrag dbo AuftragTARoute IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
132 FK_AuftragTARoute_Land dbo AuftragTARoute IDLand_FS dbo Land IDLand
133 FK_AuftragTeilauftrag_Auftrag dbo AuftragTeilauftrag IDAuftrag_FS dbo Auftrag IDAuftrag
134 FK_AuftragTeilauftragPreis_Auftrag dbo AuftragTeilauftragPreis IDAuftrag_FS dbo Auftrag IDAuftrag
135 FK_AuftragTeilauftragPreis_AuftragTeilauftrag dbo AuftragTeilauftragPreis IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
136 FK_AuftragTeilauftragPreisErweitert_AuftragTeilauftrag dbo AuftragTeilauftragPreisErweitert IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
137 FK_AuftragTeilauftragPreisErweitert_Ausstattung dbo AuftragTeilauftragPreisErweitert IDAusstattung_FS dbo Ausstattung IDAusstattung
138 FK_AuftragText_ArtAuftragstext dbo AuftragText IDArtAuftragstext_FS dbo ArtAuftragstext IDArtAuftragstext
139 FK_AuftragText_Auftrag dbo AuftragText IDAuftrag_FS dbo Auftrag IDAuftrag
140 FK_AuftragZusatz_ArtStornogrund dbo AuftragZusatz IDArtStornogrund_FS dbo ArtStornogrund IDArtStornogrund
141 FK_AuftragZusatz_Auftrag dbo AuftragZusatz IDAuftrag_FS dbo Auftrag IDAuftrag
142 FK_AuftragZusatzleistung_Auftrag dbo AuftragZusatzleistung IDAuftrag_FS dbo Auftrag IDAuftrag
143 FK_AuftragZusatzleistung_AuftragTeilauftrag dbo AuftragZusatzleistung IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
144 FK_AusstattungFahrzeugAusstattung_ArtFahrzeugAusstattungMerkmal dbo AusstattungFahrzeugAusstattung IDArtFahrzeugAusstattungMerkmal_FS dbo ArtFahrzeugAusstattungMerkmal IDArtFahrzeugAusstattungMerkmal
145 FK_AusstattungFahrzeugAusstattung_Ausstattung dbo AusstattungFahrzeugAusstattung IDAusstattung_FS dbo Ausstattung IDAusstattung
146 FK_AusstattungKalkulationsWert_Ausstattung dbo AusstattungKalkulationsWert IDAusstattung_FS dbo Ausstattung IDAusstattung
147 FK_AusstattungKalkulationsWert_KalkulationswertBezeichnung dbo AusstattungKalkulationsWert IDKalkulationsWertBezeichnung_FS dbo KalkulationswertBezeichnung IDKalkulationswertBezeichnung
148 FK_AusstattungKalkulationswertPersonen_AusstattungKalkulationsWert dbo AusstattungKalkulationswertPersonen IDAusstattungKalkulationswert_FS dbo AusstattungKalkulationsWert IDAusstattungKalkulationsWert
149 FK_AZKImport_Adresse dbo AZKImport IDAdresse_FS dbo Adresse IDAdresse
150 FK_AZKImport_AZKImportEinstellung dbo AZKImport IDAZKImportEinstellung_FS dbo AZKImportEinstellung IDAZKImportEinstellung
151 FK_Befoerderungsvertrag_Adresse dbo Befoerderungsvertrag IDAdresse_FS_Partner dbo Adresse IDAdresse
152 FK_Befoerderungsvertrag_AdresseAnschrift dbo Befoerderungsvertrag IDAdresseAnschrift_FS_Partner dbo AdresseAnschrift IDAdresseAnschrift
153 FK_BefoerderungsvertragTeilauftrag_AuftragTeilauftrag dbo BefoerderungsvertragTeilauftrag IDAuftragTeilauftrag_FS dbo AuftragTeilauftrag IDAuftragTeilauftrag
154 FK_BefoerderungsvertragTeilauftrag_Befoerderungsvertrag dbo BefoerderungsvertragTeilauftrag IDBefoerderungsvertrag_FS dbo Befoerderungsvertrag IDBefoerderungsvertrag
155 FK_Block_Adresse dbo Block IDAdresse_FS_Fahrer dbo Adresse IDAdresse
156 FK_Block_ArtBetriebshof dbo Block IDArtBetriebshof_FS_Anfang dbo ArtBetriebshof IDArtBetriebshof
157 FK_Block_ArtBetriebshof1 dbo Block IDArtBetriebshof_FS_Ende dbo ArtBetriebshof IDArtBetriebshof
158 FK_Block_ArtBlockArt dbo Block IDArtBlockart_FS dbo ArtBlockArt IDArtBlockArt
159 FK_Block_ArtFahrplanVersion dbo Block IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
160 FK_Block_ArtFremdunternehmen dbo Block IDArtFremdunternehmen_FS dbo ArtFremdunternehmen IDArtFremdunternehmen
161 FK_Block_ArtReichweitentyp dbo Block IDArtReichweitentyp_FS dbo ArtReichweitentyp IDArtReichweitentyp
162 FK_Block_Fahrzeug dbo Block IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
163 FK_Block_Ort_AbstellAnfang dbo Block IDOrt_FS_AbstellAnfang dbo Ort IDOrt
164 FK_Block_Ort_AbstellEnde dbo Block IDOrt_FS_AbstellEnde dbo Ort IDOrt
165 FK_BlockFahrzeugtyp_ArtFahrzeugTypen dbo BlockFahrzeugtyp IDArtFahrzeugTypen_FS dbo ArtFahrzeugTypen IDArtFahrzeugTypen
166 FK_BlockFahrzeugtyp_Block dbo BlockFahrzeugtyp IDBlock_FS dbo Block IDBlock
167 FK_BlockGruppeVerkehrstag_ArtGruppeVerkehrstag dbo BlockGruppeVerkehrstag IDArtGruppeVerkehrstag_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
168 FK_BlockGruppeVerkehrstag_Block dbo BlockGruppeVerkehrstag IDBlock_FS dbo Block IDBlock
169 FK_Blockkombination_ArtFahrplanVersion dbo Blockkombination IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
170 FK_BlockkombinationBlock_Block dbo BlockkombinationBlock IDBlock_FS dbo Block IDBlock
171 FK_BlockkombinationBlock_Blockkombination dbo BlockkombinationBlock IDBlockkombination_FS dbo Blockkombination IDBlockkombination
172 FK_BlockkombinationGruppeVerkehrstag_ArtGruppeVerkehrstag dbo BlockkombinationGruppeVerkehrstag IDArtGruppeVerkehrstag_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
173 FK_BlockkombinationGruppeVerkehrstag_Blockkombination dbo BlockkombinationGruppeVerkehrstag IDBlockkombination_FS dbo Blockkombination IDBlockkombination
174 FK_BlockPause_Block dbo BlockPause IDBlock_FS dbo Block IDBlock
175 FK_BlockPause_Ort dbo BlockPause IDOrt_FS dbo Ort IDOrt
176 FK_BlockPlanung_Adresse dbo BlockPlanung IDAdresse_FS_Fahrer dbo Adresse IDAdresse
177 FK_BlockPlanung_Adresse2 dbo BlockPlanung LoeschenManuellIDAdresse_FS_SB dbo Adresse IDAdresse
178 FK_BlockPlanung_ArtBetriebshof dbo BlockPlanung IDArtBetriebshof_FS_Anfang dbo ArtBetriebshof IDArtBetriebshof
179 FK_BlockPlanung_ArtBetriebshof1 dbo BlockPlanung IDArtBetriebshof_FS_Ende dbo ArtBetriebshof IDArtBetriebshof
180 FK_BlockPlanung_ArtBlockArt dbo BlockPlanung IDArtBlockart_FS dbo ArtBlockArt IDArtBlockArt
181 FK_BlockPlanung_ArtFahrplanVersion dbo BlockPlanung IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
182 FK_BlockPlanung_ArtFremdunternehmen dbo BlockPlanung IDArtFremdunternehmen_FS dbo ArtFremdunternehmen IDArtFremdunternehmen
183 FK_BlockPlanung_ArtReichweitentyp dbo BlockPlanung IDArtReichweitentyp_FS dbo ArtReichweitentyp IDArtReichweitentyp
184 FK_BlockPlanung_Block dbo BlockPlanung IDBlock_FS_Basis dbo Block IDBlock
185 FK_BlockPlanung_Fahrzeug dbo BlockPlanung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
186 FK_BlockPlanung_Ort_AbstellAnfang dbo BlockPlanung IDOrt_FS_AbstellAnfang dbo Ort IDOrt
187 FK_BlockPlanung_Ort_AbstellEnde dbo BlockPlanung IDOrt_FS_AbstellEnde dbo Ort IDOrt
188 FK_BlockPlanungFahrzeugtyp_ArtFahrzeugTypen dbo BlockPlanungFahrzeugtyp IDArtFahrzeugTypen_FS dbo ArtFahrzeugTypen IDArtFahrzeugTypen
189 FK_BlockPlanungFahrzeugtyp_BlockPlanung dbo BlockPlanungFahrzeugtyp IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
190 FK_BlockPlanungPause_BlockPlanung dbo BlockPlanungPause IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
191 FK_BlockPlanungPause_Ort dbo BlockPlanungPause IDOrt_FS dbo Ort IDOrt
192 FK_BlockPlanungPreisMehrMinder_TourPlanung dbo BlockPlanungPreisMehrMinder IDTourPlanung_FS dbo TourPlanung IDTourPlanung
193 FK_BlockPlanungZusatz_BlockPlanung dbo BlockPlanungZusatz IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
194 FK_BlockSitzenbleiber_Block dbo BlockSitzenbleiber IDBlock_FS dbo Block IDBlock
195 FK_BlockSitzenbleiber_TourNach dbo BlockSitzenbleiber IdTour_FS_Nach dbo Tour IDTour
196 FK_BlockSitzenbleiber_TourVon dbo BlockSitzenbleiber IdTour_FS_Von dbo Tour IDTour
197 FK_BlockTour_Block dbo BlockTour IDBlock_FS dbo Block IDBlock
198 FK_BlockTour_Tour dbo BlockTour IDTour_FS dbo Tour IDTour
199 FK_BlockZusatz_Block dbo BlockZusatz IDBlock_FS dbo Block IDBlock
200 FK_Buchung_Adresse dbo Buchung IDAdresse_FS_Agentur dbo Adresse IDAdresse
201 FK_Buchung_Adresse1 dbo Buchung IDAdresse_FS_ErsterSachb dbo Adresse IDAdresse
202 FK_Buchung_Adresse2 dbo Buchung IDAdresse_FS_LetzterSachb dbo Adresse IDAdresse
203 FK_Buchung_Adresse3 dbo Buchung IDAdresse_FS_Mandant dbo Adresse IDAdresse
204 FK_Buchung_IdAdressePerson dbo Buchung IdAdressePerson_FS_Anmelder dbo AdressePerson IDAdressePerson
205 FK_BuchungBemerkung_Buchung dbo BuchungBemerkung IDBuchung_FS dbo Buchung IDBuchung
206 FK_BuchungDokument_Adresse dbo BuchungDokument IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
207 FK_BuchungDokument_ArtDokument dbo BuchungDokument IDArtDokument_FS dbo ArtDokument IDArtDokument
208 FK_BuchungDokument_Buchung dbo BuchungDokument IDBuchung_FS dbo Buchung IDBuchung
209 FK_BuchungDruck_Buchung dbo BuchungDruck IDBuchung_FS dbo Buchung IDBuchung
210 FK_BuchungMeldung_Adresse dbo BuchungMeldung IDAdresse_FS_Mitarbeiter_Eingabe dbo Adresse IDAdresse
211 FK_BuchungMeldung_Adresse1 dbo BuchungMeldung IDAdresse_FS_Mitarbeiter_Meldung dbo Adresse IDAdresse
212 FK_BuchungMeldung_ArtMeldungArt dbo BuchungMeldung IDArtMeldungart_FS dbo ArtMeldungArt IDArtMeldungArt
213 FK_BuchungMeldung_Buchung dbo BuchungMeldung IDBuchung_FS dbo Buchung IDBuchung
214 FK_BuchungMeldung_BuchungTNFerienziel dbo BuchungMeldung IDBuchungTNFerienziel_FS dbo BuchungTNFerienziel IDBuchungTNFerienziel
215 FK_BuchungMeldung_BuchungTNLeistung dbo BuchungMeldung IDBuchungTNLeistung_FS dbo BuchungTNLeistung IDBuchungTNLeistung
216 FK_BuchungReisebüro_Buchung dbo BuchungReisebüro IDBuchung_FS dbo Buchung IDBuchung
217 FK_BuchungReisebüroVersicherungsGruppe_ArtVersicherungsGruppe dbo BuchungReisebüroVersicherungsGruppe IDArtVersicherungsGruppe_FS dbo ArtVersicherungsGruppe IDArtVersicherungsGruppe
218 FK_BuchungReisebüroVersicherungsGruppe_BuchungReisebüro dbo BuchungReisebüroVersicherungsGruppe IDBuchungReisebüro_FS dbo BuchungReisebüro IDBuchungReisebüro
219 FK_BuchungReisebüroVisum_BuchungReisebüro dbo BuchungReisebüroVisum IDBuchungReisebüro_FS dbo BuchungReisebüro IDBuchungReisebüro
220 FK_BuchungTextbaustein_Buchung dbo BuchungTextbaustein IDBuchung_FS dbo Buchung IDBuchung
221 FK_BuchungTextbaustein_Textbaustein dbo BuchungTextbaustein IDTextbaustein_FS dbo Textbaustein IDTextbaustein
222 FK_BuchungTN_AdressePerson dbo BuchungTN IDAdressePerson_FS dbo AdressePerson IDAdressePerson
223 FK_BuchungTN_ArtTeilnahmeStornoGrund dbo BuchungTN IDArtTeilnahmeStornoGrund_FS dbo ArtTeilnahmeStornoGrund IDArtTeilnahmeStornoGrund
224 FK_BuchungTN_Buchung dbo BuchungTN IDBuchung_FS dbo Buchung IDBuchung
225 FK_BuchungTNFerienziel_Adresse dbo BuchungTNFerienziel IDAdresse_FS_Partner dbo Adresse IDAdresse
226 FK_BuchungTNFerienziel_ArtVerpflegung dbo BuchungTNFerienziel IDArtVerpflegung_FS dbo ArtVerpflegung IDArtVerpflegung
227 FK_BuchungTNFerienziel_BuchungTN dbo BuchungTNFerienziel IDBuchungTN_FS dbo BuchungTN IDBuchungTN
228 FK_BuchungTNFerienziel_Zimmerart dbo BuchungTNFerienziel IDZimmerart_FS dbo Zimmerart IDZimmerart
229 FK_BuchungTNFerienzielPreis_BuchungTNFerienziel dbo BuchungTNFerienzielPreis IDBuchungTNFerienziel_FS dbo BuchungTNFerienziel IDBuchungTNFerienziel
230 FK_BuchungTNFerienzielPreis_BuchungTNPreis dbo BuchungTNFerienzielPreis IDBuchungTNPreis_FS dbo BuchungTNPreis IDBuchungTNPreis
231 FK_BuchungTNLeistung_BuchungTN dbo BuchungTNLeistung IDBuchungTN_FS dbo BuchungTN IDBuchungTN
232 FK_BuchungTNLeistung_Leistung dbo BuchungTNLeistung IDLeistung_FS dbo Leistung IDLeistung
233 FK_BuchungTNLeistungPreis_BuchungTNLeistung dbo BuchungTNLeistungPreis IDBuchungTNLeistung_FS dbo BuchungTNLeistung IDBuchungTNLeistung
234 FK_BuchungTNLeistungPreis_BuchungTNPreis dbo BuchungTNLeistungPreis IDBuchungTNPreis_FS dbo BuchungTNPreis IDBuchungTNPreis
235 FK_BuchungTNLeistungZusatz_BuchungTNLeistung dbo BuchungTNLeistungZusatz IDBuchungTNLeistung_FS dbo BuchungTNLeistung IDBuchungTNLeistung
236 FK_BuchungTNPreis_Adresse dbo BuchungTNPreis IDAdresse_FS_Sachb dbo Adresse IDAdresse
237 FK_BuchungTNPreis_ArtPreisschema dbo BuchungTNPreis IDArtPreisschema_FS dbo ArtPreisschema IDArtPreisschema
238 FK_BuchungTNPreis_BuchungTN dbo BuchungTNPreis IDBuchungTN_FS dbo BuchungTN IDBuchungTN
239 FK_BuchungTNPreisErm_BuchungTNPreis dbo BuchungTNPreisErm IDBuchungTNPreis_FS dbo BuchungTNPreis IDBuchungTNPreis
240 FK_BuchungTNVersicherung_BuchungTN dbo BuchungTNVersicherung IDBuchungTN_FS dbo BuchungTN IDBuchungTN
241 FK_BuchungTNVersicherung_Leistung dbo BuchungTNVersicherung IDLeistung_FS_Versicherung dbo Leistung IDLeistung
242 FK_BuchungTNVersicherungPreis_BuchungTNPreis dbo BuchungTNVersicherungPreis IDBuchungTNPreis_FS dbo BuchungTNPreis IDBuchungTNPreis
243 FK_BuchungTNVersicherungPreis_BuchungTNVersicherung dbo BuchungTNVersicherungPreis IDBuchungTNVersicherung_FS dbo BuchungTNVersicherung IDBuchungTNVersicherung
244 FK_BuchungTNWunsch_BuchungTN dbo BuchungTNWunsch IDBuchungTN_FS dbo BuchungTN IDBuchungTN
245 FK_BuchungTNZahlung_BuchungTN dbo BuchungTNZahlung IDBuchungTN_FS dbo BuchungTN IDBuchungTN
246 FK_BuchungTNZahlung_Zahlung dbo BuchungTNZahlung IDZahlung_FS dbo Zahlung IDZahlung
247 FK_BuchungTNZuschlag_BuchungTN dbo BuchungTNZuschlag IDBuchungTN_FS dbo BuchungTN IDBuchungTN
248 FK_BuchungTNZuschlagPreis_BuchungTNPreis dbo BuchungTNZuschlagPreis IDBuchungTNPreis_FS dbo BuchungTNPreis IDBuchungTNPreis
249 FK_BuchungTNZuschlagPreis_BuchungTNZuschlag dbo BuchungTNZuschlagPreis IDBuchungTNZuschlag_FS dbo BuchungTNZuschlag IDBuchungTNZuschlag
250 FK_BuchungTNZuschlagZusatz_BuchungTNZuschlag dbo BuchungTNZuschlagZusatz IDBuchungTNZuschlag_FS dbo BuchungTNZuschlag IDBuchungTNZuschlag
251 FK_BuchungUnterlagenStatus_Adresse dbo BuchungUnterlagenStatus IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
252 FK_BuchungUnterlagenStatus_ArtUnterlagenStatus dbo BuchungUnterlagenStatus IDArtUnterlagenStatus_FS dbo ArtUnterlagenStatus IDArtUnterlagenStatus
253 FK_BuchungUnterlagenStatus_Buchung dbo BuchungUnterlagenStatus IDBuchung_FS dbo Buchung IDBuchung
254 FK_BuchungVersicherungAngebot_Buchung dbo BuchungVersicherungAngebot IDBuchung_FS dbo Buchung IDBuchung
255 FK_BuchungVersicherungAngebot_Leistung dbo BuchungVersicherungAngebot IDLeistung_FS_Versicherung dbo Leistung IDLeistung
256 FK_BuchungZahlung_ArtZahlungsart dbo BuchungZahlung IDArtZahlungsart_FS dbo ArtZahlungsart IDArtZahlungsart
257 FK_BuchungZahlung_Buchung dbo BuchungZahlung IDBuchung_FS dbo Buchung IDBuchung
258 FK_BundeslandPLZOrt_ArtBundesland dbo BundeslandPLZOrt IDArtBundesland_FS dbo ArtBundesland IDArtBundesland
259 FK_ConnectChat_ArtConnectChatKategorie dbo ConnectChat IDArtConnectChatKategorie_FS dbo ArtConnectChatKategorie IDArtConnectChatKategorie
260 FK_ConnectChatKategorieKompetenz_ArtPersonalGruppeKompetenz dbo ConnectChatKategorieKompetenz IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
261 FK_ChatNachricht_ChatRaum dbo ConnectChatNachricht IDChat_FS dbo ConnectChat IDChat
262 FK_ChatTeilnehmer_ChatRaum dbo ConnectChatTeilnehmer IDChat_FS dbo ConnectChat IDChat
263 FK_ConnectDokumentReferenzen_ConnectDokument dbo ConnectDokumentReferenzen IDConnectDokument_FS dbo ConnectDokument IDConnectDokument
264 FK_ConnectKompetenz_ArtPersonalGruppeKompetenz dbo ConnectKompetenz IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
265 FK_ConnectNotificationsReceiver_ConnectNotifications dbo ConnectNotificationsReceiver IDConnectNotification dbo ConnectNotifications Id
266 FK_ConnectOrdner_ConnectOrdner dbo ConnectOrdner IDConnectOrdner_FS_Parent dbo ConnectOrdner IDConnectOrdner
267 FK_Connect_Planungsabruf_Adresse_Aenderung dbo ConnectPlanungsabruf IDAdresse_FS_Aenderung dbo Adresse IDAdresse
268 FK_Connect_Planungsabruf_Adresse_Fahrer dbo ConnectPlanungsabruf IDAdresse_FS_Fahrer dbo Adresse IDAdresse
269 FK_ConnectPlanungsabrufHistorie_Adresse dbo ConnectPlanungsabrufHistorie IDAdresse_FS_Fahrer dbo Adresse IDAdresse
270 FK_ConnectRueckmeldungMB_AuftragFahrer dbo ConnectRueckmeldungMB IDAuftragFahrer_FS dbo AuftragFahrer IDAuftragFahrer
271 FK_ConnectRueckmeldungMBFoto_ConnectRueckmeldungMB dbo ConnectRueckmeldungMBFoto IDConnectRueckmeldungMB_FS dbo ConnectRueckmeldungMB IDConnectRueckmeldungMB
272 FK_ConnectRueckmeldungMBKilometer_ConnectRueckmeldungMB dbo ConnectRueckmeldungMBKilometer IDConnectRueckmeldungMB_FS dbo ConnectRueckmeldungMB IDConnectRueckmeldungMB
273 FK_ArtConnectRueckmeldungMBText_ConnectRueckmeldungMBText dbo ConnectRueckmeldungMBText IDArtConnectRueckmeldungMBText_FS dbo ArtConnectRueckmeldungMBText IDArtConnectRueckmeldungMBText
274 FK_ConnectRueckmeldungMBText_ConnectRueckmeldungMB dbo ConnectRueckmeldungMBText IDConnectRueckmeldungMB_FS dbo ConnectRueckmeldungMB IDConnectRueckmeldungMB
275 FK_CRMAktionDesignSeite_CRMAktion dbo CRMAktionDesignSeite IDCRMAktion_FS dbo CRMAktion IDCRMAktion
276 FK_CRMAktionDesignSeiteZuweisung_CRMAktionDesignSeite dbo CRMAktionDesignSeiteZuweisung IDCRMAktionDesignSeite_FS dbo CRMAktionDesignSeite IDCRMAktionDesignSeite
277 FK_CRMAktionPLZ_CRMAktion dbo CRMAktionPLZ IDCRMAktion_FS dbo CRMAktion IDCRMAktion
278 FK_CRMAktionZuGruppe_CRMAktion dbo CRMAktionZuGruppe IDCRMAktion_FS dbo CRMAktion IDCRMAktion
279 FK_CRMAktionZuGruppe_CRMAktionZuGruppe dbo CRMAktionZuGruppe IDArtCRMGruppe_FS dbo ArtCRMGruppe IDArtCRMGruppe
280 FK_CRMAktionZuProdukt_CRMAktion dbo CRMAktionZuProdukt IDCRMAktion_FS dbo CRMAktion IDCRMAktion
281 FK_CRMAktionZuProdukt_Produkt dbo CRMAktionZuProdukt IDProdukt_FS dbo Produkt IDProdukt
282 FK_CRMAktionZuReise_CRMAktion dbo CRMAktionZuReise IDCRMAktion_FS dbo CRMAktion IDCRMAktion
283 FK_CRMAktionZuReise_Reise dbo CRMAktionZuReise IDReise_FS dbo Reise IDReise
284 FK_CRMDesignSegment_CRMDesign dbo CRMDesignSegment IDCRMDesign_FS dbo CRMDesign IDCRMDesign
285 FK_CRMInternetZuweisung_ArtCRMInternet dbo CRMInternetZuweisung IDArtCRMInternet_FS dbo ArtCRMInternet IDArtCRMInternet
286 FK_CRMInternetZuweisung_Buchung dbo CRMInternetZuweisung IDBuchung_FS dbo Buchung IDBuchung
287 FK_CRMWerbepartner_Adresse dbo CRMWerbepartner IDAdresse_FS_Partner dbo Adresse IDAdresse
288 FK_CRMWerbepartnerDesign_CRMDesign dbo CRMWerbepartnerDesign IDCRMDesign_FS dbo CRMDesign IDCRMDesign
289 FK_CRMWerbepartnerDesign_CRMWerbepartner dbo CRMWerbepartnerDesign IDCRMWerbepartner_FS dbo CRMWerbepartner IDCRMWerbepartner
290 FK_CRMWerbepartnerPLZ_CRMWerbepartner dbo CRMWerbepartnerPLZ IDCRMWerbepartner_FS dbo CRMWerbepartner IDCRMWerbepartner
291 FK_CRMZuweisung_Adresse dbo CRMZuweisung IDAdresse_FS dbo Adresse IDAdresse
292 FK_CRMZuweisung_Adresse1 dbo CRMZuweisung IDAdresse_FS_VonPersonal dbo Adresse IDAdresse
293 FK_DienstplandruckExport_ArtDienstplandruckExport dbo DienstplandruckExport IDArtDienstplandruckExport_FS dbo ArtDienstplandruckExport IDArtDienstplandruckExport
294 FK_DispoAenderung_Adresse dbo DispoAenderung IDAdresse_FS_Disponent dbo Adresse IDAdresse
295 FK_DispoAenderungDisponent_DispoAenderung dbo DispoAenderungDisponent IDDispoAenderung_FS dbo DispoAenderung IDDispoAenderung
296 FK_DispoAenderungDisponent_DispoAnmeldungDisponent dbo DispoAenderungDisponent IDDispoAnmeldungDisponent_FS dbo DispoAnmeldungDisponent IDDispoAnmeldungDisponent
297 FK_DispoAnmeldungDisponent_Adresse dbo DispoAnmeldungDisponent IDAdresse_FS_Disponent dbo Adresse IDAdresse
298 FK_DispoEinstellungKompetenzen_ArtPersonalGruppeKompetenz dbo DispoEinstellungKompetenz IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
299 FK_DispoEinstellungKompetenzBetriebshofAnzeige_ArtBetriebshof dbo DispoEinstellungKompetenzBetriebshofAnzeige IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
300 FK_DispoEinstellungKompetenzBetriebshofAnzeige_DispoEinstellungKompetenz dbo DispoEinstellungKompetenzBetriebshofAnzeige IDDispoEinstellungKompetenz_FS dbo DispoEinstellungKompetenz IDDispoEinstellungKompetenz
301 FK_DispoEinstellungKompetenzMandantAnzeige_Adresse dbo DispoEinstellungKompetenzMandantAnzeige IDAdresse_FS_Mandant dbo Adresse IDAdresse
302 FK_DispoEinstellungKompetenzMandantAnzeige_DispoEinstellungKompetenzen dbo DispoEinstellungKompetenzMandantAnzeige IDDispoEinstellungKompetenz_FS dbo DispoEinstellungKompetenz IDDispoEinstellungKompetenz
303 FK_Dokument_Adresse dbo Dokument IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
304 FK_Dokument_ArtDokument dbo Dokument IDArtDokument_FS dbo ArtDokument IDArtDokument
305 FK_DruckArchiv_Adresse dbo DruckArchiv IDAdresse_FS_SB dbo Adresse IDAdresse
306 FK_DruckArchivZIP_Adresse dbo DruckArchivZIP IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
307 FK_DTAMeldung_RechnungHaupt dbo DTAMeldung IDRechnungHaupt_FS dbo RechnungHaupt IDRechnungHaupt
308 FK_EinreisebestimmungText_Einreisebestimmung dbo EinreisebestimmungText IDEinreisebestimmung_FS dbo Einreisebestimmung IDEinreisebestimmung
309 FK_ExportInternetSpalte_ExportInternet dbo ExportInternetSpalte IDExportInternetZeile_FS dbo ExportInternetZeile IDExportInternetZeile
310 FK_ExportInternetZeile_ExportInternetZeile dbo ExportInternetZeile IDExportInternet_FS dbo ExportInternet IDExportInternet
311 FK_FahrtArt_ArtFahrtArt dbo FahrtArtKonten IdArtFahrtArt_FS dbo ArtFahrtArt IDArtFahrtArt
312 FK_Fahrzeug_ArtFahrzeugBriefOrt dbo Fahrzeug IDArtFahrzeugBriefOrt_FS dbo ArtFahrzeugBriefOrt IDArtFahrzeugBriefOrt
313 FK_Fahrzeug_ArtReichweitentyp dbo Fahrzeug IDArtReichweitentyp_FS dbo ArtReichweitentyp IDArtReichweitentyp
314 FK_Fahrzeug_FahrzeugBetriebshof dbo Fahrzeug IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
315 FK_Fahrzeug_FahrzeugEinsatz dbo Fahrzeug IDArtFahrzeugEinsatz_FS dbo ArtFahrzeugEinsatz IDArtFahrzeugEinsatz
316 FK_Fahrzeug_FahrzeugTypen dbo Fahrzeug IDArtFahrzeugTypen_FS dbo ArtFahrzeugTypen IDArtFahrzeugTypen
317 FK_FahrzeugAusstattung_AusstattungsMerkmale dbo FahrzeugAusstattung IDArtFahrzeugAusstattungMerkmal_FS dbo ArtFahrzeugAusstattungMerkmal IDArtFahrzeugAusstattungMerkmal
318 FK_FahrzeugAusstattung_Fahrzeug dbo FahrzeugAusstattung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
319 FK_FahrzeugEinbauten_Fahrzeug dbo FahrzeugEinbauten IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
320 FK_FahrzeugGerät_ArtFahrzeugGerätTyp dbo FahrzeugGerät IDArtFahrzeugGerätTyp_FS dbo ArtFahrzeugGerätTyp IDArtFahrzeugGerätTyp
321 FK_FahrzeugGerätHistorie_ArtFahrzeugGerätOrt dbo FahrzeugGerätHistorie IDArtFahrzeugGerätOrt_FS dbo ArtFahrzeugGerätOrt IDArtFahrzeugGerätOrt
322 FK_FahrzeugGerätHistorie_Fahrzeug dbo FahrzeugGerätHistorie IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
323 FK_FahrzeugGerätHistorie_FahrzeugGerät dbo FahrzeugGerätHistorie IDFahrzeugGerät_FS dbo FahrzeugGerät IDFahrzeugGerät
324 FK_FahrzeugLeasing_Fahrzeug dbo FahrzeugLeasing IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
325 FK_FahrzeugNummer_ArtFahrzeugNummer dbo FahrzeugNummer IDArtFahrzeugNummer_FS dbo ArtFahrzeugNummer IDArtFahrzeugNummer
326 FK_FahrzeugNummer_Fahrzeug dbo FahrzeugNummer IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
327 FK_FahrzeugStatistikAnmelder_Fahrzeug dbo FahrzeugStatistikAnmelder IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
328 FK_FahrzeugTerminKettenAufbau_FahrzeugTermin dbo FahrzeugTerminKettenAufbau IDFahrzeugTermin_FS dbo FahrzeugTermin IDFahrzeugTermin
329 FK_FahrzeugTerminKettenAufbau_FahrzeugTerminHaeufigkeit dbo FahrzeugTerminKettenAufbau IDFahrzeugTerminHaeufigkeit_FS dbo FahrzeugTerminHaeufigkeit IDFahrzeugTerminHaeufigkeit
330 FK_FahrzeugTerminKettenAufbau_FahrzeugTerminkette dbo FahrzeugTerminKettenAufbau IDFahrzeugTerminkette_FS dbo FahrzeugTerminkette IDFahrzeugTerminkette
331 FK_FahrzeugTerminZuweisung_Fahrzeug dbo FahrzeugTerminZuweisung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
332 FK_FahrzeugTerminZuweisung_FahrzeugTerminKettenAufbau dbo FahrzeugTerminZuweisung IDFahrzeugTerminKettenAufbau_FS dbo FahrzeugTerminKettenAufbau IDFahrzeugTerminKettenAufbau
333 FK_FahrzeugVermietung_Fahrzeug dbo FahrzeugVermietung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
334 FK_FahrzeugVersicherung_Fahrzeug dbo FahrzeugVersicherung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
335 FK_FahrzeugVerwendung_Fahrzeug dbo FahrzeugVerwendung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
336 FK_FahrzeugWerbung_Fahrzeug dbo FahrzeugWerbung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
337 FK_FehlerProtokoll_Adresse dbo FehlerProtokoll IDAdresse_FS dbo Adresse IDAdresse
338 FK_FehlerProtokoll_FehlerProtokollTyp dbo FehlerProtokoll IDFehlerProtokollTyp_FS dbo FehlerProtokollTyp IDFehlerProtokollTyp
339 FK_FehlerProtokollTypEinstellung_FehlerProtokollTyp_FS dbo FehlerProtokollTypEinstellung IDFehlerProtokollTyp_FS dbo FehlerProtokollTyp IDFehlerProtokollTyp
340 FK_FehlerProtokollTypEinstellung_Kommunikation_FS dbo FehlerProtokollTypEinstellung IDKommunikation_FS dbo Kommunikation IDKommunikation
341 FK_FerienzielZwischenPartner_Adresse dbo FerienzielZwischenPartner IDAdresse_FS dbo Adresse IDAdresse
342 FK_FerienzielZwischenPartner_FerienzielZwischenZeitraum dbo FerienzielZwischenPartner IDFerienzielZwischenZeitraum_FS dbo FerienzielZwischenZeitraum IDFerienzielZwischenZeitraum
343 FK_FerienzielZwischenZeitraum_Produkt dbo FerienzielZwischenZeitraum IDProdukt_FS dbo Produkt IDProdukt
344 FK_Fibuaufteilung_ArtFibuaufteilung dbo Fibuaufteilung IdArtFibuaufteilung_FS dbo ArtFibuaufteilung IDArtFibuaufteilung
345 FK_Fibuaufteilung_Kontenplan dbo Fibuaufteilung IdKontenplan_FS dbo Kontenplan IDKontenplan
346 FK_FibuAufteilungWerte_Buchung dbo FibuAufteilungWerte IDBuchung_FS dbo Buchung IDBuchung
347 FK_FibuAufteilungWerte_Fibuaufteilung dbo FibuAufteilungWerte IDFibuAufteilung_FS dbo Fibuaufteilung IdFibuaufteilung
348 FK_FPAllgemein_ArtFahrplanVersion dbo FPAllgemein IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
349 FK_FPLinie_ArtFahrplanVersion dbo FPLinie IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
350 FK_FPLinie_ArtFPLinienTyp dbo FPLinie IDArtFPLinienTyp_FS dbo ArtFPLinienTyp IDArtFPLinienTyp
351 FK_FPLinie_ArtLinieVerbund dbo FPLinie IDArtLinieVerbund_FS dbo ArtLinieVerbund IDArtLinieVerbund
352 FK_FPLinie_ArtLinieVUBereich dbo FPLinie IDArtLinieVUBereich_FS dbo ArtLinieVUBereich IDArtLinieVUBereich
353 FK_FPLinie_ArtStatistikGruppe dbo FPLinie IDArtStatistikgruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
354 FK_FPLinieAnschluss_FPLinie dbo FPLinieAnschluss IDFPLinie_FS dbo FPLinie IDFPLinie
355 FK_FPLinieAnschluss_FPLinie_Bringer dbo FPLinieAnschluss IDFPLinie_FS_Bringer dbo FPLinie IDFPLinie
356 FK_FPLinieAnschluss_FPLinieHaltestelle dbo FPLinieAnschluss IDFPLinieHaltestelle_FS_Position dbo FPLinieHaltestelle IDFPLinieHaltestelle
357 FK_FPLinieAnschluss_FPLinieHaltestelleZubringer dbo FPLinieAnschluss IDFPLinieHaltestelle_FS_Position_Zubringer dbo FPLinieHaltestelle IDFPLinieHaltestelle
358 FK_FPLinieAnschluss_FPLinieSymbol dbo FPLinieAnschluss IDFPLinieSymbol_FS dbo FPLinieSymbol IDFPLinieSymbol
359 FK_FPLinieAnschlussDefinition_ArtFahrplanVersion dbo FPLinieAnschlussDefinition IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
360 FK_FPLinieAnschlussDefinition_FPLinie_Abbringer dbo FPLinieAnschlussDefinition IDFPLinie_FS_Abbringer dbo FPLinie IDFPLinie
361 FK_FPLinieAnschlussDefinition_FPLinie_Zubringer dbo FPLinieAnschlussDefinition IDFPLinie_FS_Zubringer dbo FPLinie IDFPLinie
362 FK_FPLinieAnschlussDefinition_Haltepunkt_Abbringer dbo FPLinieAnschlussDefinition IDHaltepunkt_FS_Abbringer dbo Haltepunkt IDHaltepunkt
363 FK_FPLinieAnschlussDefinition_Haltepunkt_Zubringer dbo FPLinieAnschlussDefinition IDHaltepunkt_FS_Zubringer dbo Haltepunkt IDHaltepunkt
364 FK_FPLinieAnschlussDefinition_Haltestelle_Abbringer dbo FPLinieAnschlussDefinition IDHaltestelle_FS_Abbringer dbo Haltestelle IDHaltestelle
365 FK_FPLinieAnschlussDefinition_Haltestelle_Zubringer dbo FPLinieAnschlussDefinition IDHaltestelle_FS_Zubringer dbo Haltestelle IDHaltestelle
366 FK_FPLinieAnschlussDefinitionUmstieg_FPLinieAnschlussDefinition dbo FPLinieAnschlussDefinitionUmstieg IDFPLinieAnschlussDefinition_FS dbo FPLinieAnschlussDefinition IDFPLinieAnschlussDefinition
367 FK_FPLinieAnschlussDefinitionUmstiegGruppeVT_FPLinieAnschlussDefinitionUmstieg dbo FPLinieAnschlussDefinitionUmstiegGruppeVT IDFPLinieAnschlussDefinitionUmstieg_FS dbo FPLinieAnschlussDefinitionUmstieg IDFPLinieAnschlussDefinitionUmstieg
368 FK_FPLinieBeschraenkung_ArtLaufzeitschema dbo FPLinieBeschraenkung IDArtLaufzeitschema_FS dbo ArtLaufzeitschema IDArtLaufzeitschema
369 FK_FPLinieBeschraenkung_FPSondererklaerung dbo FPLinieBeschraenkung IDFPSondererklaerung_FS dbo FPSondererklaerung IDFPSondererklaerung
370 FK_FPLinieBeschraenkungFerienFeier_FPLinieBeschraenkung dbo FPLinieBeschraenkungFerienFeier IDFPLinieBeschraenkung_FS dbo FPLinieBeschraenkung IDFPLinieBeschraenkung
371 FK_FPLinieBeschraenkungLaufzeit_FPLinieBeschraenkung dbo FPLinieBeschraenkungLaufzeit IDFPLinieBeschraenkung_FS dbo FPLinieBeschraenkung IDFPLinieBeschraenkung
372 FK_FPLinieBeschraenkungWochentyp_ArtWochentyp dbo FPLinieBeschraenkungWochentyp IDArtWochentyp_FS dbo ArtWochentyp IDArtWochentyp
373 FK_FPLinieBeschraenkungWochentyp_FPLinieBeschraenkung dbo FPLinieBeschraenkungWochentyp IDFPLinieBeschraenkung_FS dbo FPLinieBeschraenkung IDFPLinieBeschraenkung
374 FK_FPLinieDruck_FPLinie dbo FPLinieDruck IDFPLinie_FS dbo FPLinie IDFPLinie
375 FK_FPLinieFahrplanAdresse_FahrplanAdresse dbo FPLinieFahrplanAdresse IDFahrplanAdresse_FS dbo FahrplanAdresse IDFahrplanAdresse
376 FK_FPLinieFahrplanAdresse_FPLinie dbo FPLinieFahrplanAdresse IDFPLinie_FS dbo FPLinie IDFPLinie
377 FK_FPLinieFahrt_ArtFremdunternehmen dbo FPLinieFahrt IDArtFremdunternehmen_FS dbo ArtFremdunternehmen IDArtFremdunternehmen
378 FK_FPLinieFahrt_FPLinie dbo FPLinieFahrt IDFPLinie_FS dbo FPLinie IDFPLinie
379 FK_FPLinieFahrt_FPLinieFahrt dbo FPLinieFahrt IDFPLinieFahrt_FS_VerstaerkerVon dbo FPLinieFahrt IDFPLinieFahrt
380 FK_FPLinieFahrt_FPLinieFahrt_TeilenOriginal dbo FPLinieFahrt IDFPLinieFahrt_FS_TeilenOriginal dbo FPLinieFahrt IDFPLinieFahrt
381 FK_FPLinieFahrt_FPLinieZeitart dbo FPLinieFahrt IDFPLinieZeitart_FS dbo FPLinieZeitart IDFPLinieZeitart
382 FK_FPLinieFahrtAnschluss_FPLinieAnschluss dbo FPLinieFahrtAnschluss IDFPLinieAnschluss_FS dbo FPLinieAnschluss IDFPLinieAnschluss
383 FK_FPLinieFahrtAnschluss_FPLinieFahrt dbo FPLinieFahrtAnschluss IDFPLinieFahrt_FS dbo FPLinieFahrt IDFPLinieFahrt
384 FK_FPLinieFahrtAnschluss_FPLinieFahrt_Bringer dbo FPLinieFahrtAnschluss IDFPLinieFahrt_FS_Bringer dbo FPLinieFahrt IDFPLinieFahrt
385 FK_FPLinieFahrtAnschluss_FPLinieHaltestelle_Bringer dbo FPLinieFahrtAnschluss IDFPLinieHaltestelle_FS_Bringer dbo FPLinieHaltestelle IDFPLinieHaltestelle
386 FK_FPLinieFahrtAnschlussBeschraenkung_FPLinieBeschraenkung dbo FPLinieFahrtAnschlussBeschraenkung IDFPLinieBeschraenkung_FS dbo FPLinieBeschraenkung IDFPLinieBeschraenkung
387 FK_FPLinieFahrtAnschlussBeschraenkung_FPLinieFahrtAnschluss dbo FPLinieFahrtAnschlussBeschraenkung IDFPLinieFahrtAnschluss_FS dbo FPLinieFahrtAnschluss IDFPLinieFahrtAnschluss
388 FK_FPLinieFahrtBeschraenkung_FPLinieBeschraenkung dbo FPLinieFahrtBeschraenkung IDFPLinieBeschraenkung_FS dbo FPLinieBeschraenkung IDFPLinieBeschraenkung
389 FK_FPLinieFahrtBeschraenkung_FPLinieFahrt dbo FPLinieFahrtBeschraenkung IDFPLinieFahrt_FS dbo FPLinieFahrt IDFPLinieFahrt
390 FK_FPLinieHaltestelle_ArtKreisGebiet dbo FPLinieHaltestelle IDArtKreisGebiet_FS dbo ArtKreisGebiet IDArtKreisGebiet
391 FK_FPLinieHaltestelle_FPLinie dbo FPLinieHaltestelle IDFPLinie_FS dbo FPLinie IDFPLinie
392 FK_FPLinieHaltestelle_FPLinieHaltestelle dbo FPLinieHaltestelle IDFPLinieHaltestelle_FS_VerschiebenAuf dbo FPLinieHaltestelle IDFPLinieHaltestelle
393 FK_FPLinieHaltestelle_Haltepunkt dbo FPLinieHaltestelle IDHaltepunkt_FS dbo Haltepunkt IDHaltepunkt
394 FK_FPLinieHaltestelle_Haltestelle dbo FPLinieHaltestelle IDHaltestelle_FS dbo Haltestelle IDHaltestelle
395 FK_FPLinieHaltestelleBemerkung_FPLinieHaltestelle dbo FPLinieHaltestelleBemerkung IDFPLinieHaltestelle_FS dbo FPLinieHaltestelle IDFPLinieHaltestelle
396 FK_FPLinieHaltestelleBemerkung_HaltestelleBemerkung dbo FPLinieHaltestelleBemerkung IDHaltestelleBemerkung_FS dbo HaltestelleBemerkung IDHaltestelleBemerkung
397 FK_FPLinieHaltestelleZeitart_ArtKreisGebiet dbo FPLinieHaltestelleZeitart IDArtKreisGebiet_FS dbo ArtKreisGebiet IDArtKreisGebiet
398 FK_FPLinieHaltestelleZeitart_FPLinieHaltestelle dbo FPLinieHaltestelleZeitart IDFPLinieHaltestelle_FS dbo FPLinieHaltestelle IDFPLinieHaltestelle
399 FK_FPLinieHaltestelleZeitart_FPLinieZeitart dbo FPLinieHaltestelleZeitart IDFPLinieZeitart_FS dbo FPLinieZeitart IDFPLinieZeitart
400 FK_FPLinieHaltestelleZeitart_HaltestelleBemerkung dbo FPLinieHaltestelleZeitart IDHaltestelleBemerkung_FS dbo HaltestelleBemerkung IDHaltestelleBemerkung
401 FK_FPLinieHaltestelleZeitart_LinieZiel dbo FPLinieHaltestelleZeitart IDLinieZiel_FS dbo LinieZiel IDLinieZiel
402 FK_FPLinieZeitart_ArtStatistikGruppe dbo FPLinieZeitart IDArtStatistikgruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
403 FK_FPLinieZeitart_FPLinie dbo FPLinieZeitart IDFPLinie_FS dbo FPLinie IDFPLinie
404 FK_FPLinieZeitart_FPLinieHaltestelle_TeilenAbschnittBis dbo FPLinieZeitart IDFPLinieHaltestelle_FS_TeilenAbschnittBis dbo FPLinieHaltestelle IDFPLinieHaltestelle
405 FK_FPLinieZeitart_FPLinieHaltestelle_TeilenAbschnittVon dbo FPLinieZeitart IDFPLinieHaltestelle_FS_TeilenAbschnittVon dbo FPLinieHaltestelle IDFPLinieHaltestelle
406 FK_FPLinieZeitart_FPLinieZeitart dbo FPLinieZeitart IDFPLinieZeitart_FS_TeilenOriginal dbo FPLinieZeitart IDFPLinieZeitart
407 FK_FPSchuelerAbsage_Adresse dbo FPSchuelerAbsage IdAdresse_FS_Bearbeitet dbo Adresse IDAdresse
408 FK_FPSchuelerAbsage_FPSchueler dbo FPSchuelerAbsage IDFPSchueler_FS dbo FPSchueler IDFPSchueler
409 FK_FPSchuelerBefoerderung_FPSchueler dbo FPSchuelerBefoerderung IDFPSchueler_FS dbo FPSchueler IDFPSchueler
410 FK_FPSchuelerBefoerderung_FPSchule dbo FPSchuelerBefoerderung IDFPSchule_FS dbo FPSchule IDFPSchule
411 FK_FPSchuelerBefoerderung_FPSchuljahr dbo FPSchuelerBefoerderung IDFPSchuljahr_FS dbo FPSchuljahr IDFPSchuljahr
412 FK_FPSchuelerBefoerderungBewegung_Haltepunkt_Ausstieg dbo FPSchuelerBefoerderungBewegung IDHaltepunkt_FS_Ausstieg dbo Haltepunkt IDHaltepunkt
413 FK_FPSchuelerBefoerderungBewegung_Haltepunkt_Einstieg dbo FPSchuelerBefoerderungBewegung IDHaltepunkt_FS_Einstieg dbo Haltepunkt IDHaltepunkt
414 FK_FPSchuelerBefoerderungBewegung_Haltestelle_Ausstieg dbo FPSchuelerBefoerderungBewegung IDHaltestelle_FS_Ausstieg dbo Haltestelle IDHaltestelle
415 FK_FPSchuelerBefoerderungBewegung_Haltestelle_Einstieg dbo FPSchuelerBefoerderungBewegung IDHaltestelle_FS_Einstieg dbo Haltestelle IDHaltestelle
416 FK_FPSchuelerBefoerderungBewegung_IDFPSchuelerBefoerderung dbo FPSchuelerBefoerderungBewegung IDFPSchuelerBefoerderung_FS dbo FPSchuelerBefoerderung IDFPSchuelerBefoerderung
417 FK_FPSchuelerBefoerderungBewegungAbsage_FPSchuelerAbsage dbo FPSchuelerBefoerderungBewegungAbsage IDFPSchuelerAbsage_FS dbo FPSchuelerAbsage IDFPSchuelerAbsage
418 FK_FPSchuelerBefoerderungBewegungAbsage_FPSchuelerBefoerderungBewegung dbo FPSchuelerBefoerderungBewegungAbsage IDFPSchuelerBefoerderungBewegung_FS dbo FPSchuelerBefoerderungBewegung IDFPSchuelerBefoerderungBewegung
419 FK_FPSchuelerBefoerderungBewegungZuordnung_FPLinieFahrt dbo FPSchuelerBefoerderungBewegungZuordnung IDFPLinieFahrt_FS dbo FPLinieFahrt IDFPLinieFahrt
420 FK_FPSchuelerBefoerderungBewegungZuordnung_FPLinieHaltestelle dbo FPSchuelerBefoerderungBewegungZuordnung IDFPLinieHaltestelle_FS dbo FPLinieHaltestelle IDFPLinieHaltestelle
421 FK_FPSchuelerBefoerderungBewegungZuordnung_FPSchuelerBefoerderungBewegung dbo FPSchuelerBefoerderungBewegungZuordnung IDFPSchuelerBefoerderungBewegung_FS dbo FPSchuelerBefoerderungBewegung IDFPSchuelerBefoerderungBewegung
422 FK_FPSchuelerBefoerderungBewegungZuordnung_FPZeitart dbo FPSchuelerBefoerderungBewegungZuordnung IDFPLinieZeitart_FS dbo FPLinieZeitart IDFPLinieZeitart
423 FK_FPSchuleHaltestelleHaltepunkt_FPSchule dbo FPSchuleHaltestelleHaltepunkt IDFPSchule_FS dbo FPSchule IDFPSchule
424 FK_FPSchuleHaltestelleHaltepunkt_Haltepunkt dbo FPSchuleHaltestelleHaltepunkt IDHaltepunkt_FS dbo Haltepunkt IDHaltepunkt
425 FK_FPSchuleHaltestelleHaltepunkt_Haltestelle dbo FPSchuleHaltestelleHaltepunkt IDHaltestelle_FS dbo Haltestelle IDHaltestelle
426 FK_FreibescheinigungManuelleEingabe_Adresse dbo FreibescheinigungManuelleEingabe IDAdresse_FS_Fahrer dbo Adresse IDAdresse
427 FK_FreibescheinigungRuhetag_Adresse dbo FreibescheinigungRuhetag IDAdresse_FS_Fahrer dbo Adresse IDAdresse
428 FK_GruppeVerkehrstag_ArtGruppeVerkehrstag dbo GruppeVerkehrstag IDArtGruppeVerkehrstag_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
429 FK_GruppeVerkehrstagFerien_ArtGruppeVerkehrstag dbo GruppeVerkehrstagFerien IDArtGruppeVerkehrstag_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
430 FK_Gutschein_ArtGutscheinversand dbo Gutschein IDArtGutscheinversand_FS dbo ArtGutscheinversand IDArtGutscheinversand
431 FK_GutscheinlayoutInternet_ArtGutscheinlayout dbo GutscheinlayoutInternet IDArtGutscheinlayout_FS dbo ArtGutscheinlayout IDArtGutscheinlayout
432 FK_Gutscheinzuschlag_Gutschein dbo GutscheinZuschlag IDGutschein_FS dbo Gutschein IDGutschein
433 FK_Gutscheinzuschlag_Kontenplan dbo GutscheinZuschlag IDKontenplan_FS dbo Kontenplan IDKontenplan
434 FK_Haltepunkt_ArtHaltepunktArt dbo Haltepunkt IDArtHaltepunktArt_FS dbo ArtHaltepunktArt IDArtHaltepunktArt
435 FK_Haltepunkt_Haltestelle dbo Haltepunkt IDHaltestelle_FS dbo Haltestelle IDHaltestelle
436 FK_HaltepunktFahrplankasten_ArtHaltepunktFahrplankasten dbo HaltepunktFahrplankasten IDArtHaltepunktFahrplankasten_FS dbo ArtHaltepunktFahrplankasten IDArtHaltepunktFahrplankasten
437 FK_HaltepunktFahrplankasten_HaltestelleHaltepunkt dbo HaltepunktFahrplankasten IDHaltestelleHaltepunkt_FS dbo HaltestelleHaltepunkt IDHaltestelleHaltepunkt
438 FK_Haltestelle_ArtHaltestelleZwischenpunkttyp dbo Haltestelle IDArtHaltestelleZwischenpunkttyp_FS dbo ArtHaltestelleZwischenpunkttyp IDArtHaltestelleZwischenpunkttyp
439 FK_Haltestelle_HaltestelleNach dbo Haltestelle IDHaltestelle_FS_ZwNach dbo Haltestelle IDHaltestelle
440 FK_Haltestelle_HaltestelleVon dbo Haltestelle IDHaltestelle_FS_ZwVon dbo Haltestelle IDHaltestelle
441 FK_HaltestelleDruck_Haltestelle dbo HaltestelleDruck IDHaltestelle_FS dbo Haltestelle IDHaltestelle
442 FK_HaltestelleFahrplanAdresse_FahrplanAdresse dbo HaltestelleFahrplanAdresse IDFahrplanAdresse_FS dbo FahrplanAdresse IDFahrplanAdresse
443 FK_HaltestelleFahrplanAdresse_Haltestelle dbo HaltestelleFahrplanAdresse IDHaltestelle_FS dbo Haltestelle IDHaltestelle
444 FK_HaltestelleHaltepunkt_ArtBetriebshof dbo HaltestelleHaltepunkt IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
445 FK_HaltestelleHaltepunkt_ArtHaltepunktAbfallbehaelter dbo HaltestelleHaltepunkt IDArtHaltepunktAbfallbehaelter_FS dbo ArtHaltepunktAbfallbehaelter IDArtHaltepunktAbfallbehaelter
446 FK_HaltestelleHaltepunkt_ArtHaltepunktBlindenleitsystem dbo HaltestelleHaltepunkt IDArtHaltepunktBlindenleitsystem_FS dbo ArtHaltepunktBlindenleitsystem IDArtHaltepunktBlindenleitsystem
447 FK_HaltestelleHaltepunkt_ArtHaltepunktBlinkaufforderung dbo HaltestelleHaltepunkt IDArtHaltepunktBlinkaufforderung_FS dbo ArtHaltepunktBlinkaufforderung IDArtHaltepunktBlinkaufforderung
448 FK_HaltestelleHaltepunkt_ArtHaltepunktBusbordstein dbo HaltestelleHaltepunkt IDArtHaltepunktBusbordstein_FS dbo ArtHaltepunktBusbordstein IDArtHaltepunktBusbordstein
449 FK_HaltestelleHaltepunkt_Haltepunkt dbo HaltestelleHaltepunkt IDHaltepunkt_FS dbo Haltepunkt IDHaltepunkt
450 FK_HaltestelleHaltepunkt_Haltestelle dbo HaltestelleHaltepunkt IDHaltestelle_FS dbo Haltestelle IDHaltestelle
451 FK_HaltestelleHaltepunkt_Ort dbo HaltestelleHaltepunkt IDOrt_FS dbo Ort IDOrt
452 FK_ImportAdressen_ArtImportAdressen dbo ImportAdressen IDArtImportAdressen_FS dbo ArtImportAdressen IDArtImportAdressen
453 FK_ImportMatrix_ArtBuchungsImport dbo ImportMatrix IDArtBuchungsImport_FS dbo ArtBuchungsImport IDArtBuchungsImport
454 FK_InternetCRMZuweisung_ArtCRMGruppe dbo InternetCRMZuweisung IDArtCRMGruppe_FS dbo ArtCRMGruppe IDArtCRMGruppe
455 FK_InternetCRMZuweisung_ArtCRMInternet dbo InternetCRMZuweisung IDArtCRMInternet_FS dbo ArtCRMInternet IDArtCRMInternet
456 FK_KalenderFahrplanversion_ArtFahrplanVersion dbo KalenderFahrplanversion IDArtFahrplanversion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
457 FK_KalenderLaufzeitschema_ArtLaufzeitschema dbo KalenderLaufzeitschema IDArtLaufzeitschema_FS dbo ArtLaufzeitschema IDArtLaufzeitschema
458 FK_KalenderSondergruppen_ArtGruppeVerkehrstag dbo KalenderSondergruppen IDArtSondergruppen_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
459 FK_KalenderWochentypen_ArtWochentyp dbo KalenderWochentypen IDArtWochentyp_FS dbo ArtWochentyp IDArtWochentyp
460 FK_KalkulationBeförderung_Kalkulation dbo KalkulationBeförderung IDKalkulation_FS dbo Kalkulation IDKalkulation
461 FK_KalkulationBeförderungLand_KalkulationBeförderung dbo KalkulationBeförderungLand IDKalkulationBeförderung_FS dbo KalkulationBeförderung IDKalkulationBeförderung
462 FK_KalkulationBusleistung_Kalkulation dbo KalkulationBusleistung IDKalkulation_FS dbo Kalkulation IDKalkulation
463 FK_KalkulationBusleistungPreis_KalkulationBusleistung dbo KalkulationBusleistungPreis IDKalkulationBusleistung_FS dbo KalkulationBusleistung IDKalkulationBusleistung
464 FK_KalkulationBusleistungPreis_Kalkulationswertbezeichnung dbo KalkulationBusleistungPreis IDKalkulationswertbezeichnung_FS dbo KalkulationswertBezeichnung IDKalkulationswertBezeichnung
465 FK_KalkulationErgebnis_Kalkulation dbo KalkulationErgebnis IDKalkulation_FS dbo Kalkulation IDKalkulation
466 FK_KalkulationErgebnisM_Kalkulation dbo KalkulationErgebnisM IDKalkulation_FS dbo Kalkulation IDKalkulation
467 FK_KalkulationErgebnisZimmerPreis_KalkulationErgebnis dbo KalkulationErgebnisZimmerPreis IDKalkulationErgebnis_FS dbo KalkulationErgebnis IDKalkulationErgebnis
468 FK_KalkulationErgebnisZimmerPreis_Zimmerart dbo KalkulationErgebnisZimmerPreis IDZimmerart_FS dbo Zimmerart IDZimmerart
469 FK_KalkulationFZAusgrenzung_KalkulationFZ dbo KalkulationFZAusgrenzung IDKalkulationFZ_FS dbo KalkulationFZ IDKalkulationFZ
470 FK_KalkulationFZBeförderung_KalkulationFZ dbo KalkulationFZBeförderung IDKalkulationFZ_FS dbo KalkulationFZ IDKalkulationFZ
471 FK_KalkulationFZErgebnis_ArtPartnerPreisCode dbo KalkulationFZErgebnis IdArtPartnerPreisCode_FS dbo ArtPartnerPreisCode IDArtPartnerPreisCode
472 FK_KalkulationFZErgebnis_ArtVerpflegung dbo KalkulationFZErgebnis IDArtVerpflegung_FS dbo ArtVerpflegung IDArtVerpflegung
473 FK_KalkulationFZErgebnis_KalkulationFZ dbo KalkulationFZErgebnis IDKalkulationFZ_FS dbo KalkulationFZ IDKalkulationFZ
474 FK_KalkulationFZTag_KalkulationFZ dbo KalkulationFZTag IDKalkulationFZ_FS dbo KalkulationFZ IDKalkulationFZ
475 FK_KalkulationPax_Kalkulation dbo KalkulationPax IDKalkulation_FS dbo Kalkulation IDKalkulation
476 FK_KalkulationReise_Kalkulation dbo KalkulationReise IDKalkulation_FS dbo Kalkulation IDKalkulation
477 FK_KalkulationReise_Reise dbo KalkulationReise IDReise_FS dbo Reise IDReise
478 FK_KalkulationSonstiges_Kalkulation dbo KalkulationSonstiges IDKalkulation_FS dbo Kalkulation IDKalkulation
479 FK_KalkulationSonstigesPreis_KalkulationSonstiges dbo KalkulationSonstigesPreis IDKalkulationSonstiges_FS dbo KalkulationSonstiges IDKalkulationSonstiges
480 FK_KalkulationUnterbringung_Kalkulation dbo KalkulationUnterbringung IDKalkulation_FS dbo Kalkulation IDKalkulation
481 FK_KalkulationUnterbringungM_Kalkulation dbo KalkulationUnterbringungM IDKalkulation_FS dbo Kalkulation IDKalkulation
482 FK_KalkulationUnterbringungMPreis_KalkulationUnterbringungM dbo KalkulationUnterbringungMPreis IDKalkulationUnterbringungM_FS dbo KalkulationUnterbringungM IDKalkulationUnterbringungM
483 FK_KalkulationUnterbringungPartner_Adresse dbo KalkulationUnterbringungPartner IDAdresse_FS_Partner dbo Adresse IDAdresse
484 FK_KalkulationUnterbringungPartner_KalkulationUnterbringung dbo KalkulationUnterbringungPartner IDKalkulationUnterbringung_FS dbo KalkulationUnterbringung IDKalkulationUnterbringung
485 FK_KalkulationUnterbringungPreis_KalkulationUnterbringung dbo KalkulationUnterbringungPreis IDKalkulationUnterbringung_FS dbo KalkulationUnterbringung IDKalkulationUnterbringung
486 FK_KalkulationUnterbringungPreis_KalkulationUnterbringungPartner dbo KalkulationUnterbringungPreis IDKalkulationUnterbringungPartner_FS dbo KalkulationUnterbringungPartner IDKalkulationUnterbringungPartner
487 FK_KalkulationUnterbringungPreis_KalkulationUnterbringungZimmer dbo KalkulationUnterbringungPreis IDKalkulationUnterbringungZimmer_FS dbo KalkulationUnterbringungZimmer IDKalkulationUnterbringungZimmer
488 FK_KalkulationUnterbringungZimmer_KalkulationUnterbringung dbo KalkulationUnterbringungZimmer IDKalkulationUnterbringung_FS dbo KalkulationUnterbringung IDKalkulationUnterbringung
489 FK_KalkulationUnterbringungZimmer_Zimmerart dbo KalkulationUnterbringungZimmer IDZimmerart_FS dbo Zimmerart IDZimmerart
490 FK_KalkulationUnterbringungZimmerPreis_KalkulationUnterbringung dbo KalkulationUnterbringungZimmerPreis IDKalkulationUnterbringung_FS dbo KalkulationUnterbringung IDKalkulationUnterbringung
491 FK_KalkulationUnterbringungZimmerPreis_KalkulationUnterbringungZimmer dbo KalkulationUnterbringungZimmerPreis IDKalkulationUnterbringungZimmerPreis dbo KalkulationUnterbringungZimmer IDKalkulationUnterbringungZimmer
492 FK_KalkulationZuschlag_Kalkulation dbo KalkulationZuschlag IDKalkulation_FS dbo Kalkulation IDKalkulation
493 FK_KalkulationZuschlagPosten_KalkulationZuschlag dbo KalkulationZuschlagPosten IDKalkulationZuschlag_FS dbo KalkulationZuschlag IDKalkulationZuschlag
494 FK_KommunikationEinstellung_Kommunikation dbo KommunikationEinstellung IDKommunikation_FS dbo Kommunikation IDKommunikation
495 FK_KonstantenErmäßigungProdukt_KonstantenErmäßigung dbo KonstantenErmäßigungProdukt IDKonstantenErmäßigungStaffel_FS dbo KonstantenErmäßigungStaffel IDKonstantenErmäßigungStaffel
496 FK_KonstantenErmäßigungProdukt_Produkt dbo KonstantenErmäßigungProdukt IDProdukt_FS dbo Produkt IDProdukt
497 FK_KonstantenErmäßigungStaffel_KonstantenErmäßigung dbo KonstantenErmäßigungStaffel IDKonstantenErmäßigung_FS dbo KonstantenErmäßigung IDKonstantenErmäßigung
498 FK_KonstantenErmäßigungZimmer_KonstantenErmäßigung dbo KonstantenErmäßigungZimmer IDKonstantenErmäßigungStaffel_FS dbo KonstantenErmäßigungStaffel IDKonstantenErmäßigungStaffel
499 FK_KonstantenErmäßigungZimmer_Zimmerart dbo KonstantenErmäßigungZimmer IDZimmerart_FS dbo Zimmerart IDZimmerart
500 FK_KonstantenErmäßigungZustieg_KonstantenErmäßigung dbo KonstantenErmäßigungZustieg IDKonstantenErmäßigungStaffel_FS dbo KonstantenErmäßigungStaffel IDKonstantenErmäßigungStaffel
501 FK_KonstantenErmäßigungZustieg_Zustieg dbo KonstantenErmäßigungZustieg IDZustieg_FS dbo Zustieg IDZustieg
502 FK_KonstantenFlexTarifStaffel_KonstantenFlexTarif dbo KonstantenFlexTarifStaffel IDKonstantenFlexTarif_FS dbo KonstantenFlexTarif IDKonstantenFlexTarif
503 FK_KonstantenFlexTarifStaffel_Leistung dbo KonstantenFlexTarifStaffel IDLeistung_FS dbo Leistung IDLeistung
504 FK_KonstantenGruppenermStaffel_KonstantenGruppenerm dbo KonstantenGruppenermStaffel IDKonstantenGruppenerm_FS dbo KonstantenGruppenerm IDKonstantenGruppenerm
505 FK_KonstantenRabattStaffelEingabe_KonstantenRabattStaffel dbo KonstantenRabattStaffelEingabe IDKonstantenRabattStaffel_FS dbo KonstantenRabattStaffel IDKonstantenRabattStaffel
506 FK_KonstantenStAuftZuschlag_Land dbo KonstantenStAuftZuschlag IDLand_FS dbo Land IDLand
507 FK_KonstantenSteueraufteilung_SteueraufteilungArt dbo KonstantenSteueraufteilung IDSteueraufteilungArt_FS dbo SteueraufteilungArt IDSteueraufteilungArt
508 FK_KonstantenSteueraufteilungDetail_KonstantenSteueraufteilung dbo KonstantenSteueraufteilungDetail IDKonstantenSteueraufteilung_FS dbo KonstantenSteueraufteilung IDKonstantenSteueraufteilung
509 FK_KonstantenSteueraufteilungDetail_Steueraufteilung dbo KonstantenSteueraufteilungDetail IDSteueraufteilungDetail_FS dbo SteueraufteilungDetail IDSteueraufteilungDetail
510 FK_KonstantenStornoStaffelTage_KonstantenStornoStaffel dbo KonstantenStornoStaffelTage IDKonstantenStornoStaffel_FS dbo KonstantenStornoStaffel IDKonstantenStornoStaffel
511 FK_ArtikelLagerort_Artikel dbo LagerRegal IDLager_FS dbo Lager IDLager
512 FK_LandFiskal_Land dbo LandFiskal IDLand_Fs dbo Land IDLand
513 FK_LandHinweis_Land dbo LandHinweis IDLand_FS dbo Land IDLand
514 FK_LandKonto_Land dbo LandKonto IDLand_FS dbo Land IDLand
515 FK_LandMwst_Land dbo LandMwst IDLand_FS dbo Land IDLand
516 FK_LandVerpflegungSpesen_ArtSpesenLand dbo LandVerpflegungSpesen IDArtSpesenLand_FS dbo ArtSpesenLand IDArtSpesenLand
517 FK_LandVerpflegungSpesen_ArtSpesenVerpflegung dbo LandVerpflegungSpesen IDArtSpesenVerpflegung_FS dbo ArtSpesenVerpflegung IDArtSpesenVerpflegung
518 FK_Leistung_ArtLeistungSonstigesUnterart dbo Leistung IDArtLeistungSonstigesUnterart_FS dbo ArtLeistungSonstigesUnterart IDArtLeistungSonstigesUnterart
519 FK_Leistung_LeistungBefoerderung dbo LeistungBefoerderung IDLeistung_FS dbo Leistung IDLeistung
520 FK_Leistung_LeistungExternSystem dbo LeistungExternSystem IDLeistung_FS dbo Leistung IDLeistung
521 FK_LeistungHotelMoeglich_Adresse dbo LeistungHotelGesperrt IDAdresse_FS_Partner dbo Adresse IDAdresse
522 FK_LeistungHotelMoeglich_LeistungBefoerderung dbo LeistungHotelGesperrt IDLeistungBefoerderung_FS dbo LeistungBefoerderung IDLeistungBefoerderung
523 FK_Adresse_LeistungMandantMoeglich dbo LeistungMandantMoeglich IDAdresse_FS dbo Adresse IDAdresse
524 FK_Leistung_LeistungMandantMoeglich dbo LeistungMandantMoeglich IDLeistung_FS dbo Leistung IDLeistung
525 FK_Adresse_LeistungPartnerMoeglich dbo LeistungPartnerMoeglich IDAdresse_FS dbo Adresse IDAdresse
526 FK_Leistung_LeistungPartnerMoeglich dbo LeistungPartnerMoeglich IDLeistung_FS dbo Leistung IDLeistung
527 FK_LeistungPreis_ArtPreisschema dbo LeistungPreis IDArtPreisSchema_FS dbo ArtPreisschema IDArtPreisschema
528 FK_LeistungPreis_Leistung dbo LeistungPreis IDLeistung_FS dbo Leistung IDLeistung
529 FK_LeistungProdukt_Leistung dbo LeistungProdukt IDLeistung_FS dbo Leistung IDLeistung
530 FK_LeistungProdukt_Produkt dbo LeistungProdukt IDProdukt_FS dbo Produkt IDProdukt
531 FK_Leistung_LeistungSelektion dbo LeistungSelektionenKunde IDLeistung_FS dbo Leistung IDLeistung
532 FK_Selektionsstamm_LeistungSelektion dbo LeistungSelektionenKunde IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
533 FK_LeistungSitzplan_Leistung dbo LeistungSitzplan IDLeistung_FS dbo Leistung IDLeistung
534 FK_LeistungSitzplan_Sitzplan dbo LeistungSitzplan IDSitzplan_FS dbo Sitzplan IDSitzplan
535 FK_Leistung_LeistungText dbo LeistungText IDLeistung_FS dbo Leistung IDLeistung
536 FK_Leistung_LeistungTicket dbo LeistungTicket IDLeistung_FS dbo Leistung IDLeistung
537 FK_LeistungTicketZusatz_LeistungTicket dbo LeistungTicketZusatz IDLeistungTicket_FS dbo LeistungTicket IDLeistungTicket
538 FK_LeistungVersicherung_Leistung dbo LeistungVersicherung IDLeistung_FS dbo Leistung IDLeistung
539 FK_LeistungVersicherung_Versicherungsbedingung_Leistung dbo LeistungVersicherung_Versicherungsbedingung IDLeistung_FS dbo Leistung IDLeistung
540 FK_LeistungVersicherung_Versicherungsbedingung_Versicherungsbedingung dbo LeistungVersicherung_Versicherungsbedingung IDVersicherungsbedingung_FS dbo Versicherungsbedingung IDVersicherungsbedingung
541 FK_LeistungVersicherungsGruppe_ArtVersicherungsGruppe dbo LeistungVersicherungsGruppe IDArtVersicherungsGruppe_FS dbo ArtVersicherungsGruppe IDArtVersicherungsGruppe
542 FK_LeistungVersicherungsGruppe_LeistungVersicherung dbo LeistungVersicherungsGruppe IDLeistungVersicherung_FS dbo LeistungVersicherung IDLeistungVersicherung
543 FK_Leistung_LeistungVoucher dbo LeistungVoucher IDLeistung_FS dbo Leistung IDLeistung
544 FK_LeistungZusatz_ArtAgenturPreisgruppe dbo LeistungZusatz IDArtAgenturPreisgruppe_FS dbo ArtAgenturPreisgruppe IDArtAgenturPreisgruppe
545 FK_LeistungZusatz_KonstantenSteueraufteilung dbo LeistungZusatz IDKonstantenSteueraufteilung_FS dbo KonstantenSteueraufteilung IDKonstantenSteueraufteilung
546 FK_LeistungZusatz_Leistung dbo LeistungZusatz IDLeistung_FS dbo Leistung IDLeistung
547 FK_LeistungZustiegMoeglich_LeistungBefoerderung dbo LeistungZustiegMoeglichGesperrt IDLeistungBefoerderung_FS dbo LeistungBefoerderung IDLeistungBefoerderung
548 FK_Zustieg_LeistungZustiegMoeglich dbo LeistungZustiegMoeglichGesperrt IDZustieg_FS dbo Zustieg IDZustieg
549 FK_LiniePlanungEinstellung_Adresse dbo LiniePlanungEinstellung IDAdresse_FS_Personal dbo Adresse IDAdresse
550 FK_LiniePlanungEinstellung_ArtPersonalGruppeKompetenz dbo LiniePlanungEinstellung IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
551 FK_LinieStatistikAufteilungSpalteZuordnung_ArtStatistikGruppe dbo LinieStatistikAufteilungSpalteZuordnung IDArtStatistikGruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
552 FK_LinieStatistikAufteilungSpalteZuordnung_Auftragsart dbo LinieStatistikAufteilungSpalteZuordnung IDAuftragsart_FS dbo Auftragsart IDAuftragsart
553 FK_LinieStatistikAufteilungSpalteZuordnung_LinieStatistikAufteilungSpalte dbo LinieStatistikAufteilungSpalteZuordnung IDLinieStatistikAufteilungSpalte_FS dbo LinieStatistikAufteilungSpalte IDLinieStatistikAufteilungSpalte
554 FK_LinieStatistikSummeSpalte_ArtLinieStatistikSumme dbo LinieStatistikSummeSpalte IDArtLinieStatistikSumme_FS dbo ArtLinieStatistikSumme IDArtLinieStatistikSumme
555 FK_LinieStatistikSummeSpalteZuordnung_ArtStatistikGruppe dbo LinieStatistikSummeSpalteZuordnung IDArtStatistikGruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
556 FK_LinieStatistikSummeSpalteZuordnung_Auftragsart dbo LinieStatistikSummeSpalteZuordnung IDAuftragsart_FS dbo Auftragsart IDAuftragsart
557 FK_LinieStatistikSummeSpalteZuordnung_LinieStatistikSummeSpalte dbo LinieStatistikSummeSpalteZuordnung IDLinieStatistikSummeSpalte_FS dbo LinieStatistikSummeSpalte IDLinieStatistikSummeSpalte
558 FK_LinieWegPunkteGM_Haltestelle dbo LinieWegPunkteGM IDHaltestelle_FS_von dbo Haltestelle IDHaltestelle
559 FK_LinieWegPunkteGM_Haltestelle1 dbo LinieWegPunkteGM IDHaltestelle_FS_nach dbo Haltestelle IDHaltestelle
560 FK_LinieZiel_ArtLinieZielSonderzeichen dbo LinieZiel IDArtLinieZielSonderzeichen_FS dbo ArtLinieZielSonderzeichen IDArtLinieZielSonderzeichen
561 FK_LinieZusatzKilometer_ArtStatistikGruppe dbo LinieZusatzKilometer IDArtStatistikgruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
562 FK_LinieZusatzKilometer_Auftragsart dbo LinieZusatzKilometer IDAuftragsart_FS dbo Auftragsart IDAuftragsart
563 FK_LinieZusatzKilometer_Fahrzeug dbo LinieZusatzKilometer IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
564 FK_ListenterminalEinstellung_Adresse dbo ListenterminalEinstellung IDAdresse_FS_Personal dbo Adresse IDAdresse
565 FK_ListenterminalEinstellung_ArtPersonalGruppeKompetenz dbo ListenterminalEinstellung IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
566 FK_Lohnart_ArtLohnsystem dbo Lohnart IDArtLohnsystem_FS dbo ArtLohnsystem IDArtLohnsystem
567 FK_LohnartPersonalSperrung_Adresse dbo LohnartPersonalSperrung IDAdresse_FS_Fahrer dbo Adresse IDAdresse
568 FK_LohnartPersonalSperrung_Lohnart dbo LohnartPersonalSperrung IDLohnart_FS dbo Lohnart IDLohnart
569 FK_LohnartTag_Lohnart dbo LohnartTag IDLohnart_FS dbo Lohnart IDLohnart
570 FK_LohnDruckLobuPersonalSperrung_Adresse dbo LohnDruckLobuPersonalSperrung IDAdresse_FS_Fahrer dbo Adresse IDAdresse
571 FK_LohnDruckLobuPersonalSperrung_ArtLohnDruckLobu dbo LohnDruckLobuPersonalSperrung IDArtLohnDruckLobu_FS dbo ArtLohnDruckLobu IDArtLohnDruckLobu
572 FK_Lohnextra_Adresse dbo Lohnextra IDAdresse_FS_Personal dbo Adresse IDAdresse
573 FK_Lohnextra_ArtLohnextra dbo Lohnextra IDArtLohnextra_FS dbo ArtLohnextra IDArtLohnextra
574 FK_LohnParameter_Adresse dbo LohnParameter IDAdresse_FS_Fahrer dbo Adresse IDAdresse
575 FK_LohnParameter_ArtLohnsystem dbo LohnParameter IDArtLohnsystem_FS dbo ArtLohnsystem IDArtLohnsystem
576 FK_LohnStundenkonto_Adresse dbo LohnStundenkonto IDAdresse_FS_Fahrer dbo Adresse IDAdresse
577 FK_LohnStundenkonto_ArtLohnStundenkonto dbo LohnStundenkonto IDArtLohnStundenkonto_FS dbo ArtLohnStundenkonto IDArtLohnStundenkonto
578 FK_LohnsystemPersonalSperrung_Adresse dbo LohnsystemPersonalSperrung IDAdresse_FS_Fahrer dbo Adresse IDAdresse
579 FK_LohnsystemPersonalSperrung_ArtLohnsystem dbo LohnsystemPersonalSperrung IDArtLohnsystem_FS dbo ArtLohnsystem IDArtLohnsystem
580 FK_LohnTagesdaten_Adresse dbo LohnTagesdaten IDAdresse_FS_Personal dbo Adresse IDAdresse
581 FK_LohnUebergabe_Adresse dbo LohnUebergabe IDAdresse_FS dbo Adresse IDAdresse
582 FK_LohnUebergabe_ArtLohnsystem dbo LohnUebergabe IDArtLohnsystem_FS dbo ArtLohnsystem IDArtLohnsystem
583 FK_MandantZuordnungZahlung_Adresse dbo MandantZuordnungKontenplan IDAdresse_FS_Mandant dbo Adresse IDAdresse
584 FK_MandantZuordnungZahlung_ZahlungCode dbo MandantZuordnungKontenplan IDMandantZuordnung_FS dbo Kontenplan IDKontenplan
585 FK_MandantZuordnungReise_Adresse dbo MandantZuordnungReise IDAdresse_FS_Mandant dbo Adresse IDAdresse
586 FK_MandantZuordnungReise_Reise dbo MandantZuordnungReise IDMandantZuordnung_FS dbo Reise IDReise
587 FK_MandantZuordnungZustieg_Adresse dbo MandantZuordnungZustieg IDAdresse_FS_Mandant dbo Adresse IDAdresse
588 FK_MandantZuordnungZustieg_Zustieg dbo MandantZuordnungZustieg IDMandantZuordnung_FS dbo Zustieg IDZustieg
589 FK_MitgliedAdresse_ArtMitgliedsstufen dbo MitgliedsstufeAdresse IDArtMitgliedsstufe_FS dbo ArtMitgliedsstufe IDArtMitgliedsstufe
590 FK_MitgliedAdresse_ArtZahlungsart dbo MitgliedsstufeAdresse IDArtZahlungsart_FS dbo ArtZahlungsart IDArtZahlungsart
591 FK_MitgliedsstufeAdresse_Adresse dbo MitgliedsstufeAdresse IDAdresse_FS dbo Adresse IDAdresse
592 FK_MitgliedsEinstellungBetrag_ArtMitgliedsstufen dbo MitgliedsstufeBetrag IDArtMitgliedsstufe_FS dbo ArtMitgliedsstufe IDArtMitgliedsstufe
593 FK_MitgliedVorteilBezeichnungArtMitgliedsstufe_ArtMitgliedsstufe dbo MitgliedsVorteilBezeichnungArtMitgliedsstufe IDArtMitgliedsstufe_FS dbo ArtMitgliedsstufe IDArtMitgliedsstufe
594 FK_Newsletter_Adresse dbo Newsletter IDAdresse_FS_ErsterSB dbo Adresse IDAdresse
595 FK_Newsletter_Adresse1 dbo Newsletter IDAdresse_FS_LetzterSB dbo Adresse IDAdresse
596 FK_NewsletterAdressat_Adresse dbo NewsletterAdressat IDAdresse_FS dbo Adresse IDAdresse
597 FK_NewsletterAdressat_Newsletter dbo NewsletterAdressat IDNewsletter_FS dbo Newsletter IDNewsletter
598 FK_NewsletterAdressat_NewsletterVersand dbo NewsletterAdressat IDNewsletterVersand_FS dbo NewsletterVersand IDNewsletterVersand
599 FK_NewsletterBlock_Newsletter dbo NewsletterBlock IDNewsletter_FS dbo Newsletter IDNewsletter
600 FK_NewsletterVersand_Adresse dbo NewsletterVersand IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
601 FK_NewsletterVersand_Newsletter dbo NewsletterVersand IDNewsletter_FS dbo Newsletter IDNewsletter
602 FK_NotizFahrerFahrzeug_ArtNotizart dbo NotizFahrerFahrzeug IDArtNotizart_FS dbo ArtNotizart IDArtNotizart
603 FK_NummernVerwaltung_Nummernkreis dbo NummernVerwaltung IDNummernkreis_FS dbo Nummernkreis IDNummernkreis
604 FK_OrtBeziehung_Ort dbo OrtBeziehung IDOrt_FS_Ort1 dbo Ort IDOrt
605 FK_OrtBeziehung_Ort1 dbo OrtBeziehung IDOrt_FS_Ort2 dbo Ort IDOrt
606 FK_PartnerBefoederungsvertragspreis_Adresse dbo PartnerBefoederungsvertragspreis IDAdresse_FS_Partner dbo Adresse IDAdresse
607 FK_PartnerDokument_Adresse dbo PartnerDokument IDAdresse_FS dbo Adresse IDAdresse
608 FK_PartnerGebiet_Land dbo PartnerGebiet IDLand_FS dbo Land IDLand
609 FK_PartnerGebietPreis_PartnerGebiet dbo PartnerGebietPreis IDPartnergebiet_FS dbo PartnerGebiet IDPartnergebiet
610 FK_PartnerKontingent_Adresse dbo PartnerKontingent IDAdresse_FS dbo Adresse IDAdresse
611 FK_PartnerLeistung_Adresse dbo PartnerLeistung IDAdresse_FS dbo Adresse IDAdresse
612 FK_PartnerLeistungPreis_PartnerLeistung dbo PartnerLeistungPreis IDPartnerLeistung_FS dbo PartnerLeistung IDPartnerLeistung
613 FK_PartnerLeistungPreis_PartnerSaisontafel dbo PartnerLeistungPreis IDPartnerSaisontafel_FS dbo PartnerSaisontafel IDPartnerSaisontafel
614 FK_PartnerPreis_ArtPreisschema dbo PartnerPreis IDPartnerSaisonTafel_FS dbo PartnerSaisontafel IDPartnerSaisontafel
615 FK_PartnerPreis_PartnerPreisKategorie dbo PartnerPreis IDPartnerPreisKategorie_FS dbo PartnerPreisKategorie IDPartnerPreisKategorie
616 FK_PartnerPreisKategorie_Adresse dbo PartnerPreisKategorie IDAdresse_FS dbo Adresse IDAdresse
617 FK_PartnerPreisKategorie_ArtPartnerPreisCode dbo PartnerPreisKategorie IDArtPartnerPreisCode_FS dbo ArtPartnerPreisCode IDArtPartnerPreisCode
618 FK_PartnerPreisKategorie_ArtVerpflegung dbo PartnerPreisKategorie IDArtVerpflegung_FS dbo ArtVerpflegung IDArtVerpflegung
619 FK_PartnerProdukt_Adresse dbo PartnerProdukt IDAdresse_FS dbo Adresse IDAdresse
620 FK_PartnerProdukt_Produkt dbo PartnerProdukt IDProdukt_FS dbo Produkt IDProdukt
621 FK_PartnerSaisontafel_Adresse dbo PartnerSaisontafel IDAdresse_FS dbo Adresse IDAdresse
622 FK_PartnerSaisonzeit_Adresse dbo PartnerSaisonzeit IDAdresse_FS dbo Adresse IDAdresse
623 FK_PartnerSaisonzeit_PartnerSaisontafel dbo PartnerSaisonzeit IDPartnerSaisonTafel_FS dbo PartnerSaisontafel IDPartnerSaisontafel
624 FK_Adresse_PartnerSelektion dbo PartnerSelektionenKunde IDAdresse_FS dbo Adresse IDAdresse
625 FK_Selektionsstamm_PartnerSelektion dbo PartnerSelektionenKunde IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
626 FK_PartnerZimmer_Adresse dbo PartnerZimmer IDAdresse_FS dbo Adresse IDAdresse
627 FK_PartnerZimmer_ArtPartnerPreisCode dbo PartnerZimmer IDArtPartnerPreisCode_FS dbo ArtPartnerPreisCode IDArtPartnerPreisCode
628 FK_PartnerZimmer_Zimmerart dbo PartnerZimmer IDZimmerart_FS dbo Zimmerart IDZimmerart
629 FK_PartnerZusatz_Adresse dbo PartnerZusatz IDAdresse_FS dbo Adresse IDAdresse
630 FK_PartnerZusatz_ArtAgenturPreisgruppe dbo PartnerZusatz IDArtAgenturPreisgruppe_FS dbo ArtAgenturPreisgruppe IDArtAgenturPreisgruppe
631 FK_PartnerZusatz_KonstantenSteueraufteilung dbo PartnerZusatz IDKonstantenSteueraufteilung_FS dbo KonstantenSteueraufteilung IDKonstantenSteueraufteilung
632 FK_PersonalGruppeDatenschutz_ArtPersonalGruppeKompetenz dbo PersonalGruppeDatenschutz IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
633 FK_PersonalGruppeDatenschutzDarstellung_ArtPersonalGruppeKompetenz dbo PersonalGruppeDatenschutzDarstellung IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
634 FK_PersonalGruppeDatenschutzLöschung_ArtPersonalGruppeKompetenz dbo PersonalGruppeDatenschutzLöschung IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
635 FK_PersonalGruppeKompetenz_ArtPersonalGruppeKompetenz dbo PersonalGruppeKompetenz IDArtPersonalGruppeKompetenz_FS dbo ArtPersonalGruppeKompetenz IDArtPersonalGruppeKompetenz
636 FK_Personalkapazitaet_Adresse dbo Personalkapazitaet IDAdresse_FS_Personal dbo Adresse IDAdresse
637 FK_Personalkapazitaet_ArtPersonalkapazitaet dbo Personalkapazitaet IDArtPersonalkapazitaet_FS dbo ArtPersonalkapazitaet IDArtPersonalkapazitaet
638 FK_PersonalkapazitaetArbeitszeit_ArtPersonalkapazitaet dbo PersonalkapazitaetArbeitszeit IDArtPersonalkapazitaet_FS dbo ArtPersonalkapazitaet IDArtPersonalkapazitaet
639 FK_PersonalkapazitaetEingabe_Adresse dbo PersonalkapazitaetEingabe IDAdresse_FS_Personal dbo Adresse IDAdresse
640 FK_PersonalkapazitaetMindestbesetzung_ArtBetriebshof dbo PersonalkapazitaetMindestbesetzung IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
641 FK_PersonalkapazitaetMindestbesetzung_ArtMindestbesetzungZeitraum dbo PersonalkapazitaetMindestbesetzung IDArtMindestbesetzungZeitraum_FS dbo ArtMindestbesetzungZeitraum IDArtMindestbesetzungZeitraum
642 FK_PersonalkapazitaetMindestbesetzungZeitraum_ArtMindestbesetzungZeitraum dbo PersonalkapazitaetMindestbesetzungZeitraum IDArtMindestbesetzungZeitraum_FS dbo ArtMindestbesetzungZeitraum IDArtMindestbesetzungZeitraum
643 FK_PlanungSoll_Adresse dbo PlanungSoll IDAdresse_FS_Fahrer dbo Adresse IDAdresse
644 FK_PlanungSoll_ArtPersonalkapazitaet dbo PlanungSoll IDArtPersonalkapazitaet_FS_Schema dbo ArtPersonalkapazitaet IDArtPersonalkapazitaet
645 FK_PlanungSollBlock_BlockPlanung dbo PlanungSollBlock IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
646 FK_PlanungSollBlock_PlanungSoll dbo PlanungSollBlock IDPlanungSoll_FS dbo PlanungSoll IDPlanungSoll
647 FK_PlanungSollLohnarten_Lohnart dbo PlanungSollLohnart IDLohnart_FS dbo Lohnart IDLohnart
648 FK_PlanungSollLohnarten_PlanungSoll dbo PlanungSollLohnart IDPlanungSoll_FS dbo PlanungSoll IDPlanungSoll
649 FK_PortalBemerkung_PortalBuchung dbo PortalBemerkung IDPortalBuchung_FS dbo PortalBuchung IDPortalBuchung
650 FK_PortalLeistung_PortalBuchung dbo PortalLeistung IDPortalBuchung_FS dbo PortalBuchung IDPortalBuchung
651 FK_PortalLeistungTN_PortalLeistung dbo PortalLeistungTN IDPortalLeistung_FS dbo PortalLeistung IDPortalLeistung
652 FK_PortalLeistungTN_PortalTN dbo PortalLeistungTN IDPortalTN_FS dbo PortalTN IDPortalTN
653 FK_PortalLeistungZusatz_PortalBuchung dbo PortalLeistungZusatz IDPortalBuchung_FS dbo PortalBuchung IDPortalBuchung
654 FK_PortalTN_PortalBuchung dbo PortalTN IDPortalBuchung_FS dbo PortalBuchung IDPortalBuchung
655 FK_Produkt_KonstantenSteueraufteilung dbo Produkt IDKonstantenSteueraufteilung_FS dbo KonstantenSteueraufteilung IDKonstantenSteueraufteilung
656 FK_ProduktArtPersonalGruppe_ArtPersonalGruppeProdukt dbo ProduktArtPersonalGruppe IDArtPersonalGruppeProdukt_FS dbo ArtPersonalGruppeProdukt IDArtPersonalGruppeProdukt
657 FK_ProduktArtPersonalGruppe_Produkt dbo ProduktArtPersonalGruppe IDProdukt_FS dbo Produkt IDProdukt
658 FK_ProduktBeschreibungInhalt_ProduktBeschreibung dbo ProduktBeschreibungInhalt IDProduktBeschreibung_FS dbo ProduktBeschreibung IDProduktBeschreibung
659 FK_ProduktbeschreibungKategorie_ProduktBeschreibung dbo ProduktbeschreibungKategorie IDProduktbeschreibung_FS dbo ProduktBeschreibung IDProduktBeschreibung
660 FK_ProduktbeschreibungKategorie_WWSuchKategorie dbo ProduktbeschreibungKategorie IDWWSuchKategorie_FS dbo WWSuchKategorie IDWWSuchKategorie
661 FK_ProduktbeschreibungKategorie_WWSuchKategorieEintrag dbo ProduktbeschreibungKategorie IDWWSuchKategorieEintrag_FS dbo WWSuchKategorieEintrag IDWWSuchKategorieEintrag
662 FK_ProduktBeschreibungZusatz_ProduktBeschreibung dbo ProduktBeschreibungZusatz IDProduktBeschreibung_FS dbo ProduktBeschreibung IDProduktBeschreibung
663 FK_ProduktDokument_Produkt dbo ProduktDokument IDProdukt_FS dbo Produkt IDProdukt
664 FK_ProduktSachbearbeiter_Adresse dbo ProduktSachbearbeiter IDAdresse_FS_Personal dbo Adresse IDAdresse
665 FK_ProduktSachbearbeiter_Produkt dbo ProduktSachbearbeiter IDProdukt_FS dbo Produkt IDProdukt
666 FK_Produkt_ProduktText dbo ProduktText IDProdukt_FS dbo Produkt IDProdukt
667 FK_Qualitaet_ArtFahrplanVersion dbo Qualitaet IDArtFahrplanversion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
668 FK_QualitaetDefinition_ArtBlockArt dbo QualitaetDefinition IDArtBlockArt_FS dbo ArtBlockArt IDArtBlockArt
669 FK_QualitaetDefinition_ArtGruppeVerkehrstag dbo QualitaetDefinition IDArtGruppeVerkehrstag_FS dbo ArtGruppeVerkehrstag IDArtGruppeVerkehrstag
670 FK_QualitaetDefinition_Qualitaet dbo QualitaetDefinition IDQualitaet_FS dbo Qualitaet IDQualitaet
671 FK_QualitaetDefinitionAuftragsart_Auftragsart dbo QualitaetDefinitionAuftragsart IDAuftragsart_FS dbo Auftragsart IDAuftragsart
672 FK_QualitaetDefinitionAuftragsart_Qualitaet dbo QualitaetDefinitionAuftragsart IDQualitaet_FS dbo Qualitaet IDQualitaet
673 FK_QualitaetDefinitionFahrzeug_Fahrzeug dbo QualitaetDefinitionFahrzeug IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
674 FK_QualitaetDefinitionFahrzeug_Qualitaet dbo QualitaetDefinitionFahrzeug IDQualitaet_FS dbo Qualitaet IDQualitaet
675 FK_QualitaetDefinitionLinie_Qualitaet dbo QualitaetDefinitionLinie IDQualitaet_FS dbo Qualitaet IDQualitaet
676 FK_QualitaetZuordnung_Qualitaet dbo QualitaetZuordnung IDQualitaet_FS dbo Qualitaet IDQualitaet
677 FK_QuittierungAusfahrt_AuftragFahrer dbo QuittierungAusfahrt IDAuftragFahrer_FS dbo AuftragFahrer IDAuftragFahrer
678 FK_QuittierungAusfahrt_BlockPlanung dbo QuittierungAusfahrt IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
679 FK_Rechnung_AdresseAnschrift dbo Rechnung IDAdresseAnschrift_FS dbo AdresseAnschrift IDAdresseAnschrift
680 FK_Rechnung_ArtZahlungsart dbo Rechnung IDArtZahlungsart_FS dbo ArtZahlungsart IDArtZahlungsart
681 FK_Rechnung_RechnungHaupt dbo Rechnung IDRechnungHaupt_FS dbo RechnungHaupt IDRechnungHaupt
682 FK_RechnungBetrag_Rechnung dbo RechnungBetrag IDRechnung_FS dbo Rechnung IDRechnung
683 FK_RechnungBetragMahnung_RechnungBetrag dbo RechnungBetragMahnung IdRechnungBetrag_FS dbo RechnungBetrag IDRechnungBetrag
684 FK_RechnungBuchung_Buchung dbo RechnungBuchung IDBuchung_FS dbo Buchung IDBuchung
685 FK_RechnungBuchung_RechnungHaupt dbo RechnungBuchung IDRechnungHaupt_FS dbo RechnungHaupt IDRechnungHaupt
686 FK_RechnungHaupt_Adresse dbo RechnungHaupt IDAdresse_FS_Mandant dbo Adresse IDAdresse
687 FK_RechnungHaupt_Adresse1 dbo RechnungHaupt IDAdresse_FS dbo Adresse IDAdresse
688 FK_RechnungPosten_Rechnung dbo RechnungPosten IDRechnung_FS dbo Rechnung IDRechnung
689 FK_RechnungPosten_Teilnehmer_BuchungTNPreis dbo RechnungPosten_Teilnehmer IDBuchungTN_FS dbo BuchungTNPreis IDBuchungTNPreis
690 FK_RechnungPosten_Teilnehmer_RechnungPostenBetragTOU dbo RechnungPosten_Teilnehmer IDRechnungPostenBetragTOU_FS dbo RechnungPostenBetragTOU IDRechnungPostenBetragTOU
691 FK_RechnungPostenBetragALL_RechnungPosten dbo RechnungPostenBetragALL IDRechnungPosten_FS dbo RechnungPosten IDRechnungPosten
692 FK_RechnungPostenBetragTOU_RechnungPosten dbo RechnungPostenBetragTOU IDRechnungPosten_FS dbo RechnungPosten IDRechnungPosten
693 FK_RechnungPostenLinieAufteilungTour_RechnungPostenLinieAufteilung dbo RechnungPostenLinieAufteilungTour IDRechnungPostenLinieAufteilung_FS dbo RechnungPostenLinieAufteilung IDRechnungPostenLinieAufteilung
694 FK_RechnungPostenMietbusAufteilung_RechnungPostenBetragALL dbo RechnungPostenMietbusAufteilung IDRechnungPostenBetragAll_FS dbo RechnungPostenBetragALL IDRechnungPostenBetragALL
695 FK_RechnungSteueraufteilung_Rechnung dbo RechnungSteueraufteilung IDRechnung_FS dbo Rechnung IDRechnung
696 FK_ReisabBefoerderung_Reisab dbo ReisabBefoerderung IdReisab_FS dbo Reisab IdReisab
697 FK_ReisabLand_Land dbo ReisabLand IdLand_FS dbo Land IDLand
698 FK_ReisabLand_Reisab dbo ReisabLand IDReisab_FS dbo Reisab IdReisab
699 FK_ReisabLeistung_ArtReiseKosten dbo ReisabLeistung IdArtReiseKosten_FS dbo ArtReiseKosten IDArtReiseKosten
700 FK_ReisabLeistung_Reisab dbo ReisabLeistung IdReisab_FS dbo Reisab IdReisab
701 FK_ReisabReise_Reisab dbo ReisabReise IDReisab_FS dbo Reisab IdReisab
702 FK_ReisabReise_Reise dbo ReisabReise IDReise_FS dbo Reise IDReise
703 FK_ReisabUmsatz_Reisab dbo ReisabUmsatz IdReisab_FS dbo Reisab IdReisab
704 FK_Reise_Produkt dbo Reise IDProdukt_FS dbo Produkt IDProdukt
705 FK_ReiseBeleg_Reise dbo ReiseBeleg IDReise_FS dbo Reise IDReise
706 FK_ReiseBelegDokument_ReiseBeleg dbo ReiseBelegDokument IDReiseBeleg_FS dbo ReiseBeleg IDReiseBeleg
707 FK_ReiseBelegPosten_ReiseBeleg dbo ReiseBelegPosten IDReiseBeleg_FS dbo ReiseBeleg IDReiseBeleg
708 FK_ReiseDevise_ArtWaehrung dbo ReiseDevise IDArtWaehrung_FS dbo ArtWaehrung IDArtWaehrung
709 FK_ReiseDevise_Reise dbo ReiseDevise IDReise_FS dbo Reise IDReise
710 FK_ReiseDokument_Reise dbo ReiseDokument IDReise_FS dbo Reise IDReise
711 FK_ReiseFlexTarif_KonstantenFlexTarif dbo ReiseFlexTarif IDKonstantenFlexTarif_FS dbo KonstantenFlexTarif IDKonstantenFlexTarif
712 FK_ReiseFlexTarif_Reise dbo ReiseFlexTarif IDReise_FS dbo Reise IDReise
713 FK_ReiseGuides_ArtReiseGuides dbo ReiseGuides IDArtReiseGuides_FS dbo ArtReiseGuides IDArtReiseGuides
714 FK_ReiseKosten_Reise dbo ReiseKosten IDReise_FS dbo Reise IDReise
715 FK_ReiseLand_Land dbo ReiseLand IDLand_FS dbo Land IDLand
716 FK_ReiseLand_Reise dbo ReiseLand IDReise_FS dbo Reise IDReise
717 FK_ReiseLeistung_Leistung dbo ReiseLeistung IDLeistung_FS dbo Leistung IDLeistung
718 FK_ReiseLeistung_Reise dbo ReiseLeistung IDReise_FS dbo Reise IDReise
719 FK_ReiseLeistungGruppe_Reise dbo ReiseLeistungGruppe IDReise_FS dbo Reise IDReise
720 FK_ReiseLeistungGruppeZuweisung_Leistung dbo ReiseLeistungGruppeZuweisung IDLeistung_FS dbo Leistung IDLeistung
721 FK_ReiseLeistungGruppeZuweisung_ReiseLeistungGruppe dbo ReiseLeistungGruppeZuweisung IDReiseLeistungGruppe_FS dbo ReiseLeistungGruppe IDReiseLeistungGruppe
722 FK_ReiseleiterAbrechnung_Adresse dbo ReiseleiterAbrechnung IDAdresse_FS_Personal dbo Adresse IDAdresse
723 FK_ReiseleiterAbrechnung_Reise dbo ReiseleiterAbrechnung IDReise_FS dbo Reise IDReise
724 FK_ReiseleiterAbrechnung_ReiseleiterZuordnungStamm dbo ReiseleiterAbrechnung IDReiseleiterZuordnungStamm_FS dbo ReiseleiterZuordnungStamm IDReiseleiterZuordnungStamm
725 FK_ReiseleiterAbrechnungPosten_ReiseleiterAbrechnung dbo ReiseleiterAbrechnungPosten IDReiseleiterAbrechnung_FS dbo ReiseleiterAbrechnung IDReiseleiterAbrechnung
726 FK_ReiseleiterAbrechnungPosten_ReiseleiterPosten dbo ReiseleiterAbrechnungPosten IDReiseleiterPosten_FS dbo ReiseleiterPosten IDReiseleiterPosten
727 FK_ReiseleiterAbrechnungSpesen_ArtSpesenVerpflegung dbo ReiseleiterAbrechnungSpesen IDArtSpesenVerpflegung_FS dbo ArtSpesenVerpflegung IDArtSpesenVerpflegung
728 FK_ReiseleiterAbrechnungSpesen_ReiseleiterAbrechnung dbo ReiseleiterAbrechnungSpesen IDReiseleiterAbrechnung_FS dbo ReiseleiterAbrechnung IDReiseleiterAbrechnung
729 FK_ReiseleiterAbrechnungZuAbschlag_ReiseleiterAbrechnung dbo ReiseleiterAbrechnungZuAbschlag IDReiseleiterAbrechnung_FS dbo ReiseleiterAbrechnung IDReiseleiterAbrechnung
730 FK_ReiseleiterAbrVergütungStaffel_ReiseleiterAbrVergütungStamm1 dbo ReiseleiterAbrVergütungStaffel IDReiseleiterAbrVergütungStamm_FS dbo ReiseleiterAbrVergütungStamm IDReiseleiterAbrVergütungStamm
731 FK_ReiseleiterAbrVergütungStaffelAnAbreise_ReiseleiterAbrVergütungStamm dbo ReiseleiterAbrVergütungStaffelAnAbreise IDReiseleiterAbrVergütungStamm_FS dbo ReiseleiterAbrVergütungStamm IDReiseleiterAbrVergütungStamm
732 FK_ReiseleiterArbeitszeit_ReiseleiterZuordnungReiseleiter dbo ReiseleiterArbeitszeit IDReiseleiterZuordnungReiseleiter_FS dbo ReiseleiterZuordnungReiseleiter IDReiseleiterZuordnungReiseleiter
733 FK_ReiseleiterHonorarStaffel_Adresse dbo ReiseleiterHonorarStaffel IDAdresse_FS_Personal dbo Adresse IDAdresse
734 FK_ReiseleiterHonorarStaffel_ArtReiseleiterHonorar dbo ReiseleiterHonorarStaffel IDArtReiseleiterHonorar_FS dbo ArtReiseleiterHonorar IDArtReiseleiterHonorar
735 FK_ReiseleiterSelektionen_Adresse dbo ReiseleiterSelektionen IDAdresse_FS_Personal dbo Adresse IDAdresse
736 FK_ReiseleiterSelektionen_Selektionsstamm dbo ReiseleiterSelektionen IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
737 FK_ReiseleiterSpesenBetrag_ArtSpesenLand dbo ReiseleiterSpesenBetrag IDArtSpesenLand_FS dbo ArtSpesenLand IDArtSpesenLand
738 FK_ReiseleiterSpesenBetrag_ReiseleiterSpesenStaffel dbo ReiseleiterSpesenBetrag IDReiseleiterSpesenStaffel_FS dbo ReiseleiterSpesenStaffel IDReiseleiterSpesenStaffel
739 FK_ReiseleiterStamm_Adresse dbo ReiseleiterStamm IDAdresse_FS dbo Adresse IDAdresse
740 FK_ReiseleiterWunschReise_Adresse dbo ReiseleiterWunschReise IDAdresse_FS_Personal dbo Adresse IDAdresse
741 FK_ReiseleiterWunschReise_Reise dbo ReiseleiterWunschReise IDReise_FS dbo Reise IDReise
742 FK_ReiseleiterZuordnungReiseleiter_Adresse1 dbo ReiseleiterZuordnungReiseleiter IDAdresse_FS dbo Adresse IDAdresse
743 FK_ReiseleiterZuordnungReiseleiter_ReiseleiterZuordnungStamm dbo ReiseleiterZuordnungReiseleiter IDReiseleiterZuordnungStamm_FS dbo ReiseleiterZuordnungStamm IDReiseleiterZuordnungStamm
744 FK_ReiseleiterZuordnungZusatzleistung_Leistung dbo ReiseleiterZuordnungZusatzleistung IDLeistung_FS dbo Leistung IDLeistung
745 FK_ReiseleiterZuordnungZusatzleistung_ReiseleiterZuordnungReiseleiter dbo ReiseleiterZuordnungZusatzleistung IDReiseleiterZuordnungReiseleiter_FS dbo ReiseleiterZuordnungReiseleiter IDReiseleiterZuordnungReiseleiter
746 FK_ReiseListenVersand_ArtListenart dbo ReiseListenVersand IdArtListenart_FS dbo ArtListenart IDArtListenArt
747 FK_ReiseListenVersand_ArtListenart1 dbo ReiseListenVersand IdArtListenart_FS dbo ArtListenart IDArtListenArt
748 FK_ReiseListenVersand_DruckEinstellungEMail dbo ReiseListenVersand IdDruckeinstellungEmail_FS dbo DruckEinstellungEMail IDDruckEinstellungEMail
749 FK_ReiseListenVersand_Reise dbo ReiseListenVersand IdReise_FS dbo Reise IDReise
750 FK_ReisePartner_Adresse dbo ReisePartner IDAdresse_FS_Partner dbo Adresse IDAdresse
751 FK_ReisePartner_ArtVerpflegung dbo ReisePartner IDArtVerpflegung_FS dbo ArtVerpflegung IDArtVerpflegung
752 FK_ReisePartner_Reise dbo ReisePartner IDReise_FS dbo Reise IDReise
753 FK_ReisePersonalZimmer_Reise dbo ReisePersonalZimmer IDReise_FS dbo Reise IDReise
754 FK_ReisePersonalZimmer_Zimmerart dbo ReisePersonalZimmer IDZimmerart_FS dbo Zimmerart IDZimmerart
755 FK_ReiseSelektionen_Reise dbo ReiseSelektionen IDReise_FS dbo Reise IDReise
756 FK_ReiseSelektionen_Selektionsstamm dbo ReiseSelektionen IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
757 FK_ReiseSitzplan_Reise dbo ReiseSitzplan IDReise_FS dbo Reise IDReise
758 FK_ReiseSitzplan_Sitzplan dbo ReiseSitzplan IDSitzplan_FS dbo Sitzplan IDSitzplan
759 FK_ReiseSitzplatzPreis_ArtSitzplatzKategorie dbo ReiseSitzplatzPreis IDArtSitzplatzKategorie_FS dbo ArtSitzplatzKategorie IDArtSitzplatzKategorie
760 FK_ReiseSitzplatzPreis_Reise dbo ReiseSitzplatzPreis IDReise_FS dbo Reise IDReise
761 FK_ReiseStatistik_Reise dbo ReiseStatistik IDReise_FS dbo Reise IDReise
762 FK_ReiseStatistikVertrieb_ReiseStatistik dbo ReiseStatistikVertrieb IDReiseStatistik_FS dbo ReiseStatistik IDReiseStatistik
763 FK_ReiseStatus_Reise dbo ReiseStatus IDReise_FS dbo Reise IDReise
764 FK_ReiseStatusBuchhaltung_ArtReiseStatusBuchhaltung dbo ReiseStatusBuchhaltung IDArtReiseStatusBuchhaltung_FS dbo ArtReiseStatusBuchhaltung IDArtReiseStatusBuchhaltung
765 FK_ReiseStatusBuchhaltung_Reise dbo ReiseStatusBuchhaltung IDReise_FS dbo Reise IDReise
766 FK_Reise_ReiseText dbo ReiseText IDReise_FS dbo Reise IDReise
767 FK_ReiseTextbaustein_Reise dbo ReiseTextbaustein IDReise_FS dbo Reise IDReise
768 FK_ReiseTextbaustein_Textbaustein dbo ReiseTextbaustein IDTextbaustein_FS dbo Textbaustein IDTextbaustein
769 FK_ReiseTextbausteinAbwJeMandant_Mandant dbo ReiseTextbausteinAbwJeMandant IDAdresse_FS_Mandant dbo Adresse IDAdresse
770 FK_ReiseTextbausteinAbwJeMandant_Reise dbo ReiseTextbausteinAbwJeMandant IDReise_FS dbo Reise IDReise
771 FK_ReiseTextbausteinAbwJeMandant_Textbaustein dbo ReiseTextbausteinAbwJeMandant IDTextbaustein_FS dbo Textbaustein IDTextbaustein
772 FK_Reiseunterlage_Reise dbo Reiseunterlage IDReise_FS dbo Reise IDReise
773 FK_Reiseunterlage_ReiseunterlagenBaustein dbo Reiseunterlage IDReiseunterlagenBaustein_FS dbo ReiseunterlagenBaustein IDReiseunterlagenBaustein
774 FK_ReiseunterlageInhalt_Reiseunterlage dbo ReiseunterlageInhalt IDReiseunterlage_FS dbo Reiseunterlage IDReiseunterlage
775 FK_ReiseunterlagenBaustein_ReiseunterlagenBausteinTyp dbo ReiseunterlagenBaustein IDReiseunterlagenBausteinTyp_FS dbo ReiseunterlagenBausteinTyp IDReiseunterlagenBausteinTyp
776 FK_ReiseunterlagenBausteinBedingung_ReiseunterlagenBaustein dbo ReiseunterlagenBausteinBedingung IDReiseunterlagenBaustein_FS dbo ReiseunterlagenBaustein IDReiseunterlagenBaustein
777 FK_ReiseunterlagenBausteinBedingung_ReiseunterlagenBedingung dbo ReiseunterlagenBausteinBedingung IDReiseunterlagenBedingung_FS dbo ReiseunterlagenBedingung IDReiseunterlagenBedingung
778 FK_ReiseunterlagenBausteinInhalt_ReiseunterlagenBaustein dbo ReiseunterlagenBausteinInhalt IDReiseunterlagenBaustein_FS dbo ReiseunterlagenBaustein IDReiseunterlagenBaustein
779 FK_ReiseunterlagenVorlageBaustein_ReiseunterlagenBaustein dbo ReiseunterlagenVorlageBaustein IDReiseUnterlagenBaustein_FS dbo ReiseunterlagenBaustein IDReiseunterlagenBaustein
780 FK_ReiseunterlagenVorlageBaustein_ReiseunterlagenVorlage dbo ReiseunterlagenVorlageBaustein IDReiseUnterlagenVorlage_FS dbo ReiseunterlagenVorlage IDReiseUnterlagenVorlage
781 FK_ReiseunterlagenVorlageInhalt_ReiseunterlagenVorlage dbo ReiseunterlagenVorlageInhalt IDReiseunterlagenVorlage_FS dbo ReiseunterlagenVorlage IDReiseUnterlagenVorlage
782 FK_ReiseVersicherungsGruppe_ArtVersicherungsGruppe dbo ReiseVersicherungsGruppe IDArtVersicherungsGruppe_FS dbo ArtVersicherungsGruppe IDArtVersicherungsGruppe
783 FK_ReiseVersicherungsGruppe_Reise dbo ReiseVersicherungsGruppe IDReise_FS dbo Reise IDReise
784 FK_ReiseVerwendung_Reise dbo ReiseVerwendung IDReise_FS dbo Reise IDReise
785 FK_ReiseVplDokument_Dokument dbo ReiseVplDokument IdDokument_FS dbo Dokument IDDokument
786 FK_ReiseVplDokument_ReiseVpl dbo ReiseVplDokument IdReiseVpl_FS dbo ReiseVpl IdReiseVpl
787 FK_ReiseVplKdVormerkung_ReiseVpl dbo ReiseVplKdVormerkung IdReiseVpl_FS dbo ReiseVpl IdReiseVpl
788 FK_ReiseVplPartner_ReiseVpl dbo ReiseVplPartner IdReiseVpl_FS dbo ReiseVpl IdReiseVpl
789 FK_ReiseVplPartnerDokument_Dokument dbo ReiseVplPartnerDokument IdDokument_FS dbo Dokument IDDokument
790 FK_ReiseVplPartnerDokument_ReiseVplPartner dbo ReiseVplPartnerDokument IdReiseVplPartner_FS dbo ReiseVplPartner IdReiseVplPartner
791 FK_ReiseVplPartnerStatus_ArtReiseVplPartnerStatus dbo ReiseVplPartnerStatus IDArtReiseVplPartnerStatus_FS dbo ArtReiseVplPartnerStatus IDArtReiseVplPartnerStatus
792 FK_ReiseVplPartnerStatus_ReiseVplPartner dbo ReiseVplPartnerStatus IDReiseVplPartner_FS dbo ReiseVplPartner IdReiseVplPartner
793 FK_ReiseVplStatus_ArtReiseVplStatus dbo ReiseVplStatus IDArtReiseVplStatus_FS dbo ArtReiseVplStatus IDArtReiseVplStatus
794 FK_ReiseVplStatus_ReiseVpl dbo ReiseVplStatus IDReiseVpl_FS dbo ReiseVpl IdReiseVpl
795 FK_ReiseVplVerwendung_ReiseVpl dbo ReiseVplVerwendung IDReiseVpl_FS dbo ReiseVpl IdReiseVpl
796 FK_ReiseWerbeplanung_Reise dbo ReiseWerbeplanung IDReise_FS dbo Reise IDReise
797 FK_ReisezielSelektionsstamm_Reiseziel dbo ReisezielSelektionsstamm IDReiseziel_FS dbo Reiseziel IDReiseziel
798 FK_ReisezielSelektionsstamm_Selektionsstamm dbo ReisezielSelektionsstamm IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
799 FK_ReiseZusatz_ArtAgenturPreisgruppe dbo ReiseZusatz IDArtAgenturPreisgruppe_FS dbo ArtAgenturPreisgruppe IDArtAgenturPreisgruppe
800 FK_ReiseZusatz_Reise dbo ReiseZusatz IDReise_FS dbo Reise IDReise
801 FK_ReiseZusatzAbwJeMandant_Adresse dbo ReiseZusatzAbwJeMandant IDAdresse_FS_Mandant dbo Adresse IDAdresse
802 FK_ReiseZusatzAbwJeMandant_Reise dbo ReiseZusatzAbwJeMandant IDReise_FS dbo Reise IDReise
803 FK_ReparaturAuftragZusatz_ReparaturAuftrag dbo ReparaturAuftragZusatz IDReparaturAuftrag_FS dbo Reparaturauftrag IDReparaturauftrag
804 FK_Rollsystem_ArtFahrplanVersion dbo Rollsystem IDArtFahrplanversion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
805 FK_RollsystemBlock_Block dbo RollsystemBlock IDBlock_FS dbo Block IDBlock
806 FK_RollsystemBlock_RollsystemFahrerFahrzeug dbo RollsystemBlock IDRollsystemFahrerFahrzeug_FS dbo RollsystemFahrerFahrzeug IDRollsystemFahrerFahrzeug
807 FK_RollsystemFahrerFahrzeug_Rollsystem dbo RollsystemFahrerFahrzeug IDRollsystem_FS dbo Rollsystem IDRollsystem
808 FK_RollsystemFerien_Rollsystem dbo RollsystemFerien IDRollsystem_FS dbo Rollsystem IDRollsystem
809 FK_RollsystemPerkap_ArtPersonalkapazitaet dbo RollsystemPerkap IDArtPersonalkapazitaet_FS dbo ArtPersonalkapazitaet IDArtPersonalkapazitaet
810 FK_RollsystemPerkap_RollsystemFahrerFahrzeug dbo RollsystemPerkap IDRollsystemFahrerFahrzeug_FS dbo RollsystemFahrerFahrzeug IDRollsystemFahrerFahrzeug
811 FK_RsbVeransAnzahlung_RsbVerans dbo RsbVeransAnzahlung IDRsbVerans_FS dbo RsbVerans IDRsbVeranstalter
812 FK_RsbVeransZusatz_RsbVerans dbo RsbVeransZusatz IDRsbVerans_FS dbo RsbVerans IDRsbVeranstalter
813 FK_Rufbus_FPLinieFahrt dbo Rufbus IDFPLinieFahrt_FS dbo FPLinieFahrt IDFPLinieFahrt
814 FK_Rufbus_FPLinieHaltestelleZeitartNach dbo Rufbus FPLinieHaltestelleZeitart_FS_Nach dbo FPLinieHaltestelleZeitart IDFPLinieHaltestelleZeitart
815 FK_Rufbus_FPLinieHaltestelleZeitartVon dbo Rufbus FPLinieHaltestelleZeitart_FS_Von dbo FPLinieHaltestelleZeitart IDFPLinieHaltestelleZeitart
816 FK_Rufbus_Haltepunkt_Nach dbo Rufbus IDHaltepunkt_FS_Nach dbo Haltepunkt IDHaltepunkt
817 FK_Rufbus_Haltepunkt_Von dbo Rufbus IDHaltepunkt_FS_Von dbo Haltepunkt IDHaltepunkt
818 FK_Rufbus_Haltestelle_Nach dbo Rufbus IDHaltestelle_FS_Nach dbo Haltestelle IDHaltestelle
819 FK_Rufbus_Haltestelle_Von dbo Rufbus IDHaltestelle_FS_Von dbo Haltestelle IDHaltestelle
820 FK_Rufbus_Linie dbo Rufbus IDFPLinie_FS dbo FPLinie IDFPLinie
821 FK_SaisonZeit_SaisonBezeichnung dbo SaisonZeit IDSaisonBezeichnung_FS dbo SaisonBezeichnung IDSaisonBezeichnung
822 FK_SchiffsDeck_Schiff dbo SchiffsDeck IDSchiff_FS dbo Schiff IDSchiff
823 FK_SchiffsKabine_SchiffsDeck dbo SchiffsKabine IDSchiffsDeck_FS dbo SchiffsDeck IDSchiffsDeck
824 FK_Schule_Schulamt dbo Schule IDSchulamt_FS dbo Schulamt IDSchulamt
825 FK_Adresse_Selektion dbo Selektionen IDAdresse_FS dbo Adresse IDAdresse
826 FK_Selektionsstamm_Selektion dbo Selektionen IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
827 FK_Selektionsgruppenstamm_Selektionsgruppe dbo Selektionsgruppe IDSelektionsgruppenstamm_FS dbo Selektionsgruppenstamm IDSelektionsgruppenstamm
828 FK_Selektionsstamm_Selektionsgruppe dbo Selektionsgruppe IDSelektionsstamm_FS dbo Selektionsstamm IDSelektionsstamm
829 FK_Sitzplan_Sitzplanobjekt dbo Sitzplanobjekt IDSitzplan_FS dbo Sitzplan IDSitzplan
830 FK_Sperrung_Adresse dbo Sperrung IDAdresse_FS dbo Adresse IDAdresse
831 FK_Sperrung_ArtSperrartFahrer dbo Sperrung IDArtSperrartFahrer_FS dbo ArtSperrartFahrer IDArtSperrartFahrer
832 FK_Sperrung_ArtSperrartFahrzeug dbo Sperrung IDArtSperrartFahrzeug_FS dbo ArtSperrartFahrzeug IDArtSperrartFahrzeug
833 FK_Sperrung_ArtSperrKategorie dbo Sperrung IDArtSperrKategorie_FS dbo ArtSperrKategorie IDArtSperrKategorie
834 FK_Sperrung_Fahrzeug dbo Sperrung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
835 FK_SperrungSperrStatus_ArtSperrStatus dbo SperrungSperrStatus IDArtSperrStatus_FS dbo ArtSperrStatus IDArtSperrStatus
836 FK_SperrungSperrStatus_Sperrung dbo SperrungSperrStatus IDSperrung_FS dbo Sperrung IDSperrung
837 FK_Spesen_Adresse dbo Spesen IDAdresse_FS_Personal dbo Adresse IDAdresse
838 FK_Spesen_ArtSpesen dbo Spesen IDArtSpesen_FS dbo ArtSpesen IDArtSpesen
839 FK_SpracheMaskeModul_Programmmodul dbo SpracheMaskeModul IDProgrammmodul_FS dbo Programmmodul IDProgrammmodul
840 FK_SpracheMaskeText_SpracheMaske dbo SpracheMaskeText IDSpracheMaske_FS dbo SpracheMaske IDSpracheMaske
841 FK_SteueraufteilungDetail_Land dbo SteueraufteilungDetail IDLand_FS dbo Land IDLand
842 FK_SteueraufteilungDetail_SteueraufteilungArt dbo SteueraufteilungDetail IDSteueraufteilungArt_FS dbo SteueraufteilungArt IDSteueraufteilungArt
843 FK_SteueraufteilungDetail_SteueraufteilungUnterart dbo SteueraufteilungDetail IDSteueraufteilungUnterart_FS dbo SteueraufteilungUnterart IDSteueraufteilungUnterart
844 FK_SteueraufteilungDetailArtVerpflegung_ArtVerpflegung dbo SteueraufteilungDetailArtVerpflegung IDArtVerpflegung_FS dbo ArtVerpflegung IDArtVerpflegung
845 FK_SteueraufteilungDetailArtVerpflegung_SteueraufteilungDetail dbo SteueraufteilungDetailArtVerpflegung IDSteueraufteilungDetail_FS dbo SteueraufteilungDetail IDSteueraufteilungDetail
846 FK_SteueraufteilungUnterart_SteueraufteilungArt dbo SteueraufteilungUnterart IDSteueraufteilungArt_FS dbo SteueraufteilungArt IDSteueraufteilungArt
847 FK_Tachostand_Fahrzeug dbo Tachostand IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
848 FK_Tachostand_TachostandImportEinstellung dbo Tachostand IDTachostandImportEinstellung_FS dbo TachostandImportEinstellung IDTachostandImportEinstellung
849 FK_Tankerfassung_ArtBetankung dbo Tankerfassung IDArtBetankung_FS dbo ArtBetankung IDArtBetankung
850 FK_Tankerfassung_ArtKarftstoffart dbo Tankerfassung IDArtKraftstoffart_FS dbo ArtKraftstoffart IDArtKraftstoffart
851 FK_Tankerfassung_Fahrzeug dbo Tankerfassung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
852 FK_Tankerfassung_TankimportEinstellung dbo Tankerfassung IDTankimportEinstellung_FS dbo TankimportEinstellung IDTankimportEinstellung
853 FK_TankimportEinstellung_ArtBetankung dbo TankimportEinstellung IDArtBetankung_FS dbo ArtBetankung IDArtBetankung
854 FK_TankimportEinstellungArtBetankung_ArtBetankung dbo TankimportEinstellungArtBetankung IDArtBetankung_FS dbo ArtBetankung IDArtBetankung
855 FK_TankimportEinstellungArtBetankung_TankimportEinstellung dbo TankimportEinstellungArtBetankung IDTankimportEinstellung_FS dbo TankimportEinstellung IDTankimportEinstellung
856 FK_TankimportEinstellungKraftstoff_ArtKraftstoffart dbo TankimportEinstellungKraftstoff IDArtKraftstoffart_FS dbo ArtKraftstoffart IDArtKraftstoffart
857 FK_TankimportEinstellungKraftstoff_TankimportEinstellung dbo TankimportEinstellungKraftstoff IDTankimportEinstellung_FS dbo TankimportEinstellung IDTankimportEinstellung
858 FK_TaxiPartner_Adresse dbo TaxiPartner IDAdresse_FS dbo Adresse IDAdresse
859 FK_TaxiPartnerKosten_TaxiPartner dbo TaxiPartnerKosten IDTaxiPartner_FS dbo TaxiPartner IDTaxiPartner
860 FK_TaxiPartnerMapGuide_TaxiPartner dbo TaxiPartnerMapGuide IDTaxiPartner_FS dbo TaxiPartner IDTaxiPartner
861 FK_TaxiPartnerZustieg_Adresse dbo TaxiPartnerZustieg IDAdresse_FS dbo Adresse IDAdresse
862 FK_TaxiPartnerZustieg_Zustieg dbo TaxiPartnerZustieg IDZustieg_FS dbo Zustieg IDZustieg
863 FK_TerminalFreigabe_ArtTerminalFreigabe dbo TerminalFreigabe IDArtTerminalFreigabe_FS dbo ArtTerminalFreigabe IDArtTerminalFreigabe
864 FK_TerminalFreigabeArtBetriebshof_ArtBetriebshof dbo TerminalFreigabeArtBetriebshof IDArtBetriebshof_FS dbo ArtBetriebshof IDArtBetriebshof
865 FK_TerminalProtokoll_Adresse dbo TerminalProtokoll IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
866 FK_TerminArtSachbearbeiter_Adresse dbo TerminArtSachbearbeiter IDAdresse_FS_Personal dbo Adresse IDAdresse
867 FK_TerminArtSachbearbeiter_TerminArt dbo TerminArtSachbearbeiter IDTerminArt_FS dbo TerminArt IDTerminArt
868 FK_TerminKetteAbfolge_TerminKette dbo TerminKetteAbfolge IDTerminArt_FS dbo TerminArt IDTerminArt
869 FK_TerminKetteAbfolge_TerminKette1 dbo TerminKetteAbfolge IDTerminKette_FS dbo TerminKette IDTerminKette
870 FK_TerminSachbearbeiter_Termin dbo TerminSachbearbeiter IDTermin_FS dbo Termin IDTermin
871 FK_Tour_ArtFahrplanVersion dbo Tour IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
872 FK_Tour_ArtStatistikGruppe dbo Tour IDArtStatistikgruppe_FS_Haupt dbo ArtStatistikGruppe IDArtStatistikGruppe
873 FK_Tour_FPLinieFahrt dbo Tour IDFPLinieFahrt_FS dbo FPLinieFahrt IDFPLinieFahrt
874 FK_Tour_Haltepunkt_Anfang dbo Tour IDHaltepunkt_FS_Anfang dbo Haltepunkt IDHaltepunkt
875 FK_Tour_Haltepunkt_Ende dbo Tour IDHaltepunkt_FS_Ende dbo Haltepunkt IDHaltepunkt
876 FK_Tour_Haltestelle_Anfang dbo Tour IDHaltestelle_FS_Anfang dbo Haltestelle IDHaltestelle
877 FK_Tour_Haltestelle_Ende dbo Tour IDHaltestelle_FS_Ende dbo Haltestelle IDHaltestelle
878 FK_Tour_Ort_Anfang dbo Tour IDOrt_FS_Anfang dbo Ort IDOrt
879 FK_Tour_Ort_Ende dbo Tour IDOrt_FS_Ende dbo Ort IDOrt
880 FK_TourFahrzeugtyp_ArtFahrzeugTypen dbo TourFahrzeugtyp IDArtFahrzeugTypen_FS dbo ArtFahrzeugTypen IDArtFahrzeugTypen
881 FK_TourFahrzeugtyp_Tour dbo TourFahrzeugtyp IDTour_FS dbo Tour IDTour
882 FK_TourFerienFeier_Tour dbo TourFerienFeier IDTour_FS dbo Tour IDTour
883 FK_TourHaltestelleHaltepunkt_Haltepunkt dbo TourHaltestelleHaltepunkt IDHaltepunkt_FS dbo Haltepunkt IDHaltepunkt
884 FK_TourHaltestelleHaltepunkt_Haltestelle dbo TourHaltestelleHaltepunkt IDHaltestelle_FS dbo Haltestelle IDHaltestelle
885 FK_TourHaltestelleHaltepunkt_Tour dbo TourHaltestelleHaltepunkt IDTour_FS dbo Tour IDTour
886 FK_TourKreisGebiet_ArtKreisGebiet dbo TourKreisGebiet IDArtKreisGebiet_FS dbo ArtKreisGebiet IDArtKreisGebiet
887 FK_TourKreisGebiet_Tour dbo TourKreisGebiet IDTour_FS dbo Tour IDTour
888 FK_TourLaufzeit_TourLaufzeit dbo TourLaufzeit IDTour_FS dbo Tour IDTour
889 FK_TourPlanung_Adresse dbo TourPlanung IDAdresse_FS_Fahrer dbo Adresse IDAdresse
890 FK_TourPlanung_Adresse2 dbo TourPlanung LoeschenManuellIDAdresse_FS_SB dbo Adresse IDAdresse
891 FK_TourPlanung_ArtFahrplanVersion dbo TourPlanung IDArtFahrplanVersion_FS dbo ArtFahrplanVersion IDArtFahrplanVersion
892 FK_TourPlanung_ArtStatistikGruppe dbo TourPlanung IDArtStatistikgruppe_FS_Haupt dbo ArtStatistikGruppe IDArtStatistikGruppe
893 FK_TourPlanung_BlockPlanung dbo TourPlanung IDBlockPlanung_FS dbo BlockPlanung IDBlockPlanung
894 FK_TourPlanung_Fahrzeug dbo TourPlanung IDFahrzeug_FS dbo Fahrzeug IDFahrzeug
895 FK_Tourplanung_Haltepunkt_Anfang dbo TourPlanung IDHaltepunkt_FS_Anfang dbo Haltepunkt IDHaltepunkt
896 FK_Tourplanung_Haltepunkt_Ende dbo TourPlanung IDHaltepunkt_FS_Ende dbo Haltepunkt IDHaltepunkt
897 FK_Tourplanung_Haltestelle_Anfang dbo TourPlanung IDHaltestelle_FS_Anfang dbo Haltestelle IDHaltestelle
898 FK_Tourplanung_Haltestelle_Ende dbo TourPlanung IDHaltestelle_FS_Ende dbo Haltestelle IDHaltestelle
899 FK_TourPlanung_Ort_Anfang dbo TourPlanung IDOrt_FS_Anfang dbo Ort IDOrt
900 FK_TourPlanung_Ort_Ende dbo TourPlanung IDOrt_FS_Ende dbo Ort IDOrt
901 FK_TourPlanung_Tour dbo TourPlanung IDTour_FS_Basis dbo Tour IDTour
902 FK_TourPlanungFahrzeugtyp_ArtFahrzeugTypen dbo TourPlanungFahrzeugtyp IDArtFahrzeugTypen_FS dbo ArtFahrzeugTypen IDArtFahrzeugTypen
903 FK_TourPlanungFahrzeugtyp_TourPlanung dbo TourPlanungFahrzeugtyp IDTourPlanung_FS dbo TourPlanung IDTourPlanung
904 FK_TourPlanungKreisGebiet_ArtKreisGebiet dbo TourPlanungKreisGebiet IDArtKreisGebiet_FS dbo ArtKreisGebiet IDArtKreisGebiet
905 FK_TourPlanungKreisGebiet_TourPlanung dbo TourPlanungKreisGebiet IDTourPlanung_FS dbo TourPlanung IDTourPlanung
906 FK_TourPlanungStatistik_ArtStatistikGruppe dbo TourPlanungStatistik IDArtStatistikGruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
907 FK_TourPlanungStatistik_TourPlanung dbo TourPlanungStatistik IDTourPlanung_FS dbo TourPlanung IDTourPlanung
908 FK_TourPlanungZusatz_TourPlanung dbo TourPlanungZusatz IDTourPlanung_FS dbo TourPlanung IDTourPlanung
909 FK_TourStatistik_ArtStatistikGruppe dbo TourStatistik IDArtStatistikGruppe_FS dbo ArtStatistikGruppe IDArtStatistikGruppe
910 FK_TourStatistik_Tour dbo TourStatistik IDTour_FS dbo Tour IDTour
911 FK_TourWochentyp_ArtWochentyp dbo TourWochentyp IDArtWochentyp_FS dbo ArtWochentyp IDArtWochentyp
912 FK_TourWochentyp_Tour dbo TourWochentyp IDTour_FS dbo Tour IDTour
913 FK_TourZeitraum_ArtLaufzeitschema dbo TourZeitraum IDArtLaufzeitschema_FS dbo ArtLaufzeitschema IDArtLaufzeitschema
914 FK_TourZeitraum_Tour dbo TourZeitraum IDTour_FS dbo Tour IDTour
915 FK_TourZusatz_Tour dbo TourZusatz IDTour_FS dbo Tour IDTour
916 FK_UserStartmenue_Adresse dbo UserStartmenue IDAdresse_FS dbo Adresse IDAdresse
917 FK_UserStartmenue_Programmmodul dbo UserStartmenue IDProgrammmodul_FS dbo Programmmodul IDProgrammmodul
918 FK_VorplanungRasterAblauf_VorplanungRaster dbo VorplanungRasterAblauf IDVorplanungRaster_FS dbo VorplanungRaster IDVorplanungRaster
919 FK_VorplanungRasterAblaufAbwPartner_Adresse dbo VorplanungRasterAblaufAbwPartner IDAdresse_FS_Partner dbo Adresse IDAdresse
920 FK_VorplanungRasterAblaufAbwPartner_VorplanungRasterAblauf dbo VorplanungRasterAblaufAbwPartner IDVorplanungRasterAblauf_FS dbo VorplanungRasterAblauf IDVorplanungRasterAblauf
921 FK_VorplanungRasterAblaufAbwPartner_VorplanungRasterTermin dbo VorplanungRasterAblaufAbwPartner IDVorplanungRasterTermin_FS dbo VorplanungRasterTermin IDVorplanungRasterTermin
922 FK_VorplanungRasterAblaufStatus_Adresse dbo VorplanungRasterAblaufStatus IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
923 FK_VorplanungRasterAblaufStatus_ArtReiseVplPartnerStatus dbo VorplanungRasterAblaufStatus IDArtReiseVplPartnerStatus_FS dbo ArtReiseVplPartnerStatus IDArtReiseVplPartnerStatus
924 FK_VorplanungRasterAblaufStatus_VorplanungRasterAblauf dbo VorplanungRasterAblaufStatus IDVorplanungRasterAblauf_FS dbo VorplanungRasterAblauf IDVorplanungRasterAblauf
925 FK_VorplanungRasterAblaufStatus_VorplanungRasterTermin dbo VorplanungRasterAblaufStatus IDVorplanungRasterTermin_FS dbo VorplanungRasterTermin IDVorplanungRasterTermin
926 FK_VorplanungRasterAblaufZusatz_VorplanungRasterAblauf dbo VorplanungRasterAblaufZusatz IDVorplanungRasterAblauf_FS dbo VorplanungRasterAblauf IDVorplanungRasterAblauf
927 FK_VorplanungRasterBemerkung_VorplanungRaster dbo VorplanungRasterBemerkung IDVorplanungRaster_FS dbo VorplanungRaster IDVorplanungRaster
928 FK_VorplanungRasterDokument_Adresse dbo VorplanungRasterDokument IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
929 FK_VorplanungRasterDokument_ArtDokument dbo VorplanungRasterDokument IDArtDokument_FS dbo ArtDokument IDArtDokument
930 FK_VorplanungRasterDokument_VorplanungRaster dbo VorplanungRasterDokument IDVorplanungRaster_FS dbo VorplanungRaster IDVorplanungRaster
931 FK_VorplanungRasterKalkulationÜbernahme_VorplanungRasterKalkulation dbo VorplanungRasterKalkulationÜbernahme IDVorplanungRasterKalkulation_FS dbo VorplanungRasterKalkulation IDVorplanungRasterKalkulation
932 FK_VorplanungRasterTermin_VorplanungRaster dbo VorplanungRasterTermin IDVorplanungRaster_FS dbo VorplanungRaster IDVorplanungRaster
933 FK_WaehrungsKurse_ArtWaehrung dbo WaehrungsKurse IDArtWaehrung_FS dbo ArtWaehrung IDArtWaehrung
934 FK_WerbeplanungPunkte_ArtWerbeplanungReiseart dbo WerbeplanungPunkte IDArtWerbeplanungReiseart_FS dbo ArtWerbeplanungReiseart IDArtWerbeplanungReiseart
935 FK_WWKategorieEintrag_WWSuchKategorie dbo WWSuchKategorieEintrag IDWWSuchKategorie_FS dbo WWSuchKategorie IDWWSuchKategorie
936 FK_Zahlung_Adresse dbo Zahlung IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
937 FK_Zahlung_ArtWaehrung dbo Zahlung IDWaehrung_FS dbo ArtWaehrung IDArtWaehrung
938 FK_Zahlung_ArtZahlungsart dbo Zahlung IDArtZahlungart_FS dbo ArtZahlungsart IDArtZahlungsart
939 FK_Zahlung_ZahlungCode dbo Zahlung IDKontenplan_FS dbo Kontenplan IDKontenplan
940 FK_Zahlung_ZahlungStamm dbo Zahlung IDZahlungStamm_FS dbo ZahlungStamm IDZahlungStamm
941 FK_ZahlungDokument_Adresse dbo ZahlungDokument IDAdresse_FS_Sachbearbeiter dbo Adresse IDAdresse
942 FK_ZahlungDokument_ArtDokument dbo ZahlungDokument IDArtDokument_FS dbo ArtDokument IDArtDokument
943 FK_ZahlungDokument_Zahlung dbo ZahlungDokument IDZahlung_FS dbo Zahlung IDZahlung
944 FK_ZahlungStamm_Adresse dbo ZahlungStamm IDAdresse_FS_Mandant dbo Adresse IDAdresse
945 FK_ZahlungStamm_ArtWaehrung dbo ZahlungStamm IDWaehrung_FS dbo ArtWaehrung IDArtWaehrung
946 FK_ZahlungStamm_Nummernkreis dbo ZahlungStamm IDNummernkreis_FS dbo Nummernkreis IDNummernkreis
947 FK_ZiellandRoute_Land dbo ZiellandRoute IDLand_FS_Route dbo Land IDLand
948 FK_ZiellandRoute_Land1 dbo ZiellandRoute IDLand_FS_Zielland dbo Land IDLand
949 FK_Zusatzinformation_Adresse dbo Zusatzinformation IDAdresse_FS_Partner dbo Adresse IDAdresse
950 FK_Zusatzinformation_ArtZusatzinfoStamm dbo Zusatzinformation IDArtZusatzinfoStamm_FS dbo ArtZusatzinfoStamm IDArtZusatzinfoStamm
951 FK_Zusatzinformation_Reise dbo Zusatzinformation IDReise_FS dbo Reise IDReise
952 FK_ZusatzZimmer_ArtBuchungsStatus dbo ZusatzZimmer IDArtBuchungsstatus_FS dbo ArtBuchungsStatus IDArtBuchungsStatus
953 FK_ZusatzZimmer_Reise dbo ZusatzZimmer IDReise_FS dbo Reise IDReise
954 FK_ZustiegHinweis_Zustieg dbo ZustiegHinweis IDZustieg_FS dbo Zustieg IDZustieg
955 FK_Zustiegkoordinate_Zustieg dbo Zustiegkoordinate IDZustieg_FS dbo Zustieg IDZustieg
956 FK_ZustiegKoordinate_ZustiegKoordinatenArt dbo Zustiegkoordinate IDArtKoordinaten_FS dbo ArtZustiegKoordinaten IDArtZustiegKoordinaten
957 FK_ZustiegPLZ_Zustieg1 dbo ZustiegPLZ IDZustieg_FS dbo Zustieg IDZustieg
958 FK_ZustiegPreis_ArtZustiegPreis1 dbo ZustiegPreis IDArtZustiegPreis_FS dbo ArtZustiegPreis IDArtZustiegPreis
959 FK_ZustiegPreis_Zustieg1 dbo ZustiegPreis IDZustieg_FS dbo Zustieg IDZustieg
960 FK_ZustiegRoute_ArtZustiegRoutenbeschreibung dbo ZustiegRoute IDArtZustiegRoutenbeschreibung_FS dbo ArtZustiegRoutenbeschreibung IDArtZustiegRoutenbeschreibung
961 FK_ZustiegRoute_Zustieg dbo ZustiegRoute IDZustieg_FS dbo Zustieg IDZustieg
962 FK_ZustiegsPlanungBesonders_ZustiegsPlanungPerson dbo ZustiegsPlanungBesonders IDZustiegsPlanungPerson_FS dbo ZustiegsPlanungPerson IDZustiegsPlanungPerson
963 FK_ZustiegsPlanungBus_ZustiegsPlanung dbo ZustiegsPlanungBus IDZustiegsPlanung_FS dbo ZustiegsPlanung IDZustiegsPlanung
964 FK_ZustiegsPlanungBusStelle_ZustiegsPlanungBus dbo ZustiegsPlanungBusStelle IDZustiegsPlanungBus_FS dbo ZustiegsPlanungBus IDZustiegsPlanungBus
965 FK_ZustiegsPlanungLeistung_ZustiegsPlanung dbo ZustiegsPlanungLeistung IDZustiegsPlanung_FS dbo ZustiegsPlanung IDZustiegsPlanung
966 FK_ZustiegsPlanungPerson_BuchungTN dbo ZustiegsPlanungPerson IDBuchungTN_FS dbo BuchungTN IDBuchungTN
967 FK_ZustiegsPlanungPerson_Leistung dbo ZustiegsPlanungPerson IDLeistung_FS dbo Leistung IDLeistung
968 FK_ZustiegsPlanungPerson_ZustiegsPlanung dbo ZustiegsPlanungPerson IDZustiegsPlanung_FS dbo ZustiegsPlanung IDZustiegsPlanung
969 FK_ZustiegsPlanungPersonStelle_ZustiegsPlanungBusStelle dbo ZustiegsPlanungPersonStelle IDZustiegsPlanungBusStelle_FS dbo ZustiegsPlanungBusStelle IDZustiegsPlanungBusStelle
970 FK_ZustiegsPlanungPersonStelle_ZustiegsPlanungPerson dbo ZustiegsPlanungPersonStelle IDZustiegsPlanungPerson_FS dbo ZustiegsPlanungPerson IDZustiegsPlanungPerson
971 FK_ZustiegZeitplan_ArtZustiegZeitplan dbo ZustiegZeitplan IDArtZustiegZeitplan_FS dbo ArtZustiegZeitplan IDArtZustiegZeitplan
+94
View File
@@ -0,0 +1,94 @@
# Boarding Plan — Table Relations (BusPro schema)
> **Authority: [`docs/buspro-database-reference.md`](../buspro-database-reference.md) §8.4.**
> Retained for the detailed ER diagram of the `ZustiegsPlanung*` subsystem.
Read-only reference for building the boarding-plan API endpoint (look up a plan
by `IDZustiegsPlanung`, returning names, addresses, and times).
The query walks:
**`ZustiegsPlanung` → persons → (name via `BuchungTN`/`AdressePerson`) →
`PersonStelle` junction → `BusStelle` (time) → `Zustieg` (address) → `Bus`.**
`ZustiegsPlanungPersonStelle` is the pivot that ties a passenger to a timed stop.
## ER diagram
```mermaid
erDiagram
ZustiegsPlanung ||--o{ ZustiegsPlanungBus : "IDZustiegsPlanung_FS"
ZustiegsPlanung ||--o{ ZustiegsPlanungPerson : "IDZustiegsPlanung_FS"
ZustiegsPlanungBus ||--o{ ZustiegsPlanungBusStelle : "IDZustiegsPlanungBus_FS"
ZustiegsPlanungPerson ||--o{ ZustiegsPlanungPersonStelle : "IDZustiegsPlanungPerson_FS"
ZustiegsPlanungBusStelle ||--o{ ZustiegsPlanungPersonStelle : "IDZustiegsPlanungBusStelle_FS"
ZustiegsPlanungPerson }o..|| BuchungTN : "IDBuchungTN_FS"
BuchungTN }o..|| AdressePerson : "IDAdressePerson_FS (name)"
ZustiegsPlanungBusStelle }o..o| Zustieg : "IDZustieg_FS (soft, address)"
ZustiegsPlanung {
bigint IDZustiegsPlanung PK
datetime Datum
}
ZustiegsPlanungBus {
bigint IDZustiegsPlanungBus PK
string ReiseleiterName
}
ZustiegsPlanungBusStelle {
bigint IDZustiegsPlanungBusStelle PK
datetime Zeit "TIME"
smallint Sortierung
}
ZustiegsPlanungPerson {
bigint IDZustiegsPlanungPerson PK
}
ZustiegsPlanungPersonStelle {
bigint IDZustiegsPlanungPersonStelle PK
string Art "Einstieg/Ausstieg"
}
AdressePerson {
string Name
string Vorname
}
Zustieg {
string Strasse
string Plz
string Ort
}
```
## ASCII fallback
```
ZustiegsPlanung (the planning id)
/ \
IDZustiegsPlanung_FS IDZustiegsPlanung_FS
/ \
ZustiegsPlanungBus ZustiegsPlanungPerson ──IDBuchungTN_FS──▶ BuchungTN
│ (Reiseleiter) │ │
IDZustiegsPlanungBus_FS IDZustiegsPlanungPerson_FS IDAdressePerson_FS
│ │ ▼
▼ ▼ AdressePerson
ZustiegsPlanungBusStelle ◀──┐ ZustiegsPlanungPersonStelle (NAME)
• Zeit (TIME) │ • Art (boarding/alighting)
• IDZustieg_FS ··soft··▶ Zustieg (ADDRESS)
└──IDZustiegsPlanungBusStelle_FS───┘ (junction: passenger ↔ stop)
```
**Legend:** `||--o{` / solid = enforced FK constraint; `}o..` / `··soft··` =
convention-only `_FS` reference (no DB constraint — join defensively, expect
`NULL`/`0`/orphaned values).
## Notes for the query
- **Name** is not stored in the plan; join out live via
`ZustiegsPlanungPerson.IDBuchungTN_FS → BuchungTN.IDAdressePerson_FS → AdressePerson`.
- **Time** lives on `ZustiegsPlanungBusStelle.Zeit` (per stop), not on the plan
header (`ZustiegsPlanung.Datum` is the plan date).
- **Address** comes from `Zustieg` (the boarding point). Prefer reaching it via
`ZustiegsPlanungBusStelle.IDZustieg_FS` so it never depends on
`ZustiegsPlanungPerson.IDZustieg_FS` being populated.
- A passenger can have multiple `ZustiegsPlanungPersonStelle` rows (boarding +
alighting), distinguished by `Art`. Filter on `Art` for boarding-only.
- To verify against real data: the actual `Art` codes (`nvarchar(6)`), and
whether `BusStelle.IDZustieg_FS` always matches the passenger's
`Person.IDZustieg_FS` on the boarding leg.
@@ -0,0 +1,469 @@
# `SelektionCRM` — how the XML is assembled, and how to debug a missing selection
> **Authority: [`docs/buspro-database-reference.md`](../buspro-database-reference.md).**
> Schema semantics and the falsified-theory record live there and win on any conflict.
> This file is retained as the **full investigation record** for the missing-selection /
> `aenderbar` problem, including the queries that closed each theory.
Companion to `travel-queries.md` (static catalog) and `live-api-queries.md` (live
socket endpoints). This one covers the `KUNDENKONTO` / `art=SelektionCRM` response —
the document that drives the portal's entire authorization model.
Request side: `ApiClient::getCrmAttributes()` (`src/BusProNet/ApiClient.php`) sends
`satz typ="KUNDENKONTO"` + `art=SelektionCRM` + the customer's email/password.
Response side: `CrmAttributesResponseParser`
(`src/BusProNet/XmlParser/CrmAttributesResponseParser.php`) turns selection ids into
Symfony roles:
| `IDSelektionsstamm` | Role |
| --- | --- |
| `1070` | `ROLE_TEAMER` |
| `1292` | `ROLE_ADMIN` (+ `ROLE_HOUSE_MANAGER`, + hotel code `SSL`) |
| `1293` | `ROLE_MANAGER` |
| `1477` | `ROLE_GROUPS_MANAGER` |
| `1478` | `ROLE_GROUPS_ADMIN` |
| label `Hausleitung {CODE}` | `ROLE_HOUSE_MANAGER` + hotel code `{CODE}` |
| nothing matched | `ROLE_CUSTOMER` |
Only selections with `auswahl="True"` count. Every `Admin/*` controller is gated on
one of these roles.
---
## The four tables
From `BusPronet_20260601-1517.csv` (columns) and `BusPronet_20260601-1518.csv` (FKs):
| Table | Columns | Role |
| --- | --- | --- |
| `dbo.Selektionsstamm` | `IDSelektionsstamm`, `Selektion`, `Status` nvarchar(2) null, `System` tinyint | the selection master — that's *all four* columns |
| `dbo.Selektionsgruppenstamm` | `IDSelektionsgruppenstamm`, `Selektionsgruppe`, `Status`, `System`, `Ausgrenzung`, `Position` | the group master |
| `dbo.Selektionsgruppe` | `IDSelektionsgruppenstamm_FS`, `IDSelektionsstamm_FS`, `Position` | **membership** — which selection sits in which group, and in what order |
| `dbo.Selektionen` | `IDAdresse_FS`, `IDSelektionsstamm_FS` | **assignment** — which address holds which selection |
`<crmaktionen>` comes from a parallel pair: `dbo.CRMAktion` (master: `Code`,
`Bezeichnung`, `Aktiv`, `Status`, `AktivDatumVon/Bis`, …) and `dbo.CRMZuweisung`
(assignment via `IDAdresse_FS` + `IDCRMAktion_FS`).
### XML → column mapping
| XML | Source |
| --- | --- |
| `<idadresse>` | `Adresse.IDAdresse` (the authenticated account) |
| `<idperson>` | `AdressePerson.IDAdressePerson` |
| `<selektionsgruppe id>` / `bezeichnung` | `Selektionsgruppenstamm.IDSelektionsgruppenstamm` / `.Selektionsgruppe` |
| `<selektion id>` / `bezeichnung` | `Selektionsstamm.IDSelektionsstamm` / `.Selektion` |
| `selektion@auswahl` | `EXISTS (Selektionen WHERE IDAdresse_FS = <account> AND IDSelektionsstamm_FS = <id>)` — confirmed |
| `selektion@aenderbar` | **computed, not stored** — no such column exists anywhere (see below) |
| group order | `Selektionsgruppenstamm.Position`, `<ohne Gruppe>` first |
| selection order within a group | `Selektionsgruppe.Position` |
| `<crmaktion …>` | `CRMAktion` + `CRMZuweisung` (`auswahl` = assignment exists) |
### `aenderbar` is not a stored flag
A case-insensitive search for `aenderbar` / `auswahl` across **every column name in the
database** (1023 tables, `ABOBewegungsdaten``ZustiegsPlanungPersonStelle`, so the
export is complete and untruncated) returns no hit on any `Selektion*` table. The only
`*Aenderbar*` column in the entire schema is `AdresseAgenturZusatz.ZahlungsartAenderbar`,
which is unrelated. And the three core tables have no spare bit to hide it in:
`Selektionsstamm` has exactly four columns, `Selektionsgruppe` three, `Selektionen` two.
So `aenderbar` is **derived at response time**. Don't go looking for the column again —
this is what Query D and Query E are for.
The `<crmaktionen>` half of the document hints at the intended semantics: `CRMAktion`
*does* carry real flags (`Aktiv`, `Anzeige`, `AktivDatumVon`/`Bis`), and in the reference
sample the long-expired "Deal Der Woche KW40-2018" is `aenderbar="False"` while the
standing "NOMAIL" opt-out is `"True"`. `aenderbar` reads as *"the customer may still
toggle this"* — a validity/whitelist question, not a static per-row property.
Two orderings worth noting, because they rule out the obvious alternatives:
- Inside `TEAM` the ids run `… 1374, 1375, 1376, 1373, 1377 …` — neither id order nor
label order. That is `Selektionsgruppe.Position`.
- Within `Interessen` the labels *are* alphabetical, which is consistent with
`Position` having been maintained alphabetically there. Don't read it as a
different rule.
### The decisive observation: the catalog is group-driven
Every `Hausleitung *` row is emitted with `auswahl="False"` for an account that holds
none of them. So the endpoint does **not** list "the selections this address has" — it
lists **the whole published catalog** and then flags which entries the address holds.
`<selektionsgruppe id="0" bezeichnung="&lt;ohne Gruppe&gt;">` is the bucket for
selections with no (or a `0`) `Selektionsgruppe` membership row.
The practical consequence: **inserting a row into `dbo.Selektionen` can never make a
selection appear.** It can only flip `auswahl` from `False` to `True` on an entry that
the catalog already emits. A selection that is absent from the XML is absent from the
*catalog*, and the assignment is irrelevant until that is fixed.
---
## Query A — reconstruct the response
Run this for the account in question and diff its rows against the actual XML. A clean
match proves the reconstruction above; any mismatch belongs in the caveats section.
```sql
DECLARE @AddressId bigint = 141747;
SELECT COALESCE(sg.IDSelektionsgruppenstamm, 0) AS groupId,
COALESCE(sg.Selektionsgruppe, '<ohne Gruppe>') AS groupLabel,
s.IDSelektionsstamm AS selectionId,
s.Selektion AS selectionLabel,
CASE WHEN s.System = 0 THEN 'True' ELSE 'False' END AS aenderbar,
CASE WHEN sel.IDAdresse_FS IS NULL THEN 'False' ELSE 'True' END AS auswahl
FROM dbo.Selektionsstamm s
LEFT JOIN dbo.Selektionsgruppe sgm
ON sgm.IDSelektionsstamm_FS = s.IDSelektionsstamm
LEFT JOIN dbo.Selektionsgruppenstamm sg
ON sg.IDSelektionsgruppenstamm = sgm.IDSelektionsgruppenstamm_FS
LEFT JOIN dbo.Selektionen sel
ON sel.IDSelektionsstamm_FS = s.IDSelektionsstamm
AND sel.IDAdresse_FS = @AddressId
WHERE COALESCE(s.Status, '') <> 'L'
AND COALESCE(sg.Status, '') <> 'L'
ORDER BY COALESCE(sg.Position, -1), sgm.Position, s.Selektion;
```
(`Status = 'L'` is this database's soft-delete marker — see
`../bpn-connect-query-reference.md`.)
Note the join fans out: a selection can belong to **several** groups (confirmed —
`1292` is in both `10` and `91`), so this query emits one row per membership. The XML
shows a selection once per group it is published in.
`Selektionsgruppenstamm.Ausgrenzung` is *exclusion* semantics (mutually exclusive
group), not visibility — don't mistake it for a publish flag.
---
## Query B — diagnose a selection that never appears
Compares the suspect row against known-good neighbours: `1292`/`1293` (long-standing,
emitted, `aenderbar=False`) and `1462` (most recent one that *is* emitted,
`aenderbar=True`). Whatever column differs is the answer.
```sql
SELECT s.IDSelektionsstamm,
s.Selektion,
s.Status,
s.System,
sgm.IDSelektionsgruppenstamm_FS AS groupId,
sgm.Position AS positionInGroup,
(SELECT COUNT(*) FROM dbo.Selektionen x
WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm
AND x.IDAdresse_FS = 141747) AS assignedToAddress
FROM dbo.Selektionsstamm s
LEFT JOIN dbo.Selektionsgruppe sgm
ON sgm.IDSelektionsstamm_FS = s.IDSelektionsstamm
WHERE s.IDSelektionsstamm IN (1477, 1478, 1292, 1293, 1462)
ORDER BY s.IDSelektionsstamm;
```
### What Query B ruled out (address `141747`, 2026-08-04)
| id | Selektion | Status | System | groupId | posInGroup | assigned |
| --- | --- | --- | --- | --- | --- | --- |
| 1292 | Admin | *(blank)* | 1 | 10 | 33 | 1 |
| 1292 | Admin | *(blank)* | 1 | **91** | 1 | 1 |
| 1293 | Manager | *(blank)* | 1 | **92** | 1 | 1 |
| 1293 | Manager | *(blank)* | 1 | 10 | 34 | 1 |
| 1462 | Hausleitung AGR | *(blank)* | 1 | 10 | 74 | 0 |
| 1477 | Preisrechner | *(blank)* | 1 | 10 | 75 | 0 |
| 1478 | Preisrechner Admin | *(blank)* | 1 | 10 | 76 | 1 |
Three conclusions:
1. **The missing-membership theory is dead.** `1477`/`1478` *are* in group `10` (TEAM),
at positions `75`/`76`, and `1478` *is* assigned to the address. On every column
available in these three tables, `1478` is indistinguishable from `1462` — which the
XML does emit. Whatever excludes them lives **outside**
`Selektionsstamm` / `Selektionsgruppe` / `Selektionen`.
2. **`aenderbar` is not derived from `System`.** `1292` (`aenderbar="False"`) and `1462`
(`aenderbar="True"`) both have `System = 1`. `Selektionsstamm` has no other column,
so `aenderbar` comes from somewhere else entirely.
3. **A selection can belong to several groups, and some groups are not published.**
`1292` is in `10` + `91`, `1293` is in `10` + `92`; groups `91`/`92` appear nowhere in
the XML, which only emits `0`, `10`, `83`. So there is a **group-level publish
filter** — and, suggestively, the two rows with a second (unpublished) group
membership are exactly the two that come back `aenderbar="False"`.
---
## Query D — the agency whitelist (run this first)
`dbo.AgenturSelektionenKunde` is a bare two-column link table,
`(IDAdresse_FS, IDSelektionsstamm_FS)` — literally *"agency's customer selections"*. The
portal authenticates against BusPro as an **agency** account (`bpn_username` in
`ApiClient`), so a per-agency whitelist of which customer selections that agency may see
and/or edit is exactly the right shape. It is the only candidate found so far that could
explain the `1478` omission **and** `aenderbar` through one mechanism.
```sql
SELECT ask.IDAdresse_FS AS agencyAddressId,
a.SuchName AS agencyName,
ask.IDSelektionsstamm_FS AS selectionId,
s.Selektion AS selectionLabel
FROM dbo.AgenturSelektionenKunde ask
JOIN dbo.Selektionsstamm s ON s.IDSelektionsstamm = ask.IDSelektionsstamm_FS
LEFT JOIN dbo.Adresse a ON a.IDAdresse = ask.IDAdresse_FS
ORDER BY ask.IDAdresse_FS, s.Selektion;
-- same shape, same question:
SELECT * FROM dbo.PartnerSelektionenKunde;
```
Compare the row set for the portal's agency address against a freshly captured response:
| Result | Meaning |
| --- | --- |
| set == the 32 emitted entries | **this is the publish gate**`1477`/`1478` just need rows here |
| set == the `aenderbar="True"` subset only | this is the `aenderbar` source |
| set is some third thing | note it in this doc and continue to C1 |
| table empty | both hypotheses dead — fall through to C1/C2/C3 |
**Result (2026-08-04): `dbo.AgenturSelektionenKunde` is empty.** The agency-whitelist
theory is dead. Do not re-run.
---
## Query E — group-count cross-check (the secondary `aenderbar` theory)
Query B hinted that the two `aenderbar="False"` rows were the two with a *second*,
unpublished group membership (`1292`→{10, 91}, `1293`→{10, 92}) while `aenderbar="True"`
`1462` sat in group `10` alone. Two data points is not a rule — this settles it in one run:
```sql
SELECT s.IDSelektionsstamm,
s.Selektion,
COUNT(*) AS groupCount,
STRING_AGG(CAST(sgm.IDSelektionsgruppenstamm_FS AS varchar(10)), ',') AS groupIds
FROM dbo.Selektionsstamm s
JOIN dbo.Selektionsgruppe sgm ON sgm.IDSelektionsstamm_FS = s.IDSelektionsstamm
WHERE s.IDSelektionsstamm IN (1064,1065,1066,1067,1068,1069,1070,1156,1292,1293,
1299,1304,1377,1459,1461,1462,1477,1478)
GROUP BY s.IDSelektionsstamm, s.Selektion
ORDER BY s.IDSelektionsstamm;
```
Read against the known `aenderbar` values from the reference response:
- `aenderbar="False"`: `1070`, `1156`, `1292`, `1293`, `1299`, `1304`, `1377`
- `aenderbar="True"`: `1064``1069`, `1459`, `1461`, `1462`
If every `False` row has `groupCount > 1` and every `True` row has `groupCount = 1`, the
theory holds. Note it still would not explain `1478` (group `10` only, yet omitted), so
Query D remains the priority.
**Result (2026-08-04): the theory is dead.** Group membership does not correlate with
`aenderbar` at all:
| id | Selektion | groupCount | groupIds | `aenderbar` |
| --- | --- | --- | --- | --- |
| 10641069 | *Interessen* | 1 | 83 | **True** |
| 1070 | E&P Teamer - allg. Merkmal | 1 | 10 | **False** |
| 1292 | Admin | 2 | 91, 10 | **False** |
| 1293 | Manager | 2 | 92, 10 | **False** |
| 1299 / 1304 / 1377 | Hausleitung SSL / DKS / KHH | 1 | 10 | **False** |
| 1459 / 1461 / 1462 | Hausleitung SVS / SHM / AGR | 1 | 10 | **True** |
| 1477 / 1478 | Preisrechner, Preisrechner Admin | 1 | 10 | *(not emitted)* |
`1299`/`1304`/`1377` and `1459`/`1461`/`1462` have **identical** group membership,
identical `Status`, identical `System` — and opposite `aenderbar`. The `1292`/`1293`
double membership was a coincidence.
Confirmed as a side effect: `1156` is absent from this result because the inner join
found no `Selektionsgruppe` row for it. `<ohne Gruppe>` really does mean "no membership
row", as modelled at the top of this document.
---
## Query F — exhaust every remaining link to `Selektionsstamm`
After D and E, the schema export lists exactly these tables with an FK into
`Selektionsstamm`. This counts all of them at once for the rows whose behaviour differs,
which is the last thing the database can tell us:
```sql
SELECT s.IDSelektionsstamm, s.Selektion,
(SELECT COUNT(*) FROM dbo.Selektionen x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS addressAssignments,
(SELECT COUNT(*) FROM dbo.PartnerSelektionenKunde x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS partnerLinks,
(SELECT COUNT(*) FROM dbo.LeistungSelektionenKunde x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS serviceLinks,
(SELECT COUNT(*) FROM dbo.ReiseleiterSelektionen x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS guideLinks,
(SELECT COUNT(*) FROM dbo.ReiseSelektionen x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS travelLinks,
(SELECT COUNT(*) FROM dbo.ReisezielSelektionsstamm x WHERE x.IDSelektionsstamm_FS = s.IDSelektionsstamm) AS destinationLinks
FROM dbo.Selektionsstamm s
WHERE s.IDSelektionsstamm IN (1070,1156,1292,1293,1299,1304,1377,1459,1461,1462,1477,1478,1064)
ORDER BY s.IDSelektionsstamm;
```
The decisive comparison is `1377` (`aenderbar="False"`) vs `1462` (`"True"`) vs `1478`
(omitted). If all three rows are identical here too, then **no per-selection property in
this database distinguishes them**, and the rule is not in the schema at all — go to
"Where this leaves the investigation" below.
**Result (2026-08-04): all link counts are zero** for every row queried, except
`travelLinks` on `1070` (11) and `1156` (3) via `ReiseSelektionen` — neither of which
correlates with `aenderbar` or with being emitted. Assignment counts don't explain
anything either:
| id | assignments | emitted? | `aenderbar` |
| --- | --- | --- | --- |
| 1377 Hausleitung KHH | **0** | yes | False |
| 1462 Hausleitung AGR | 1 | yes | True |
| 1478 Preisrechner Admin | **3** | **no** | — |
`1377` is published with zero assignments; `1478` has three and is not published. This
exhausts every FK path into `Selektionsstamm` in the schema. **Stop querying the
database** — the answer is not in it.
---
## Query C — locate the publish gate
Point (1) means some table or config outside the three core tables decides what gets
emitted. Run these in order; the first hit explains everything.
**C1 — what distinguishes a published group from an unpublished one.** Groups `0`, `10`,
`83` are emitted; `91`, `92` are not:
```sql
SELECT IDSelektionsgruppenstamm, Selektionsgruppe, Status, System, Ausgrenzung, Position
FROM dbo.Selektionsgruppenstamm
ORDER BY Position;
```
If exactly the emitted groups share a `Status`/`System`/`Position` value that `91`/`92`
lack, that's the group gate. It still won't explain `1478` (same group as `1462`), but
it pins down half the rule — and tells you whether `aenderbar` tracks membership in one
of these system groups.
**C2 — hunt for a published-selection whitelist in the config stores.** This is the
leading theory for `1478`: a config value enumerating exposed selection ids that was
maintained up to `1462` and never extended. This database does store id lists in
delimited string columns (`CRMAktion.IDsAgenturEingrenzung`,
`ImportAdressen.ZuweisungSelektionIDs`, `AdresseHistorie.SelektionsIDs`), so the pattern
exists. Search for a known-published id:
```sql
SELECT * FROM dbo.Einstellung
WHERE Wert LIKE '%1462%' OR Wert LIKE '%1292%'
OR Bezeichnung LIKE '%elektion%' OR Beschreibung LIKE '%elektion%';
SELECT * FROM dbo.ProgrammEinstellung
WHERE Wert LIKE '%1462%' OR Wert LIKE '%1292%' OR Variable LIKE '%elektion%';
SELECT * FROM dbo.ConnectEinstellung
WHERE WertString LIKE '%1462%' OR WertString LIKE '%1292%';
```
**C3 — brute-force the whole schema** if C1/C2 come up empty. Find every wide text
column that mentions a published selection id:
```sql
DECLARE @needle nvarchar(20) = '1462';
DECLARE @sql nvarchar(max) = '';
SELECT @sql = @sql + 'SELECT ''' + QUOTENAME(t.name) + ''' AS tbl, ''' + QUOTENAME(c.name)
+ ''' AS col, COUNT(*) AS hits FROM dbo.' + QUOTENAME(t.name)
+ ' WHERE CAST(' + QUOTENAME(c.name) + ' AS nvarchar(max)) LIKE ''%'
+ @needle + '%'' HAVING COUNT(*) > 0;' + CHAR(10)
FROM sys.tables t
JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types ty ON ty.user_type_id = c.user_type_id
WHERE ty.name IN ('nvarchar', 'varchar', 'nchar', 'char')
AND (c.max_length = -1 OR c.max_length >= 100)
AND t.name NOT LIKE 'Selektion%';
EXEC sp_executesql @sql; -- read-only; slow, run off-peak
```
**C4 — rule out staleness/caching first, it's free.** `1478` is structurally identical
to an emitted row, which is also what a cached catalog looks like. Re-fetch the XML now
and confirm the sample postdates the insert:
```php
// bin/console or a scratch script
$client->getCrmAttributes($email, $password);
```
If BusPro caches the catalog in-process, an application-pool/service restart on the
BusProNet host is the fix, and no schema change is needed.
---
## Portal side: a correct XML is not enough
`BpnAuthenticator::createOrUpdateLocalUser()` snapshots the roles onto the local `User`
entity at login (`setRoles($crmAttributes->roles)` /
`setHotelCodes($crmAttributes->hotelCodes)`). Roles are **not** re-read per request. So
after fixing BusPro the affected user must **log out and log in again** before
`ROLE_GROUPS_ADMIN` takes effect — an active session keeps the stale role set.
---
## Where this leaves the investigation
**Conclusion as of 2026-08-04, after Queries AF: the schema search is exhausted.**
- `1478` and `1462` are identical on every column and every link the schema exposes —
same blank `Status`, same `System = 1`, same single membership in group `10`, adjacent
positions (76 vs 74), zero links in all five side tables. `1462` is emitted, `1478` is
not.
- `1377` (`aenderbar="False"`) and `1462` (`"True"`) are identical by the same measure.
Opposite flag.
- Assignment count is not it either: `1377` is published with zero assignments, `1478`
has three and is not published.
Rows that are indistinguishable in the database behave differently in the response. Every
column of the three core tables, every FK path into `Selektionsstamm`, and a
whole-schema column-name search have now been checked. So **the publish set and the
`aenderbar` flag are not derived from this database** — they live in the BusProNet
service layer: its own configuration, or an in-process cache of the catalog.
Only C2/C3 (a text search of the config stores, then of every wide text column) remain,
and they are long shots. Prefer the escalation path below.
Escalation path, cheapest first:
1. **Re-fetch and confirm staleness.** Our side does not cache this call — the
`xml-sync` cache tag covers the XML *export* sync, and `ApiClient::getCrmAttributes()`
has no cache layer — so a fresh login hits BusPro directly. If `1478` is still absent
from a response captured after the insert, the staleness is on the BusProNet host and
an application-pool/service restart there is the test.
2. **The UI experiment.** Create a throwaway selection in the TEAM group *through the
BusPro UI*, then diff its rows against `1478` across `Selektionsstamm` /
`Selektionsgruppe` / `Selektionen`. If it appears in the XML, the diff names exactly
what a manual `INSERT` misses. If it does not, the gate is provably config/cache and
not per-row data.
3. **Ask the vendor.** "What determines which `Selektionsstamm` entries `SelektionCRM`
publishes, given group membership is not sufficient — and what drives `aenderbar`?"
Both are one-sentence answers for them and may not be discoverable from the schema at
all. Worth bundling into the open BPN thread.
## Caveats
- **`aenderbar` has no known source.** No such column exists in any of the 1023 tables;
`Selektionsstamm.System` (Query B), the agency whitelist (Query D) and group membership
(Query E) are all falsified. Treat it as unmodellable in a `bpn-connect` endpoint until
the vendor explains it — if `bpn-connect` must serve this response, the safe move is to
keep `SelektionCRM` on the socket API rather than guess, exactly as
`live-api-queries.md` recommends for `getMutableData()`.
- Groups `91` and `92` are known to exist and are never emitted; what they are is still
unexplained (Query C1). Record the answer here when you have it.
- **The publish gate is not identified.** Group membership is necessary but not
sufficient: `1478` sits in the published TEAM group with an assignment and is still
omitted. Query C is the open investigation.
- Consequently Query A **over-reports**: it will return `1477`/`1478` (and anything in
groups `91`/`92`) that the real XML omits. It reconstructs the shape of the response,
not yet its exact membership.
- `dbo.Selektionen` has no status column and no exported primary key, so a duplicate
assignment row may well be insertable. Check before inserting.
- The schema exports carry no PK/index catalog (noted in
`../bpn-connect-query-reference.md`); none of the queries here are
performance-sensitive, but a `bpn-connect` endpoint built on them would want indexes
on `Selektionen.IDAdresse_FS` and `Selektionsgruppe.IDSelektionsstamm_FS` confirmed.
- `Adresse` vs. `AdressePerson`: assignments hang off `IDAdresse`, not `IDPerson`.
+165
View File
@@ -0,0 +1,165 @@
# Live socket-API endpoints — direct-MSSQL feasibility & queries
> **Authority: [`docs/buspro-database-reference.md`](../buspro-database-reference.md).**
> Schema semantics live there and win on any conflict. This file is retained for the
> per-endpoint migration verdicts and the `frei` discovery SQL.
This complements `travel-queries.md`. That doc replaced the **XML export** (static
catalog). This one covers the **live socket API** methods on
`src/BusProNet/ApiClient.php` and classifies how replicable each is by direct MSSQL
query in the Go proxy.
**Verdict in one line:** the *structural* parts replicate cleanly; the *live "free"
counts* are computed by BusPro's allocation logic (not a flat column) and should either
stay on the socket API or be reproduced with an explicitly-approximated query;
`getMutableData()` is pure business-rule logic — keep it on the socket API.
| Endpoint (type) | Tier | Replicable in SQL? |
|---|---|---|
| `getProducts()` (`PRODUKTE`) | 1 | ✅ trivial |
| `getAgencies()` (`AGENTUREN`) | 1 | ✅ structural (confirm agency filter + address joins) |
| `getTravelData()` (`PRODUKTDATEN`) | 1 | ✅ = `travel-queries.md` Query B |
| `getAvailabilities()` (`VERFUEGBARKEIT`) | 2 | ⚠ structure yes; `frei` count is computed |
| `getAvailabilitiesExtended()` (`VERFUEGBARKEIT2`) | 2 | ⚠ structure yes (we have the extra fields); `frei` computed |
| `getHotelAvailability()` (`VERFUEGBARKEITHOTEL`) | 2 | ⚠ `frei` = contingent active bookings |
| `getMutableData()` (`MOEGLICHEAENDERUNGEN`) | 3 | ✋ business rules — keep on socket API |
---
## Tier 1 — structural, replicate as-is
### `getProducts()` → `Product{id, code, name}`
Parser keeps only rows with a non-empty `code` (`ProductsParser`).
```sql
SELECT IDProdukt AS id, Code AS code, Bezeichnung AS name
FROM dbo.Produkt
WHERE Code IS NOT NULL AND Code <> ''
ORDER BY Bezeichnung;
```
### `getTravelData(idprodukt[, hotelId])` → `Travel`
This is the same payload as `travel-queries.md` **Query B** (header + services +
pickups + hotels/rooms + tags). The *static* structure is fully covered there. Its
embedded live `preis`/`frei` values overlap Tier 2 — source those the same way you
decide to handle availability below. No new SQL needed; reuse Query B.
### `getAgencies()` → `Agency{id, name, code, street, postCode, city, phone}`
`name/code` map to `Adresse.SuchName` + a code column; `street/postCode/city` live in
`AdresseAnschrift`, `phone` in `AdresseKommunikation` (1-to-N → pick the primary row).
Two things to pin with the discovery queries below: (1) **which `Adresse` rows are
agencies**, and (2) the exact `AdresseAnschrift`/`AdresseKommunikation` column + primary-row flag.
```sql
-- skeleton (fill the agency filter + verified column names from discovery):
SELECT a.IDAdresse AS id,
a.SuchName AS name,
a.Code AS code, -- ⚠ confirm code column on Adresse
an.Strasse AS street, -- ⚠ from AdresseAnschrift
an.Plz AS postCode,
an.Ort AS city,
ak.Wert AS phone -- ⚠ from AdresseKommunikation (primary tel)
FROM dbo.Adresse a
LEFT JOIN dbo.AdresseAnschrift an ON an.IDAdresse_FS = a.IDAdresse /* AND an.IsPrimary */
LEFT JOIN dbo.AdresseKommunikation ak ON ak.IDAdresse_FS = a.IDAdresse /* AND ak.Art = 'TEL' */
WHERE /* a is an agency — see discovery */ 1 = 0;
```
Discovery:
```sql
-- (1) how agencies are flagged (inspect the org/role tables):
SELECT TOP 20 * FROM dbo.AdresseAgenturOrganisation;
SELECT IDArtAgenturOrganisation, * FROM dbo.ArtAgenturOrganisation; -- the agency "types"
-- (2) the address + comm column names / primary-row flags:
SELECT TOP 5 * FROM dbo.AdresseAnschrift;
SELECT TOP 5 * FROM dbo.AdresseKommunikation;
SELECT TOP 5 * FROM dbo.Adresse; -- find the 'code' column
```
---
## Tier 2 — availability: structure is flat, the **`frei` count is computed**
The response models (`Availability`, `ExtendedAvailability`, `Room`) carry per-item
`status`, `preis`, structural attrs (dates/ages/mandatory/board) **and** `frei`. The
first set is a flat read; **`frei` is not stored**.
**Why `frei` is computed (validated):** `Leistung.Kontingent` is a fixed planning
allotment, not the remaining free count — e.g. service `155234` has `Kontingent=2500`
but `2945` booking rows (bookings *exceed* the allotment). So:
```
frei = Kontingent (active, non-cancelled, non-expired bookings) [± pooled contingent]
```
with three real complications:
- **Cancellations**: `BuchungTNLeistung` has no own status; join up via `IDBuchungTN_FS`
`BuchungTN``Buchung` and exclude Storno (the `BuchungStatus*` flags / Storno date).
- **Option expiry**: `BuchungTNLeistung.OptionsDatum` + `Leistung.KontingentVerfallTage`
— expired options free their slots back.
- **Pooled contingents**: `Leistung.IDLeistung_FS_KontingentAUS` / `KontingentAusPartner`
— a service may draw from another service's pool (or a `PartnerKontingent`), so its
`frei` depends on a sibling, not just its own bookings.
> **Recommendation:** keep the *authoritative* `frei` on the socket API
> (`getAvailabilities`/`getHotelAvailability`). If you want it in SQL, treat it as a
> documented **approximation** and validate row-by-row against the socket API before
> trusting it for booking decisions. The structural fields below are safe to serve from SQL.
### `getAvailabilities()` / `getAvailabilitiesExtended()` — structural part
```sql
SELECT
l.IDLeistung AS serviceId,
l.Status AS status,
lp.Preis AS price,
l.Kontingent AS allotment, -- NOT 'frei' (see calc above)
-- extended-only fields (VERFUEGBARKEIT2):
l.Termin_VON AS dateFrom, l.Termin_BIS AS dateTo,
l.Alter_VON AS ageFrom, l.Alter_BIS AS ageTo,
l.Pflichtmerkmal AS mandatory
FROM dbo.ReiseLeistung rl
JOIN dbo.Leistung l ON l.IDLeistung = rl.IDLeistung_FS
LEFT JOIN dbo.LeistungPreis lp ON lp.IDLeistung_FS = l.IDLeistung AND lp.IDArtPreisSchema_FS = 1
WHERE rl.IDReise_FS = @DateId
ORDER BY l.Art, l.Unterart;
-- travel-level 'buchungstatusmoeglich' / 'status' come from the Reise + the allowed
-- ArtBuchungsStatus set; the extended 'uhrzeit_von'/'hinweis' come from the pickup
-- time plan (ZustiegZeitplan) and a Leistung text — see travel-queries.md B2/B2b.
```
The live `frei` per `serviceId` = the calc above (see recommendation).
### `getHotelAvailability(idreise, idpartner, terminbis)` → `Room{frei, status, preis, …}`
Rooms/price/`status` are the `travel-queries.md` **B3** chain;
`status` = `PartnerKontingent.BuchungsStatus` (`''`/`S`/`A`). `frei` = `PartnerKontingent.Anzahl`
**minus active hotel bookings** for that `(IDAdresse, IDZimmer, date-span)` — same
cancellation/expiry caveats as above.
### Discovery — quantify the `frei` calc against the socket API
```sql
-- active (non-storno) booking rows for a service, with option dates:
SELECT btl.IDLeistung_FS, COUNT(*) AS rows_total,
SUM(CASE WHEN btl.OptionsDatum IS NULL OR btl.OptionsDatum >= GETDATE() THEN 1 ELSE 0 END) AS rows_live
FROM dbo.BuchungTNLeistung btl
JOIN dbo.BuchungTN bt ON bt.IDBuchungTN = btl.IDBuchungTN_FS
JOIN dbo.Buchung b ON b.IDBuchung = bt.IDBuchung_FS -- ⚠ confirm FK name
WHERE btl.IDLeistung_FS = @ServiceId
/* AND b.<storno flag> = 0 */ -- ⚠ confirm Storno column
GROUP BY btl.IDLeistung_FS;
-- then compare Leistung.Kontingent rows_live vs the socket-API 'frei' for the same service.
```
---
## Tier 3 — `getMutableData()` — keep on the socket API
Returns per-aspect `möglich` (bool) + `möglichbiszum` (deadline) for: participant
count, transportation, pickup, accommodation, additional services, participant data.
These are **derived from booking rules / change-cutoff config / departure timing**
(not a flat table). Reproducing them in SQL would mean re-implementing BusPro's
change-deadline logic and risks silent divergence. Recommendation: leave this on the
socket API; don't migrate it.
---
## Summary for the Go proxy
- **Migrate now (SQL):** `getProducts`, `getAgencies` (after the agency-filter discovery),
`getTravelData` (reuse Query B), and the **structural** fields of the two availability
endpoints.
- **Keep computed:** the live `frei` counts — socket API, or an explicitly-validated
approximation.
- **Keep on socket:** `getMutableData`.
@@ -0,0 +1,247 @@
# Schema refresh & Zustieg-pricing verification queries
> **Superseded by [`docs/buspro-database-reference.md`](../buspro-database-reference.md) §12**,
> which carries the refresh queries and the verification log. Retained only for the
> 2026-08-04 run detail; safe to delete once that is no longer of interest.
Read-only queries to (a) check whether the June schema dump still matches
production after a BusPro update, (b) regenerate it if not, and (c) resolve the
open `Abfahrtsortzuschlag (Rückfahrt)` question from the database side.
Current dump: `BusPronet_20260601-1517.csv` (columns),
`BusPronet_20260601-1518.csv` (foreign keys), exported 2026-06-01.
**All queries are `SELECT`-only.** Run in order — Query 1 decides whether 24 are
needed at all.
---
## 1. Drift check — run this first
Cheapest, highest signal. If it returns nothing, the June dump is still accurate
and the re-export can be skipped.
```sql
SELECT s.name AS schema_name, o.name AS object_name, o.type_desc,
o.create_date, o.modify_date
FROM sys.objects o
JOIN sys.schemas s ON s.schema_id = o.schema_id
WHERE o.is_ms_shipped = 0
AND (o.create_date > '2026-06-01' OR o.modify_date > '2026-06-01')
ORDER BY o.modify_date DESC;
```
Note: `modify_date` moves on metadata changes, so a long list is expected after a
version upgrade. What matters is whether anything under `Zustieg*`, `Leistung*`,
`Buchung*` appears.
**Result 2026-08-04.** Every object reports `create_date` **2026-06-03** — the
database was restored/rebuilt that day, so `create_date` is a restore artifact and
the `> '2026-06-01'` filter matches everything. Use `modify_date` after the restore
instead. Only two genuine clusters exist:
- **2026-06-11** — six new tables, all absent from `…-1517.csv`: `Reichweite`,
`ReichweiteZeitraum`, `ReichweiteZeitraumVonBis`, `ReichweiteRestFarbe`,
`LadungTankungBetriebshof`, `ConnectViafintechSlip`.
- **2026-07-02** — modified: `Tachostand`, `GutscheinAktion`,
`AdressePersonalZusatz`, `BlockPlanung`, `Block`, `LeistungZusatz`,
`ConnectViafintechSlip`, `TourPlanung`.
**Nothing under `Zustieg*`, `ZustiegPreis`, `ArtZustiegPreis`,
`LeistungBefoerderung` or `BuchungTNZuschlag` changed after the restore.** The June
dump is accurate for the booking and boarding areas; the only staleness is the six
fleet/payment tables above. For future runs, filter on `o.modify_date > '2026-06-03'`
to skip the restore baseline.
---
## 2. Columns — regenerates `…-1517.csv`
Column order and names match the existing header exactly, so the output is a
drop-in replacement. Export semicolon-separated with quoted values, same settings
as the June file.
```sql
SELECT s.name AS schema_name,
t.name AS table_name,
c.name AS column_name,
ty.name AS data_type,
c.max_length,
c.precision,
c.scale,
c.is_nullable,
c.is_identity,
dc.definition AS default_definition
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.columns c ON c.object_id = t.object_id
JOIN sys.types ty ON ty.user_type_id = c.user_type_id
LEFT JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id
ORDER BY t.name, c.column_id;
```
## 3. Foreign keys — regenerates `…-1518.csv`
```sql
SELECT fk.name AS foreign_key_name,
cs.name AS child_schema, ct.name AS child_table, cc.name AS child_column,
ps.name AS parent_schema, pt.name AS parent_table, pc.name AS parent_column
FROM sys.foreign_keys fk
JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
JOIN sys.tables ct ON ct.object_id = fkc.parent_object_id
JOIN sys.schemas cs ON cs.schema_id = ct.schema_id
JOIN sys.columns cc ON cc.object_id = fkc.parent_object_id
AND cc.column_id = fkc.parent_column_id
JOIN sys.tables pt ON pt.object_id = fkc.referenced_object_id
JOIN sys.schemas ps ON ps.schema_id = pt.schema_id
JOIN sys.columns pc ON pc.object_id = fkc.referenced_object_id
AND pc.column_id = fkc.referenced_column_id
ORDER BY ct.name, fk.name, fkc.constraint_column_id;
```
## 4. Primary keys & indexes — the documented gap
`bpn-connect-query-reference.md` records that PK/index data was expected but
missing, and that identity flags are not a reliable PK substitute here. This closes
it. Suggested filename: `BusPronet_<date>-pk-index.csv`.
```sql
SELECT s.name AS schema_name,
t.name AS table_name,
i.name AS index_name,
i.type_desc,
i.is_primary_key,
i.is_unique,
i.is_unique_constraint,
ic.key_ordinal,
c.name AS column_name,
ic.is_included_column,
ic.is_descending_key
FROM sys.indexes i
JOIN sys.tables t ON t.object_id = i.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE i.type > 0 -- exclude heaps
ORDER BY t.name, i.is_primary_key DESC, i.name, ic.key_ordinal;
```
---
## 5. Boarding-price types — `ArtZustiegPreis`
**Answered 2026-08-04:** this is a **tariff-scheme** lookup, *not* a direction
lookup. Active schemes are 36 `Woche26/27`, 37 `WE26/27`, 38 `Event26/27`,
39 `SER26/27` (plus legacy AT at `Status = 'L'`). There is no Hinfahrt/Rückfahrt
concept in this table.
```sql
SELECT IDArtZustiegPreis, Code, Kurztext, Langtext, Status, Hierarchie
FROM dbo.ArtZustiegPreis
ORDER BY Hierarchie, IDArtZustiegPreis;
```
## 6. Configured prices for boarding point 18
```sql
SELECT zp.IDZustiegPreis,
zp.IDZustieg_FS,
z.Zustiegcode, z.Ort, z.Plz,
zp.IDArtZustiegPreis_FS,
ap.Code AS PreisArtCode, ap.Kurztext AS PreisArt,
zp.Preis, zp.PreisProvisionPflichtig,
zp.Sockelbetrag, zp.SockelbetragProvisionPflichtig
FROM dbo.ZustiegPreis zp
JOIN dbo.Zustieg z ON z.IDZustieg = zp.IDZustieg_FS
LEFT JOIN dbo.ArtZustiegPreis ap ON ap.IDArtZustiegPreis = zp.IDArtZustiegPreis_FS
WHERE zp.IDZustieg_FS = 18
ORDER BY zp.IDArtZustiegPreis_FS;
```
**Answered 2026-08-04:** three rows for point 18 (`ESS-Route`, Essen), one per
active tariff scheme — 36 → **17,90**, 37 → 12,90, 38 → 19,90. Prices are keyed by
(point, tariff scheme), **not** by direction. The export's
`<zustiege_rueck preis="17,90">` is therefore the same row surfaced through the
return service, not a separately configured return price.
## 7. How the two bus services resolve their boarding price — the mechanism
`LeistungBefoerderung` carries **`IDArtZustiegPreis_FS`** and
**`Richtung_Hin_Rueck`**, so each transport service selects which price type
applies. This query shows what outbound service 194779 and return service 194776
are configured to use.
```sql
SELECT l.IDLeistung, l.Bezeichnung, l.Art, l.Unterart,
lb.Richtung_Hin_Rueck,
lb.IDArtZustiegPreis_FS,
ap.Code AS PreisArtCode, ap.Kurztext AS PreisArt,
lb.IDArtZustiegZeitplan_FS,
lb.ZustiegeGesperrt,
lb.IDZustieg_FS_Basisstelle,
lb.ZustiegIDs
FROM dbo.LeistungBefoerderung lb
JOIN dbo.Leistung l ON l.IDLeistung = lb.IDLeistung_FS
LEFT JOIN dbo.ArtZustiegPreis ap ON ap.IDArtZustiegPreis = lb.IDArtZustiegPreis_FS
WHERE l.IDLeistung IN (194779, 194776);
```
**Answered 2026-08-04 — configuration is symmetric, config cause excluded:**
| Leistung | Richtung | `IDArtZustiegPreis_FS` | `ZustiegeGesperrt` | `ZustiegIDs` |
|---|---|---|---|---|
| 194779 Bus-Hinfahrt | H | 36 (Woche26/27) | 0 | 3,4,18,86,320,470,473 |
| 194776 Bus-Rückfahrt | R | 36 (Woche26/27) | 0 | 3,4,18,86,320,470,473 |
Both legs resolve to the same 17,90 and both have point 18 enabled. The differing
BusPro behaviour is therefore not explained by product configuration.
## 8. Surcharge types — `ArtZuschlag`
**Answered 2026-08-04:** a discounts/fees lookup (Zwei-Wochen-Rabatt,
Kinderermäßigung, Bearbeitungsgebühr, Preiskorrektur, …). No direction concept and
**no `Abfahrtsortzuschlag` entry** — so the `SON`/`TRA` positions in the booking
response are computed transport surcharges, not `BuchungTNZuschlag` rows. Query 9
below is aimed at the wrong table and can be skipped.
```sql
SELECT IDArtZuschlag, Code, Kurztext, Langtext, Status, Hierarchie
FROM dbo.ArtZuschlag
ORDER BY Hierarchie, IDArtZuschlag;
```
## 9. Booked surcharge rows for an affected booking
The decisive one *if* a completed booking exhibiting the fault is available: does
the working booking persist two `BuchungTNZuschlag` rows and the failing one only
one?
```sql
SELECT b.Vorgang,
tn.IDBuchungTN,
z.IDBuchungTNZuschlag,
z.BZText, z.Text,
z.Art,
z.IDZustieg_FS,
az.Code AS ZuschlagArtCode, az.Kurztext AS ZuschlagArt,
z.BZPreisMitProvision, z.BZPreisOhneProvision
FROM dbo.BuchungTNZuschlag z
JOIN dbo.BuchungTN tn ON tn.IDBuchungTN = z.IDBuchungTN_FS
JOIN dbo.Buchung b ON b.IDBuchung = tn.IDBuchung_FS
LEFT JOIN dbo.ArtZuschlag az ON az.IDArtZuschlag = z.IDArtZuschlag_FS
WHERE b.Vorgang IN ('<Vorgang-1>', '<Vorgang-2>')
ORDER BY b.Vorgang, tn.IDBuchungTN, z.IDBuchungTNZuschlag;
```
**Caveat:** both captured cases were `<buchungsart>Anfrage</buchungsart>` inquiries,
and our flow only commits at step 4 — so these rows may not exist for them. Use the
`Vorgang` of an actually completed booking that showed the short total. If none
exists, skip this query; queries 57 carry the argument on their own.
---
## What to send back
Query 1's result, plus 5, 6, 7 and 8 as plain result sets — those four are small and
answer the pricing question directly. Queries 24 only if query 1 shows drift, as
CSV files replacing the ones in this directory.
+305
View File
@@ -0,0 +1,305 @@
# Travel catalog — direct MSSQL queries (to replace the XML export)
> **Authority: [`docs/buspro-database-reference.md`](../buspro-database-reference.md).**
> Schema semantics, conventions and confidence marks live there and win on any conflict.
> This file is retained as a **query cookbook** — it holds worked SQL (included-services
> A2a/A2b, the full room-pricing chain B3) not reproduced in the reference.
Purpose: reproduce, straight from the BusPro MSSQL tables, the data the Symfony app
currently parses from the `Ziel_*.xml` exports, so the Go proxy can serve it without
the SFTP/XML round-trip. Two read paths:
- **Query A — travel list:** every bookable departure + product + dates (+ hotels,
+ a minimal bookable-services list).
- **Query B — detail:** everything for one selected `(date, hotel)` combination.
Validated against the live DB using the sample `var/xmlexport/Ziel_1121.xml`
(Produkt `1121`, departure `Reise.IDReise=12665`, hotel `Adresse.IDAdresse=224923`,
room-type `Zimmerart 1413`, pickup `Zustieg 494`). Columns verified in
`docs/buspronet-schema/*.csv`. Header, services, pickups, hotels, room pricing,
availability and tags are all confirmed against live data; the "included services"
list for Query A (§A2) is defined as price-`0.00` services + the 10 hardcoded
"Leistungen" selection groups (ids baked in). Nothing left to resolve.
## The naming trap (read first)
The XML export **renames** the core entities — do not map by name:
| XML term | Real table | Notes |
|---|---|---|
| `<reise idbuspro=1121>` | **`Produkt`** | the travel *product*: `IDProdukt`, `Code`, `Bezeichnung` |
| `<termin idprodukt=1121 idbuspro=12665>` | **`Reise`** | the **dated departure**: `IDReise=12665`, `IDProdukt_FS=1121`, `Code`, `TerminVon/Bis`, `ReiseArt`, `Status`, `StornoDatum` |
| DB `Termin` table | — | **ignore**: generic appointments (odometer/repairs) |
| `<leistung>` (lei_befoerderung / lei_sonstiges) | `ReiseLeistung → Leistung` | `Leistung.Art` = `BEF` / `SON`; price via `LeistungPreis` |
| `<hotel idbuspro=224923>` + rooms | `ReisePartner` (+ `Partner*` subsystem) | **not** `ReiseLeistung`; keyed by the hotel `Adresse` |
| `<zustieg>` | `LeistungBefoerderung.ZustiegIDs``Zustieg` (+ `ZustiegZeitplan` for the time) | |
| `<selektion>` / `<selektiongruppe>` | `ReiseSelektionen → Selektionsstamm` (+ `Selektionsgruppe → Selektionsgruppenstamm`) | |
`Produkt 1—N Reise`. **`Reise.IDReise` is the "date id"** and the anchor for all
per-departure data.
**Two distinct status axes** — don't conflate them:
1. **Departure lifecycle**`Reise.Status` (`nvarchar(2)`), observed `''` ≈ 9767,
`S` ≈ 945, `L` ≈ 845. Confirmed against the live DB:
- `''` = active/bookable.
- `S` = **Storno** (cancelled): every `S` row has `StornoDatum` set.
- `L` = **template / future master** (not a real sellable departure): every `L`
row has `StornoDatum NULL`, far-future `TerminVon` (20292035) and template-style
`Code`s (`MRAGRMP`, no date suffix). `Leistung.Status` mirrors this (`''` = 196 504,
`L` = 1 672 — the leistungen attached to those template departures).
2. **Availability / booking status** — booking-state codes, **not** `Leistung.Status`
(which only holds `''`/`L`). Canonical dictionary = **`dbo.ArtBuchungsStatus`**
(`Code`), confirmed values:
| Code | Kurztext | meaning |
|---|---|---|
| `F` | Fest | firm/final booking (available) |
| `O` | Option | held option |
| `A` | Anfrage | on request / inquiry-only (groups-inquiry path) |
| `W` | Warteliste | waitlist |
| `S` | Storno | cancelled |
| `U` | Umbuchung | rebooking |
The **working column** for hotel availability is **`PartnerKontingent.BuchungsStatus`**
(`nvarchar(2)`) — confirmed to carry these: observed `''` ≈ 19 664 (free/Fest),
`S` ≈ 12 215 (stop), `A` ≈ 2 060 (on request). So per room/date: `''` = bookable,
`S` = not bookable, `A` = inquiry-only. (The same codes also appear via
`…IDArtBuchungsstatus_FS` on individual bookings such as `ZusatzZimmer`.) Transport
`<status_hin>`/`<status_rueck>` is not in `Leistung.Status`; treat it as derived from
the transport `Kontingent` count.
Bookable filter (departure-level): `Reise.Status = '' AND Reise.StornoDatum IS NULL`
(excludes both `S` Storno and `L` templates), then apply `PartnerKontingent.BuchungsStatus`
per room/date (exclude `S`, treat `A` as inquiry-only).
Note the XML repeats `lei_sonstiges` under each hotel; in the DB the services exist
**once** on the departure (`ReiseLeistung`).
Conventions: ids `bigint``int64`; prices `decimal(18,2)`; `_FS` = foreign key (many
soft/unenforced — join defensively); bracket non-ASCII columns (`[Reisebüro]`).
---
## Query A — travel list
### A1. Departures + product + dates (header)
```sql
SELECT
p.IDProdukt AS ProductId, p.Code AS ProductCode, p.Bezeichnung AS ProductLabel,
r.IDReise AS DateId, r.Code AS DateCode,
r.ReiseArt AS TravelType, -- XML reiseart, e.g. 'F'
r.Bezeichnung AS DateLabel,
r.TerminVon AS DateFrom, r.TerminBis AS DateTo
FROM dbo.Reise AS r
JOIN dbo.Produkt AS p ON p.IDProdukt = r.IDProdukt_FS
WHERE r.Status = '' AND r.StornoDatum IS NULL -- bookable (confirm status codes)
ORDER BY r.TerminVon, p.Code;
```
Customer description (XML `<text>`) = `dbo.ReiseText.ExternText` (`IDReise_FS`) — join if wanted.
### A2. Included-services list per departure
"Minimum services" = the **included** services (no surcharge), from two sources that
get merged into one plain list per departure.
**A2a — included `Leistung`s (sales price = 0.00).** Priced services are optional
add-ons; the package-included ones have a `0.00` sales price (schema 1).
```sql
SELECT
rl.IDReise_FS AS DateId,
l.IDLeistung AS ServiceId,
l.Art AS Type, -- 'BEF' (transport) | 'SON' (other)
l.Unterart AS SubType, -- BUS/PKW/SPA/VER/SON/LVS/...
l.Bezeichnung AS Label
FROM dbo.ReiseLeistung rl
JOIN dbo.Leistung l ON l.IDLeistung = rl.IDLeistung_FS
JOIN dbo.LeistungPreis lp ON lp.IDLeistung_FS = l.IDLeistung
AND lp.IDArtPreisSchema_FS = 1 -- standard sales price (confirmed)
WHERE rl.IDReise_FS IN (@DateIds)
AND lp.Preis = 0.00 -- included = no surcharge
ORDER BY rl.IDReise_FS, l.Art, l.Unterart;
```
> Note: a `LEFT JOIN` would also surface services with **no** price row (NULL). Those
> are *not* the same as priced-at-zero — keep the inner join so "included" means an
> explicit `0.00`. (If BusPro models some included items as price-less rows, widen to
> `lp.Preis = 0.00 OR lp.IDLeistungPreis IS NULL` — confirm with the discovery query.)
**A2b — "Leistungen…" selection groups (plain list).** The catalog also lists included
services as selection tags under the "Leistungen" groups. Filter by a **hardcoded list
of `Selektionsgruppenstamm` ids** (configured in the proxy) rather than a label match —
the labels can be renamed, the ids are stable. Same join as B4; emit `Selektion` as the
plain text item.
```sql
SELECT rs.IDReise_FS AS DateId,
gs.IDSelektionsgruppenstamm AS GroupId,
gs.Selektionsgruppe AS GroupLabel, -- e.g. 'Leistungen inklusive'
s.Selektion AS Item
FROM dbo.ReiseSelektionen rs
JOIN dbo.Selektionsstamm s ON s.IDSelektionsstamm = rs.IDSelektionsstamm_FS
JOIN dbo.Selektionsgruppe sg ON sg.IDSelektionsstamm_FS = s.IDSelektionsstamm
JOIN dbo.Selektionsgruppenstamm gs ON gs.IDSelektionsgruppenstamm = sg.IDSelektionsgruppenstamm_FS
WHERE rs.IDReise_FS IN (@DateIds)
AND gs.IDSelektionsgruppenstamm IN (70, 89, 87, 88, 86, 7, 8, 90, 85, 71)
ORDER BY rs.IDReise_FS, gs.Position, sg.Position;
```
> The "Leistungen" `Selektionsgruppenstamm` ids (captured from the live DB — hardcode in
> the proxy; re-check if groups are added/renamed):
>
> | id | group | id | group |
> |---|---|---|---|
> | 70 | Leistungen | 86 | Leistungen Programm |
> | 89 | Leistungen Events | 7 | Leistungen Skipass |
> | 87 | Leistungen Kurse | 8 | Leistungen Sonstige |
> | 88 | Leistungen Personal | 90 | Leistungen Transport |
> | 85 | Leistungen Übernachtung | 71 | Leistungen Verpflegung |
> `LeistungPreis` has one row per `(Leistung, IDArtPreisSchema_FS)`; schema `1` is the
> standard sales price and reproduced the XML service prices exactly (13.90, 50.00, …).
---
## Query B — detail for one `(@DateId [, @HotelId])`
Run a header query + one query per child collection; assemble in Go.
### B1. Header — A1 with `WHERE r.IDReise = @DateId` (+ `ReiseText.ExternText`).
### B2. Services (transport + other, with direction & pickups) — **confirmed**
```sql
SELECT
l.IDLeistung AS ServiceId,
l.Art AS Type, -- BEF | SON
l.Unterart AS SubType,
l.Bezeichnung AS Label,
l.Pflichtmerkmal AS Mandatory,
l.Kontingent AS Available,
l.Alter_VON AS AgeFrom, l.Alter_BIS AS AgeTo,
l.Termin_VON AS DateFrom, l.Termin_BIS AS DateTo,
lb.Richtung_Hin_Rueck AS Direction, -- 'H' | 'R' (transport only)
lb.ZustiegIDs AS PickupIds, -- delimited list of dbo.Zustieg ids
lb.IDArtZustiegZeitplan_FS AS PickupTimePlanId,
lp.Preis AS Price
FROM dbo.ReiseLeistung rl
JOIN dbo.Leistung l ON l.IDLeistung = rl.IDLeistung_FS
LEFT JOIN dbo.LeistungBefoerderung lb ON lb.IDLeistung_FS = l.IDLeistung
LEFT JOIN dbo.LeistungPreis lp ON lp.IDLeistung_FS = l.IDLeistung
AND lp.IDArtPreisSchema_FS = 1
WHERE rl.IDReise_FS = @DateId
ORDER BY l.Art, l.Unterart, l.Bezeichnung;
```
`LeistungBefoerderung` present ⇒ transport (`lei_befoerderung`), else `lei_sonstiges`.
English texts (`<fremdsprache>`) = `dbo.LeistungText.ExternText` (validate).
### B2b. Pickup detail (resolve the `ZustiegIDs` list + time) — **confirmed**
For each id parsed from `lb.ZustiegIDs`:
```sql
SELECT z.IDZustieg AS PickupId, z.Zustiegcode AS Code,
z.Plz AS PostalCode, z.Ort AS City, z.Strasse AS Street,
CONVERT(time, zp.Uhrzeit) AS PickupTime
FROM dbo.Zustieg z
LEFT JOIN dbo.ZustiegZeitplan zp
ON zp.IDZustieg_FS = z.IDZustieg
AND zp.IDArtZustiegZeitplan_FS = @PickupTimePlanId -- from B2 (0 ⇒ no time)
WHERE z.IDZustieg = @PickupId;
```
Only the **time-of-day** of `Uhrzeit` is meaningful (the date part is a placeholder).
Verified: zustieg `494`, plan `2546``05:15`.
### B3. Hotels + rooms + board — **Partner subsystem**
The XML `<hotel idbuspro=224923>` is a hotel **`Adresse.IDAdresse`** (224923 =
"NEU Sportclub Waldschlössli Gruppen 2"), **not** a `ReisePartner`. Hotels are
assigned at the **product** level via the join table `PartnerProdukt
(IDProdukt_FS, IDAdresse_FS)` — that's why a departure (`IDReise`) has no `ReisePartner`
row. (`ReisePartner`/`IDArtVerpflegung_FS` is the booking-side hotel; for the *catalog*
use `PartnerProdukt`. `ProduktBeschreibung.IDAdresse_FS_Hotel` = the single featured hotel.)
```sql
-- hotels of the product (each IDAdresse_FS = an XML <hotel idbuspro>)
SELECT pp.IDAdresse_FS AS HotelAddressId, a.SuchName AS HotelName
FROM dbo.PartnerProdukt pp
JOIN dbo.Adresse a ON a.IDAdresse = pp.IDAdresse_FS
WHERE pp.IDProdukt_FS = @ProductId -- e.g. 1121
-- AND pp.IDAdresse_FS = @HotelAddressId
ORDER BY a.SuchName;
```
Board (`IDArtVerpflegung`) and stay dates aren't on `PartnerProdukt`; board comes from
the `PartnerPreisKategorie` rows below, and the stay span = the departure dates
(`Reise.TerminVon/TerminBis`, here `11.13.12.2026``Naechte = 2`).
Rooms / price / availability for a hotel address. The pricing fans out over
`room → price-category → season tafel → nights`; **validated** against the live DB
for hotel `224923`, room-type `Zimmerart 1413` (Code `MBZ`) → `IDArtPartnerPreisCode 38`
→ category `9478`, season `15420` (covers `2026-12-11`), `Naechte=2`, `EK_VK='VK'`,
`IDArtPreisSchema_FS=1`**`269,00`** (single clean row; same schema id `1` as the
`LeistungPreis` side). Map a room to its price category via `IDArtPartnerPreisCode_FS`.
(The XML headline `abpreis` of `289,00` = this room price + mandatory services, i.e.
computed — see note below; the flat per-room price is `269,00`.)
```sql
-- 1) rooms the hotel offers
-- PartnerZimmer ⋈ PartnerPreisKategorie on (IDAdresse_FS, IDArtPartnerPreisCode_FS)
SELECT pz.IDPartnerZimmer AS RoomId, za.Code AS RoomCode, za.Bezeichnung AS RoomLabel,
za.PaxMin, za.PaxMax, pz.IDArtPartnerPreisCode_FS AS PriceCode
FROM dbo.PartnerZimmer pz
JOIN dbo.Zimmerart za ON za.IDZimmerart = pz.IDZimmerart_FS
WHERE pz.IDAdresse_FS = @HotelAddressId;
-- 2) which season tafel covers the arrival date
SELECT IDPartnerSaisonTafel_FS FROM dbo.PartnerSaisonzeit
WHERE IDAdresse_FS = @HotelAddressId
AND TerminVon <= @Anreise AND TerminBis >= @Anreise
AND EK_VK = 'VK'; -- sale side
-- 3) price for the room's category × that season × nights
SELECT pp.Preis AS RoomPrice, pp.Naechte, pp.Verlaengerung
FROM dbo.PartnerPreisKategorie pk
JOIN dbo.PartnerPreis pp ON pp.IDPartnerPreisKategorie_FS = pk.IDPartnerPreisKategorie
WHERE pk.IDAdresse_FS = @HotelAddressId
AND pk.IDArtPartnerPreisCode_FS = @PriceCode -- from step 1 (room → category)
AND pk.IDArtVerpflegung_FS = @BoardId -- ReisePartner.IDArtVerpflegung_FS
AND pk.EK_VK = 'VK'
AND pp.IDPartnerSaisonTafel_FS = @SaisonTafelId -- from step 2
AND pp.Naechte = @Nights; -- nights of the stay
```
> `EK_VK` distinguishes purchase (`EK`) from sale (`VK`) — always filter `VK` for the
> customer price. `PartnerZimmer.PreisJeZimmer` flags per-room vs. per-person pricing.
```sql
-- availability (XML 'verfuegbar') — VALIDATED: = PartnerKontingent.Anzahl for the
-- (hotel, room-type, date-span). IDZimmer_FS = the XML idbuspro_zimmer (a Zimmerart).
-- Sample: IDAdresse_FS=224923, IDZimmer_FS=1413, 2026-12-11 → Anzahl=25 = XML verfuegbar.
SELECT IDZimmer_FS, Anzahl, BuchungsStatus FROM dbo.PartnerKontingent
WHERE IDAdresse_FS = @HotelAddressId
AND IDZimmer_FS = @ZimmerartId -- the room type (XML idbuspro_zimmer)
AND TerminVon <= @Abreise AND TerminBis >= @Anreise;
```
> `verfuegbar` is a **flat column** (`PartnerKontingent.Anzahl`) — reproducible by SQL.
> Gate it with `BuchungsStatus` (`''` bookable, `S` stop, `A` on-request).
> `<abpreis>` (the headline "from" price) is still **computed** (cheapest valid room +
> mandatory services) — recompute in the proxy from the per-room prices above.
### B4. Selection tags + groups — **confirmed**
```sql
SELECT gs.Selektionsgruppe AS GroupLabel, gs.Position AS GroupPos,
s.IDSelektionsstamm AS SelectionId, s.Selektion AS SelectionLabel
FROM dbo.ReiseSelektionen rs
JOIN dbo.Selektionsstamm s ON s.IDSelektionsstamm = rs.IDSelektionsstamm_FS
JOIN dbo.Selektionsgruppe sg ON sg.IDSelektionsstamm_FS = s.IDSelektionsstamm
JOIN dbo.Selektionsgruppenstamm gs ON gs.IDSelektionsgruppenstamm = sg.IDSelektionsgruppenstamm_FS
WHERE rs.IDReise_FS = @DateId
ORDER BY gs.Position, sg.Position;
```
---
## Status / open decisions
1. ~~**Status codes** (A1)~~ — ✅ confirmed: `Reise.Status` `''` = bookable, `S` = Storno
(cancelled, `StornoDatum` set), `L` = template/future master (exclude both).
2. ~~**F/A/O/S column**~~ — ✅ codes in `dbo.ArtBuchungsStatus` (F/O/A/W/S/U); the
working hotel-availability column is `PartnerKontingent.BuchungsStatus` (`''`/`S`/`A`).
3. ~~**Hotel link**~~ — ✅ XML `<hotel idbuspro>` = `Adresse.IDAdresse`; departure→hotel
via `PartnerProdukt(IDProdukt_FS, IDAdresse_FS)` at product level (not `ReisePartner`).
4. ~~**Partner room pricing**~~ — ✅ fully validated end-to-end: room `1413` (MBZ) →
code `38` → category `9478` → season `15420` × `Naechte=2` × `VK` × schema `1` =
**`269,00`**. (XML `abpreis 289,00` = room + mandatory services = computed.)
5. ~~**`verfuegbar`**~~ — ✅ flat: `PartnerKontingent.Anzahl` for `(IDAdresse_FS, IDZimmer_FS,
date-span)`; `1413 / 2026-12-11 → 25`. `<abpreis>` remains computed (recompute in proxy).
6. ~~**Minimum-services filter**~~ — ✅ defined: "included services" =
(A2a) `Leistung`s with sales price `0.00` (schema 1) **+** (A2b) selection items from
the hardcoded "Leistungen" `Selektionsgruppenstamm` ids, merged into one plain list.
+380
View File
@@ -0,0 +1,380 @@
# EP Reisen Mobile App — React Native Plan
**Copy this file into the React Native repository** (suggested: `docs/plan.md`). It is
written to be self-contained: you do not need access to the backend codebase to work from
it. Where it says "the contract", it means the API guide and fixtures shipped by the
backend team — see §3.
**Companion (backend side, not needed here):** `docs/mobile-app/backend-plan.md` in the
`myep` Symfony repository.
---
## 1. What this app is
EP Reisen sells group travel — primarily ski and coach trips. A booking is not "one person
buys one thing": it is **one applicant booking a set of rooms for a group of participants**,
where each participant independently selects ski passes, equipment rental, board, courses,
transport, insurance and more, with prices and eligibility varying per person (notably by
age).
The existing web product is a server-rendered Symfony application. This app covers its
**public** surface. The admin area is explicitly out of scope and will remain web-only.
The app is being built for App Store presence and a native-feeling booking flow. Push
notifications are **not** currently a requirement — do not build infrastructure for them
without asking.
### The two systems behind the API
You will see this distinction leak into behaviour, so it is worth knowing:
- **BusProNet (BPN)** — an external, third-party XML system that is the system of record
for individual travel bookings. It is slow, occasionally unavailable, and its rules are
not ours to change. Endpoints backed by it can fail in ways local data cannot.
- **Local database** — system of record for group/accommodation bookings, user accounts,
newsletter consent, and booking drafts. Fast and reliable.
Increments are deliberately ordered local-data-first so you are not fighting BPN latency
while also debugging your own foundations.
---
## 2. The one architectural rule
> **Business rules live on the server. The app renders what it is told.**
This is not a stylistic preference; it is the reason the project is viable. The backend
already contains, in one place, 27 condition classes and 25 field handlers that decide —
per participant, per field — whether a field is visible, editable, required, or shown as
read-only text, and which choices it offers. Reimplementing any of that in TypeScript
creates two sources of truth that will silently diverge.
**Concretely, never write code in this repo that:**
- decides whether a field is shown, e.g. inferring that a licence-plate input appears
because transport is by car;
- computes or re-computes a price, total, discount or voucher deduction from line items;
- decides whether a participant is eligible for a service, especially by age;
- validates a business constraint (as opposed to a formatting constraint like "this looks
like an email").
**If the app appears to need one of those, the schema is missing information. That is a
backend bug.** Report it; do not patch around it. This single discipline is what the whole
architecture buys, and it is lost the first time it is violated.
Client-side validation is limited to immediate input affordances — keyboard type, max
length, obviously-malformed email — purely for responsiveness. The server's verdict is
always authoritative and always re-checked on submit.
---
## 3. The contract
The backend ships two artifacts. Together they are your ground truth.
1. **The API guide** — a self-contained markdown document describing every endpoint:
method, path, auth scope, request shape, response shape, error shapes. The backend
team updates it in the same commit as the endpoint.
2. **Fixtures** — real JSON responses, written out by the backend's own tests. Because
they are test *output*, they cannot silently go stale.
### How to work with them
- **Build against fixtures first**, then point at a live backend. This means app work
never blocks on a deployed endpoint.
- **Generate your TypeScript types from the contract** rather than hand-writing them, so
a schema change surfaces as a compile error instead of a runtime surprise.
- **When the guide is ambiguous, ask — do not guess.** A guess that happens to work
becomes an undocumented dependency on an accident.
### Error shapes to expect
The existing API does not have one universal error envelope. Handle all of these:
- `{"message": "..."}` — typically with 404 or 400.
- `{"error": "...", "type": "api_error"}` — upstream (BPN) failure. **Some endpoints
return this with HTTP 200.** Check for the presence of an `error` key, not only the
status code.
- `{"success": false, "message": "..."}` — some write endpoints.
- **400 with a constraint-violation body** — validation failures. These are the ones you
map back onto form fields; see §5.
`401` means the token is missing or invalid (refresh, then retry once). `403` means
insufficient scope — a bug, not a user-recoverable state.
---
## 4. Authentication
OAuth2 **authorization_code with PKCE**, against the backend's `/token` endpoint. The
password and implicit grants are disabled server-side and are not available to you.
Requirements:
- Use the system browser / `ASWebAuthenticationSession` / Custom Tabs — **not** a
`WebView`. App Store review and OAuth best practice both require this.
- Store tokens in the platform secure store (Keychain / Keystore), never in
`AsyncStorage`.
- **Access tokens are short-lived** — 10 minutes today, likely 1 hour by the time you
build. Confirm with the backend team in Increment 0. Either way the refresh-token grant
is enabled and you must use it.
- **Refresh-token rotation is ON.** Each refresh returns a *new* refresh token and revokes
the one you just used. This has two consequences you must design for, not discover:
- **Single-flight refresh is mandatory.** If two requests 401 at the same time and both
try to refresh, one wins and the other presents an already-revoked token — logging the
user out mid-booking. Put a mutex around refresh and queue every other 401 behind it,
then replay them with the new token. This is the most common OAuth bug in mobile apps
and the booking flow's per-field schema refreshes will find it immediately.
- **Persist the rotated token atomically before using it.** A crash between receiving a
new refresh token and storing it logs the user out permanently.
- The refresh TTL is a sliding window (currently ~1 month, likely 3), so an active user
should never be forced to re-authenticate. If yours are, the refresh path is broken —
treat it as a bug, not as expected behaviour.
- The redirect URI must be registered server-side against the exact host the app calls.
This bites during local development — see §8.
**You will never handle credentials for the upstream BPN system.** The server resolves
those internally. If any task seems to require the app to send a BPN password, stop and
ask; the answer is no.
---
## 5. Server-driven UI
The dynamic parts of the booking flow are rendered from a schema the server computes. You
build **one generic renderer**, not per-screen field logic.
### Expected schema shape
Confirm against the fixtures — they are authoritative — but the agreed shape is:
```json
{
"fields": [
{
"name": "skiPass",
"type": "choice",
"label": "Skipass",
"required": true,
"value": 881,
"choices": [
{"id": 881, "label": "6 Tage", "price": 249.0}
]
},
{"name": "licensePlate", "type": "text", "hidden": true},
{"name": "pickup", "type": "choice", "readonly": true, "value": 12, "choices": []},
{"name": "firstName", "type": "text", "staticText": true, "value": "Anna"}
],
"dependsOn": {
"licensePlate": ["transportationOutbound"],
"pickup": ["transportationOutbound"]
}
}
```
### Field states — all four are distinct
| State | Meaning | Render as |
|---|---|---|
| `hidden` | Not applicable at all | Nothing |
| `staticText` | Value matters, user may not change it | Read-only text, no input affordance |
| `readonly` | Input shown but not editable | Disabled-looking input |
| `disabled` | Temporarily not interactive | Greyed input |
`hidden` and `staticText` are genuinely different and the backend treats them
differently — `staticText` is used, for example, when personal data is locked because
changing it would create a duplicate customer record upstream. Collapsing the two will
produce wrong screens.
### `dependsOn`
Maps a field to the fields whose changes invalidate it. When the user changes field *X*,
any field listing *X* in its `dependsOn` may now have different visibility, state, or
choices. **Re-fetch the schema from the server** — do not attempt to recompute locally.
This is the mechanism that keeps rule evaluation server-side.
Debounce these refreshes and keep the UI responsive during them, but never predict the
result optimistically for anything that affects price or eligibility.
### Field types you must support
`text`, `email`, `tel`, `date`, `choice` (single), `multichoice`, `checkbox`, `address`
(composite), plus a `static` presentation mode. Confirm the final list against the
contract before building.
### Mapping validation errors back
The server returns violations keyed by a property path (e.g.
`participants[2].dateOfBirth`). Your renderer must resolve those onto the right field on
the right participant. Design for this from the start — retrofitting it is painful.
---
## 6. Domain glossary
Enough to read the API without guessing.
- **Travel** — a dated departure of a product, at a specific hotel. Identified by a
numeric `dateId` + `hotelId`, or by string codes. Carries the available rooms, services,
pickups, insurances.
- **Applicant** — participant index 0. The person who books and is billed. Subject to
extra rules the others are not; their personal data is frequently locked (`staticText`).
- **Participant** — one traveller. Most selections live per participant, not per booking.
- **Room selection** — how many of which room type. This determines the participant count,
which is why step 1 precedes step 2.
- **Service** — anything bookable alongside: ski pass, equipment rental, board, courses,
transport, parking, additional services. Some are mandatory, some auto-booked with
opt-out, some age-restricted.
- **Booking status** — `F` firm booking, `O` option (held), `A` inquiry. Determined by
server rules, not user choice.
- **Payment method** — `transfer` or `debit`. Debit requires bank account details.
- **Voucher** — purchase vouchers (a balance), goodwill vouchers, and promo vouchers
(fixed or percentage, per-participant or per-booking). **Always** server-validated;
never compute a discount locally.
- **Baby** — participants aged 02 are a real special case in eligibility and pricing.
- **Mutability** — for existing bookings, BPN decides per field whether a change is still
permitted. Surfaces as `staticText`/`readonly`. Never override it.
---
## 7. Increments
Each increment is a working loop with the backend session; see §9. Do not start an
increment before its backend endpoints and fixtures exist.
### Increment 0 — Foundations
- RN app skeleton, navigation, theming, error boundary.
- OAuth2 authorization_code + PKCE, secure token storage, silent refresh with request
queuing.
- API client: auth injection, 401-refresh-retry, the error shapes in §3, and a fixture
mock mode toggled by env.
- **The generic SDUI renderer** — consumes `{fields, dependsOn}`, renders every field type,
emits changes, maps server violations onto fields.
- Type generation from the contract wired into the build.
- **Done when:** Increment 1 renders entirely through the generic renderer.
### Increment 1 — Accommodation & group offers (pilot)
Local data, fast, low risk. Deliberately first so the foundations are exercised end-to-end
before anything hard.
- Offer list for the signed-in user, offer detail, accept an offer.
- **Validates:** auth, error handling, navigation, the fixture pipeline.
### Increment 2 — Account, personal data, newsletter, registration
- Sign-up, password reset, profile view/edit, newsletter preferences.
- **First real use of SDUI** on a small form, before betting the booking flow on it. Expect
to find gaps in the renderer here — that is the point of doing it now.
### Increment 3 — Booking read
- "My travels": booking list, booking detail with participants, services and price
breakdown, document/invoice download.
- First BPN-backed screens. Expect slower responses and genuine upstream failures — build
proper loading and error states here, and reuse them everywhere after.
### Increment 4 — *(backend only)*
An internal backend refactor that produces the participant field schema. No app work.
Good moment to pay down debt or firm up the renderer.
### Increment 5 — Booking edit
- Edit an existing booking through a server-persisted draft: load draft, edit participants
via SDUI, review changes, submit.
- Honour mutability strictly — many fields will be `staticText`, and that is correct.
- Drafts are server-side, so edits survive app restarts. Design the UX around that.
### Increment 6 — Booking create
The full four-step flow, last, once everything above is proven.
1. **Rooms** — select room types and quantities. Determines participant count.
2. **Participants** — one card per participant, each opening an SDUI form. Groups can be
large (50+); the web version lazy-loads per participant and you should too.
3. **Payment** — method, and bank details when debit.
4. **Confirmation** — full summary, terms, submit.
Notes:
- State lives in a **server-side draft keyed by UUID**, not on the device. The app holds
the draft id and renders server state.
- Price refreshes are server calls. Never compute totals locally, not even for a
"preview".
- Submission goes to BPN and can fail or partially succeed. Treat the submit step as
genuinely fallible and make retry safe.
### Increment 7 — Discovery *(not yet scoped)*
Browsing travels and hotels currently lives in a separate CMS website, not in the backend
this app talks to. If the app must be a standalone entry point rather than something users
deep-link into, that is a second integration project. Do not assume it is in scope.
---
## 8. Local development
- The backend runs in DDEV. A **simulator** can reach it via the host; a **physical
device** cannot resolve `*.ddev.site`. The backend team will expose a shareable URL
(`ddev share` / ngrok).
- OAuth2 redirect URIs are registered per host, so switching between simulator and device
URLs needs a backend-side change. Agree the setup in Increment 0 rather than discovering
it mid-increment.
- Keep fixture-mock mode working permanently, not just as scaffolding — it is how you stay
unblocked and how you write deterministic tests.
---
## 9. Working agreement with the backend session
The backend lives in a separate repository and a separate sandboxed session. Neither side
can see the other's code. The contract is the only coupling point, and keeping it that way
is a shared discipline.
**Per-increment loop:**
1. Backend ships: endpoints + tests + fixtures + updated guide.
2. Handoff brief: what is live, which fixtures to mock, what changed in the guide.
3. App builds against fixtures, then against a live backend.
4. Joint end-to-end verification.
The two sessions do not work the same increment concurrently — they overlap by one stage,
so the backend starts *N+1* while the app builds *N*.
**Escalate to the backend rather than solving locally when:**
- a rule seems missing from the schema;
- a response shape is undocumented or contradicts the guide;
- you need a field the API does not expose;
- you are tempted to hardcode a business constant.
Each of those is a contract gap. Fixing it in the app is the failure mode this entire
architecture exists to prevent.
**Suggested `AGENTS.md` for this repo**, so future sessions inherit the rule:
> Business rules live server-side. This app renders a server-provided schema and never
> decides field visibility, eligibility, or pricing. If a rule appears to be missing,
> that is a backend bug — report it, do not implement it here. Never recompute prices
> from line items or infer field visibility from other field values.
---
## 10. Verification
- **Unit:** the SDUI renderer against every field type and state combination, including
`hidden` vs `staticText`, and violation-path mapping onto nested participant fields.
- **Auth:** an explicit test that fires several concurrent requests against an expired
access token and asserts *exactly one* refresh call is made, all requests succeed, and
the rotated refresh token is persisted. Rotation makes this a correctness test, not a
performance one.
- **Integration:** screens against committed fixtures — deterministic, no backend needed.
- **Contract:** types regenerate cleanly and compile against current fixtures. A failure
here is an early warning of drift; treat it as urgent.
- **End-to-end:** at the close of Increment 6, complete one booking through the app
against a real backend. The backend team verifies the resulting upstream payload is
**identical** to the same booking made through the web flow. That equivalence is the
project's actual acceptance criterion — everything else is a proxy for it.
+354
View File
@@ -0,0 +1,354 @@
# Mobile App — Backend Plan (myep / Symfony)
**Audience:** sessions working in *this* repository (`myep`, Symfony 6.4).
**Companion:** `docs/mobile-app/app-plan.md` — the React Native side. That document is
written to be self-contained and is meant to be **copied into the RN repository**, whose
sessions have no access to this codebase.
---
## 1. Context
`myep` is the booking engine behind the separate CMS marketing site (`ep-reisen.de`;
see `BookingSessionManager::DEFAULT_RETURN_URL` and `CmsDataProvider`). It serves:
- **Individual travel bookings** — system of record is **BusProNet** (BPN), an external
XML service reached through `src/BusProNet/ApiClient.php`.
- **Groups / accommodation bookings** — system of record is local Doctrine entities under
`src/Entity/Groups/`.
The public UI is Twig + HTMX + Tailwind. The admin UI under `/admin` is **out of scope**
for the mobile app and stays web-only.
### What we are building and why
A React Native app covering the **full public surface, including the booking create
flow**. Drivers: App Store presence/brand and a native-feeling booking experience. A PWA
was explicitly ruled out. Push notifications were *not* named as a driver — worth
remembering, since push is normally what makes native unarguable; the payoff here rests
on brand and UX.
### The decision that shapes everything
**The sibling project is the React Native app only. The API stays in this repository.**
A second backend would recreate exactly the duplication of validation and business rules
this plan exists to prevent. The API is a new `src/Controller/Api/App/` namespace reusing
the existing services and DTOs.
**Client strategy: server-driven UI (SDUI).** The server emits a JSON field schema per
participant/step; RN renders it generically. Business rules never leave PHP.
### Why this codebase can actually support that
The rules are already headless:
- **Validation lives on DTOs, not form types.** `src/Form/Model/ParticipantDto.php` (21
constraints), `BookingDto.php`, `BankAccountDto.php`, `RegistrationDto.php` carry
`Assert\*` plus custom `App\Validator\Constraints\Participant`, with validation groups
(`booking_create`, `booking_edit`, `strict_required`, `applicant_address`). An API
endpoint can denormalize → `validate($dto, groups: [...])` and get identical results.
- **Dynamic field logic is a rules engine.** `src/Form/Service/` holds
`Contract/FieldStateProviderInterface` (hidden / readonly / disabled / required /
static_text), `Contract/FieldOptionsProviderInterface` (labels + choices),
`ParticipantFieldHandlerRegistry` (25 handlers) and 27 reusable `Condition/` classes.
- **Orchestration is in services, not controllers.** `BookingConfigurator` (652 lines),
`RoomAssigner`, `BookingPricingAssembler`, `BookingSummaryAssembler`,
`VoucherValidator`, `BookingEditSubmitGuard`, `BookingEditSubmitter`. Controllers are
thin — `Step2Controller` is 147 lines, mostly session handling and redirects.
---
## 2. The four real obstacles
Everything else is mechanical. These need design work before the increments that depend
on them.
### Obstacle 1 — The create flow is session-bound
`src/Service/BookingSessionManager.php` keys the entire create flow off
`$request->getSession()` (`booking_create`, `booking_create_baseline_snapshot`,
`booking_return_url`). Stateless OAuth2 clients have no session.
**Fix:** a server-persisted draft addressed by UUID. The pattern already exists for edit —
`src/Entity/BookingEditDraft.php` plus `BookingEditDraftManager` / `BookingEditDraftMerger`.
Generalise into a `BookingDraft` store and put `BookingStateStoreInterface` in front, with
two backends: session (web, unchanged) and draft (app). Do **not** fork the flow logic.
### Obstacle 2 — `FieldStateProviderInterface` leaks Symfony Form
Two leaks:
- `getBookingDtoFromForm(FormInterface $form)` is pure Form coupling and belongs in a
form-side adapter, not the interface.
- `getFieldState()` returns **Symfony form options** (`disabled`, `required`,
`attr => ['readonly' => true]`), and `ParticipantFieldOptionsProvider` returns `choices`
as domain objects (`Service`, `Pickup`, `Insurance`) plus occasional `choice_loader`.
**Fix:** a neutral `FieldDescriptor` value object — name, type, label, required, readonly,
disabled, hidden, staticText, choices, value. Both `BookingParticipantType` and the new
JSON serializer consume it. Conditions and handlers are untouched.
Note the `hidden` vs `static_text` distinction documented in `AbstractFieldStateProvider`:
`hidden` means excluded entirely; `static_text` means "show the value, don't let them edit
it". The app must honour both, so `FieldDescriptor` has to carry them separately.
### Obstacle 3 — Token lifetimes and refresh-token rotation
`config/packages/league_oauth2_server.yaml` sets `access_token_ttl: PT10M` — deliberately,
since the bundle's own default is `PT1H`. Find out why before changing it.
**TTLs are global.** They live under `authorization_server`; the bundle has no per-client
TTL. Any change affects the CMS and M2M clients too. "Raise it just for the app" is not
available without a custom grant or response type.
Two values are unset and defaulted, and both matter:
- `refresh_token_ttl`**`P1M`** (1 month)
- `revoke_refresh_tokens`**`true`**, so **refresh-token rotation is on**
Rotation is correct security, and it is also the main source of mobile auth bugs: two
requests 401 concurrently, both refresh, one rotates, the second presents a revoked
refresh token and the user is logged out mid-booking. At a 10-minute TTL with step 2
firing schema refreshes per field change, this *will* happen. The mitigation is client-side
— single-flight refresh — and it is a hard requirement in `app-plan.md` §4.
A longer access-token TTL does **not** create an unrevocable window here:
`persist_access_token` defaults to true and `BearerTokenValidator` checks
`isAccessTokenRevoked()` on every request, so tokens can be killed immediately. The usual
argument for a very short TTL does not apply.
**Recommendation:** `access_token_ttl: PT1H`, `refresh_token_ttl: P3M` set explicitly,
rotation left on. Rotation issues a fresh refresh token each time, so the refresh TTL is a
sliding window — active users never re-auth, only ~3 months of true inactivity forces it.
M2M clients get fewer token round-trips. Extra token rows are already handled by
`league:oauth2-server:clear-expired-tokens`, scheduled in `config/packages/zenstruck_schedule.yaml`.
**Settle this before the RN auth layer is written, not after.**
Otherwise auth is ready: `enable_auth_code_grant: true` with
`require_code_challenge_for_public_clients: true` (PKCE), and
`enable_password_grant: false` / `enable_implicit_grant: false` — correct for a native app.
### Obstacle 4 — BPN per-user calls need the user's plaintext password
`ApiClient::getBookings()`, `getBooking()`, `getPersonalData()`, `updatePersonalData()`,
`updateNewsletterRegistration()` all take `(string $email, string $password)`.
`src/Controller/Booking/IndexController.php` supplies them via
`$this->crypt->decrypt($user->getPassword())` — the local `User` stores the BPN password
RSA-encrypted (`src/Security/Crypt.php`).
Consequences:
- **The app must never see BPN credentials.** The API layer resolves them server-side from
the authenticated `User`, exactly as the web controllers do. This is not a change, but
it must be stated so nobody "simplifies" it by proxying credentials.
- **BPN-backed user data only works for users with a local `User` record** carrying the
encrypted password. Guest flows and app-only accounts cannot read BPN bookings. Confirm
how registration-via-app populates this before Increment 3.
- The OAuth2 token identifies the user; it does **not** carry BPN authority. Every
BPN-backed endpoint needs an explicit ownership check, not just a valid token.
---
## 3. Increments
Ordered local-data-first, BPN-last, so each stage ships something usable and the riskiest
integration lands after the SDUI machinery is proven.
### Increment 0 — Foundations
No user-visible feature. Backend side:
- Register an OAuth2 client for the app (authorization_code + PKCE, native redirect URI).
- Resolve Obstacle 3 (TTL).
- Resolve device→DDEV access: `.ddev/config.yaml` has `ngrok_args`; `ddev share` is the
path. Redirect URIs must be registered against whatever host the app actually calls.
- Create `docs/app-api/` with the contract skeleton and the fixtures directory.
### Increment 1 — Accommodation & group offers (pilot)
Local Doctrine data, UUID-addressed, and a write endpoint already exists. Zero BPN risk.
- Reuse `GET /api/accommodation-bookings/{uuid}` and
`POST /api/accommodation-bookings/{uuid}/accept`
(`src/Controller/Api/AccommodationBookingController.php`).
- Add a list endpoint scoped to the authenticated user.
- Mirrors `src/Controller/Groups/Offer/IndexController.php`; reuse
`AccommodationBookingService`, `AccommodationBookingBreakdownCalculator`,
`AccommodationBookingApiResponse`.
- **Validates:** auth, serialization conventions, RN navigation, the fixture pipeline.
### Increment 2 — Account, personal data, newsletter, registration
- Mirror `src/Controller/Account/`, `RegistrationController`, `ResetPasswordController`,
`src/Controller/Newsletter/`.
- Reuse `RegistrationDto`, the `PersonalDataType` DTO, `NewsletterManager`,
`ProfileCompletenessChecker`, and existing `/api/newsletter-subscriptions`,
`/api/userinfo`, `/api/crm-attributes`.
- **First real SDUI use**, on a small low-risk form, before betting the booking flow on it.
- Registration here is what makes Obstacle 4 tractable — verify the encrypted-password
path is populated for app-registered users.
### Increment 3 — Booking read
- `GET /api/app/bookings` and `/api/app/bookings/{id}`, mirroring
`src/Controller/Booking/IndexController.php` (note its `TravelLoader::patchBookings()`
enrichment step).
- Documents/invoice, mirroring `src/Controller/Booking/DownloadController.php`.
- Reuse `BookingSummaryAssembler`, `BookingPricingAssembler`, `BookingEditDataLoader`.
- BPN **reads only, no writes** — the safe way to shake out `BusProNet\Model`
normalization (`Travel`, `Booking`, `Service`, `Room`, `Pickup`, `Insurance`), which
every later increment depends on.
### Increment 4 — `FieldDescriptor` refactor
Pure internal refactor. No new endpoints. Covered by the existing 155 test files.
- Introduce `FieldDescriptor`; split `getBookingDtoFromForm` out of
`FieldStateProviderInterface`.
- Adapt `BookingParticipantType::mergeFieldState()` / `addDynamicFields()` to consume it.
- Add `ParticipantFieldSchemaSerializer` producing the JSON schema, including the
`dependsOn` map derived from `FieldConditionInterface::getDependentFields()` and
`ParticipantFieldHandlerInterface::getDependencies()`.
- **Ship criterion:** web behaviour byte-identical, Cypress specs green, **no test file
changed**. A required test change means a behaviour regression.
### Increment 5 — Booking edit
Before create, because drafts already exist here.
- Endpoints over `BookingEditDraftManager`, `BookingEditPreFlightChecker`,
`BookingEditSubmitGuard`, `BookingEditSubmitter`, `BookingChangeTracker`.
- Participant schema endpoint from Increment 4.
- Honour `BookingMutabilityDto` and BPN's `aenderungmoeglich` mutability rules — these
already drive `static_text`, so SDUI inherits them.
- **Caution:** the participant[0]/applicant block is on hold pending BPN vendor
confirmation about the shared customer id. Do not try to resolve it here.
### Increment 6 — Booking create
The full flow, last. Web routes being mirrored:
| Step | Web route | Controller |
|---|---|---|
| init | `/bookings/create`, `/bookings/create/init` | `Create/IndexController.php` |
| 1 — rooms | `/bookings/create/rooms` (+ `/refresh`) | `Create/Step1Controller.php` |
| 2 — participants | `/bookings/create/participants` (+ `/{index}`, `/{index}/refresh`) | `Create/Step2Controller.php`, `Step2ParticipantController.php` |
| 3 — payment | `/bookings/create/payment` (+ `/refresh`) | `Create/Step3Controller.php` |
| 4 — confirmation | `/bookings/create/confirmation` | `Create/Step4Controller.php` |
| success | `/bookings/create/success` | `Create/SuccessController.php` |
- Generalise draft storage behind `BookingStateStoreInterface` (Obstacle 1).
- Reuse `BookingConfigurator` (`startFreshBooking`, `preselectDefaultServices`,
`applyCreateBookingStatusRules`, `updateBookingStatusFromRoomSelection`), `RoomAssigner`,
`ParticipantDataPrefiller`, `TravelDataProvider`, `VoucherValidator`,
`FamilyInsuranceAvailabilityChecker`.
- Submit via `BusProNet\ApiClient::createBooking()` / `createBookingInquiry()` with
`BookingPayloadBuilder`, exactly as `Step4Controller` does.
- Every HTMX refresh route gets a JSON sibling returning recomputed schema + pricing.
### Increment 7 — Discovery (scoping decision, not yet planned)
Travel/hotel browsing lives in the **CMS**, not here — this repo only proxies it via
`CmsDataProvider` and `/api/hotels`, `/api/products`, `/api/travels`. If the app is to be
a standalone entry point rather than a deep-link target, that is a second integration
project and should be scoped separately.
---
## 4. Files
**New (representative):**
- `src/Controller/Api/App/` — one controller per resource, mirroring the public tree
- `src/Form/Service/Model/FieldDescriptor.php`
- `src/Form/Service/ParticipantFieldSchemaSerializer.php`
- `src/Service/BookingStateStoreInterface.php` + draft-backed implementation
- `src/Entity/BookingDraft.php` (generalised from `BookingEditDraft`) + migration
- Normalizers for `BusProNet\Model\*` value objects
- `tests/Controller/Api/App/`
**Modified:**
- `src/Form/Service/Contract/FieldStateProviderInterface.php` — drop the Form-coupled method
- `src/Form/Service/Abstract/AbstractFieldStateProvider.php`, `CreateFieldStateProvider.php`,
`EditFieldStateProvider.php`
- `src/Form/BookingParticipantType.php` — consume `FieldDescriptor`
- `src/Service/BookingSessionManager.php` — implement the store interface
- `config/packages/league_oauth2_server.yaml` — TTL, app client, scopes
- `docs/api-consumer-guide.md` / `docs/app-api/` — the contract
**Unchanged by design:** every `src/Form/Service/Condition/*`, every
`src/Form/Service/Participant*FieldHandler.php`, every `src/Validator/Constraints/*`, and
all pricing services. If an increment starts wanting to edit these, the design has drifted
— stop and reconsider.
---
## 5. Working across two repos and two sessions
The RN work happens in a separate repo and a separate sandboxed session. The risk that
creates is **contract drift**: the app session guessing at response shapes, or worse,
re-deriving business rules in TypeScript because the JSON was ambiguous. That is the
original duplication problem arriving through a side door.
### The contract is an artifact in this repo
`docs/api-consumer-guide.md` already opens with *"It is self-contained: no access to this
codebase is required to use it."* That is the format. Extend it — or split out
`docs/app-api/guide.md` once it outgrows one file — **in the same commit as the endpoint**,
every time.
Rule: **the RN session never reads this PHP repo.** Its ground truth is the guide plus
fixtures. If it has to ask "what does the server send here?", the guide has a gap — fix
the guide, not the app.
### Fixtures decouple the sessions
Parity tests in `tests/Controller/Api/App/` write their JSON responses to
`docs/app-api/fixtures/*.json` (mirroring the existing `tests/Resources/*.xml`
convention). Commit them. The RN session mocks against those files, so app work never
waits on a deployed endpoint — and because they are test *output*, they cannot silently
go stale.
### Per-increment rhythm
1. **Backend session (here):** endpoint + parity test + fixtures + guide update.
2. **Handoff:** a short brief — endpoints now live, fixtures to mock, what changed in the
guide since last time.
3. **App session (RN repo):** build against fixtures first, then against DDEV.
4. **Joint verification:** run the increment end-to-end against a real backend.
Do not run both sessions on the same increment concurrently. Overlap by one stage: while
the app session builds increment *N*, start *N+1* here.
---
## 6. Verification
Per increment:
1. `vendor/bin/phpunit` — 155 existing test files, notably `tests/Form/`, `tests/Service/`,
`tests/BusProNet/`. **Increment 4 must pass with no test changes.**
2. `vendor/bin/phpstan analyse` and `vendor/bin/php-cs-fixer fix --dry-run`.
3. `npx cypress run` — existing specs cover the web booking flow and guard against SDUI
refactors leaking into Twig rendering.
4. **Parity tests** under `tests/Controller/Api/App/`, asserting the JSON schema matches
what `BookingParticipantType` builds for the same `BookingDto`. This is the single most
valuable artifact in the project — it mechanically proves web and app share one rule set.
5. Manual: extend the existing `api.http` / `http-client.env.json` collection per increment.
6. End-to-end: run one booking through the RN client against a DDEV backend and confirm the
BPN payload is identical to a web-flow booking with the same inputs — compare via
`src/Controller/Admin/Log/XmlDumpController.php`.
---
## 7. Open questions before Increment 6
- App-client access token TTL (Obstacle 3).
- How app registration populates the encrypted BPN password (Obstacle 4), and whether
guest/unauthenticated create is supported in the app as it is on the web via
`/bookings/create/init`.
- Draft retention and expiry policy.
- Whether the app deep-links from the CMS site or must own discovery (Increment 7).
+87 -13
View File
@@ -7,8 +7,8 @@
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://myep-next-booking.ddev.site/authorize",
"Token URL": "https://myep-next-booking.ddev.site/token",
"Auth URL": "https://myep.ddev.site/authorize",
"Token URL": "https://myep.ddev.site/token",
"Redirect URL": "https://myep-team.ddev.site/auth/check",
"Scope": "email"
},
@@ -17,8 +17,8 @@
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://myep-next-booking.ddev.site/authorize",
"Token URL": "https://myep-next-booking.ddev.site/token",
"Auth URL": "https://myep.ddev.site/authorize",
"Token URL": "https://myep.ddev.site/token",
"Redirect URL": "https://myep-team.ddev.site/auth/check",
"Scope": "email profile"
},
@@ -27,12 +27,73 @@
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://myep-next-booking.ddev.site/authorize",
"Token URL": "https://myep-next-booking.ddev.site/token",
"Auth URL": "https://myep.ddev.site/authorize",
"Token URL": "https://myep.ddev.site/token",
"Scope": "api"
},
"oauth2_newsletter": {
"Type": "OAuth2",
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://myep.ddev.site/authorize",
"Token URL": "https://myep.ddev.site/token",
"Scope": "api"
}
}
},
"clickup_baseurl": "https://api.clickup.com/api/v2",
"clickup_api_token": "abcdef123456789",
"clickup_list_id": "12345",
"clickup_template_id": "t-12345"
},
"staging": {
"Security": {
"Auth": {
"oauth2_email": {
"Type": "OAuth2",
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://my.ep-reisen.net/authorize",
"Token URL": "https://my.ep-reisen.net/token",
"Redirect URL": "https://myep-team.ep-reisen.de/auth/check",
"Scope": "email"
},
"oauth2_profile": {
"Type": "OAuth2",
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://my.ep-reisen.net/authorize",
"Token URL": "https://my.ep-reisen.net/token",
"Redirect URL": "https://myep-team.ep-reisen.de/auth/check",
"Scope": "email profile"
},
"oauth2_api": {
"Type": "OAuth2",
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://my.ep-reisen.net/authorize",
"Token URL": "https://my.ep-reisen.net/token",
"Scope": "api"
},
"oauth2_newsletter": {
"Type": "OAuth2",
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://my.ep-reisen.net/authorize",
"Token URL": "https://my.ep-reisen.net/token",
"Scope": "api"
}
}
},
"clickup_baseurl": "https://api.clickup.com/api/v2",
"clickup_api_token": "abcdef123456789",
"clickup_list_id": "12345",
"clickup_template_id": "t-12345"
},
"prod": {
"Security": {
@@ -42,8 +103,8 @@
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://myep.ep-reisen.de/authorize",
"Token URL": "https://myep.ep-reisen.de/token",
"Auth URL": "https://my.ep-reisen.de/authorize",
"Token URL": "https://my.ep-reisen.de/token",
"Redirect URL": "https://myep-team.ep-reisen.de/auth/check",
"Scope": "email"
},
@@ -52,8 +113,8 @@
"Grant Type": "Authorization Code",
"Client ID": "{{oauth2_client_id}}",
"Client Secret": "{{oauth2_client_secret}}",
"Auth URL": "https://myep.ep-reisen.de/authorize",
"Token URL": "https://myep.ep-reisen.de/token",
"Auth URL": "https://my.ep-reisen.de/authorize",
"Token URL": "https://my.ep-reisen.de/token",
"Redirect URL": "https://myep-team.ep-reisen.de/auth/check",
"Scope": "email profile"
},
@@ -62,11 +123,24 @@
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://myep.ep-reisen.de/authorize",
"Token URL": "https://myep.ep-reisen.de/token",
"Auth URL": "https://my.ep-reisen.de/authorize",
"Token URL": "https://my.ep-reisen.de/token",
"Scope": "api"
},
"oauth2_newsletter": {
"Type": "OAuth2",
"Grant Type": "Client Credentials",
"Client ID": "{{oauth2_api_client_id}}",
"Client Secret": "{{oauth2_api_client_secret}}",
"Auth URL": "https://my.ep-reisen.de/authorize",
"Token URL": "https://my.ep-reisen.de/token",
"Scope": "api"
}
}
}
},
"clickup_baseurl": "https://api.clickup.com/api/v2",
"clickup_api_token": "abcdef123456789",
"clickup_list_id": "12345",
"clickup_template_id": "t-12345"
}
}
+172
View File
@@ -0,0 +1,172 @@
###
# Mailjet API test requests for IntelliJ HTTP Client
#
# 1) Fill in variables below (or move them to http-client.private.env.json).
# 2) Set `mailjet_api_key` and `mailjet_api_secret` in your env file.
# IntelliJ HTTP Client will inject them into the Authorization header below.
#
# Required variables:
# - mailjet_base_url (example: https://api.mailjet.com/v3/REST)
# - mailjet_api_key
# - mailjet_api_secret
# - mailjet_contact_email
# - mailjet_list_id
#
# @no-cookie-jar
### Mailjet health check (authenticated)
# @no-cookie-jar
GET {{mailjet_base_url}}/apikey
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Find contact by email
# @no-cookie-jar
GET {{mailjet_base_url}}/contact?Email={{mailjet_contact_email}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
> {%
if (response.body && response.body.Data && response.body.Data.length > 0) {
client.global.set("contact_id", String(response.body.Data[0].ID));
}
%}
### Create contact (run if not found)
# @no-cookie-jar
POST {{mailjet_base_url}}/contact
Accept: application/json
Content-Type: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
{
"Email": "{{mailjet_contact_email}}"
}
> {%
if (response.body && response.body.Data && response.body.Data.length > 0) {
client.global.set("contact_id", String(response.body.Data[0].ID));
}
%}
### Get contact by ID (after find/create)
# @no-cookie-jar
GET {{mailjet_base_url}}/contact/{{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Get contact metadata by ID (after find/create)
# @no-cookie-jar
GET {{mailjet_base_url}}/contactdata/{{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Get newsletter list by ID
# @no-cookie-jar
GET {{mailjet_base_url}}/contactslist/{{mailjet_list_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### List all available contact lists
# @no-cookie-jar
GET {{mailjet_base_url}}/contactslist?Limit=1000
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Check list recipient status (before actions)
# @no-cookie-jar
GET {{mailjet_base_url}}/listrecipient?ContactsList={{mailjet_list_id}}&Contact={{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
> {%
if (response.body && response.body.Data && response.body.Data.length > 0) {
client.global.set("listrecipient_id", String(response.body.Data[0].ID));
}
%}
### Subscribe to list (addnoforce)
# @no-cookie-jar
POST {{mailjet_base_url}}/contactslist/{{mailjet_list_id}}/managecontact
Accept: application/json
Content-Type: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
{
"Action": "addnoforce",
"Email": "{{mailjet_contact_email}}"
}
### Verify list recipient after addnoforce
# @no-cookie-jar
GET {{mailjet_base_url}}/listrecipient?ContactsList={{mailjet_list_id}}&Contact={{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Unsubscribe from list (unsub)
# @no-cookie-jar
POST {{mailjet_base_url}}/contactslist/{{mailjet_list_id}}/managecontact
Accept: application/json
Content-Type: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
{
"Action": "unsub",
"Email": "{{mailjet_contact_email}}"
}
### Verify list recipient after unsub
# @no-cookie-jar
GET {{mailjet_base_url}}/listrecipient?ContactsList={{mailjet_list_id}}&Contact={{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Re-subscribe attempt with addnoforce (expected to keep unsubscribed state)
# @no-cookie-jar
POST {{mailjet_base_url}}/contactslist/{{mailjet_list_id}}/managecontact
Accept: application/json
Content-Type: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
{
"Action": "addnoforce",
"Email": "{{mailjet_contact_email}}"
}
### Verify list recipient after addnoforce re-subscribe attempt
# @no-cookie-jar
GET {{mailjet_base_url}}/listrecipient?ContactsList={{mailjet_list_id}}&Contact={{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
### Re-subscribe with addforce (expected to re-subscribe)
# @no-cookie-jar
POST {{mailjet_base_url}}/contactslist/{{mailjet_list_id}}/managecontact
Accept: application/json
Content-Type: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
{
"Action": "addforce",
"Email": "{{mailjet_contact_email}}"
}
### Verify list recipient after addforce
# @no-cookie-jar
GET {{mailjet_base_url}}/listrecipient?ContactsList={{mailjet_list_id}}&Contact={{contact_id}}
Accept: application/json
Authorization: Basic {{mailjet_api_key}} {{mailjet_api_secret}}
+33
View File
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260106091117 extends AbstractMigration
{
public function getDescription(): string
{
return 'Create booking_edit_draft table for persisting user edits during booking edit flow';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE booking_edit_draft (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, booking_id INT NOT NULL, form_data JSON NOT NULL COMMENT \'(DC2Type:json)\', created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', updated_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_E6548098A76ED395 (user_id), UNIQUE INDEX user_booking_unique (user_id, booking_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE booking_edit_draft ADD CONSTRAINT FK_E6548098A76ED395 FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE booking_edit_draft DROP FOREIGN KEY FK_E6548098A76ED395');
$this->addSql('DROP TABLE booking_edit_draft');
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260109081315 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE booking_edit_draft ADD travel_date DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\'');
$this->addSql('CREATE INDEX IDX_DRAFT_TRAVEL_DATE ON booking_edit_draft (travel_date)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP INDEX IDX_DRAFT_TRAVEL_DATE ON booking_edit_draft');
$this->addSql('ALTER TABLE booking_edit_draft DROP travel_date');
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20260110105253 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add booking_number column to booking_edit_draft table';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE booking_edit_draft ADD booking_number INT DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE booking_edit_draft DROP booking_number');
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20260113140000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add date_id and hotel_id columns to booking_edit_draft table for export functionality';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE booking_edit_draft ADD date_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE booking_edit_draft ADD hotel_id INT DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE booking_edit_draft DROP date_id');
$this->addSql('ALTER TABLE booking_edit_draft DROP hotel_id');
}
}

Some files were not shown because too many files have changed in this diff Show More