FileMaster
Search
Toggle Dark Mode
Home
/
.
/
wp-content
/
plugins
/
latepoint
/
lib
/
misc
Edit File: booking_resource.php
<?php /* * Copyright (c) 2022 LatePoint LLC. All rights reserved. */ namespace LatePoint\Misc; class BookingResource { public int $agent_id; public int $service_id; public int $location_id; public int $max_capacity; public int $min_capacity; public int $min_capacity_to_be_blocked; public int $timeblock_interval; public string $date; public array $work_time_periods = []; public array $booked_time_periods = []; // time periods that are usually part of work periods but a blocked now for some reason(time past today), // it's different from booked periods, because they have no bookings public array $blocked_time_periods = []; public array $slots = []; public array $bookable_minutes = []; public array $work_minutes = []; function __construct( $args = [] ) { $allowed_props = self::allowed_props(); foreach ( $args as $key => $arg ) { if ( in_array( $key, $allowed_props ) ) { $this->$key = $arg; } } } /** * @return \OsAgentModel */ function get_agent(): \OsAgentModel { return ( $this->agent_id ) ? new \OsAgentModel( $this->agent_id ) : new \OsAgentModel(); } protected function retrieve_service_data() { $service = new \OsServiceModel( $this->service_id ); $this->max_capacity = $service->capacity_max; $this->timeblock_interval = $service->timeblock_interval ? intval( $service->timeblock_interval ) : \OsSettingsHelper::get_default_timeblock_interval(); $this->min_capacity_to_be_blocked = $service->get_capacity_needed_before_slot_is_blocked(); } public function get_timeblock_interval() { if ( isset( $this->timeblock_interval ) ) { return $this->timeblock_interval; } else { $this->retrieve_service_data(); return $this->timeblock_interval; } } public function get_min_capacity_to_be_blocked() { if ( isset( $this->min_capacity_to_be_blocked ) ) { return $this->min_capacity_to_be_blocked; } else { $this->retrieve_service_data(); return $this->min_capacity_to_be_blocked; } } public function get_max_capacity() { if ( isset( $this->max_capacity ) ) { return $this->max_capacity; } else { $this->retrieve_service_data(); return $this->max_capacity; } } /** * @param BookingRequest $booking_request * @param int $selectable_time_interval * @return void */ public function build_bookable_slots( BookingRequest $booking_request, int $selectable_time_interval ) { $this->slots = []; $this->work_minutes = []; foreach ( $this->work_time_periods as $time_period ) { for ( $minute = $time_period->start_time; $minute <= $time_period->end_time - $booking_request->duration; $minute += $selectable_time_interval ) { $period = new TimePeriod( [ 'start_time' => $minute - $booking_request->buffer_before, 'end_time' => $minute + $booking_request->duration + $booking_request->buffer_after, ] ); $this->work_minutes[] = $minute; // add booking slot $slot = new BookingSlot(); $slot->start_date = $this->date; $slot->start_time = $minute; $slot->max_capacity = $this->get_max_capacity(); $slot->min_capacity_to_be_blocked = $this->get_min_capacity_to_be_blocked(); // --------------------- // LOGIC FOR "BOOKED" PERIODS // --------------------- foreach ( $this->booked_time_periods as $booked_period ) { if ( $booked_period->start_time_with_buffer() >= $period->end_time || $booked_period->end_time_with_buffer() <= $period->start_time ) { // not intersected } else { // intersects with a booked period, disqualify it if ( $booked_period->service_id != $this->service_id ) { // if it's a different service being performed - block full capacity of a slot, because you can't share capacities between different services $slot->booked_capacity = $this->max_capacity; } else { $slot->booked_capacity += $booked_period->total_attendees; } } } // --------------------- // LOGIC FOR "BLOCKED" PERIODS // --------------------- foreach ( $this->blocked_time_periods as $blocked_period ) { if ( $blocked_period->start_time >= $period->end_time || $blocked_period->end_time <= $period->start_time ) { // not intersected } else { // intersects with a blocked period, disqualify it $slot->booked_capacity = $slot->max_capacity; } } $this->slots[] = $slot; } } } // Function to print the intersection private function find_intersection( array $time_periods ) { // First interval $start = $time_periods[0]->start_time; $end = $time_periods[0]->end_time; // Check rest of the intervals and find the intersection $total = count( $time_periods ); for ( $i = 1; $i < $total; $i++ ) { // If no intersection exists if ( $time_periods[ $i ]->start_time > $end || $time_periods[ $i ]->end_time < $start ) { return []; } else { // Else update the intersection $start = max( $start, $time_periods[ $i ]->start_time ); $end = min( $end, $time_periods[ $i ]->end_time ); } } return new TimePeriod( [ 'start_time' => $start, 'end_time' => $end, ] ); } public function add_blocked_period( BlockedPeriod $blocked_period ) { $this->blocked_time_periods[] = $blocked_period; } public function add_booked_period( BookedPeriod $booked_period, $block_full_capacity = false ) { if ( $block_full_capacity ) { $max_capacity_booked_period = clone $booked_period; $max_capacity_booked_period->total_attendees = $this->max_capacity; $this->booked_time_periods[] = $max_capacity_booked_period; } else { $this->booked_time_periods[] = $booked_period; } } public function add_available_periods( array $work_period_groups ) { $available_periods = []; foreach ( $work_period_groups as $group_work_periods ) { // loop through groups, if multiple group - add them by comparing them against each other $available_periods = ( $available_periods ) ? $this->compare_periods( $available_periods, $group_work_periods ) : $group_work_periods; } $this->work_time_periods = $available_periods; } private function compare_periods( array $available_periods, array $periods_to_intersect ): array { $intersects = []; foreach ( $available_periods as $available_period ) { foreach ( $periods_to_intersect as $intersect_period ) { $intersect = $this->find_intersection( [ $available_period, $intersect_period ] ); if ( $intersect ) { $intersects[] = $intersect; } } } return $intersects; } public function intersect_time_period( TimePeriod $time_period ) { } // TODO instead of trying to find overlaps, just add a period and then overlaps can be skipped using array_unique for available minutes public function add_time_period( TimePeriod $time_period_to_add ) { $overlapped_time_periods = []; $not_overlapped_time_periods = []; // search for all periods that overlap, to later merge them into one foreach ( $this->work_time_periods as $time_period ) { if ( $time_period->check_if_overlaps( $time_period_to_add ) ) { $overlapped_time_periods[] = $time_period; } else { $not_overlapped_time_periods[] = $time_period; } } if ( $overlapped_time_periods ) { // if overlapping periods were found - find a unified range between them and create a new list of available time // periods which should include those that were not overlapped $this->work_time_periods = $not_overlapped_time_periods; $merged_time_period = TimePeriod::get_unified_period_from_overlapped_periods( $merged_time_period ); $this->work_time_periods[] = $merged_time_period; } else { // nothing was overlapped, simply add this time period $this->work_time_periods[] = $time_period_to_add; } } public function generate_resource_id(): string { return $this->agent_id . '_' . $this->service_id . '_' . $this->location_id; } public static function create_from_connection( \OsConnectorModel $connection ): BookingResource { $booking_request = new BookingResource( [ 'agent_id' => $connection->agent_id, 'service_id' => $connection->service_id, 'location_id' => $connection->location_id, ] ); $booking_request->retrieve_service_data(); return $booking_request; } public static function allowed_props(): array { return [ 'agent_id', 'service_id', 'location_id', 'date', 'start_time', 'end_time', ]; } }
Save
Back