chore: seminarhof customer project

This commit is contained in:
e2e
2026-06-22 00:08:38 +02:00
commit 48b795b3be
161 changed files with 18517 additions and 0 deletions

View File

View File

@@ -0,0 +1,102 @@
@admin @bookings
Feature: Admin booking detail — read & edit
The admin booking-detail page replaces the spreadsheet admins must be able
to *edit* every column they used to edit, not just look at it.
Background:
Given I am logged in as "christina@seminarhof.example" with password "admin1234"
When I visit "/admin/bookings/b_yoga_2026_summer"
# ── Read ────────────────────────────────────────────────────────────────
Scenario: admin opens the summer retreat detail
Then I see "Summer Yoga Retreat 2026"
And I see "Yoga Retreat e.V."
And I see "Teilnehmende"
Scenario: admin sees the seeded participant list
When I click "Teilnehmende"
Then I see "Anja Weber"
And I see "Bernd Krause"
# ── Edit booking metadata ───────────────────────────────────────────────
Scenario: admin edits the course name and persists across reload
When I fill "courseName" with "Summer Yoga Retreat 2026 revised"
And I click "Änderungen speichern"
Then I see "Gespeichert"
When I visit "/admin/bookings/b_yoga_2026_summer"
Then I see "Summer Yoga Retreat 2026 revised"
Scenario: admin updates expected participants
When I fill "expectedPersons" with "32"
And I click "Änderungen speichern"
Then I see "Gespeichert"
Scenario: admin toggles half-house and online listing flags
When I select "Ja" from "halfHouse"
And I select "Ja" from "onlineAd"
And I click "Änderungen speichern"
Then I see "Gespeichert"
Scenario: admin cannot save when no field changed
Then I see "Änderungen speichern"
# Save button is disabled until a field is touched — clicking has no effect.
# ── Edit organisation ──────────────────────────────────────────────────
Scenario: admin edits organisation contact email and phone
When I fill "organisation-email" with "ops@yoga-retreat.example"
And I fill "organisation-phone" with "+49 30 12345678"
And I click "Organisation speichern"
Then I see "Organisation gespeichert"
When I visit "/admin/bookings/b_yoga_2026_summer"
Then the field "organisation-email" has value "ops@yoga-retreat.example"
And the field "organisation-phone" has value "+49 30 12345678"
Scenario: organisation save rejects an invalid email
When I fill "organisation-email" with "not-an-email"
And I click "Organisation speichern"
Then I do not see "Organisation gespeichert"
# ── Booking status transitions ─────────────────────────────────────────
Scenario: admin cancels a booking
When I accept the next confirmation
And I click "Buchung stornieren"
Then I see "Storniert"
And I do not see "Buchung stornieren"
# ── Participants CRUD ──────────────────────────────────────────────────
Scenario: admin adds a participant
When I click "Teilnehmende"
And I fill "new-participant-name" with "Ingrid Vogel"
And I click "Hinzufügen"
Then I see "Ingrid Vogel"
Scenario: admin removes a participant
When I click "Teilnehmende"
And I accept the next confirmation
And I click "remove-participant-p_s_08"
Then I do not see "Hans Becker"
Scenario: admin changes a participant's diet
When I click "Teilnehmende"
And I select "Pescetarisch" from "participant-diet-p_s_06"
Then the field "participant-diet-p_s_06" has value "Pescetarisch"
# ── Allergies CRUD ─────────────────────────────────────────────────────
Scenario: admin adds an allergy to a participant
When I click "Teilnehmende"
And I fill "new-allergy-p_s_02" with "shellfish"
And I click "add-allergy-p_s_02"
Then I see "Meeresfrüchte"
Scenario: admin removes an existing allergy
When I click "Teilnehmende"
And I click "remove-allergy-p_s_01-nuts"
Then I do not see "nuts"
# ── Rooms assign / unassign ────────────────────────────────────────────
Scenario: admin assigns and then unassigns a participant to a room
When I click "Zimmer"
And I select "Anja Weber" from "assign-room-r_1"
Then I see "Anja Weber"
When I click "Entfernen"
Then the field "assign-room-r_1" has value ""

View File

@@ -0,0 +1,41 @@
@auth
Feature: Authentication
Users authenticate with email + password. Sessions are cookie-based.
Roles (client / admin / owner) gate access to portals.
Background:
Given I visit "/login"
Scenario: client logs in and lands on their portal
When I log in as "demo@yoga-retreat.example" with password "demo1234"
Then the URL contains "/"
And I see "Seminarhof Drawehn"
Scenario: admin logs in and reaches the admin bookings list
When I log in as "christina@seminarhof.example" with password "admin1234"
And I visit "/admin/bookings"
Then I see "Buchungen"
And I see "Summer Yoga Retreat"
Scenario: owner logs in and reaches the admin bookings list
When I log in as "sarah@seminarhof.example" with password "owner1234"
And I visit "/admin/bookings"
Then I see "Buchungen"
Scenario: wrong password is rejected
When I fill "input[type=email]" with "demo@yoga-retreat.example"
And I fill "input[type=password]" with "wrong-password"
And I click "Anmelden"
Then I see "E-Mail oder Passwort ist falsch."
Scenario: client is redirected away from the admin portal
When I log in as "demo@yoga-retreat.example" with password "demo1234"
And I visit "/admin/bookings"
Then the URL does not contain "/admin/"
Scenario: logout clears the session
Given I am logged in as "demo@yoga-retreat.example" with password "demo1234"
When I log out
Then I see "Sie wurden abgemeldet. Bis bald."
When I click "Zurück zur Anmeldung"
Then the URL contains "/login"

