chore: add documentation
This commit is contained in:
@@ -7,11 +7,20 @@ use App\Model\TimelineItem;
|
||||
use Carbon\CarbonPeriod;
|
||||
use function Symfony\Component\String\b;
|
||||
|
||||
/**
|
||||
* Service for processing assignments into timeline visualization data.
|
||||
* Organizes assignments and dispositions by hotel in a timeline format,
|
||||
* handling overlapping dates by distributing items across multiple rows.
|
||||
*/
|
||||
class TimelineService
|
||||
{
|
||||
/**
|
||||
* @param Assignment[] $assignments
|
||||
* @return array
|
||||
* Preprocesses assignments into a timeline structure organized by hotel.
|
||||
* Creates timeline items for both vacant assignment slots and actual dispositions,
|
||||
* distributing them across multiple rows to avoid date overlaps.
|
||||
*
|
||||
* @param Assignment[] $assignments Array of assignments to process
|
||||
* @return array Multi-dimensional array: [hotelCode][rowIndex][itemKey] => TimelineItem
|
||||
*/
|
||||
public function preprocess(array $assignments): array
|
||||
{
|
||||
@@ -34,18 +43,21 @@ class TimelineService
|
||||
$dispositionsCount = $assignment->getDispositions()->count();
|
||||
$dispositionsAvailable = $assignment->getAvailableDispositions();
|
||||
|
||||
// Handle assignments with no dispositions - create items for all available slots
|
||||
if (0 === $dispositionsCount) {
|
||||
$item = TimelineItem::fromAssignment($assignment);
|
||||
for ($i = 1; $i <= $assignment->getAvailableDispositions(); $i++) {
|
||||
$this->addItem($rows[$hotelCode], $item);
|
||||
}
|
||||
} else {
|
||||
// Create items for remaining vacant slots if any
|
||||
if ($dispositionsCount < $dispositionsAvailable) {
|
||||
$item = TimelineItem::fromAssignment($assignment);
|
||||
for ($i = 1; $i <= $dispositionsAvailable - $dispositionsCount; $i++) {
|
||||
$this->addItem($rows[$hotelCode], $item);
|
||||
}
|
||||
}
|
||||
// Create items for actual dispositions
|
||||
foreach ($assignment->getDispositions() as $disposition) {
|
||||
$item = TimelineItem::fromDisposition($disposition);
|
||||
$this->addItem($rows[$hotelCode], $item);
|
||||
@@ -56,15 +68,25 @@ class TimelineService
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a timeline item to the appropriate row, ensuring no date overlaps.
|
||||
* Finds the first available row where the item doesn't overlap with existing items,
|
||||
* or creates a new row if necessary.
|
||||
*
|
||||
* @param array $rows Reference to the rows array for a specific hotel
|
||||
* @param TimelineItem $item The timeline item to add
|
||||
*/
|
||||
private function addItem(array &$rows, TimelineItem $item): void
|
||||
{
|
||||
$rowIndex = 0;
|
||||
$fitsRow = false;
|
||||
|
||||
// Find first row where item doesn't overlap with existing items
|
||||
foreach ($rows as $index => $row) {
|
||||
$fitsRow = true;
|
||||
foreach ($row as $entry) {
|
||||
/** @var TimelineItem $entry */
|
||||
// Check for date overlap: item overlaps if its end >= entry start AND item start <= entry end
|
||||
if ($entry->getDateTo() >= $item->getDateFrom() && $entry->getDateFrom() <= $item->getDateTo()) {
|
||||
$fitsRow = false;
|
||||
}
|
||||
@@ -75,6 +97,7 @@ class TimelineService
|
||||
}
|
||||
}
|
||||
|
||||
// If no existing row fits, create a new row
|
||||
if (false === $fitsRow) {
|
||||
++$rowIndex;
|
||||
}
|
||||
@@ -82,6 +105,13 @@ class TimelineService
|
||||
$rows[$rowIndex][$item->getKey()] = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a time window for timeline visualization.
|
||||
* Returns a period from 6 weeks ago to 6 months in the future,
|
||||
* providing context for both recent and upcoming assignments.
|
||||
*
|
||||
* @return CarbonPeriod The active time window for timeline display
|
||||
*/
|
||||
public function getActiveWindow(): CarbonPeriod
|
||||
{
|
||||
$dateFrom = (new \DateTimeImmutable())->modify('-6 weeks');
|
||||
|
||||
Reference in New Issue
Block a user