feat: accommodation booking type and status as dedicated properties

This commit is contained in:
Björn Fromme
2026-08-06 08:52:09 +02:00
parent 2cfa87f44b
commit aa8fa5c1b2
22 changed files with 218 additions and 151 deletions
+15 -12
View File
@@ -11,6 +11,7 @@ use App\Entity\Groups\AccommodationPrice;
use App\Entity\Groups\AdditionalService;
use App\Entity\Groups\BoardService;
use App\Enum\Groups\AccommodationBookingStatus;
use App\Enum\Groups\AccommodationBookingType;
use App\Form\Model\AccommodationBookingDto;
use App\Model\AccommodationBookingQueryParams;
use App\Model\CmsHotelData;
@@ -265,11 +266,11 @@ class AccommodationBookingService
$booking->setPaxCount($dto->paxCount);
$booking->setMinorsCount($dto->minorsCount);
$booking->setChildrenCount($dto->childrenCount);
$booking->setStatus(
$dto->forceInquiry || $this->computeInquiryStatus($dto, $prices)->isInquiry
? AccommodationBookingStatus::Inquiry
: AccommodationBookingStatus::Booking
);
// An inquiry arrives live — the office has nothing to prepare first, so it goes
// straight to Offen. A direct booking is binding on arrival, hence Bestätigt.
$isInquiry = $dto->forceInquiry || $this->computeInquiryStatus($dto, $prices)->isInquiry;
$booking->setType($isInquiry ? AccommodationBookingType::Inquiry : AccommodationBookingType::Booking);
$booking->setStatus($isInquiry ? AccommodationBookingStatus::Open : AccommodationBookingStatus::Accepted);
// Freeze board service as scalar fields (no FK)
if (null !== $dto->selectedBoardServiceId) {
@@ -432,9 +433,9 @@ class AccommodationBookingService
}
/**
* Issues the access link only for a confirmed booking. Inquiries from the public flow
* Issues the access link only for a direct booking. Inquiries from the public flow
* deliberately get no link — the office prepares the offer first and issues the link
* when it switches the booking to Anfrage.
* when it publishes the offer.
*/
public function issueAccessLinkForDirectBooking(AccommodationBooking $booking): void
{
@@ -452,7 +453,7 @@ class AccommodationBookingService
*/
public function sendCustomerConfirmationEmail(AccommodationBooking $booking): void
{
if (!$booking->isInquiry()) {
if ($booking->isAccepted()) {
$subject = 'Deine Buchung ist bestätigt';
} elseif (null !== $booking->getAccessLinkIssuedAt()) {
$subject = 'Dein Angebot ist bereit';
@@ -481,16 +482,18 @@ class AccommodationBookingService
}
/**
* Transitions a booking from inquiry to booking and notifies office and customer.
* Idempotent — a no-op (including no emails) if the booking is already accepted.
* Accepts an open offer and notifies office and customer. The type stays Anfrage —
* only the status moves to Bestätigt, so an offer-originated booking remains
* distinguishable from a direct one.
* Idempotent — a no-op (including no emails) if the offer is not open any more.
*/
public function acceptBooking(AccommodationBooking $booking): void
{
if (!$booking->isInquiry()) {
if (!$booking->isInquiry() || !$booking->isOpen()) {
return;
}
$booking->setStatus(AccommodationBookingStatus::Booking);
$booking->setStatus(AccommodationBookingStatus::Accepted);
$booking->setAcceptedAt(new \DateTimeImmutable());
$this->entityManager->flush();