Commit Graph
12 Commits
Author SHA1 Message Date
UbuntuandClaude Opus 4.8 0fd7f7a7a5 Fix "Conflict. Timeslot is taken" raw-JSON error on booking
Customers intermittently hit a full-screen raw JSON error when booking:
{"error":"Conflict. Timeslot is taken or does not fit the service."}

booking_process() re-validates the chosen slot at submit time and returned
409/403 raw JSON. Because the public booking form is a full-page POST, that
JSON filled the whole screen.

The trigger is a double submit. After inserting the booking, booking_process()
synchronously runs two Google Calendar createEvent calls, a lunch sync, an ntfy
push and an SMTP confirmation e-mail before redirecting - several seconds - and
the submit button was never disabled. On mobile the guest taps "Send" again; the
second request arrives after the first has committed, so the slot reads as taken.

Evidence: 168 duplicate booking pairs exist in prod (same guest, slot and worker,
consecutive booking ids, including runs of four). All are from 2025, none from
2026 - the 409 guard added around May 2025 converted those silent duplicates
into today's visible error.

Prevent the double submit:
- disable the submit button and relabel it on first submit, ignore later ones
- add a hidden sendBooking field, since disabling a submit button can drop its
  name/value from the POST and booking_process() bails to the homepage without it

Handle it gracefully when it still happens:
- new _booking_error() renders a localised page in the right skin instead of raw
  JSON, replacing all six JSON responses in booking_process()
- new booking-error views for barber/beauty in no/en/hu, each with a message per
  error case and a link back to booking
- new Service_model::getBookingBySlotAndGuest(); if the guest's own booking for
  that exact slot already exists the submit is a duplicate rather than a real
  conflict, so finish normally instead of erroring. Guarded on a non-empty
  e-mail, as admin block bookings are stored with an empty guest_email.

No schema change. Verified on test, dev and prod: friendly page in all three
languages and both skins, double submit redirects to booking-finished without
creating a duplicate row, and no raw JSON in any response.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJso3iGT7TkW5tm4RSBohs
2026-07-21 16:21:53 +00:00
Ubuntu e24e68f603 Fix manage-booking time slots; align modify email with original
- getAvailableTimes() takes optional exclude_booking_id so a guest's
  own booking isn't counted as a conflict when editing — original time
  now reappears when extending services
- Manage-booking AJAX passes manage_token; server resolves to booking_id
- manage_booking_process uses the new param instead of the date-swap
  workaround (removes a small race-condition risk)
- Modify-booking emails (no/en/hu) now include Name/Email/Phone rows
  and the 24h cancellation policy, matching the original booking email
2026-05-10 13:18:07 +00:00
UbuntuandClaude Opus 4.6 6abb90329d Add visual booking calendar (weekly Teams-style view)
- New weekly calendar at /bookings/calendar with time blocks per booking
- Color-coded by worker, overlapping bookings shown side-by-side
- Click booking to see details, edit or delete
- Worker filter dropdown, week navigation (prev/next/today)
- AJAX week loading for smooth navigation
- Link between list view and calendar view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:03:41 +00:00
UbuntuandClaude Opus 4.6 420bcb37fd Security hardening: fix SQLi, XSS, file upload, and migrate DB to RDS
- Fix all SQL injection vulnerabilities across Service_model, User_model,
  Module_model, Log_model, and Admin controller using parameterized queries
- Add htmlspecialchars() to all user-controlled output in admin views
  (bookings, services, workers, service categories, login form)
- Fix XSS in AJAX worker response and manage-booking-cancelled view
- Add file extension whitelist (jpg, jpeg, png, gif, webp) to all uploads
- Remove webshell (pentest2.php) from assets/img/profiles/
- Stop logging plaintext passwords on failed login attempts
- Migrate database.php hostname from localhost to AWS RDS endpoint
- Fix dropdown styling (white-on-white) in worker calendar view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 13:00:32 +00:00
Astral04andClaude Sonnet 4.6 307f17faa6 Fix timezone bug causing slots past closing time; remove lunch fallback outside window
- Add Europe/Oslo timezone to all DateTime constructors in getAvailableTimes() and
  computeLunchBreak() to prevent UTC vs local time mismatch that allowed booking
  slots 1 hour past the worker's end time on same-day bookings
