Server : Apache System : Linux 145.162.205.92.host.secureserver.net 5.14.0-611.45.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 1 05:56:53 EDT 2026 x86_64 User : tradze ( 1001) PHP Version : 8.1.34 Disable Function : NONE Directory : /home/tradze/www/test.tradze.com/app/Modules/Schedules/Repositories/ |
<?php
namespace App\Modules\Schedules\Repositories;
use App\Modules\Invoices\Repositories\BookingInvoiceRepository;
use App\Modules\Schedules\Models\BookingOrder;
use App\Modules\Schedules\Models\Schedule;
use App\Modules\Postcodes\Models\Postcode;
use App\Modules\Services\Models\ServiceDuration;
use App\Modules\Services\Models\ServiceType;
use App\Modules\Users\Repositories\MessageThreadRepository;
use App\Modules\Vouchers\Models\Voucher;
use App\Modules\Vouchers\Repositories\VoucherRepository;
use App\User;
use App\Modules\Services\Models\FocalPoint;
use App\Modules\Schedules\Models\ScheduleDaysOff;
use Bican\Roles\Models\Role;
use Braintree\Transaction;
use Carbon\Carbon;
use Cmgmyr\Messenger\Models\Message;
use Cmgmyr\Messenger\Models\Participant;
use Cmgmyr\Messenger\Models\Thread;
use GoogleMaps\GoogleMaps;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Mockery\CountValidator\Exception;
use App\Modules\Notifications\Facades\NotifRepository;
use Omnipay\Omnipay;
class BookingRepository {
/**
* Get available therapists
* @return array
*/
public function therapists() {
$booking = Session::get('booking');
// return $booking;
$users = collect();
//if one of mandatory fields is missing, return empty array results
$mandatory_fields = ['postcode', 'duration', 'massage', 'date'];
foreach ($mandatory_fields as $field) {
if (!isset($booking[$field]))
return $users;
} //endforeach
//get postcode zone
$postcode = Postcode::where('postcode', $booking['postcode'])->first();
//users are not available for the past dates
$today = Carbon::today();
$dateC = Carbon::createFromFormat('Y-m-d', $booking['date']);
$diff = $today->diffInHours($dateC, false);
if ($diff < 0)
return $users;
//query therapists
DB::enableQueryLog();
$users = User::OfTherapists()
->whereHas('servicetypes', function ($query) use ($booking) {
if (isset($booking['massage']) && $booking['massage'] > 0)
$query->where('users_servicetype.servicetype_id', $booking['massage']);
return $query;
})
// ->whereHas('zones', function ($query) use ($postcode) {
// $query->where('users_area_coverage.zone_id', $postcode->zone_id);
// return $query;
// })
->whereHas('workingdays', function ($query) use ($booking) {
if (!array_key_exists('hour', $booking))
return $query;
$weekday = date('w', strtotime($booking['date']));
$hour = $booking['hour'] . ':00';
$duration = ServiceDuration::find($booking['duration'])->duration;
$hourEnd = Carbon::createFromFormat('H:i:s', $hour)->addMinutes($duration)->format('H:i:s');
if (strtotime($hour) > strtotime($hourEnd))
return $query->where('id', '-1');
$query->where('dayoff', 0);
$query->where('weekday', $weekday);
$query->whereRaw("TIME(STR_TO_DATE(bo_start, '%H:%i')) <= TIME(STR_TO_DATE('{$hour}','%H:%i')) and TIME(STR_TO_DATE(bo_end, '%H:%i')) >= TIME(STR_TO_DATE('{$hourEnd}','%H:%i'))");
return $query;
})
// ->whereDoesntHave('daysoff', function ($query) use ($booking) {
// if (!isset($booking['hour']))
// return $query;
//
// $dateHour = $booking['date'].' '.$booking['hour'].':00';
// $query->whereRaw("STR_TO_DATE('{$dateHour}','%Y-%m-%d %H:%i') between date_start and date_end");
// return $query;
// })
->whereDoesntHave('daysoff', function ($query) use ($booking) {
if (!isset($booking['hour']))
return $query;
$duration = ServiceDuration::find($booking['duration'])->duration;
$dateHour = $booking['date'] . ' ' . $booking['hour'] . ':00';
$dateHourEnd = $booking['date'] . ' ' . date('H:i', strtotime($booking['hour'] . "+{$duration} minutes")) . ':00';
$query->whereRaw('STR_TO_DATE("' . $dateHour . '","%Y-%m-%d %H:%i") between date_start and date_end')
->orWhereRaw('STR_TO_DATE("' . $dateHourEnd . '","%Y-%m-%d %H:%i") between date_start and date_end');
// $query->whereRaw('STR_TO_DATE("'.$dateHour.'","%Y-%m-%d %H:%i") between date_start and date_end');
// $query->whereRaw('STR_TO_DATE("'.$dateHour.'","%Y-%m-%d %H:%i") between SUBTIME(SUBTIME(date_start,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00") and ADDTIME(ADDTIME(date_end,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00")');
// $query->whereRaw("STR_TO_DATE('{$dateHour}','%Y-%m-%d %H:%i') between SUBTIME(date_start, STR_TO_DATE(CONCAT(FLOOR({$duration}/60):MOD({$duration},60)),\"%h:%i:%s\"))) and date_end");
return $query;
})
// ->where(function($query) use ($booking){
// if ($booking['selected_therapists']){
//// $query->whereIn('id',$booking['selected_therapists']);
// }
// return $query;
// })
// ->where(function($query) use ($booking){
// if (isset($booking['hour'])){
// $query->whereDoesntHave('therapistbookings', function($query) use ($booking){
// $query->where('date',$booking['date']);
// $query->whereRaw('`hour` between SUBTIME("'.$booking['hour'].'","00:15:00") and ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")),"0:15:00")');
// });
// }
//
// return $query;
// })
->get();
// if (isset($booking['hour'])){
// foreach ($users as $key => $u) {
//
// //remove user if has booking
// $count = $u->therapistbookings()
// ->where('date', $booking['date'])
// ->whereRaw('`hour` between SUBTIME("' . $booking['hour'] . '","00:15:00") and ADDTIME(ADDTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")),"0:15:00")')
// ->whereHas('booking', function ($query) {
// return $query->where('is_active', 1);
// })
// ->count();
// if ($count) $users->forget($key);
//
// //remove user if he is selected into a basket
// $countSession = $u->sessionBlockedTherapists()
// ->where('date', $booking['date'])
// ->whereRaw('`hour` between SUBTIME("' . $booking['hour'] . '","00:15:00") and ADDTIME(ADDTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(duration_min/60),\':\',MOD(duration_min,60)),"%h:%i:%s")),"0:15:00")')
// ->count();
// if ($countSession) $users->forget($key);
//
//
// //check if user has a day off
//
//
//
// } //end foreach: ecxclude users from results
//
// } //endif
// dd($users);
//unselect unavailable selected users
if (isset($booking['selected_therapists'])) {
$usersAvailable = [];
foreach ($users as $usr)
$usersAvailable[] = $usr->id;
foreach ($booking['selected_therapists'] as $key => $selected) {
if (!in_array($selected, $usersAvailable))
unset($booking['selected_therapists'][$key]);
}
Session::put('booking', $booking);
}
if (isset($booking['hour']) && isset($booking['duration'])) {
$duration = ServiceDuration::find($booking['duration']);
$bufferMin = 55;
$buffer = $duration->duration + 55;
foreach ($users as $key => $u) {
//remove user is he has already a booking at selected date&hour + duration interval
$count = $u->therapistbookings()
->where('date', $booking['date'])
->where(function($query) use ($booking, $duration, $buffer, $bufferMin) {
return $query->whereRaw('
TIME("' . $booking['hour'] . '") BETWEEN SUBTIME(`hour`,STR_TO_DATE(CONCAT(FLOOR(' . $buffer . '/60),\':\',MOD(' . $buffer . ',60)),"%h:%i:%s")) AND ADDTIME(`hour`,STR_TO_DATE(CONCAT(FLOOR((duration+' . $bufferMin . ')/60),\':\',MOD((duration+' . $bufferMin . '),60)),"%h:%i:%s"))
');
})
// ->where(function($query) use ($booking, $duration, $buffer, $bufferMin){
// return $query->whereRaw('
// `hour` between SUBTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:15:00")
// OR
// ADDTIME(`hour`, STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")) BETWEEN SUBTIME("'.$booking['hour'].'", STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s") )AND ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:15:00")
// OR
// "'.$booking['hour'].'" between SUBTIME(hour,STR_TO_DATE(CONCAT(FLOOR('.$bufferMin.'/60),\':\',MOD('.$bufferMin.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME(hour,STR_TO_DATE(CONCAT(FLOOR('.$bufferMin.'/60),\':\',MOD('.$bufferMin.',60)),"%h:%i:%s")),"0:00:00")
// OR
// "'.$booking['hour'].'" between SUBTIME(hour,STR_TO_DATE(CONCAT(FLOOR('.$bufferMin.'/60),\':\',MOD('.$bufferMin.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME(hour,STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")),"0:00:00")
// ');
//
// })
// ->where(function($query) use ($booking, $duration, $buffer, $bufferMin){
// return $query->whereRaw('
// `hour` between SUBTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:00:00")
// OR
// ADDTIME(`hour`, STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")) BETWEEN SUBTIME("'.$booking['hour'].'", "00:55:00") AND ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:00:00")
// OR
// "'.$booking['hour'].'" between SUBTIME(hour,STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME(hour,STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:00:00")
// ');
//
// })
// ->where(function($query) use ($booking, $duration, $buffer){
// return $query->whereRaw('
// `hour` between SUBTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")) and ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:15:00")
// OR
// ADDTIME(`hour`, STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")) BETWEEN SUBTIME("'.$booking['hour'].'", STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s") )AND ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR('.$buffer.'/60),\':\',MOD('.$buffer.',60)),"%h:%i:%s")),"0:15:00")
// ');
//
// })
->whereHas('booking', function($query) {
return $query->where('is_active', 1);
})
->count();
// if ($u->id==86)
// dd([
// 'booking'=>$booking,
// 'bufferMin'=>$bufferMin,
// 'buffer'=>$buffer,
// 'count' => $count
// ]);
if ($count)
$users->forget($key);
//remove user if he is selected into a basket at the same date&hour + duration interval
// $countSession = $u->sessionBlockedTherapists()
// ->where('date',$booking['date'])
// ->whereRaw('`hour` between SUBTIME("'.$booking['hour'].'","'.$buffer.'") and ADDTIME(ADDTIME("'.$booking['hour'].'",STR_TO_DATE(CONCAT(FLOOR(duration_min/60),\':\',MOD(duration_min,60)),"%h:%i:%s")),"'.$buffer.'")')
// ->count();
$countSession = $u->sessionBlockedTherapists()
->where('date', $booking['date'])
->where(function($query) use ($booking, $duration, $buffer, $bufferMin) {
return $query->whereRaw('
`hour` between SUBTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(' . $buffer . '/60),\':\',MOD(' . $buffer . ',60)),"%h:%i:%s")) and ADDTIME(ADDTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(' . $buffer . '/60),\':\',MOD(' . $buffer . ',60)),"%h:%i:%s")),"0:00:00")
OR
ADDTIME(`hour`, STR_TO_DATE(CONCAT(FLOOR(duration_min/60),\':\',MOD(duration_min,60)),"%h:%i:%s")) BETWEEN SUBTIME("' . $booking['hour'] . '", "00:55:00") AND ADDTIME(ADDTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(' . $buffer . '/60),\':\',MOD(' . $buffer . ',60)),"%h:%i:%s")),"0:00:00")
');
})
->count();
if ($countSession)
$users->forget($key);
} //end foreach
} //endif
//unselect unavailable selected users
if (isset($booking['selected_therapists'])) {
$usersAvailable = [];
foreach ($users as $usr)
$usersAvailable[] = $usr->id;
foreach ($booking['selected_therapists'] as $key => $selected) {
if (!in_array($selected, $usersAvailable))
unset($booking['selected_therapists'][$key]);
}
Session::put('booking', $booking);
}
//return results
return $users;
}
/**
* Get available therapists right now based on their location and google time travel estimation
* @return array
*/
public function therapistsNow() {
$users = collect();
$booking = Session::get('booking');
$booking['date'] = Carbon::today()->format('Y-m-d');
$booking['hour'] = Carbon::today()->format('H:i');
//check if the current date is marked as day off
$daysOff = $this->days_off($booking['date']);
if ($daysOff->count())
return $users;
//get weekday working hours: if weekday is non working day, return
$weekday = date('w', strtotime($booking['date']));
$whours = Schedule::where('weekday', $weekday)->where('open', 1)->first();
if (!$whours)
return $users;
//the therapists can be booked only in working hours of the weekday
if (strtotime($whours->bo_end) < strtotime(date('H:i')))
return $users;
// dd("here", $whours->bo_start, strtotime(date('H:i')));
//if the start working day hour is bigger then the current hour, return no therapists
if (strtotime($whours->bo_start) > strtotime(date('H:i')))
return $users;
//if the current hour + desired massage duration exceed closing time, return no therapists
if (isset($booking['duration'])) {
$checkduration = ServiceDuration::find($booking['duration'])->duration;
if (strtotime($whours->bo_end) < strtotime(date('H:i') . "+{$checkduration} minutes"))
return $users;
}
//if one of mandatory fields is missing, return empty array results
$mandatory_fields = ['postcode', 'duration', 'massage', 'date'];
foreach ($mandatory_fields as $field) {
if (!isset($booking[$field]))
return $users;
} //endforeach
//get postcode zone
$postcode = Postcode::where('postcode', $booking['postcode'])->first();
//users are not available for the past dates
$today = Carbon::today();
$dateC = Carbon::createFromFormat('Y-m-d', $booking['date']);
$diff = $today->diffInHours($dateC, false);
if ($diff < 0)
return $users;
//query therapists
// DB::enableQueryLog();
$users = User::OfTherapists()
->with('servicetypes','mywork')
->whereHas('servicetypes', function ($query) use ($booking) {
if (isset($booking['massage']) && $booking['massage'] > 0)
$query->where('users_servicetype.servicetype_id', $booking['massage']);
return $query;
})
// ->whereHas('zones', function ($query) use ($postcode) {
// $query->where('users_area_coverage.zone_id', $postcode->zone_id);
// return $query;
// })
->whereHas('workingdays', function ($query) use ($booking) {
$weekday = date('w', strtotime($booking['date']));
$hour = Carbon::now()->format('H:i:s');
$duration = ServiceDuration::find($booking['duration'])->duration;
$hourEnd = Carbon::createFromFormat('H:i:s', $hour)->addMinutes($duration)->format('H:i:s');
if (strtotime($hour) > strtotime($hourEnd))
return $query->where('id', '-1');
// dd($hour);
$query->where('dayoff', 0);
$query->where('weekday', $weekday);
$query->whereRaw("TIME(STR_TO_DATE(bo_start, '%H:%i')) <= TIME(STR_TO_DATE('{$hour}','%H:%i')) and TIME(STR_TO_DATE(bo_end, '%H:%i')) >= TIME(STR_TO_DATE('{$hourEnd}','%H:%i'))");
return $query;
})
// ->whereHas('profile', function ($query) {
// $query->where('massage_me_now', 1);
// return $query;
// })
->whereDoesntHave('daysoff', function ($query) use ($booking) {
// if (!isset($booking['hour']))
// return $query;
$hour = Carbon::now()->format('H:i');
$duration = ServiceDuration::find($booking['duration'])->duration;
$dateHour = $booking['date'] . ' ' . $hour . ':00';
$dateHourEnd = $booking['date'] . ' ' . date('H:i', strtotime($hour . "+{$duration} minutes")) . ':00';
$query->whereRaw('STR_TO_DATE("' . $dateHour . '","%Y-%m-%d %H:%i") between date_start and date_end')
->orWhereRaw('STR_TO_DATE("' . $dateHourEnd . '","%Y-%m-%d %H:%i") between date_start and date_end');
// $query->whereRaw('STR_TO_DATE("'.$dateHour.'","%Y-%m-%d %H:%i") between SUBTIME(SUBTIME(date_start,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00") and ADDTIME(ADDTIME(date_end,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00")');
return $query;
})
->whereHas('geoLocation', function($query) use ($booking) {
$query->whereRaw("DATE('" . date('Y-m-d') . "') between DATE(updated_at) and DATE(updated_at)");
return $query;
})
->whereHas('geoLocation', function($query) use ($booking) {
$query->whereRaw('"' . date('H:i:0') . '" between SUBTIME(TIME(updated_at),"02:30:00") and ADDTIME(TIME(updated_at),"02:30:00")');
return $query;
})
->where(function($query) use ($booking) {
$query
->whereDoesntHave('therapistbookings', function($query) use ($booking) {
$duration = ServiceDuration::find($booking['duration']);
// $buffer = $duration->duration+0;
$bufferMin = 55;
$buffer_before = $duration->duration + 31;
$buffer = $duration->duration + $bufferMin;
$buffer_as_time_before = floor($buffer_before / 60) . ':' . ($buffer_before % 60);
$buffer_as_time = floor($buffer / 60) . ':' . ($buffer % 60);
$query
->where('date', date('Y-m-d'))
->where(function($query) use ($booking, $duration, $buffer, $bufferMin) {
return $query->whereRaw('
TIME("' . date('H:i') . '") BETWEEN SUBTIME(`hour`,STR_TO_DATE(CONCAT(FLOOR(' . $buffer . '/60),\':\',MOD(' . $buffer . ',60)),"%h:%i:%s")) AND ADDTIME(`hour`,STR_TO_DATE(CONCAT(FLOOR((duration+' . $bufferMin . ')/60),\':\',MOD((duration+' . $bufferMin . '),60)),"%h:%i:%s"))
');
})
->whereHas('booking', function($query) {
return $query->where('is_active', 1);
});
// $query->where('date',date('Y-m-d'))
// ->whereRaw('`hour` between SUBTIME("'.date('H:i').'","'.$buffer_as_time_before.'") and ADDTIME(ADDTIME("'.date('H:i').'",STR_TO_DATE(CONCAT(FLOOR('.$duration->duration.'/60),\':\',MOD('.$duration->duration.',60)),"%h:%i")),"'.$buffer_as_time.'")')
//// ->whereRaw('`hour` between SUBTIME(hour,"'.$buffer_as_time_before.'") and ADDTIME(ADDTIME(hour,STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i")),"'.$buffer_as_time.'")')
//// ->whereRaw('`hour` between SUBTIME("'.date('H:i').'","00:00") and ADDTIME(ADDTIME("'.date('H:i').'",STR_TO_DATE(CONCAT(FLOOR('.$duration->duration.'/60),\':\',MOD('.$duration->duration.',60)),"%h:%i")),"'.$buffer_as_time.'")')
// ->whereHas('booking',function($query){
// return $query->where('is_active',1);
// });
return $query;
})
->where(function($query) use ($booking) {
$query->whereDoesntHave('sessionBlockedTherapists', function($query) use ($booking) {
$duration = ServiceDuration::find($booking['duration']);
$buffer_before = $duration->duration + 31;
$buffer = $duration->duration + 30;
// $buffer = $duration->duration+0;
$buffer_as_time_before = floor($buffer_before / 60) . ':' . ($buffer_before % 60) . ':00';
$buffer_as_time = floor($buffer / 60) . ':' . ($buffer % 60) . ':00';
$query->where('date', date('Y-m-d'))
->whereRaw('`hour` between SUBTIME("' . date('H:i:0') . '","' . $buffer_as_time_before . '") and ADDTIME("' . date('H:i:0') . '","' . $buffer_as_time . '")');
});
return $query;
});
return $query;
})
->get();
// return $users;
//delete unavailable selected users
if (isset($booking['selected_therapists'])) {
// dd("here", $booking['selected_therapists']);
$usersAvailable = [];
foreach ($users as $usr)
$usersAvailable[] = $usr->id;
foreach ($booking['selected_therapists'] as $key => $selected) {
if (!in_array($selected, $usersAvailable))
unset($booking['selected_therapists'][$key]);
} //ennforeach
Session::put('booking', $booking);
} //endif
// dd($booking['selected_therapists']);
//calculate first available hour
foreach ($users as $user) {
$user->firstAvHour = $this->getFirstHour($user, $booking);
// dd($user->firstAvHour);
} //endforeach
$checkduration = ServiceDuration::find($booking['duration'])->duration;
foreach ($users as $key => $u) {
$userSchedule = $u->workingdays()->where('weekday', $weekday)->get()->first();
if (!$u->firstAvHour)
$users->forget($key);
// if (strtotime($whours->bo_end) < strtotime($u->firstAvHour))
// $users->forget($key);
if (strtotime($userSchedule->bo_end) < strtotime($u->firstAvHour . "+{$checkduration} minutes"))
$users->forget($key);
} //endforeach
$sorted = $users->sortBy('firstAvHour');
//return results
return $sorted->values()->all();
}
/**
* Get the first available hour for a specific user
* @param $user
* @param $booking
*/
public function getFirstHour($user, $booking) {
$result = null;
// dd($user->geoLocation);
$fromGeo = [
'lat' => $user->geoLocation->lat,
'lng' => $user->geoLocation->lng
];
if (!$fromGeo || !$booking['postcode'])
return $result;
//compose from coordinates
$from = "{$fromGeo['lat']},{$fromGeo['lng']}";
//compose to coordonates
// $response = \GoogleMaps::load('textsearch')
// ->setParam([
// 'query' => "{$booking['postcode']}, London UK",
// ])->get('results'); // return $this
$address = "{$booking['postcode']}, London UK";
$response = \GoogleMaps::load('geocoding')
->setParam(['address' => $address])
->get('results');
if (empty($response['results']))
$to = $address;
else {
$toGeo = $response['results'][0]['geometry']['location'];
$to = "{$toGeo['lat']},{$toGeo['lng']}";
} //endif
$mode = $user->transport_mode;
$eta = $this->gTimeTravel($from, $to, $mode);
if ((!$eta && $eta != '0.0') || $eta > 60)
return null;
// dd("here", $eta);
//add booking buffer for reservation process: equivalent with the availability in the basket
$eta += 5;
$result = Carbon::now()->addMinutes($eta)->format('H:i');
//return result
return $result;
}
/**
* Calculated estimated time arrival using google maps api: directions
* @param $from
* @param $to
* @param string $mode
* @return mixed
*/
protected function gTimeTravel($from, $to, $mode = "DRIVING") {
$params = [
'origin' => $from,
'destination' => $to,
'mode' => $mode,
'departure_time' => 'now',
];
$direction = \GoogleMaps::load('directions')
->setParam($params)
->get();
$time = json_decode($direction, true);
// dd($time);
if ($time['status'] != "OK")
return null;
//get estimated time arrival in minutes
// $buffer = 5;
$buffer = 0;
$eta = ceil($time['routes'][0]['legs'][0]['duration']['value'] / 60) + $buffer;
//return eta
return $eta;
}
/**
* Therapist bookings
* @return \Illuminate\Support\Collection
*/
public function therapistsbookings() {
$booking = Session::get('booking');
$users = collect();
//if one of mandatory fields is missing, return empty array results
$mandatory_fields = ['postcode', 'duration', 'massage', 'date'];
foreach ($mandatory_fields as $field) {
if (!isset($booking[$field]))
return $users;
} //endforeach
//get postcode zone
$postcode = Postcode::where('postcode', $booking['postcode'])->first();
//query therapists
// DB::enableQueryLog();
$users = User::OfTherapists()
->whereHas('servicetypes', function ($query) use ($booking) {
$query->where('users_servicetype.servicetype_id', $booking['massage']);
return $query;
})
->whereHas('zones', function ($query) use ($postcode) {
$query->where('users_area_coverage.zone_id', $postcode->zone_id);
return $query;
})
->whereHas('workingdays', function ($query) use ($booking) {
$weekday = date('w', strtotime($booking['date']));
$query->where('dayoff', 0);
$query->where('weekday', $weekday);
return $query;
})
// ->whereDoesntHave('daysoff', function($query) use ($booking){
// $query->whereRaw("DATE('".$booking["date"]."') between DATE(date_start) and DATE(date_end)");
// return $query;
//// })
// ->whereDoesntHave('daysoff', function ($query) use ($booking) {
// if (!isset($booking['hour']))
// return $query;
//
// $duration = ServiceDuration::find($booking['duration'])->duration;
//
// $dateHour = $booking['date'].' '.$booking['hour'].':00';
// $query->whereRaw('STR_TO_DATE("'.$dateHour.'","%Y-%m-%d %H:%i") between SUBTIME(SUBTIME(date_start,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00") and ADDTIME(ADDTIME(date_end,STR_TO_DATE(CONCAT(FLOOR('.$duration.'/60),\':\',MOD('.$duration.',60)),"%h:%i:%s")),"0:15:00")');
//// $query->whereRaw("STR_TO_DATE('{$dateHour}','%Y-%m-%d %H:%i') between SUBTIME(date_start, STR_TO_DATE(CONCAT(FLOOR({$duration}/60):MOD({$duration},60)),\"%h:%i:%s\"))) and date_end");
//
// return $query;
// })
->whereHas('therapistbookings', function($query) use ($booking) {
$query->where('date', $booking['date']);
if (isset($booking['hour']))
$query->whereRaw('`hour` between SUBTIME("' . $booking['hour'] . '","00:15:00") and ADDTIME(ADDTIME("' . $booking['hour'] . '",STR_TO_DATE(CONCAT(FLOOR(duration/60),\':\',MOD(duration,60)),"%h:%i:%s")),"0:15:00")');
return $query;
})
->get();
// dd(DB::getQueryLog());
// dd($users);
// dd($booking);
//return results
return $users;
}
/**
* Get selected therapists
* @return \Illuminate\Support\Collection
*/
public function selected_therapists() {
$booking = Session::get('booking');
$users = collect();
//if one of mandatory fields is missing, return empty array results
$mandatory_fields = ['selected_therapists'];
foreach ($mandatory_fields as $field) {
if (!isset($booking[$field]))
return $users;
} //endforeach
//query therapists
// DB::enableQueryLog();
$users = User::OfTherapists()
->whereIn('id', $booking['selected_therapists'])
->get();
// dd($users);
//return results
return $users;
}
/**
* Get focal points
*
* @return array
*/
public function focal_points() {
$points = [];
$focalPoints = FocalPoint::all();
foreach ($focalPoints as $fp)
$points[$fp->side][$fp->slug] = ['id' => $fp->id, 'name' => $fp->name];
//return focal points array
return $points;
}
/**
* Get available days
*
* @return array
*/
public function days() {
$days = [];
//todo
//return dates
return $days;
}
/**
* Get operation hours
*
* @param $date
* @param null $therapist
* @return array|\Illuminate\Support\Collection
*/
public function all_hours($date, $therapist = null) {
$booking = Session::get('booking');
//hours collection
$hours = [];
//get today
$today = Carbon::today();
$today_now = Carbon::now();
//cast current date into Carbon object
$dateC = Carbon::createFromFormat('Y-m-d', $date)->startOfDay();
$diff = $today->diffInHours($dateC, false);
if ($diff < 0)
return $hours;
//the buffer between bookings
$buffer = 30;
//if selected date is marked as day off, return empty hours array
$daysOff = $this->days_off($date);
if ($daysOff->count())
return $hours;
//get weekday working hours: if weekday is non working day, return
$weekday = date('w', strtotime($dateC->format('Y-m-d')));
$whours = Schedule::where('weekday', $weekday)->where('open', 1)->first();
if (!$whours)
return $hours;
//data curenta este aceeasi cu cea selectata si ultima ora este mai mica decat ora curenta, nmu mai pot alege o ora din ziua dea zi
if ((date('Y-m-d') == date('Y-m-d', strtotime($date))) && (strtotime($whours->bo_end) < strtotime(date('H:i'))))
return $hours;
//create working hours interval collection
$start = strtotime($whours->bo_start);
$end = strtotime($whours->bo_end);
//pentru data curenta, daca este trecut de ora 23, nu mai poate alege nicio ora.
if (date('Y-m-d') == date('Y-m-d', strtotime($date))) {
$h = date('H');
$i = date('i');
if ($h == 23 and $i > 10)
return $hours;
} //endif
$key = date('H:i', $start);
$hours[$key] = [
'available' => 1,
'hour' => date('H:i', $start)
];
//add remaining hours
while ($start !== $end) {
$start = strtotime('+30 minutes', $start);
$key = date('H:i', $start);
$hours[$key] = [
'available' => 1,
'hour' => date('H:i', $start)
];
} //endwhile
$results = $hours;
//available hours based on current duration selection and therapist schedule
// if(isset($booking['duration'])){
// $unvhours=[];
// $duration = ServiceDuration::find($booking['duration'])->duration;
// $collection = collect($results);
// $unavailable = $collection->filter(function ($value, $key) {
// return $value['available'] == 0;
// });
//
// $unavailable->all();
// foreach($unavailable as $key=>$value){
// $start_hour = Carbon::createFromFormat('H:i',$key)->subMinutes($duration+$buffer);
// $start = strtotime($start_hour->format('H:i'));
//
// //the starting hour cannot be lower than 8:00am
// if ($start < strtotime("08:00"))
// $start = strtotime("08:00");
//
// //set max hour
// $end = strtotime($key);
//
// $unvhours[date('H:i',$start)] = [
// 'available'=>1,
// 'hour'=>date('H:i', $start)
// ];
// while ($start !== $end)
// {
// $start = strtotime('+30 minutes',$start);
// $key = date('H:i', $start);
// $unvhours[$key] = [
// 'available'=>1,
// 'hour'=>date('H:i', $start)
// ];
// } //endwhile
//
// } //endforeach
//
// $results = array_merge($results,$unvhours);
//
// } //endif
// dd($results);
// asort($results);
//available hours for today based on current time
if ($today->format('Y-m-d') == $dateC->format('Y-m-d')) {
//create disabled hours array for today
$inow = Carbon::now()->format('i');
if ($inow >= 30)
$next_time = 60 - Carbon::now()->format('i') + 60;
else
$next_time = 60 - Carbon::now()->format('i') + 30;
$first_av_hour = Carbon::now()->addMinutes($next_time)->format('H:i');
foreach ($results as $hour => $values) {
if (strtotime($hour) < strtotime($first_av_hour)) {
$results[$hour]['available'] = 0;
//if hour is set on unavailable time, reset it with the first available hour
if (isset($booking['hour']) && $booking['hour'] == $hour) {
$booking['hour'] = $first_av_hour;
Session::put('booking', $booking);
}
} //endif
} //ensdforeach
} //endif
//if (selected hour is not available, deselect it and save the new session value)
if (isset($booking['hour']) && @$results[$booking['hour']]['available'] == 0) {
$booking['hour'] = null;
unset($booking['hour']);
Session::put('booking', $booking);
} //endif
//return hours
return collect($results);
}
/**
* Get operation hours
*
* @param $date
* @param null $therapist
* @return array|\Illuminate\Support\Collection
*/
public function hours($date, $therapist = null) {
$booking = Session::get('booking');
//hours collection
$hours = [];
//get today
$today = Carbon::today();
//cast current date into Carbon object
$dateC = Carbon::createFromFormat('Y-m-d', $date)->startOfDay();
$diff = $today->diffInHours($dateC, false);
if ($diff < 0)
return $hours;
//the buffer between bookings
$buffer = 30;
//if selected date is marked as day off, return empty hours array
$daysOff = $this->days_off($date);
if ($daysOff->count())
return $hours;
//get weekday working hours: if weekday is non working day, return
$weekday = date('w', strtotime($dateC->format('Y-m-d')));
$whours = Schedule::where('weekday', $weekday)->where('open', 1)->first();
if (!$whours)
return $hours;
//create working hours interval collection
$start = strtotime($whours->bo_start);
$end = strtotime($whours->bo_end);
$key = date('H:i', $start);
// dd($key);
$hours[$key] = [
'available' => 0,
'hour' => date('H:i', $start)
];
//add remaining hours
while ($start !== $end && $start <= $end) {
$start = strtotime('+30 minutes', $start);
$key = date('H:i', $start);
$hours[$key] = [
'available' => 0,
'hour' => date('H:i', $start)
];
} //endwhile
// dd($hours);
// dd($therapist);
//available hours based on therapist schedule
if ($therapist != null) {
//therapist from the booking or any other specific request
$therapists = User::whereIn('id', $therapist)->get();
} else {
//available therapists besed on user selection
$therapists = $this->therapists();
}
$th_hours = [];
// dd($booking);
//select hours only for selected therapists
if (isset($booking['selected_therapists']) && !empty($booking['selected_therapists'])) {
$filtered = $therapists->filter(function ($user, $key) use ($booking) {
return in_array($user->id, $booking['selected_therapists']);
});
$therapists = $filtered;
}
foreach ($therapists as $therapist) {
// $twd = $therapist->workingdays()->where('dayoff', 0)->where('weekday', $weekday)->first();
$twds = $therapist->workingdays()->where('dayoff', 0)->where('weekday', $weekday)->get();
if ($twds) {
$blockedHours = $therapist->blockedHours($date);
foreach($twds as $key=>$twd) {
if (count($blockedHours)) {
foreach ($this->process_hours($twd->bo_start, $twd->bo_end, $blockedHours) as $key => $value) {
if (isset($th_hours[$key]) && $th_hours[$key]['available'] == 0)
continue;
else
$th_hours[$key] = $value;
} //endforeach
// $th_hours = array_merge($th_hours,$this->process_hours($twd->bo_start,$twd->bo_end,$blockedHours));
}
else {
foreach ($this->process_hours($twd->bo_start, $twd->bo_end) as $key => $value) {
if (isset($th_hours[$key]) && $th_hours[$key]['available'] == 0)
continue;
else
$th_hours[$key] = $value;
} //endforeach
// $th_hours = array_merge($th_hours,$this->process_hours($twd->bo_start,$twd->bo_end));
}
}
} //endif
} //endforeach
$results = array_merge($hours, $th_hours);
//available hours based on current duration selection and therapist schedule
if (isset($booking['duration'])) {
$unvhours = [];
$duration = ServiceDuration::find($booking['duration'])->duration;
$collection = collect($results);
$unavailable = $collection->filter(function ($value, $key) {
return $value['available'] == 0;
});
$unavailable->all();
foreach ($unavailable as $key => $value) {
$start_hour = Carbon::createFromFormat('H:i', $key)->subMinutes($duration + $buffer);
$start = strtotime($start_hour->format('H:i'));
//the starting hour cannot be lower than 8:00am
if ($start < strtotime("08:00"))
$start = strtotime("08:00");
//set max hour
$end = strtotime($key);
$unvhours[date('H:i', $start)] = [
'available' => 0,
'hour' => date('H:i', $start)
];
// dd($start, $end);
while ($start !== $end && $start <= $end) {
$start = strtotime('+30 minutes', $start);
// dd(date('H:i', $start));
$key = date('H:i', $start);
// echo $key;
$unvhours[$key] = [
'available' => 0,
'hour' => date('H:i', $start)
];
} //endwhile
} //endforeach
$results = array_merge($results, $unvhours);
} //endif
// asort($results);
//available hours for today based on current time
if ($today->format('Y-m-d') == $dateC->format('Y-m-d')) {
//create disabled hours array for today
$next_time = 60 - Carbon::now()->format('i') + 30;
$first_av_hour = Carbon::now()->addMinutes($next_time)->format('H:i');
foreach ($results as $hour => $values) {
if (strtotime($hour) < strtotime($first_av_hour)) {
$results[$hour]['available'] = 0;
//if hour is set on unavailable time, reset it with the first available hour
if (isset($booking['hour']) && $booking['hour'] == $hour) {
$booking['hour'] = $first_av_hour;
Session::put('booking', $booking);
}
} //endif
} //ensdforeach
} //endif
//if (selected hour is not available, deselect it and save the new session value)
if (isset($booking['hour']) && @$results[$booking['hour']]['available'] == 0) {
$booking['hour'] = null;
unset($booking['hour']);
Session::put('booking', $booking);
} //endif
//return hours
return collect($results);
}
/**
* Get operation hours
*
* @param $date
* @return array
*/
public function hours_without_buffer($date, $therapist = null) {
$booking = Session::get('booking');
//hours collection
$hours = [];
//get today
$today = Carbon::today();
//cast current date into Carbon object
$dateC = Carbon::createFromFormat('Y-m-d', $date)->startOfDay();
$diff = $today->diffInHours($dateC, false);
if ($diff < 0)
return $hours;
//if selected date is marked as day off, return empty hours array
$daysOff = $this->days_off($date);
if ($daysOff->count())
return $hours;
//get weekday working hours: if weekday is non working day, return
$weekday = date('w', strtotime($dateC->format('Y-m-d')));
$whours = Schedule::where('weekday', $weekday)->where('open', 1)->first();
if (!$whours)
return $hours;
//create working hours interval collection
$start = strtotime($whours->bo_start);
$end = strtotime($whours->bo_end);
$key = date('H:i', $start);
$hours[$key] = [
'available' => 0,
'hour' => date('H:i', $start)
];
//add remaining hours
while ($start !== $end) {
$start = strtotime('+30 minutes', $start);
$key = date('H:i', $start);
$hours[$key] = [
'available' => 0,
'hour' => date('H:i', $start)
];
} //endwhile
//available hours based on therapist schedule
if ($therapist != null) {
//therapist from the booking or any other specific request
$therapists = User::whereIn('id', $therapist)->get();
} else {
//available therapists besed on user selection
$therapists = $this->therapists();
}
$th_hours = [];
//select hours only for selected therapists
if (isset($booking['selected_therapists'])) {
$filtered = $therapists->filter(function ($user, $key) use ($booking) {
return in_array($user->id, $booking['selected_therapists']);
});
$therapists = $filtered;
}
foreach ($therapists as $therapist) {
$twd = $therapist->workingdays()->where('dayoff', 0)->where('weekday', $weekday)->first();
if ($twd) {
$blockedHours = $therapist->blockedHours($date);
if (count($blockedHours)) {
foreach ($this->process_hours($twd->bo_start, $twd->bo_end, $blockedHours) as $key => $value) {
if (isset($th_hours[$key]) && $th_hours[$key]['available'] == 0)
continue;
else
$th_hours[$key] = $value;
} //endforeach
// $th_hours = array_merge($th_hours,$this->process_hours($twd->bo_start,$twd->bo_end,$blockedHours));
}
else {
foreach ($this->process_hours($twd->bo_start, $twd->bo_end) as $key => $value) {
if (isset($th_hours[$key]) && $th_hours[$key]['available'] == 0)
continue;
else
$th_hours[$key] = $value;
} //endforeach
// $th_hours = array_merge($th_hours,$this->process_hours($twd->bo_start,$twd->bo_end));
}
} //endif
} //endforeach
$results = array_merge($hours, $th_hours);
//available hours based on current duration selection and therapist schedule
if (isset($booking['duration'])) {
$unvhours = [];
$duration = ServiceDuration::find($booking['duration'])->duration;
$collection = collect($results);
$unavailable = $collection->filter(function ($value, $key) {
return $value['available'] == 0;
});
$unavailable->all();
foreach ($unavailable as $key => $value) {
$start_hour = Carbon::createFromFormat('H:i', $key)->subMinutes($duration);
$start = strtotime($start_hour->format('H:i'));
$end = strtotime($key);
$unvhours[date('H:i', $start)] = [
'available' => 0,
'hour' => date('H:i', $start)
];
// while ($start !== $end)
// {
// $start = strtotime('+30 minutes',$start);
// $key = date('H:i', $start);
// $unvhours[$key] = [
// 'available'=>0,
// 'hour'=>date('H:i', $start)
// ];
// } //endwhile
} //endforeach
$results = array_merge($results, $unvhours);
} //endif
// dd($results);
// asort($results);
//available hours for today based on current time
if ($today->format('Y-m-d') == $dateC->format('Y-m-d')) {
//create disabled hours array for today
$next_time = 60 - Carbon::now()->format('i') + 30;
$first_av_hour = Carbon::now()->addMinutes($next_time)->format('H:i');
foreach ($results as $hour => $values) {
if (strtotime($hour) < strtotime($first_av_hour)) {
$results[$hour]['available'] = 0;
//if hour is set on unavailable time, reset it with the first available hour
if (isset($booking['hour']) && $booking['hour'] == $hour) {
$booking['hour'] = $first_av_hour;
Session::put('booking', $booking);
}
} //endif
} //ensdforeach
} //endif
//if (selected hour is not available, deselect it and save the new session value)
if (isset($booking['hour']) && @$results[$booking['hour']]['available'] == 0) {
$booking['hour'] = null;
unset($booking['hour']);
Session::put('booking', $booking);
} //endif
//return hours
return collect($results);
}
/**
* Process hours
*
* @param $starth
* @param $endh
* @param array $excepts
* @return array
*/
protected function process_hours($starth, $endh, $excepts = []) {
$hours = [];
$start = strtotime($starth);
$end = strtotime($endh);
//first hour
$key = date('H:i', $start);
$hours[$key] = [
'available' => 1,
'hour' => date('H:i', $start)
];
//add remaining hours
while ($start !== $end) {
$start = strtotime('+30 minutes', $start);
$key = date('H:i', $start);
$hours[$key] = [
'available' => 1,
'hour' => date('H:i', $start)
];
}
//remove hours
if (!empty($excepts)) {
foreach ($excepts as $ex) {
$hours[$ex]['available'] = 0;
// unset($hours[$ex]);
}
}
//return hours
return $hours;
}
/**
* Check if a date is a non-working day
*/
public function days_off($start_date = null) {
//set date
if (!$start_date)
$start_date = date('Y-m-d 00:00:00');
else
$start_date = Carbon::createFromFormat('Y-m-d', $start_date)->format('Y-m-d H:i:s');
//query selected date between non working days
$nwdays = ScheduleDaysOff::whereRaw("'" . $start_date . "' between date_start and date_end")->get();
//return results: non working days
return $nwdays;
}
/**
* Get Order Details by Card transaction id
* @param $card_trans_id
*/
public function get_order_cart($card_trans_id) {
return BookingOrder::where('card_trans_id', $card_trans_id)->get();
}
/**
* Return if the booking can be cancelled
* @param $id
* @return bool
*/
public function can_be_safe_canceled(BookingOrder $obj) {
//default response value
$response = false;
//get order info
$orderInfo = json_decode($obj->orderInfo, true);
//if in the order has been used an voucher code, the amount is not refundable
// if ($orderInfo['has_voucher'])
// return $response=false;
$now = Carbon::now();
$dateHourOrder = $obj->date->format('Y-m-d') . ' ' . $obj->hour;
$orderTime = Carbon::createFromFormat('Y-m-d H:i', $dateHourOrder);
//if the cancellation is done by the client in less than 3 hours before the booking, the amount is not refundable
$safe_cancel = $now->diffInMinutes($orderTime, false);
if ($safe_cancel > 90) {
$response = true;
} else {
$response = false;
}
//return response
return $response;
}
/**
* Cancel order and refund value
* @param BookingOrder $obj
*/
public function cancel_order(BookingOrder $obj, $admin = false) {
//start transaction
DB::beginTransaction();
//first refund the value
$refundStatus = $this->refund_value_of($obj, $admin);
$orderInfo = json_decode($obj->orderInfo, true);
$therapistsIds = [];
if(isset($orderInfo['salon_id']) && $orderInfo['salon_id'] != "") {
$therapistsIds[] = $orderInfo['therapist']['id'];
} else {
$therapistsIds = $orderInfo['therapistIds'];
}
// dd($therapistsIds);
//cancel order
$obj->is_active = 0;
$success = $obj->save();
//refund voucher and cvancel invoice only if the booking can be safe canceled
if ($this->can_be_safe_canceled($obj)) {
if(isset($orderInfo['salon_id']) && $orderInfo['salon_id'] != ""){
} else {
//refund voucher value
$refundVoucher = $this->refund_voucher_of($obj, $admin);
}
//refund invoice
$refundInvoice = $this->cancel_invoice_of($obj);
} //end
//add mobile app notifications to the client and therepists
//compose message
$notif_message = trans("schedules::booking.mobile_cancel_order", ['number' => $obj->id, 'date' => $obj->date_to_human, 'hour' => $obj->hour_to_human]);
//notification users array
$notif_users[] = $obj->user_id;
foreach ($therapistsIds as $thid)
$notif_users[] = $thid;
//store notifications
// foreach ($notif_users as $user)
// NotifRepository::add($user, $notif_message, 'cancelBooking', 'Booking cancelled');
//commit-rollback transaction
if ($success) {
//commit
DB::commit();
//send confirmation email
$user = User::findOrFail($obj->user_id);
$data['user'] = $user;
$data['order'] = $obj;
// Mail::send('schedules::frontend.emails.cancelorder', ['user' => $user, 'order' => $obj], function ($m) use ($data) {
// $m->from(env('MAIL_FROM'), env('APP_NAME'));
// $m->to($data['user']->email, $data['user']->name);
// $m->bcc(explode(',', env('MAIL_NEWORDER_BCC')), env('MAIL_NEWORDER_BCC_NAME'));
// $m->subject('Zen London Massage website – cancel booking #' . $data['order']->id);
// });
//send therapist email confirmation
//send confirmation email
$thusers = User::whereIn('id', $notif_users)->get();
// foreach ($thusers as $therapist) {
// $data['user'] = $therapist;
// Mail::send('schedules::frontend.emails.therapist_cancelorder', ['user' => $therapist, 'order' => $obj], function ($m) use ($data) {
// $m->from(env('MAIL_FROM'), env('APP_NAME'));
// $m->to($data['user']->email, $data['user']->name);
// $m->bcc(explode(',', env('MAIL_NEWORDER_BCC')), env('MAIL_NEWORDER_BCC_NAME'));
// $m->subject(env('APP_NAME') . ' – cancel booking #' . $data['order']->id);
// });
// }
} else {
//rollback actions
DB::rollBack();
} //end elseif transaction
//create response array
$response = [
'success' => $success,
'message' => $refundStatus['message'],
];
//return response
return $response;
}
// Edited by CIS
public function active_order(BookingOrder $obj, $admin = false)
{
$obj->is_active = 1;
$success = $obj->save();
if ($success) {
$response = [
'success' => $success,
'message' => null
];
}else{
$response = [
'success' => $success,
'message' => null
];
}
return $response;
}
/**
* Refund payments with credit card
* @param BookingOrder $obj
* @return bool
*/
protected function refund_value_of(BookingOrder $obj, $admin = false) {
$response = [
'success' => false,
'message' => null,
];
if (!$admin) {
$safe_cancel = $this->can_be_safe_canceled($obj);
$response = [
'success' => false,
'message' => null,
];
} else
$safe_cancel = true;
//to refund, all the conditions must be valid
// if (!$safe_cancel || !$obj->card_trans_id || !$obj->card_trans_status || !$obj->amount>0 || !$obj->is_active)
// return $response;
//if the booking was paid by cash
if (!$safe_cancel && empty($obj->card_trans_id) && $obj->amount > 0 && $obj->is_active) {
$response['message'] = $this->charge_from_card($obj);
return $response;
} //end
//The Booking was paid with card and cannot be canceled.
if (!$obj->card_trans_id || !$obj->card_trans_status || !($obj->amount > 0) || !$obj->is_active || !$safe_cancel)
return $response;
// Try to refund the amount
try {
//according with sagepay, refund is available only for yesterday
if ($obj->created_at->format('Y-m-d') != date('Y-m-d'))
$response = $this->opt_refund($obj);
else
$response = $this->opt_void($obj);
// //BRAINTREE first find breintree transaction
// $trans = Transaction::find($obj->card_trans_id);
//
// //then select method based on transaction status
// switch ($trans->status){
// case 'settled':
// case 'settling':
// $response = $this->opt_refund($obj);
// break;
// case 'submitted_for_settlement':
// $response = $this->opt_void($obj);
// break;
// default:
// $response = $this->opt_void($obj);
// break;
// } //endwitch
} catch (\Exception $e) {
//the transaction id not found
$response['message'] = $e->getMessage();
}
//return message
return $response;
}
/**
* Charge money from card
* @param $obj
*/
public function charge_from_card($obj) {
//todo: for the moment, just return null.
return null;
$user = User::find($obj->user_id);
$message = '';
//check if user exists
if (!$user)
return $message;
//user has no valid card defined
if (!$user->braintree_id) {
$message = strtoupper("You have no valid card defined. Please enter one below!");
return $message;
} //endif
try {
$name = "massage services";
$total = $obj->amount;
$response = $user->invoiceFor($name, $total);
} catch (\Exception $e) {
$message = $e->getMessage();
$message = str_ireplace('braintree', 'Zen London', $message);
return $message;
}
//update transaction type from cash to card
$data = [
'card_trans_id' => $response->transaction->id,
'card_trans_status' => (bool) $response->success,
'card_details' => json_encode([
'customerLocation' => $response->transaction->creditCardDetails->customerLocation,
'cardType' => $response->transaction->creditCardDetails->cardType,
'expirationDate' => $response->transaction->creditCardDetails->expirationDate,
'imageUrl' => $response->transaction->creditCardDetails->imageUrl,
'maskedNumber' => $response->transaction->creditCardDetails->maskedNumber,
'last4' => $response->transaction->creditCardDetails->last4,
'bin' => $response->transaction->creditCardDetails->bin,
]),
];
//update transaction type
$obj->update($data);
}
/**
* Refund voucher value of booking order
* @param BookingOrder $obj
* @param bool $admin
*/
protected function refund_voucher_of(BookingOrder $obj, $admin = false) {
$response = [
'success' => false,
'message' => null,
];
$info = json_decode($obj->orderInfo, true);
if (!$admin) {
$safe_cancel = $this->can_be_safe_canceled($obj);
$response = [
'success' => false,
'message' => null,
];
} else
$safe_cancel = true;
//to refund voucher value, all conditions must be true
if (!$safe_cancel || !$info['has_voucher'] || !$info['price_net'] || !$info['voucher']['code'])
return $response;
//continue with voucher value refund
$qty = 1;
switch ($info['therapistsOpt']) {
case '4hands':
$qty = 1;
break;
default:
$qty = 1;
break;
} //end switch
$voucherRepo = new VoucherRepository();
$status = $voucherRepo->refund_value($info['voucher']['code'], $info['price_net'], $qty);
//cancel invoice
$response = [
'success' => $status['status'],
'message' => $status['message'],
];
//return response
return $response;
}
/**
* Refund Function
* @param $obj
* @return array
*/
protected function opt_refund($obj) {
$gateway = Omnipay::create('SagePay\Direct');
$gateway->setVendor(env('SAGEPAY_VENDOR_NAME'));
$gateway->setTestMode(env('SAGEPAY_TEST_MODE'));
$payload = json_decode($obj->card_trans_id, true);
$result = $gateway->refund(array(
'useAuthenticate' => false,
'transactionReference' => $obj->card_trans_id,
'transactionId' => $payload['VendorTxCode'] . '-REF',
'amount' => $obj->amount,
'currency' => env('SAGEPAY_CCY'),
'description' => 'Massage services cancelled',
))->send();
$response = [
'success' => $result->isSuccessful(),
'message' => (!$result->isSuccessful()) ? $result->getMessage() : trans('schedules::booking.text_successfully_refunded'),
];
return $response;
}
/**
* Void Function
* @param $obj
* @return array
*/
protected function opt_void($obj) {
$gateway = Omnipay::create('SagePay\Direct');
$gateway->setVendor(env('SAGEPAY_VENDOR_NAME'));
$gateway->setTestMode(env('SAGEPAY_TEST_MODE'));
$result = $gateway->void(array(
'useAuthenticate' => false,
'transactionReference' => $obj->card_trans_id,
'amount' => $obj->amount,
'currency' => env('SAGEPAY_CCY'),
'description' => 'Massage services cancelled',
))->send();
$orderInfo = json_decode($obj->orderInfo, true);
//void the extension
if ($orderInfo['has_extension'] && array_key_exists('extension', $orderInfo)) {
$ext_result = $gateway->void(array(
'useAuthenticate' => false,
'transactionReference' => $orderInfo['extension']['card_details']['transaction_reference'],
'amount' => $orderInfo['extension']['price'],
'currency' => env('SAGEPAY_CCY'),
'description' => 'Massage services - extension cancelled',
))->send();
} //end void the extension
$response = [
'success' => $result->isSuccessful(),
'message' => (!$result->isSuccessful()) ? $result->getMessage() : trans('schedules::booking.text_successfully_refunded'),
];
return $response;
}
/**
* Cancel invoice of booking order
*/
public function cancel_invoice_of($obj) {
$status = false;
$invoice = $obj->invoice;
if (!$invoice)
return $status;
$repoInv = new BookingInvoiceRepository();
$status = $repoInv->cancel_invoice($invoice->id);
return $status;
}
/**
* Set saved booking data into session
* @param $obj
*/
public function set_booking_data($obj) {
//first unset any booking data
$this->unset_booking_data();
//get info of booking details
$info = json_decode($obj->orderInfo, true);
//set new data
$data = [
'postcode' => !empty($info['postcode'])?$info['postcode']:'',
'duration' => $info['duration_id'],
'massage' => !empty($info['massage_type_id'])?$info['massage_type_id']:0,
'date' => $obj->date->format('Y-m-d'),
'hour' => $obj->hour,
'selected_therapists' => !empty($info['therapistIds'])?$info['therapistIds']:'',
'therapists_opt' => !empty($info['therapistsOpt'])?$info['therapistsOpt']:'',
'therapists' => !empty($info['therapistsNo'])?$info['therapistsNo']:'',
'type' => !empty($info['type'])?$info['type']:'',
];
//store new data into session
Session::put('booking', $data);
}
/**
* Set saved booking data into session
* @param $obj
*/
public function unset_booking_data() {
Session::forget('booking');
}
/**
* User can extends thier booking with another service
*
* @param $booking
* @param $service
* @return bool
*/
public function can_extend_with($booking, $service) {
//default status
$status = false;
//get booking therapists
$therapists = $booking->therapists;
//add extention time to the current booking + 15min buffer to check if booking will overlaps
$addTime = $booking->duration_min + $service->duration + 58;
$addTime2 = $booking->duration_min + $service->duration;
//calculate diff in minutes between end of massage session and current time
$bookingEndTime = Carbon::createFromFormat('Y-m-d H:i', "{$booking->date->format('Y-m-d')} {$booking->hour}")->addMinutes($booking->duration_min);
$diff = $bookingEndTime->diffInMinutes(Carbon::now(), false);
$bookingEndTime2 = Carbon::createFromFormat('Y-m-d H:i', "{$booking->date->format('Y-m-d')} {$booking->hour}")->addMinutes($addTime2)->format('Y-m-d H:i');
//check if extension ca be made regarding the therapist schedule
$weekday = date('w', strtotime($booking->date));
foreach ($therapists as $th) {
$thWeekDaySchedule = $th->workingdays()->where('weekday', $weekday)->get()->first();
if (!$thWeekDaySchedule)
continue;
$endOfSchedule = Carbon::createFromFormat('Y-m-d H:i A', "{$booking->date->format('Y-m-d')} {$thWeekDaySchedule->bo_end}")->format('Y-m-d H:i');
/* $diffEndOfSchedule = strtotime($endOfSchedule) - strtotime($bookingEndTime2);
if ($diffEndOfSchedule < 0)
return false; */
} //endforeach
//if the current time is bigger than the booking session time, add minutes which passed over session booking end time to the addTime variable.
//this will
if ($diff > 0)
$addTime += $diff;
$timewithbuffer = floor($addTime / 60) . ':' . ($addTime % 60);
$count = 0;
//for each therapist, check if selected service-extension overlap on another booking
foreach ($therapists as $trp) {
// DB::enableQueryLog();
$thBookings = $trp->therapistbookings()
->where('date', '=', $booking->date->format('Y-m-d'))
->whereRaw('hour between SUBTIME("' . $booking->hour . '","00:15") and ADDTIME("' . $booking->hour . '" ,"' . $timewithbuffer . '")')
->where('booking_id', '!=', $booking->id)
->whereHas('booking', function($query) {
return $query->where('is_active', 1);
})
->get();
// dd(DB::getQueryLog());
$count += $thBookings->count();
//todo: check if other booking is in the session basket
} //endforeach
//if the therapists has bookings, deny extension
if ($count)
return $status;
//if the therapists has no other bookings, let the user to extend his session
$status = true;
//return status
return $status;
}
/**
* Therapist can delay the booking with number of minutes (@param delay)
* @param $booking
* @param int $delay
* @return bool
*/
public function can_delay_with($booking, $delay) {
//default status
$status = false;
$delay = (int) $delay;
//get booking therapists
$therapists = $booking->therapists;
//add delay time to the current booking + 15min buffer to determine if booking will overlaps
$addTime = $booking->duration_min + $delay + 15;
//calculate diff in minutes between end of massage session and current time
$bookingEndTime = Carbon::createFromFormat('Y-m-d H:i', "{$booking->date->format('Y-m-d')} {$booking->hour}")->addMinutes($booking->duration_min);
$diff = $bookingEndTime->diffInMinutes(Carbon::now(), false);
//if the current time is bigger than the booking session time, add minutes which passed over session booking end time to the addTime variable.
//this will
if ($diff > 0)
$addTime += $diff;
$timewithbuffer = floor($addTime / 60) . ':' . ($addTime % 60);
$count = 0;
//for each therapist, check if selected service-extension overlap on another booking
foreach ($therapists as $trp) {
// DB::enableQueryLog();
$thBookings = $trp->therapistbookings()
->where('date', '=', $booking->date->format('Y-m-d'))
->whereRaw('hour between SUBTIME("' . $booking->hour . '","00:15") and ADDTIME("' . $booking->hour . '" ,"' . $timewithbuffer . '")')
->where('booking_id', '!=', $booking->id)
->whereHas('booking', function($query) {
return $query->where('is_active', 1);
})
->get();
// dd(DB::getQueryLog());
$count += $thBookings->count();
//todo: check if other booking is in the session basket
} //endforeach
//if the therapists has bookings, deny extension
if ($count)
return $status;
//if the therapists has no other bookings, let the user to extend his session
$status = true;
//return status
return $status;
}
/**
* Start booking threading
* @param $booking
*/
public function create_thread($booking) {
$subject = $booking->treadsubject;
$thread = Thread::where('subject', $subject)->first();
//create the thread if not exists
if (!$thread) {
$thread = Thread::create(
[
'subject' => $subject,
]
);
} //endif
// create message
Message::create(
[
'thread_id' => $thread->id,
'user_id' => $booking->user_id,
'body' => trans('schedules::booking.default_message_thread'),
]
);
// Add replier as a participant
$participant = Participant::firstOrCreate(
[
'thread_id' => $thread->id,
'user_id' => $booking->user_id,
]
);
$participant->last_read = new Carbon();
$participant->save();
//add recipients: is this case the recipients are the therapists
foreach ($booking->therapists as $rec)
$recipients[] = $rec->id;
if (!empty($recipients))
$thread->addParticipant($recipients);
}
//end method
}