View File

@@ -0,0 +1,8 @@
@public @availability
Feature: Public availability calendar
Visitors can see which days the venue is free to book.
Scenario: visitor opens the availability calendar
Given I visit "/availability"
Then I see "Seminarhof Drawehn"
And I see "2026"

View File

@@ -0,0 +1,42 @@
@booking @flow
Feature: Full booking flow — enquiry through confirmed
A client submits an enquiry via the public form. The admin then drives
the booking through every step: approval, contract, deposit, confirmation.
# Guest: submit enquiry
Scenario: client submits an enquiry via the public form
Given I visit "/enquiry"
When I fill "courseName" with "E2E Full Flow Test"
And I fill "startDate" with "2028-06-15"
And I fill "endDate" with "2028-06-22"
And I fill "organisationName" with "E2E Organisation"
And I fill "contactEmail" with "e2e@example.com"
And I check "agbAccepted"
And I check "privacyAccepted"
And I click "Anfrage absenden"
Then I see "Ihre Anfrage ist eingegangen"
# ── Admin: full flow from enquiry to confirmed ──────────────────────────
Scenario: admin drives a booking from enquiry through to confirmed
Given I am logged in as "christina@seminarhof.example" with password "admin1234"
# 1. Open the seeded enquiry directly
When I visit "/admin/bookings/b_lc_enquiry"
# 2. Approve the enquiry → reserved
When I trigger booking action "action-approve-enquiry"
Then I see "Reserviert"
And the audit log tab includes "Reservierung bestätigt"
# 3. Send the contract manually (bypasses the 365-day cron window)
When I trigger booking action "action-send-contract"
Then the audit log tab includes "Vertrag & Anzahlungsrechnung"
# 4. Record the client's contract signature
When I trigger booking action "action-contract-approved"
Then I see "Anzahlung als erhalten markieren"
# 5. Record the deposit received → confirmed
When I trigger booking action "action-deposit-received"
Then I see "Bestätigt"
And the audit log tab includes "Buchung bestätigt"

View File

@@ -0,0 +1,25 @@
@admin @lifecycle
Feature: Booking lifecycle — rule-based cron assertions
Verifies each cron rule fires against pre-seeded bookings whose dates are
computed relative to today in testReset, so the rules always trigger.
Background:
Given I am logged in as "christina@seminarhof.example" with password "admin1234"
# ── R1: contract + deposit email ────────────────────────────────────────
Scenario: lifecycle R1 — cron sends contract and deposit email to a reserved booking
# b_lc_reserved: reserved, no contractSentAt, startDate 200 days away
Then the lifecycle cron sent 1 contracts
And the audit log for "b_lc_reserved" includes "Vertrag & Anzahlungsrechnung"
# ── R2: deposit reminder ─────────────────────────────────────────────────
Scenario: lifecycle R2 — cron sends deposit reminder when deposit is 7+ days unpaid
# b_lc_contract_sent: contractSentAt 8 days ago, deposit invoice unpaid
Then the lifecycle cron sent 1 reminders
And the audit log for "b_lc_contract_sent" includes "Anzahlungserinnerung"
# ── R4: auto-complete ────────────────────────────────────────────────────
Scenario: lifecycle R4 — cron auto-completes a confirmed booking after it ends
# b_lc_confirmed: confirmed, endDate yesterday
Then the lifecycle cron completed 2 bookings
And the booking "b_lc_confirmed" has status "Beendet"

View File

@@ -0,0 +1,13 @@
@public @events
Feature: Public events listing
Anyone can browse the public retreats listing without logging in. Only
bookings flagged for online listing appear here.
Scenario: visitor sees the published summer retreat
Given I visit "/events"
Then I see "Summer Yoga Retreat 2026"
And I see "Yoga Retreat e.V."
Scenario: unpublished retreats stay hidden
Given I visit "/events"
Then I do not see "Winter Stille 2026"

View File

@@ -0,0 +1,30 @@
@admin @invoices
Feature: Invoice creation and payment recording
Admin issues invoices against a booking and records payments when they
arrive. Both actions create audit trail entries.
Background:
Given I am logged in as "christina@seminarhof.example" with password "admin1234"
When I visit "/admin/bookings/b_yoga_2026_summer"
And I click "Rechnungen"
Scenario: admin creates a final invoice
When I create an invoice numbered "2026-FIN-002" for 1500.00
Then I see "2026-FIN-002"
And I see "Offen"
Scenario: admin creates an invoice with an attached PDF
When I attach invoice PDF "invoice-sample.pdf"
And I create an invoice numbered "2026-PDF-001" for 500.00
Then I see "PDF öffnen"
Scenario: admin records a payment on an outstanding invoice
When I create an invoice numbered "2026-PAY-001" for 250.00
And I mark invoice "2026-PAY-001" as paid on "2026-05-10"
Then I see "Bezahlt"
Scenario: admin cancels an outstanding invoice
When I create an invoice numbered "2026-CXL-001" for 100.00
And I accept the next confirmation
And I click "invoice-cancel-2026-CXL-001"
Then I see "Storniert"