*/ #[ORM\Column(type: Types::JSON)] private array $additionalServices = []; /** @var array|null */ #[ORM\Column(type: Types::JSON, nullable: true)] private ?array $priceBreakdown = null; #[ORM\Column(nullable: true)] private ?int $totalPrice = null; #[ORM\Column(length: 3, nullable: true)] private ?string $pricingCurrency = null; #[ORM\Column(type: Types::SMALLINT, nullable: true)] private ?int $pricingVersion = null; #[ORM\Column(length: 20, enumType: AccommodationBookingStatus::class)] private AccommodationBookingStatus $status = AccommodationBookingStatus::Draft; /** * What kind of record this is — an offer the customer still has to accept, or a * directly placed, binding booking. Independent of the status: an accepted offer * keeps its Inquiry type, which is how offer-originated bookings stay recognisable. */ #[ORM\Column(length: 20, enumType: AccommodationBookingType::class)] private AccommodationBookingType $type = AccommodationBookingType::Inquiry; #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $accessLinkIssuedAt = null; #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $acceptedAt = null; /** * When the office validated the requested services and capacities and released the * booking confirmation to the customer — deliberately distinct from acceptedAt, which * only records that the customer committed. */ #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] private ?\DateTimeImmutable $confirmedAt = null; #[ORM\Column(length: 255, nullable: true)] #[Assert\NotBlank(groups: ['edit'])] private ?string $groupName = null; #[ORM\Column(length: 10, nullable: true)] private ?string $salutation = null; #[ORM\Column(length: 100, nullable: true)] #[Assert\NotBlank(groups: ['edit'])] private ?string $firstName = null; #[ORM\Column(length: 100, nullable: true)] #[Assert\NotBlank(groups: ['edit'])] private ?string $lastName = null; /** * The `offer` group covers the one field a customer-facing booking cannot do without: * the access link and every notification are addressed to it. It is enforced on * creation as soon as the booking is not a draft, while `edit` additionally demands * the rest of the contact data. */ #[ORM\Column(length: 255, nullable: true)] #[Assert\NotBlank(groups: ['edit', 'offer'])] #[Assert\Email(groups: ['edit', 'offer'])] private ?string $email = null; #[ORM\Column(length: 50, nullable: true)] private ?string $phone = null; #[ORM\Column(length: 255, nullable: true)] private ?string $street = null; #[ORM\Column(length: 20, nullable: true)] private ?string $zip = null; #[ORM\Column(length: 100, nullable: true)] private ?string $city = null; #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $remarks = null; #[ORM\Column(nullable: true)] #[Assert\Range(min: 1, max: 100)] private ?int $accommodationDiscount = null; #[ORM\Column(nullable: true)] #[Assert\Range(min: 1, max: 100)] private ?int $boardServiceDiscount = null; #[ORM\Column(nullable: true)] #[Assert\Range(min: 1, max: 100)] private ?int $additionalServicesDiscount = null; #[ORM\ManyToOne] #[ORM\JoinColumn(onDelete: 'SET NULL')] private ?User $managedBy = null; public function __construct() { $this->uuid = Uuid::v4()->toRfc4122(); } public function getId(): ?int { return $this->id; } public function getUuid(): string { return $this->uuid; } public function getAccommodation(): ?Accommodation { return $this->accommodation; } public function setAccommodation(?Accommodation $accommodation): self { $this->accommodation = $accommodation; return $this; } public function getDateFrom(): ?\DateTimeImmutable { return $this->dateFrom; } public function setDateFrom(\DateTimeImmutable $dateFrom): self { $this->dateFrom = $dateFrom; return $this; } public function getDateTo(): ?\DateTimeImmutable { return $this->dateTo; } public function setDateTo(\DateTimeImmutable $dateTo): self { $this->dateTo = $dateTo; return $this; } public function getNights(): int { if (null === $this->dateFrom || null === $this->dateTo) { return 0; } return $this->dateFrom->diff($this->dateTo)->days; } public function getPaxCount(): int { return $this->paxCount; } public function setPaxCount(int $paxCount): self { $this->paxCount = $paxCount; return $this; } public function getMinorsCount(): int { return $this->minorsCount; } public function setMinorsCount(int $minorsCount): self { $this->minorsCount = $minorsCount; return $this; } public function getChildrenCount(): int { return $this->childrenCount; } public function setChildrenCount(int $childrenCount): self { $this->childrenCount = $childrenCount; return $this; } public function getBoardServiceLabel(): ?string { return $this->boardServiceLabel; } public function setBoardServiceLabel(?string $boardServiceLabel): self { $this->boardServiceLabel = $boardServiceLabel; return $this; } public function getBoardServicePrice(): ?int { return $this->boardServicePrice; } public function setBoardServicePrice(?int $boardServicePrice): self { $this->boardServicePrice = $boardServicePrice; return $this; } public function getBoardServiceOriginalId(): ?int { return $this->boardServiceOriginalId; } public function setBoardServiceOriginalId(?int $boardServiceOriginalId): self { $this->boardServiceOriginalId = $boardServiceOriginalId; return $this; } /** @return list */ public function getAdditionalServices(): array { return $this->additionalServices; } /** @param list $additionalServices */ public function setAdditionalServices(array $additionalServices): self { $this->additionalServices = $additionalServices; return $this; } public function addAdditionalServiceSnapshot(string $label, int $price, AdditionalServiceType|string $type, ?int $originalServiceId): self { $this->additionalServices[] = [ 'label' => $label, 'price' => $price, 'type' => $type instanceof AdditionalServiceType ? $type->value : $type, 'originalServiceId' => $originalServiceId, ]; return $this; } /** @return array|null */ public function getPriceBreakdown(): ?array { return $this->priceBreakdown; } /** @param array $priceBreakdown */ public function setPriceSnapshot(array $priceBreakdown, int $totalPrice, string $currency, int $version): self { $this->priceBreakdown = $priceBreakdown; $this->totalPrice = $totalPrice; $this->pricingCurrency = $currency; $this->pricingVersion = $version; return $this; } public function clearPriceSnapshot(): self { $this->priceBreakdown = null; $this->totalPrice = null; $this->pricingCurrency = null; $this->pricingVersion = null; return $this; } public function getTotalPrice(): ?int { return $this->totalPrice; } public function getPricingCurrency(): ?string { return $this->pricingCurrency; } public function getPricingVersion(): ?int { return $this->pricingVersion; } public function getStatus(): AccommodationBookingStatus { return $this->status; } public function setStatus(AccommodationBookingStatus $status): self { $this->status = $status; return $this; } public function isDraft(): bool { return AccommodationBookingStatus::Draft === $this->status; } public function isOpen(): bool { return AccommodationBookingStatus::Open === $this->status; } public function isReceived(): bool { return AccommodationBookingStatus::Received === $this->status; } public function isConfirmed(): bool { return AccommodationBookingStatus::Confirmed === $this->status; } public function isDiscarded(): bool { return AccommodationBookingStatus::Discarded === $this->status; } public function getType(): AccommodationBookingType { return $this->type; } public function setType(AccommodationBookingType $type): self { $this->type = $type; return $this; } public function isInquiry(): bool { return AccommodationBookingType::Inquiry === $this->type; } public function isBooking(): bool { return AccommodationBookingType::Booking === $this->type; } public function getAccessLinkIssuedAt(): ?\DateTimeImmutable { return $this->accessLinkIssuedAt; } public function setAccessLinkIssuedAt(?\DateTimeImmutable $accessLinkIssuedAt): self { $this->accessLinkIssuedAt = $accessLinkIssuedAt; return $this; } public function getAcceptedAt(): ?\DateTimeImmutable { return $this->acceptedAt; } public function setAcceptedAt(?\DateTimeImmutable $acceptedAt): self { $this->acceptedAt = $acceptedAt; return $this; } public function getConfirmedAt(): ?\DateTimeImmutable { return $this->confirmedAt; } public function setConfirmedAt(?\DateTimeImmutable $confirmedAt): self { $this->confirmedAt = $confirmedAt; return $this; } public function getGroupName(): ?string { return $this->groupName; } public function setGroupName(?string $groupName): self { $this->groupName = $groupName; return $this; } public function getSalutation(): ?string { return $this->salutation; } public function setSalutation(?string $salutation): self { $this->salutation = $salutation; return $this; } public function getFirstName(): ?string { return $this->firstName; } public function setFirstName(?string $firstName): self { $this->firstName = $firstName; return $this; } public function getLastName(): ?string { return $this->lastName; } public function setLastName(?string $lastName): self { $this->lastName = $lastName; return $this; } public function getEmail(): ?string { return $this->email; } public function setEmail(?string $email): self { $this->email = $email; return $this; } public function getPhone(): ?string { return $this->phone; } public function setPhone(?string $phone): self { $this->phone = $phone; return $this; } public function getStreet(): ?string { return $this->street; } public function setStreet(?string $street): self { $this->street = $street; return $this; } public function getZip(): ?string { return $this->zip; } public function setZip(?string $zip): self { $this->zip = $zip; return $this; } public function getCity(): ?string { return $this->city; } public function setCity(?string $city): self { $this->city = $city; return $this; } public function getRemarks(): ?string { return $this->remarks; } public function setRemarks(?string $remarks): self { $this->remarks = $remarks; return $this; } public function getAccommodationDiscount(): ?int { return $this->accommodationDiscount; } public function setAccommodationDiscount(?int $accommodationDiscount): self { $this->accommodationDiscount = $accommodationDiscount; return $this; } public function getBoardServiceDiscount(): ?int { return $this->boardServiceDiscount; } public function setBoardServiceDiscount(?int $boardServiceDiscount): self { $this->boardServiceDiscount = $boardServiceDiscount; return $this; } public function getAdditionalServicesDiscount(): ?int { return $this->additionalServicesDiscount; } public function setAdditionalServicesDiscount(?int $additionalServicesDiscount): self { $this->additionalServicesDiscount = $additionalServicesDiscount; return $this; } public function getManagedBy(): ?User { return $this->managedBy; } public function setManagedBy(?User $managedBy): self { $this->managedBy = $managedBy; return $this; } }