- Remove fallback loop in computeLunchBreak() that pushed the lunch break outside
  the configured window; lunch break is now strictly enforced within the interval

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 11:52:30 +01:00
Astral04andClaude Sonnet 4.6 f30d8d1a07 Fix lunch break: float-to-gap logic + Google Calendar sync
- Lunch slot no longer pre-blocked; a slot is only unavailable if
  booking it would eliminate the last possible 30-min break window
- Added preferred lunch time per worker (closest-to-preferred slot wins)
- Lunch break only applies for shifts >= 6 hours
- Google Calendar: lunch event created/updated/deleted on every
  booking create, modify, or cancel via _syncLunchCalendarEvent()
- New table worker_lunch_gcal_events tracks lunch event IDs per worker/date
- New model methods: getBookingsForWorkerDay, getLunchGcalEventId,
  upsertLunchGcalEventId, deleteLunchGcalEventRecord, getBookingsForWorkerMonth,
  computeLunchBreak

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 21:12:08 +01:00
Astral04andClaude Sonnet 4.6 b8f4f67b23 Add visual worker calendar and floating lunch break system
- Monthly calendar grid per worker with colour-coded day status
- Override types: vacation, sick, custom hours, other, day-off
- Date-range override support via modal
- Floating 30-min lunch break: finds slot closest to preferred time
  within configurable window, adapts to existing bookings
- Lunch break only applies for shifts >= 6 hours
- Lunch slot shown in admin calendar; blocked in booking availability
- DB migrations: absence_type/note on worker_schedule_overrides,
  lunch_window_start/end/preferred_time on workers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 13:34:58 +01:00
Astral04andClaude Sonnet 4.6 bb3a65259b Google Calendar integration for booking notifications
- New GoogleCalendar library: createEvent/updateEvent/deleteEvent via service account, all wrapped in try/catch so failures never break booking flow
- booking_process: creates worker + owner calendar events on new booking
- manage_booking_process: deletes old events, creates new ones on modify
- manage_booking_cancel: deletes events before cancellation
- Service_model: updateBookingCalEvents() stores gcal event IDs
- Admin worker form: Google Calendar ID field added
- PHPMailer: enabled exceptions (was silently swallowing SMTP errors)
- Config: application/config/google_calendar.php for service account path + Evelin calendar ID

DB migration required:
  ALTER TABLE workers ADD COLUMN google_calendar_id VARCHAR(255) NULL DEFAULT NULL;
  ALTER TABLE bookings ADD COLUMN gcal_event_id_worker VARCHAR(255) NULL DEFAULT NULL;
  ALTER TABLE bookings ADD COLUMN gcal_event_id_owner VARCHAR(255) NULL DEFAULT NULL;

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 14:46:58 +01:00
Astral04andClaude Sonnet 4.6 2183c8aff2 guest booking self-management feature + layout fixes
- add manage_token column to bookings (DB migration done)
- generate unique token per booking, include manage link in confirmation emails (no/en/hu)
- new routes: manage-booking, manage-booking-process, manage-booking-cancel
- new views: manage-booking.php, manage-booking-cancelled.php
- 24h cutoff enforcement for cancel/modify; emails sent to guest + studio CC
- fix manage-booking step 3 float layout (overflow:auto BFC clearfix)
- fix booking page time slot overflow: bookingResultsWrapper 378px -> 360px

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 16:01:12 +01:00
Astral04 3a7dd84992 foglalás időpont +1 órás baszakodás 2025-12-16 11:10:33 +01:00
Astral04 45c192058a 3 month limit setup 2025-10-04 13:52:17 +02:00
Astral04 68c8245cef add all files 2025-10-04 11:38:07 +02:00