feat: move display-assembly out of BookingPriceCalculator

This commit is contained in:
Björn Fromme
2026-04-16 13:34:54 +02:00
parent d1c92f2957
commit 4d86629315
8 changed files with 1093 additions and 1028 deletions
+287
View File
@@ -0,0 +1,287 @@
<?php
declare(strict_types=1);
namespace App\Tests\Service;
use App\BusProNet\Model\Booking;
use App\BusProNet\Model\Room;
use App\BusProNet\Model\Travel;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Model\RoomSelectionDto;
use App\Service\RoomPricingCalculator;
use PHPUnit\Framework\TestCase;
class RoomPricingCalculatorTest extends TestCase
{
private RoomPricingCalculator $calculator;
protected function setUp(): void
{
$this->calculator = new RoomPricingCalculator();
}
public function testCalculateRoomPricingWithParticipantBasedCalculation(): void
{
$room = new Room();
$room->id = 1;
$room->price = 100.0;
$room->minPax = 2;
$room->label = 'Double Room';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 1;
$roomSelection->quantity = 2;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$bookingDto->participants = [
$this->participantInRoom(1),
$this->participantInRoom(1),
$this->participantInRoom(1),
$this->participantInRoom(1),
];
$result = $this->calculator->calculateRoomPricing($bookingDto);
// 4 assigned participants × €100 = €400 total
$this->assertCount(1, $result);
$this->assertEquals(1, $result[0]['roomId']);
$this->assertEquals('Double Room', $result[0]['label']);
$this->assertEquals(2, $result[0]['quantity']);
$this->assertEquals(4, $result[0]['participantCount']);
$this->assertEquals(100.0, $result[0]['unitPrice']);
$this->assertEquals(400.0, $result[0]['totalPrice']);
}
public function testCalculateRoomPricingWithSingleRoomSelection(): void
{
$room = new Room();
$room->id = 2;
$room->price = 150.0;
$room->minPax = 3;
$room->label = 'Triple Room';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 2;
$roomSelection->quantity = 1;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$bookingDto->participants = [
$this->participantInRoom(2),
$this->participantInRoom(2),
];
$result = $this->calculator->calculateRoomPricing($bookingDto);
// 2 assigned participants × €150 = €300 total
$this->assertCount(1, $result);
$this->assertEquals(2, $result[0]['roomId']);
$this->assertEquals('Triple Room', $result[0]['label']);
$this->assertEquals(1, $result[0]['quantity']);
$this->assertEquals(2, $result[0]['participantCount']);
$this->assertEquals(150.0, $result[0]['unitPrice']);
$this->assertEquals(300.0, $result[0]['totalPrice']);
}
public function testCalculateRoomPricingWithMultipleRoomTypes(): void
{
$singleRoom = new Room();
$singleRoom->id = 1;
$singleRoom->price = 80.0;
$singleRoom->minPax = 1;
$singleRoom->label = 'Single Room';
$doubleRoom = new Room();
$doubleRoom->id = 2;
$doubleRoom->price = 120.0;
$doubleRoom->minPax = 2;
$doubleRoom->label = 'Double Room';
$travel = new Travel();
$travel->rooms = [$singleRoom, $doubleRoom];
$singleRoomSelection = new RoomSelectionDto();
$singleRoomSelection->id = 1;
$singleRoomSelection->quantity = 1;
$doubleRoomSelection = new RoomSelectionDto();
$doubleRoomSelection->id = 2;
$doubleRoomSelection->quantity = 2;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection];
$bookingDto->participants = [
$this->participantInRoom(1),
$this->participantInRoom(2),
$this->participantInRoom(2),
$this->participantInRoom(2),
];
$result = $this->calculator->calculateRoomPricing($bookingDto);
// Single: 1 participant × €80 = €80
// Double: 3 participants × €120 = €360
$this->assertCount(2, $result);
$this->assertEquals(1, $result[0]['roomId']);
$this->assertEquals(1, $result[0]['quantity']);
$this->assertEquals(1, $result[0]['participantCount']);
$this->assertEquals(80.0, $result[0]['unitPrice']);
$this->assertEquals(80.0, $result[0]['totalPrice']);
$this->assertEquals(2, $result[1]['roomId']);
$this->assertEquals(2, $result[1]['quantity']);
$this->assertEquals(3, $result[1]['participantCount']);
$this->assertEquals(120.0, $result[1]['unitPrice']);
$this->assertEquals(360.0, $result[1]['totalPrice']);
}
public function testCalculateRoomPricingSkipsRoomsWithNullPrice(): void
{
$room = new Room();
$room->id = 1;
$room->price = null;
$room->minPax = 2;
$room->label = 'Free Room';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 1;
$roomSelection->quantity = 1;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$result = $this->calculator->calculateRoomPricing($bookingDto);
$this->assertEmpty($result);
}
public function testCalculateRoomPricingWithZeroQuantityRooms(): void
{
$room = new Room();
$room->id = 1;
$room->price = 100.0;
$room->minPax = 2;
$room->label = 'Double Room';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 1;
$roomSelection->quantity = 0;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$result = $this->calculator->calculateRoomPricing($bookingDto);
$this->assertEmpty($result);
}
public function testCalculateRoomPricingShowsSelectedRoomWithZeroAssignments(): void
{
$room = new Room();
$room->id = 1;
$room->price = 100.0;
$room->label = 'Double Room';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 1;
$roomSelection->quantity = 1;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$bookingDto->participants = [];
$result = $this->calculator->calculateRoomPricing($bookingDto);
$this->assertCount(1, $result);
$this->assertEquals(1, $result[0]['roomId']);
$this->assertEquals(1, $result[0]['quantity']);
$this->assertEquals(0, $result[0]['participantCount']);
$this->assertEquals(0.0, $result[0]['totalPrice']);
}
public function testCalculateRoomPricingUsesSelectionModeForStepOneSummary(): void
{
$room = new Room();
$room->id = 3;
$room->price = 229.0;
$room->minPax = 2;
$room->label = 'Doppelzimmer Dusche/WC';
$travel = new Travel();
$travel->rooms = [$room];
$roomSelection = new RoomSelectionDto();
$roomSelection->id = 3;
$roomSelection->quantity = 1;
$bookingDto = new BookingDto($travel, 1);
$bookingDto->roomSelections = [$roomSelection];
$bookingDto->participants = [
$this->participantInRoom(3),
$this->participantInRoom(3),
];
$result = $this->calculator->calculateRoomPricing($bookingDto, RoomPricingCalculator::PRICING_MODE_SELECTION);
$this->assertCount(1, $result);
$this->assertEquals(2, $result[0]['participantCount']);
$this->assertEquals(458.0, $result[0]['totalPrice']);
}
public function testCalculateRoomPricingInEditModeUsesStoredIndividualPrices(): void
{
$travel = new Travel();
$bookingDto = new BookingDto($travel, 2);
$participantA = new ParticipantDto();
$participantA->assignedRoomId = 10;
$participantB = new ParticipantDto();
$participantB->assignedRoomId = 10;
$bookingDto->participants = [$participantA, $participantB];
$booking = new Booking();
$room = new Room();
$room->id = 10;
$room->label = 'Stored Room';
$room->mapping = [0, 1];
$room->individualPrice = [0 => 200.0, 1 => 220.0];
$room->totalCount = 1;
$booking->rooms = [$room];
$bookingDto->booking = $booking;
$result = $this->calculator->calculateRoomPricing($bookingDto);
$this->assertCount(1, $result);
$this->assertEquals(10, $result[0]['roomId']);
$this->assertEquals(2, $result[0]['participantCount']);
$this->assertEquals(210.0, $result[0]['unitPrice']);
$this->assertEquals(420.0, $result[0]['totalPrice']);
}
private function participantInRoom(int $roomId): ParticipantDto
{
$participant = new ParticipantDto();
$participant->assignedRoomId = $roomId;
return $participant;
}
}