| Server IP : 34.87.99.72 / Your IP : 216.73.217.31 Web Server : Apache/2.4.46 (Unix) OpenSSL/1.1.1n System : Linux zlock-bitnami-lamp-prod-v2-vm 4.19.0-16-cloud-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 User : bitnami ( 1000) PHP Version : 7.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /opt/bitnami/apache/htdocs/app/app/Http/Services/ |
Upload File : |
<?php
namespace App\Http\Services;
use App\Http\Services\LockerBoxTypeService;
use Carbon\Carbon;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use App\Models\LockerSchedule;
use App\Models\UserCredit;
class PriceCalculationService{
public function __construct(
LockerBoxTypeService $lockerBoxTypeService
)
{
$this->lockerBoxTypeService = $lockerBoxTypeService;
}
public $booking_fees_minute = 60;
public $max_overtime_minute = 4500;
public $overtime_fees_minute = 60;
public $include_free_time = true;
public function computeBookingPrice(Array $request)
{
$box_type = $this->lockerBoxTypeService->lockerBoxTypeInfo([
"id" => $request['box_size_id'],
]);
$price_per_min = $box_type->booking_fees / $this->booking_fees_minute;
$total_booking_minutes = $request['reserved_minute'];
// free time
$total_free_time_minutes = 0;
if($this->include_free_time && isset($request['type'])){
if($request['type'] == 'inventory_booking')
{
$free_times = $this->getNonOperationHours([
"locker_id" =>$request['locker_id'],
"date" => now(),
]);
$today = today()->format('Y-m-d ');
$reserved_time = new CarbonPeriod(now(), now()->add($total_booking_minutes,'minute'));
foreach ($free_times as $free_time) {
$start_time = $free_time->start_time;
$end_time = $free_time->end_time;
if($start_time > $end_time)
$end_time->addDay();
$free_time_period = new CarbonPeriod($start_time->format('Y-m-d H:i:s'), $end_time->format('Y-m-d H:i:s'));
$total_free_time_minutes += round($this->calculatePeriodsOverlap($reserved_time, $free_time_period)->totalMinutes) * -1;
}
}
}
// \Debugbar::info($total_free_time_minutes);
$price_per_hour = $price_per_min * 60;
$total_hour_booked = ceil(($total_booking_minutes - $total_free_time_minutes)/60);
$final_price = $total_hour_booked * $price_per_hour;
return number_format((float)$final_price, 2, '.', '');
}
public function computeOvertimePrice(Array $request)
{
$expired_at = new Carbon($request['expired_at']);
$now = $request['now'];
if($now <= $expired_at)
return number_format(0.00, 2, '.', '');
if(isset($request['box_size_id'])){
$box_type = $this->lockerBoxTypeService->lockerBoxTypeInfo([
"id" => $request['box_size_id'],
]);
}else{
$box_type = $request['box_size'];
}
$price_per_min = $box_type->overtime_fees / $this->overtime_fees_minute;
// OLD PENALTY CODE
// $booking_end_of_day = $this->getBookingEndOfDay($request);
// if($now > $booking_end_of_day)
// $total_overtime_minutes = $expired_at->diffInMinutes($booking_end_of_day);
// else
// $total_overtime_minutes = $expired_at->diffInMinutes($now);
$total_overtime_minutes = min($expired_at->diffInMinutes($now), $this->max_overtime_minute);
// free time
$total_free_time_minutes = 0;
if($this->include_free_time){
$free_times = LockerSchedule::where('locker_id',$request['locker_id'])
->where('type_id',LockerSchedule::SPECIAL_DAY)
->where('date',now()->format('Y-m-d'))
->get();
$reserved_time = new CarbonPeriod(now(), now()->add($total_overtime_minutes,'minute'));
foreach ($free_times as $free_time) {
$free_time_period = new CarbonPeriod($free_time->start_time->format('Y-m-d H:i:s'), $free_time->end_time->format('Y-m-d H:i:s') );
$total_free_time_minutes += round($this->calculatePeriodsOverlap($reserved_time, $free_time_period)->totalMinutes) * -1;
}
}
$price_per_hour = $price_per_min * 60;
$total_hour_overtime = ceil(($total_overtime_minutes - $total_free_time_minutes)/60);
//OLD PENALTY CODE
// $is_penalized = $now > $booking_end_of_day;
// if($is_penalized)
// $final_price = ($total_hour_overtime * $price_per_hour) + 1;
// else
// $final_price = $total_hour_overtime * $price_per_hour;
$is_penalized = false;
$final_price = $total_hour_overtime * $price_per_hour;
$result = [
"overtime_price" => number_format((float)$final_price, 2, '.', ''),
"has_penalty" => $is_penalized,
"total_hour_overtime" => $total_hour_overtime,
];
return $result;
}
public function calculatePeriodsOverlap(CarbonPeriod $periodA, CarbonPeriod $periodB)
{
if (!$periodA->overlaps($periodB)) {
return new CarbonInterval(0);
}
$firstEndDate = min($periodA->calculateEnd(), $periodB->calculateEnd());
$latestStartDate = max($periodA->getStartDate(), $periodB->getStartDate());
return CarbonInterval::make($firstEndDate->diff($latestStartDate));
}
public function getMinimumWalletCap(Array $request)
{
$non_operations_hour = LockerSchedule::where('locker_id',$request['locker_id'])
->where('type_id',LockerSchedule::WEEKLY)
->get();
if($non_operations_hour->isEmpty())
return [
'wallet_cap' => UserCredit:: TWENTY_FOUR_HOUR_OPERATION_CAP,
'error_message' => 'Minimum wallet credit of RM' . UserCredit:: TWENTY_FOUR_HOUR_OPERATION_CAP . ' is required to book the locker.',
];
else
return [
'wallet_cap' => UserCredit:: TWELVE_HOUR_OPERATION_CAP,
'error_message' => 'Minimum wallet credit of RM' . UserCredit:: TWELVE_HOUR_OPERATION_CAP . ' is required to book the locker.',
];
}
public function getMinutesOverlap(Array $request)
{
$non_operations_hours = $this->getNonOperationHours([
"locker_id" =>$request['locker_id'],
"date" => now(),
]);
if($non_operations_hours->isEmpty())
return 0;
else
{
$today = today()->format('Y-m-d ');
$non_operations_hour = $non_operations_hours[0];
$start_time = $non_operations_hour->start_time;
$end_time = $non_operations_hour->end_time;
if($start_time > $end_time)
$end_time->addDay();
if($request['type'] == 'inventory_booking')
$reserved_time = new CarbonPeriod(now(), now()->add($request['reserved_minute'],'minute'));
else{
return now() > $start_time && now() < $end_time;
}
$non_operations_hour_period = new CarbonPeriod($start_time->format('Y-m-d H:i:s'), $end_time->format('Y-m-d H:i:s') );
return round($this->calculatePeriodsOverlap($reserved_time, $non_operations_hour_period)->totalMinutes);
}
}
public function getBookingEndOfDay(Array $request)
{
$expired_at = Carbon::parse($request['expired_at']);
$non_operations_hours = $this->getNonOperationHours([
"locker_id" => $request['locker_id'],
"date" => $expired_at,
]);
$now = now();
if($non_operations_hours->isEmpty())
{
$cut_off = Carbon::parse(LockerSchedule::TWENTY_FOUR_HOUR_CUT_OFF_TIME);
}
else
{
$non_operations_hour = $non_operations_hours[0];
$cut_off = $non_operations_hour->start_time;
}
$diff_days = $cut_off->diffInDays($expired_at);
if($diff_days>0)
{
$cut_off = $cut_off->subDays($diff_days);
}
else if($expired_at > $cut_off)
{
$cut_off->addDays(1);
}
return $cut_off;
}
public function getNonOperationHours(Array $request)
{
return LockerSchedule::where('locker_id',$request['locker_id'])
->where('type_id',LockerSchedule::WEEKLY)
->where('day', $request['date']->dayOfWeek)
->get();
}
}