feat: split summary DTOs into typed sub-objects
This commit is contained in:
@@ -136,7 +136,7 @@ class Step4Controller extends AbstractController
|
|||||||
// Success: Store booking data in flash for conversion tracking
|
// Success: Store booking data in flash for conversion tracking
|
||||||
$bookingCreateContext = $this->createContextFactory->createWithParticipantPrices($bookingCreateDto);
|
$bookingCreateContext = $this->createContextFactory->createWithParticipantPrices($bookingCreateDto);
|
||||||
$this->addFlash('booking_number', $bookingResponse->bookingNumber);
|
$this->addFlash('booking_number', $bookingResponse->bookingNumber);
|
||||||
$this->addFlash('booking_total', $bookingCreateContext->summaryData->payableAmount);
|
$this->addFlash('booking_total', $bookingCreateContext->summaryData->vouchers->payableAmount);
|
||||||
$this->addFlash('booking_travel_name', $bookingCreateDto->travel->label);
|
$this->addFlash('booking_travel_name', $bookingCreateDto->travel->label);
|
||||||
$this->clearTravelDataCache($bookingCreateDto);
|
$this->clearTravelDataCache($bookingCreateDto);
|
||||||
$this->bookingSessionService->clearBookingDto($request, BookingDto::MODE_CREATE);
|
$this->bookingSessionService->clearBookingDto($request, BookingDto::MODE_CREATE);
|
||||||
|
|||||||
@@ -4,22 +4,19 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Form\Model;
|
namespace App\Form\Model;
|
||||||
|
|
||||||
use App\BusProNet\Model\Room;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bundles the data needed to render the booking create flow.
|
* Bundles the data needed to render the booking create flow.
|
||||||
*/
|
*/
|
||||||
class BookingCreateContext
|
class BookingCreateContext
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array{by_pax: array<int, Room>, by_room: array<int, Room>} $groupedRooms
|
* @param array<int, ParticipantCardDataDto>|null $cardsData
|
||||||
* @param array<int, ParticipantCardDataDto>|null $cardsData
|
* @param array<int, float>|null $participantPrices
|
||||||
* @param array<int, float>|null $participantPrices
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly BookingDto $bookingDto,
|
public readonly BookingDto $bookingDto,
|
||||||
public readonly BookingSummaryDto $summaryData,
|
public readonly BookingSummaryDto $summaryData,
|
||||||
public readonly array $groupedRooms,
|
public readonly RoomGroupsDto $groupedRooms,
|
||||||
public readonly ?array $cardsData = null,
|
public readonly ?array $cardsData = null,
|
||||||
public readonly bool $isSubmitted = false,
|
public readonly bool $isSubmitted = false,
|
||||||
public readonly ?array $participantPrices = null,
|
public readonly ?array $participantPrices = null,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Form\Model;
|
namespace App\Form\Model;
|
||||||
|
|
||||||
use App\BusProNet\Model\BaseData;
|
|
||||||
use App\BusProNet\Model\Booking;
|
use App\BusProNet\Model\Booking;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +17,7 @@ class BookingEditContext
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly BookingDto $bookingDto,
|
public readonly BookingDto $bookingDto,
|
||||||
public readonly ?Booking $bookingData,
|
public readonly ?Booking $bookingData,
|
||||||
public readonly ?BaseData $mutableData,
|
public readonly ?BookingMutabilityDto $mutableData,
|
||||||
public readonly BookingSummaryDto $summaryData,
|
public readonly BookingSummaryDto $summaryData,
|
||||||
public readonly ?array $cardsData = null,
|
public readonly ?array $cardsData = null,
|
||||||
public readonly bool $isDirty = false,
|
public readonly bool $isDirty = false,
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Form\Model;
|
||||||
|
|
||||||
|
use App\BusProNet\Model\BaseData;
|
||||||
|
use App\BusProNet\Model\MutableData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typed wrapper for edit-mode mutability data.
|
||||||
|
*/
|
||||||
|
final class BookingMutabilityDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly ?MutableData $participantCount,
|
||||||
|
public readonly ?MutableData $participantData,
|
||||||
|
public readonly ?MutableData $transportation,
|
||||||
|
public readonly ?MutableData $pickup,
|
||||||
|
public readonly ?MutableData $accommodation,
|
||||||
|
public readonly ?MutableData $additionalServices,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromBaseData(?BaseData $baseData): ?self
|
||||||
|
{
|
||||||
|
if (null === $baseData) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self(
|
||||||
|
participantCount: self::getItem($baseData, MutableData::CATEGORY_PARTICIPANT_COUNT),
|
||||||
|
participantData: self::getItem($baseData, MutableData::CATEGORY_PARTICIPANT_DATA),
|
||||||
|
transportation: self::getItem($baseData, MutableData::CATEGORY_TRANSPORTATION),
|
||||||
|
pickup: self::getItem($baseData, MutableData::CATEGORY_PICKUP),
|
||||||
|
accommodation: self::getItem($baseData, MutableData::CATEGORY_ACCOMMODATION),
|
||||||
|
additionalServices: self::getItem($baseData, MutableData::CATEGORY_ADDITIONAL_SERVICES),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getItem(BaseData $baseData, string $key): ?MutableData
|
||||||
|
{
|
||||||
|
$item = $baseData->getItemByKey($key);
|
||||||
|
|
||||||
|
return $item instanceof MutableData ? $item : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,30 +6,17 @@ namespace App\Form\Model;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO containing all booking summary data for sidebar display.
|
* DTO containing all booking summary data for sidebar display.
|
||||||
*
|
|
||||||
* Provides pricing breakdowns, room assignments, participant counts,
|
|
||||||
* and CMS product information in a single typed object.
|
|
||||||
*/
|
*/
|
||||||
class BookingSummaryDto
|
class BookingSummaryDto
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array<int, RoomSelectionDto> $selectedRooms Selected room DTOs from booking
|
* @param array<int, RoomSelectionDto> $selectedRooms Selected room DTOs from booking
|
||||||
* @param int $participantCount Total participant count from room capacity
|
|
||||||
* @param float $totalPrice Total price before voucher deductions
|
|
||||||
* @param float $payableAmount Amount after voucher deductions
|
|
||||||
* @param array<array{room: mixed, count: int}> $groupedSelectedRooms Rooms grouped by participant assignments
|
|
||||||
* @param array<int, int> $assignmentCounts Room ID to participant count mapping
|
|
||||||
* @param array $pricingData Detailed pricing breakdown
|
|
||||||
* @param array|null $cmsData CMS product data (images, etc.)
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly array $selectedRooms,
|
public readonly array $selectedRooms,
|
||||||
public readonly int $participantCount,
|
public readonly int $participantCount,
|
||||||
public readonly float $totalPrice,
|
public readonly BookingSummaryPricingDto $pricing,
|
||||||
public readonly float $payableAmount,
|
public readonly BookingSummaryVoucherDto $vouchers,
|
||||||
public readonly array $groupedSelectedRooms,
|
|
||||||
public readonly array $assignmentCounts,
|
|
||||||
public readonly array $pricingData,
|
|
||||||
public readonly ?array $cmsData,
|
public readonly ?array $cmsData,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Form\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typed pricing section for the booking summary.
|
||||||
|
*/
|
||||||
|
final class BookingSummaryPricingDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<int, array<string, mixed>> $rooms
|
||||||
|
* @param array<int, array<string, mixed>> $services
|
||||||
|
* @param array<int, array<string, mixed>>|null $surcharges
|
||||||
|
* @param array<int, int> $assignmentCounts
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly array $rooms,
|
||||||
|
public readonly array $services,
|
||||||
|
public readonly ?array $surcharges,
|
||||||
|
public readonly array $assignmentCounts,
|
||||||
|
public readonly float $grandTotal,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Form\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typed voucher section for the booking summary.
|
||||||
|
*/
|
||||||
|
final class BookingSummaryVoucherDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly ?AcceptedVouchersDto $acceptedVouchers,
|
||||||
|
public readonly float $payableAmount,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Form\Model;
|
||||||
|
|
||||||
|
use App\BusProNet\Model\Room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typed room grouping used by the booking create flow.
|
||||||
|
*/
|
||||||
|
final class RoomGroupsDto
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<int, Room> $byPax
|
||||||
|
* @param array<int, Room> $byRoom
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly array $byPax,
|
||||||
|
public readonly array $byRoom,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ namespace App\Service;
|
|||||||
|
|
||||||
use App\Form\Model\BookingCreateContext;
|
use App\Form\Model\BookingCreateContext;
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
use App\Form\Model\BookingSummaryDto;
|
||||||
|
use App\Form\Model\RoomGroupsDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the shared view model for booking create.
|
* Prepares the shared view model for booking create.
|
||||||
@@ -60,15 +62,13 @@ class BookingCreateContextFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{summaryData: \App\Form\Model\BookingSummaryDto, groupedRooms: array{by_pax: array<int, \App\BusProNet\Model\Room>, by_room: array<int, \App\BusProNet\Model\Room>}}
|
* @return array{summaryData: BookingSummaryDto, groupedRooms: RoomGroupsDto}
|
||||||
*/
|
*/
|
||||||
private function buildBaseContext(BookingDto $bookingDto, string $pricingMode): array
|
private function buildBaseContext(BookingDto $bookingDto, string $pricingMode): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'summaryData' => $this->summaryDataService->getSummaryData($bookingDto, $pricingMode),
|
'summaryData' => $this->summaryDataService->getSummaryData($bookingDto, $pricingMode),
|
||||||
'groupedRooms' => $this->roomSelectionService->groupRoomsBySelectionType(
|
'groupedRooms' => $this->roomSelectionService->groupRoomsBySelectionType($bookingDto->travel->getAvailableRooms()),
|
||||||
$bookingDto->travel->getAvailableRooms()
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\BusProNet\Model\Booking;
|
|||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingEditContext;
|
use App\Form\Model\BookingEditContext;
|
||||||
use App\Form\Model\BookingSummaryDto;
|
use App\Form\Model\BookingSummaryDto;
|
||||||
|
use App\Form\Model\BookingMutabilityDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the shared booking edit flow context.
|
* Prepares the shared booking edit flow context.
|
||||||
@@ -37,7 +38,9 @@ class BookingEditContextFactory
|
|||||||
return new BookingEditContext(
|
return new BookingEditContext(
|
||||||
bookingDto: $bookingDto,
|
bookingDto: $bookingDto,
|
||||||
bookingData: $bookingData,
|
bookingData: $bookingData,
|
||||||
mutableData: $bookingData ? $this->travelDataService->getMutabilityData($bookingData->dateId) : null,
|
mutableData: BookingMutabilityDto::fromBaseData(
|
||||||
|
$bookingData ? $this->travelDataService->getMutabilityData($bookingData->dateId) : null
|
||||||
|
),
|
||||||
summaryData: $this->createSummaryData($bookingDto),
|
summaryData: $this->createSummaryData($bookingDto),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -52,7 +55,7 @@ class BookingEditContextFactory
|
|||||||
return new BookingEditContext(
|
return new BookingEditContext(
|
||||||
bookingDto: $bookingDto,
|
bookingDto: $bookingDto,
|
||||||
bookingData: $bookingData,
|
bookingData: $bookingData,
|
||||||
mutableData: $this->travelDataService->getMutabilityData($bookingData->dateId),
|
mutableData: BookingMutabilityDto::fromBaseData($this->travelDataService->getMutabilityData($bookingData->dateId)),
|
||||||
summaryData: $this->createSummaryData($bookingDto),
|
summaryData: $this->createSummaryData($bookingDto),
|
||||||
cardsData: $this->participantCardDataService->getAllCardsDataWithValidation($bookingDto),
|
cardsData: $this->participantCardDataService->getAllCardsDataWithValidation($bookingDto),
|
||||||
isDirty: $isDirty,
|
isDirty: $isDirty,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use App\BusProNet\Model\Room;
|
use App\BusProNet\Model\Room;
|
||||||
|
use App\Form\Model\RoomGroupsDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups room data for booking steps.
|
* Groups room data for booking steps.
|
||||||
@@ -13,10 +14,8 @@ class BookingRoomSelectionService
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array<int, Room> $rooms
|
* @param array<int, Room> $rooms
|
||||||
*
|
|
||||||
* @return array{by_pax: array<int, Room>, by_room: array<int, Room>}
|
|
||||||
*/
|
*/
|
||||||
public function groupRoomsBySelectionType(array $rooms): array
|
public function groupRoomsBySelectionType(array $rooms): RoomGroupsDto
|
||||||
{
|
{
|
||||||
$groups = [
|
$groups = [
|
||||||
Room::SELECTION_TYPE_BY_PAX => [],
|
Room::SELECTION_TYPE_BY_PAX => [],
|
||||||
@@ -35,6 +34,9 @@ class BookingRoomSelectionService
|
|||||||
uasort($groups[Room::SELECTION_TYPE_BY_PAX], static fn (Room $a, Room $b): int => $a->maxPax <=> $b->maxPax);
|
uasort($groups[Room::SELECTION_TYPE_BY_PAX], static fn (Room $a, Room $b): int => $a->maxPax <=> $b->maxPax);
|
||||||
uasort($groups[Room::SELECTION_TYPE_BY_ROOM], static fn (Room $a, Room $b): int => $a->maxPax <=> $b->maxPax);
|
uasort($groups[Room::SELECTION_TYPE_BY_ROOM], static fn (Room $a, Room $b): int => $a->maxPax <=> $b->maxPax);
|
||||||
|
|
||||||
return $groups;
|
return new RoomGroupsDto(
|
||||||
|
byPax: $groups[Room::SELECTION_TYPE_BY_PAX],
|
||||||
|
byRoom: $groups[Room::SELECTION_TYPE_BY_ROOM],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ namespace App\Service;
|
|||||||
use App\BusProNet\DataProvider\CountryDataProvider;
|
use App\BusProNet\DataProvider\CountryDataProvider;
|
||||||
use App\BusProNet\Model\Hotel;
|
use App\BusProNet\Model\Hotel;
|
||||||
use App\BusProNet\XmlLoader\HotelLoader;
|
use App\BusProNet\XmlLoader\HotelLoader;
|
||||||
|
use App\Form\Model\AcceptedVouchersDto;
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingSummaryDto;
|
use App\Form\Model\BookingSummaryDto;
|
||||||
|
use App\Form\Model\BookingSummaryPricingDto;
|
||||||
|
use App\Form\Model\BookingSummaryVoucherDto;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Contracts\Cache\CacheInterface;
|
use Symfony\Contracts\Cache\CacheInterface;
|
||||||
use Symfony\Contracts\Cache\ItemInterface;
|
use Symfony\Contracts\Cache\ItemInterface;
|
||||||
@@ -53,18 +56,6 @@ class BookingSummaryDataService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group selected rooms with counts (for display)
|
|
||||||
$groupedSelectedRooms = [];
|
|
||||||
foreach ($roomCounts as $roomId => $count) {
|
|
||||||
$room = $bookingDto->travel->getRoomById($roomId);
|
|
||||||
if (null !== $room) {
|
|
||||||
$groupedSelectedRooms[] = [
|
|
||||||
'room' => $room,
|
|
||||||
'count' => $count,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get detailed pricing breakdown
|
// Get detailed pricing breakdown
|
||||||
$pricingData = $this->priceCalculator->getPricingBreakdown($bookingDto, $roomPricingMode);
|
$pricingData = $this->priceCalculator->getPricingBreakdown($bookingDto, $roomPricingMode);
|
||||||
|
|
||||||
@@ -74,17 +65,29 @@ class BookingSummaryDataService
|
|||||||
// Calculate participant count from room capacity (source of truth)
|
// Calculate participant count from room capacity (source of truth)
|
||||||
$participantCount = $this->calculateParticipantCountFromRooms($bookingDto);
|
$participantCount = $this->calculateParticipantCountFromRooms($bookingDto);
|
||||||
|
|
||||||
|
$acceptedVouchers = $bookingDto->getAcceptedVouchers($participantPrices);
|
||||||
|
|
||||||
// Calculate payable amount after voucher deductions
|
// Calculate payable amount after voucher deductions
|
||||||
$payableAmount = $this->calculatePayableAmount($bookingDto, $pricingData['grandTotal'], $participantPrices);
|
$payableAmount = $this->calculatePayableAmount($pricingData['grandTotal'], $acceptedVouchers);
|
||||||
|
|
||||||
|
$pricing = new BookingSummaryPricingDto(
|
||||||
|
rooms: $pricingData['rooms'],
|
||||||
|
services: $pricingData['services'],
|
||||||
|
surcharges: $pricingData['surcharges'] ?? null,
|
||||||
|
assignmentCounts: $roomCounts,
|
||||||
|
grandTotal: $pricingData['grandTotal'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$vouchers = new BookingSummaryVoucherDto(
|
||||||
|
acceptedVouchers: $acceptedVouchers,
|
||||||
|
payableAmount: $payableAmount,
|
||||||
|
);
|
||||||
|
|
||||||
return new BookingSummaryDto(
|
return new BookingSummaryDto(
|
||||||
selectedRooms: $selectedRooms,
|
selectedRooms: $selectedRooms,
|
||||||
participantCount: $participantCount,
|
participantCount: $participantCount,
|
||||||
totalPrice: $pricingData['grandTotal'],
|
pricing: $pricing,
|
||||||
payableAmount: $payableAmount,
|
vouchers: $vouchers,
|
||||||
groupedSelectedRooms: $groupedSelectedRooms,
|
|
||||||
assignmentCounts: $roomCounts,
|
|
||||||
pricingData: $pricingData,
|
|
||||||
cmsData: $cmsData,
|
cmsData: $cmsData,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -92,12 +95,10 @@ class BookingSummaryDataService
|
|||||||
/**
|
/**
|
||||||
* Calculates the payable amount after voucher deductions.
|
* Calculates the payable amount after voucher deductions.
|
||||||
*
|
*
|
||||||
* @param array<int, float> $participantPrices Prices per participant for percentage voucher calculation
|
* @param AcceptedVouchersDto|null $acceptedVouchers Accepted vouchers for discount calculation
|
||||||
*/
|
*/
|
||||||
private function calculatePayableAmount(BookingDto $bookingDto, float $grandTotal, array $participantPrices): float
|
private function calculatePayableAmount(float $grandTotal, ?AcceptedVouchersDto $acceptedVouchers): float
|
||||||
{
|
{
|
||||||
$acceptedVouchers = $bookingDto->getAcceptedVouchers($participantPrices);
|
|
||||||
|
|
||||||
if (null === $acceptedVouchers) {
|
if (null === $acceptedVouchers) {
|
||||||
return $grandTotal;
|
return $grandTotal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="shrink-0 px-4 lg:px-8 py-4 lg:flex lg:flex-col lg:justify-center shadow-md relative z-10">
|
<div class="shrink-0 px-4 lg:px-8 py-4 lg:flex lg:flex-col lg:justify-center shadow-md relative z-10">
|
||||||
<div class="flex items-center justify-between pb-2">
|
<div class="flex items-center justify-between pb-2">
|
||||||
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
||||||
<span class="font-semibold">{{ summaryData.payableAmount|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ summaryData.vouchers.payableAmount|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span class="block uppercase font-semibold">Buchungsübersicht</span>
|
<span class="block uppercase font-semibold">Buchungsübersicht</span>
|
||||||
@@ -83,8 +83,8 @@
|
|||||||
Zusatzleistungen
|
Zusatzleistungen
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{% if mutableData.items['additional_services'].mutable %}
|
{% if mutableData.additionalServices and mutableData.additionalServices.mutable %}
|
||||||
{{ mutableData.items['additional_services'].mutableBefore|date('d.m.Y') }}
|
{{ mutableData.additionalServices.mutableBefore|date('d.m.Y') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
nicht mehr möglich
|
nicht mehr möglich
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -95,8 +95,8 @@
|
|||||||
Beförderung
|
Beförderung
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{% if mutableData.items['transportation'].mutable %}
|
{% if mutableData.transportation and mutableData.transportation.mutable %}
|
||||||
{{ mutableData.items['transportation'].mutableBefore|date('d.m.Y') }}
|
{{ mutableData.transportation.mutableBefore|date('d.m.Y') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
nicht mehr möglich
|
nicht mehr möglich
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -107,8 +107,8 @@
|
|||||||
Zustiege
|
Zustiege
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{% if mutableData.items['pickup'].mutable %}
|
{% if mutableData.pickup and mutableData.pickup.mutable %}
|
||||||
{{ mutableData.items['pickup'].mutableBefore|date('d.m.Y') }}
|
{{ mutableData.pickup.mutableBefore|date('d.m.Y') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
nicht mehr möglich
|
nicht mehr möglich
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -119,8 +119,8 @@
|
|||||||
Unterkunft
|
Unterkunft
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{% if mutableData.items['accommodation'].mutable %}
|
{% if mutableData.accommodation and mutableData.accommodation.mutable %}
|
||||||
{{ mutableData.items['accommodation'].mutableBefore|date('d.m.Y') }}
|
{{ mutableData.accommodation.mutableBefore|date('d.m.Y') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
nicht mehr möglich
|
nicht mehr möglich
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -131,13 +131,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Rooms Section #}
|
{# Rooms Section #}
|
||||||
{% if summaryData.pricingData.rooms is not empty %}
|
{% if summaryData.pricing.rooms is not empty %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
Unterkunft
|
Unterkunft
|
||||||
</div>
|
</div>
|
||||||
<table class="w-full table-fixed">
|
<table class="w-full table-fixed">
|
||||||
{% for roomPricing in summaryData.pricingData.rooms %}
|
{% for roomPricing in summaryData.pricing.rooms %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="p-2 align-top">
|
<td class="p-2 align-top">
|
||||||
{{ roomPricing.quantity }}x {{ roomPricing.label }}
|
{{ roomPricing.quantity }}x {{ roomPricing.label }}
|
||||||
@@ -152,12 +152,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Services Section #}
|
{# Services Section #}
|
||||||
{% if summaryData.pricingData.services is not empty %}
|
{% if summaryData.pricing.services is not empty %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
Leistungen
|
Leistungen
|
||||||
</div>
|
</div>
|
||||||
{% for serviceGroup in summaryData.pricingData.services %}
|
{% for serviceGroup in summaryData.pricing.services %}
|
||||||
<div class="p-2 text-primary-dark/70 uppercase font-semibold">
|
<div class="p-2 text-primary-dark/70 uppercase font-semibold">
|
||||||
{{ serviceGroup.groupName }}
|
{{ serviceGroup.groupName }}
|
||||||
</div>
|
</div>
|
||||||
@@ -178,13 +178,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Surcharges Section (Edit mode only) #}
|
{# Surcharges Section (Edit mode only) #}
|
||||||
{% if summaryData.pricingData.surcharges is defined and summaryData.pricingData.surcharges is not empty %}
|
{% if summaryData.pricing.surcharges is not empty %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
Zu-/Abschläge
|
Zu-/Abschläge
|
||||||
</div>
|
</div>
|
||||||
<table class="w-full table-fixed">
|
<table class="w-full table-fixed">
|
||||||
{% for surchargePricing in summaryData.pricingData.surcharges %}
|
{% for surchargePricing in summaryData.pricing.surcharges %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-2 pb-2 align-top">
|
<td class="px-2 pb-2 align-top">
|
||||||
{{ surchargePricing.participantCount }}x {{ surchargePricing.label }}
|
{{ surchargePricing.participantCount }}x {{ surchargePricing.label }}
|
||||||
@@ -199,9 +199,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Total Section #}
|
{# Total Section #}
|
||||||
{% if summaryData.totalPrice > 0 %}
|
{% if summaryData.pricing.grandTotal > 0 %}
|
||||||
{# Show subtotal and voucher discounts when vouchers are applied #}
|
{# Show subtotal and voucher discounts when vouchers are applied #}
|
||||||
{% set acceptedVouchers = bookingDto.getAcceptedVouchers() %}
|
{% set acceptedVouchers = summaryData.vouchers.acceptedVouchers %}
|
||||||
{% if acceptedVouchers and acceptedVouchers.hasVouchers() %}
|
{% if acceptedVouchers and acceptedVouchers.hasVouchers() %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
Gesamtpreis
|
Gesamtpreis
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 pb-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="px-2 pb-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{{ summaryData.totalPrice|format_currency('EUR') }}
|
{{ summaryData.pricing.grandTotal|format_currency('EUR') }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{# Voucher discounts breakdown #}
|
{# Voucher discounts breakdown #}
|
||||||
@@ -239,12 +239,12 @@
|
|||||||
{# Amount to pay after vouchers #}
|
{# Amount to pay after vouchers #}
|
||||||
<div class="flex items-center justify-between px-2 pb-2">
|
<div class="flex items-center justify-between px-2 pb-2">
|
||||||
<span class="block uppercase font-semibold">Zu zahlen</span>
|
<span class="block uppercase font-semibold">Zu zahlen</span>
|
||||||
<span class="font-semibold">{{ summaryData.payableAmount|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ summaryData.vouchers.payableAmount|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="flex items-center justify-between pb-2">
|
<div class="flex items-center justify-between pb-2">
|
||||||
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
||||||
<span class="font-semibold">{{ summaryData.payableAmount|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ summaryData.vouchers.payableAmount|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -65,19 +65,19 @@
|
|||||||
{% block room_selection_form %}
|
{% block room_selection_form %}
|
||||||
<div id="room-selection-form"{% if htmx_oob_swap is defined and htmx_oob_swap %} hx-swap-oob="true"{% endif %}>
|
<div id="room-selection-form"{% if htmx_oob_swap is defined and htmx_oob_swap %} hx-swap-oob="true"{% endif %}>
|
||||||
{{ form_errors(form) }}
|
{{ form_errors(form) }}
|
||||||
{% if bookingCreateContext.groupedRooms.by_room is not empty %}
|
{% if bookingCreateContext.groupedRooms.byRoom is not empty %}
|
||||||
<h3>
|
<h3>
|
||||||
Zimmer
|
Zimmer
|
||||||
</h3>
|
</h3>
|
||||||
{% for roomId, room in bookingCreateContext.groupedRooms.by_room %}
|
{% for roomId, room in bookingCreateContext.groupedRooms.byRoom %}
|
||||||
{{ _self.stepFormField(form.roomSelections[roomId]) }}
|
{{ _self.stepFormField(form.roomSelections[roomId]) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if bookingCreateContext.groupedRooms.by_pax is not empty %}
|
{% if bookingCreateContext.groupedRooms.byPax is not empty %}
|
||||||
<h3>
|
<h3>
|
||||||
Betten
|
Betten
|
||||||
</h3>
|
</h3>
|
||||||
{% for roomId, room in bookingCreateContext.groupedRooms.by_pax %}
|
{% for roomId, room in bookingCreateContext.groupedRooms.byPax %}
|
||||||
{{ _self.stepFormField(form.roomSelections[roomId]) }}
|
{{ _self.stepFormField(form.roomSelections[roomId]) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<div class="shrink-0 px-4 lg:px-8 py-4 lg:flex lg:flex-col lg:justify-center shadow-md relative z-10">
|
<div class="shrink-0 px-4 lg:px-8 py-4 lg:flex lg:flex-col lg:justify-center shadow-md relative z-10">
|
||||||
<div class="flex items-center justify-between pb-2">
|
<div class="flex items-center justify-between pb-2">
|
||||||
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
||||||
<span class="font-semibold">{{ bookingCreateContext.summaryData.payableAmount|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ bookingCreateContext.summaryData.vouchers.payableAmount|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span class="block uppercase font-semibold">Buchungsübersicht</span>
|
<span class="block uppercase font-semibold">Buchungsübersicht</span>
|
||||||
@@ -132,18 +132,18 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{# Rooms Section #}
|
{# Rooms Section #}
|
||||||
{% if bookingCreateContext.summaryData.pricingData.rooms is not empty %}
|
{% if bookingCreateContext.summaryData.pricing.rooms is not empty %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
Unterkunft
|
Unterkunft
|
||||||
</div>
|
</div>
|
||||||
<table class="w-full table-fixed">
|
<table class="w-full table-fixed">
|
||||||
{% for roomPricing in bookingCreateContext.summaryData.pricingData.rooms %}
|
{% for roomPricing in bookingCreateContext.summaryData.pricing.rooms %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="p-2 align-top">
|
<td class="p-2 align-top">
|
||||||
<div>{{ roomPricing.quantity }}x {{ roomPricing.label }}</div>
|
<div>{{ roomPricing.quantity }}x {{ roomPricing.label }}</div>
|
||||||
{% if bookingCreateContext.summaryData.assignmentCounts[roomPricing.roomId] is defined %}
|
{% if bookingCreateContext.summaryData.pricing.assignmentCounts[roomPricing.roomId] is defined %}
|
||||||
<div class="text-sm text-gray-600">{{ bookingCreateContext.summaryData.assignmentCounts[roomPricing.roomId] }} Person(en) belegt</div>
|
<div class="text-sm text-gray-600">{{ bookingCreateContext.summaryData.pricing.assignmentCounts[roomPricing.roomId] }} Person(en) belegt</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="p-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
@@ -156,12 +156,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Services Section #}
|
{# Services Section #}
|
||||||
{% if bookingCreateContext.summaryData.pricingData.services is not empty %}
|
{% if bookingCreateContext.summaryData.pricing.services is not empty %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
Leistungen
|
Leistungen
|
||||||
</div>
|
</div>
|
||||||
{% for serviceGroup in bookingCreateContext.summaryData.pricingData.services %}
|
{% for serviceGroup in bookingCreateContext.summaryData.pricing.services %}
|
||||||
<div class="p-2 text-primary-dark/70 uppercase font-semibold">
|
<div class="p-2 text-primary-dark/70 uppercase font-semibold">
|
||||||
{{ serviceGroup.groupName }}
|
{{ serviceGroup.groupName }}
|
||||||
</div>
|
</div>
|
||||||
@@ -462,8 +462,8 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{# Grand Total #}
|
{# Grand Total #}
|
||||||
{% if bookingCreateContext.summaryData.pricingData.grandTotal is defined and bookingCreateContext.summaryData.pricingData.grandTotal > 0 %}
|
{% if bookingCreateContext.summaryData.pricing.grandTotal > 0 %}
|
||||||
{% set acceptedVouchers = bookingCreateContext.bookingDto.getAcceptedVouchers() %}
|
{% set acceptedVouchers = bookingCreateContext.summaryData.vouchers.acceptedVouchers %}
|
||||||
{% if acceptedVouchers and acceptedVouchers.hasVouchers() %}
|
{% if acceptedVouchers and acceptedVouchers.hasVouchers() %}
|
||||||
<div class="border border-primary-bg mb-4">
|
<div class="border border-primary-bg mb-4">
|
||||||
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
<div class="p-2 bg-primary-bg uppercase font-semibold">
|
||||||
@@ -475,7 +475,7 @@
|
|||||||
Gesamtpreis
|
Gesamtpreis
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 pb-2 align-top w-24 text-right whitespace-nowrap">
|
<td class="px-2 pb-2 align-top w-24 text-right whitespace-nowrap">
|
||||||
{{ bookingCreateContext.summaryData.pricingData.grandTotal|format_currency('EUR') }}
|
{{ bookingCreateContext.summaryData.pricing.grandTotal|format_currency('EUR') }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% for voucher in acceptedVouchers.vouchers %}
|
{% for voucher in acceptedVouchers.vouchers %}
|
||||||
@@ -498,12 +498,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between px-2 pb-4">
|
<div class="flex items-center justify-between px-2 pb-4">
|
||||||
<span class="block uppercase font-semibold">Zu zahlen</span>
|
<span class="block uppercase font-semibold">Zu zahlen</span>
|
||||||
<span class="font-semibold">{{ bookingCreateContext.summaryData.payableAmount|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ bookingCreateContext.summaryData.vouchers.payableAmount|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="flex items-center justify-between pb-4">
|
<div class="flex items-center justify-between pb-4">
|
||||||
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
<span class="block uppercase font-semibold">Gesamtpreis</span>
|
||||||
<span class="font-semibold">{{ bookingCreateContext.summaryData.pricingData.grandTotal|format_currency('EUR') }}</span>
|
<span class="font-semibold">{{ bookingCreateContext.summaryData.pricing.grandTotal|format_currency('EUR') }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\BusProNet\Model\Room;
|
|||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingCreateContext;
|
use App\Form\Model\BookingCreateContext;
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
use App\Form\Model\RoomGroupsDto;
|
||||||
use App\Form\Model\ParticipantCardDataDto;
|
use App\Form\Model\ParticipantCardDataDto;
|
||||||
use App\Form\Model\ParticipantCardPriceDto;
|
use App\Form\Model\ParticipantCardPriceDto;
|
||||||
use App\Form\Model\BookingSummaryDto;
|
use App\Form\Model\BookingSummaryDto;
|
||||||
@@ -56,13 +57,14 @@ class BookingCreateContextFactoryTest extends TestCase
|
|||||||
->willReturn($summaryData);
|
->willReturn($summaryData);
|
||||||
|
|
||||||
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
||||||
|
$groupedRooms = new RoomGroupsDto(
|
||||||
|
byPax: [$roomByPax->id => $roomByPax],
|
||||||
|
byRoom: [$roomByRoom->id => $roomByRoom],
|
||||||
|
);
|
||||||
$roomSelectionService->expects($this->once())
|
$roomSelectionService->expects($this->once())
|
||||||
->method('groupRoomsBySelectionType')
|
->method('groupRoomsBySelectionType')
|
||||||
->with([$roomByRoom->id => $roomByRoom, $roomByPax->id => $roomByPax])
|
->with([$roomByRoom->id => $roomByRoom, $roomByPax->id => $roomByPax])
|
||||||
->willReturn([
|
->willReturn($groupedRooms);
|
||||||
Room::SELECTION_TYPE_BY_PAX => [$roomByPax->id => $roomByPax],
|
|
||||||
Room::SELECTION_TYPE_BY_ROOM => [$roomByRoom->id => $roomByRoom],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
||||||
$participantCardDataService->expects($this->never())
|
$participantCardDataService->expects($this->never())
|
||||||
@@ -86,10 +88,7 @@ class BookingCreateContextFactoryTest extends TestCase
|
|||||||
$this->assertSame($summaryData, $context->summaryData);
|
$this->assertSame($summaryData, $context->summaryData);
|
||||||
$this->assertSame(null, $context->cardsData);
|
$this->assertSame(null, $context->cardsData);
|
||||||
$this->assertFalse($context->isSubmitted);
|
$this->assertFalse($context->isSubmitted);
|
||||||
$this->assertSame([
|
$this->assertSame($groupedRooms, $context->groupedRooms);
|
||||||
Room::SELECTION_TYPE_BY_PAX => [$roomByPax->id => $roomByPax],
|
|
||||||
Room::SELECTION_TYPE_BY_ROOM => [$roomByRoom->id => $roomByRoom],
|
|
||||||
], $context->groupedRooms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateWithParticipantCardsBuildsStep2Context(): void
|
public function testCreateWithParticipantCardsBuildsStep2Context(): void
|
||||||
@@ -124,13 +123,14 @@ class BookingCreateContextFactoryTest extends TestCase
|
|||||||
->willReturn($summaryData);
|
->willReturn($summaryData);
|
||||||
|
|
||||||
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
||||||
|
$groupedRooms = new RoomGroupsDto(
|
||||||
|
byPax: [],
|
||||||
|
byRoom: [$room->id => $room],
|
||||||
|
);
|
||||||
$roomSelectionService->expects($this->once())
|
$roomSelectionService->expects($this->once())
|
||||||
->method('groupRoomsBySelectionType')
|
->method('groupRoomsBySelectionType')
|
||||||
->with([$room->id => $room])
|
->with([$room->id => $room])
|
||||||
->willReturn([
|
->willReturn($groupedRooms);
|
||||||
Room::SELECTION_TYPE_BY_PAX => [],
|
|
||||||
Room::SELECTION_TYPE_BY_ROOM => [$room->id => $room],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
||||||
$participantCardDataService->expects($this->once())
|
$participantCardDataService->expects($this->once())
|
||||||
@@ -181,13 +181,14 @@ class BookingCreateContextFactoryTest extends TestCase
|
|||||||
->willReturn($summaryData);
|
->willReturn($summaryData);
|
||||||
|
|
||||||
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
$roomSelectionService = $this->createMock(BookingRoomSelectionService::class);
|
||||||
|
$groupedRooms = new RoomGroupsDto(
|
||||||
|
byPax: [],
|
||||||
|
byRoom: [$room->id => $room],
|
||||||
|
);
|
||||||
$roomSelectionService->expects($this->once())
|
$roomSelectionService->expects($this->once())
|
||||||
->method('groupRoomsBySelectionType')
|
->method('groupRoomsBySelectionType')
|
||||||
->with([$room->id => $room])
|
->with([$room->id => $room])
|
||||||
->willReturn([
|
->willReturn($groupedRooms);
|
||||||
Room::SELECTION_TYPE_BY_PAX => [],
|
|
||||||
Room::SELECTION_TYPE_BY_ROOM => [$room->id => $room],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
$participantCardDataService = $this->createMock(ParticipantCardDataService::class);
|
||||||
$participantCardDataService->expects($this->never())
|
$participantCardDataService->expects($this->never())
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ namespace App\Tests\Service;
|
|||||||
|
|
||||||
use App\BusProNet\Model\BaseData;
|
use App\BusProNet\Model\BaseData;
|
||||||
use App\BusProNet\Model\Booking;
|
use App\BusProNet\Model\Booking;
|
||||||
|
use App\BusProNet\Model\MutableData;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
use App\Form\Model\BookingMutabilityDto;
|
||||||
use App\Form\Model\BookingEditContext;
|
use App\Form\Model\BookingEditContext;
|
||||||
use App\Form\Model\BookingSummaryDto;
|
use App\Form\Model\BookingSummaryDto;
|
||||||
use App\Service\BookingEditContextFactory;
|
use App\Service\BookingEditContextFactory;
|
||||||
@@ -51,7 +53,9 @@ class BookingEditContextFactoryTest extends TestCase
|
|||||||
$bookingData = new Booking();
|
$bookingData = new Booking();
|
||||||
$bookingData->dateId = 1234;
|
$bookingData->dateId = 1234;
|
||||||
|
|
||||||
$mutableData = new BaseData([]);
|
$mutableData = new BaseData([
|
||||||
|
MutableData::CATEGORY_ADDITIONAL_SERVICES => new MutableData(MutableData::CATEGORY_ADDITIONAL_SERVICES, true, new \DateTimeImmutable('2030-01-02')),
|
||||||
|
]);
|
||||||
$summaryData = $this->createMock(BookingSummaryDto::class);
|
$summaryData = $this->createMock(BookingSummaryDto::class);
|
||||||
|
|
||||||
$summaryDataService = $this->createMock(BookingSummaryDataService::class);
|
$summaryDataService = $this->createMock(BookingSummaryDataService::class);
|
||||||
@@ -77,7 +81,9 @@ class BookingEditContextFactoryTest extends TestCase
|
|||||||
$this->assertInstanceOf(BookingEditContext::class, $context);
|
$this->assertInstanceOf(BookingEditContext::class, $context);
|
||||||
$this->assertSame($bookingDto, $context->bookingDto);
|
$this->assertSame($bookingDto, $context->bookingDto);
|
||||||
$this->assertSame($bookingData, $context->bookingData);
|
$this->assertSame($bookingData, $context->bookingData);
|
||||||
$this->assertSame($mutableData, $context->mutableData);
|
$this->assertInstanceOf(BookingMutabilityDto::class, $context->mutableData);
|
||||||
|
$this->assertSame($mutableData->getItemByKey(MutableData::CATEGORY_ADDITIONAL_SERVICES), $context->mutableData->additionalServices);
|
||||||
|
$this->assertNull($context->mutableData->transportation);
|
||||||
$this->assertSame($summaryData, $context->summaryData);
|
$this->assertSame($summaryData, $context->summaryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Tests\Service;
|
namespace App\Tests\Service;
|
||||||
|
|
||||||
use App\BusProNet\Model\Room;
|
use App\BusProNet\Model\Room;
|
||||||
|
use App\Form\Model\RoomGroupsDto;
|
||||||
use App\Service\BookingRoomSelectionService;
|
use App\Service\BookingRoomSelectionService;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
@@ -27,8 +28,9 @@ class BookingRoomSelectionServiceTest extends TestCase
|
|||||||
|
|
||||||
$groups = $this->service->groupRoomsBySelectionType($rooms);
|
$groups = $this->service->groupRoomsBySelectionType($rooms);
|
||||||
|
|
||||||
$this->assertSame([10, 12], array_keys($groups[Room::SELECTION_TYPE_BY_PAX]));
|
$this->assertInstanceOf(RoomGroupsDto::class, $groups);
|
||||||
$this->assertSame([11], array_keys($groups[Room::SELECTION_TYPE_BY_ROOM]));
|
$this->assertSame([10, 12], array_keys($groups->byPax));
|
||||||
|
$this->assertSame([11], array_keys($groups->byRoom));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createRoom(int $id, string $label, int $maxPax): Room
|
private function createRoom(int $id, string $label, int $maxPax): Room
|
||||||
|
|||||||
Reference in New Issue
Block a user