879 lines
35 KiB
PHP
879 lines
35 KiB
PHP
<?php
|
||
|
||
namespace App\Core\Service;
|
||
|
||
|
||
use App\Core\Repository\PropertyWeb\PropertyWebRepository;
|
||
use App\Exceptions\ApiErrorException;
|
||
use App\Models\Booking;
|
||
use App\Models\BookingRoom;
|
||
use App\Models\BookingRoomPax;
|
||
use App\Models\Country;
|
||
use App\Models\PropertyBookingEngine;
|
||
use App\Models\PropertyChannel;
|
||
use App\Models\PropertyChannelMapping;
|
||
use App\Models\PropertyWebLog;
|
||
use App\Models\vwBookingSummaryAll;
|
||
use Carbon\Carbon;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
|
||
class DashboardPlusService
|
||
{
|
||
private $countryRepository;
|
||
|
||
public function __construct(
|
||
CurrencyService $currencyService,
|
||
PropertyWebRepository $propertyWebRepository
|
||
)
|
||
{
|
||
$this->currencyService = $currencyService;
|
||
$this->propertyWebRepository = $propertyWebRepository;
|
||
}
|
||
|
||
|
||
public function webVisitor(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$criteria = [
|
||
'criteria' => [
|
||
['field' => 'property_id', 'condition' => '=', 'value' => $params['property_id']],
|
||
],
|
||
'firstRow' => true
|
||
];
|
||
|
||
$propertyWeb = $this->propertyWebRepository->findByCriteria($criteria, $columns);
|
||
if (empty($propertyWeb)) {
|
||
throw new ApiErrorException('No record found.');
|
||
}
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->timestamp;
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->timestamp;
|
||
$propertyWebLogRaw = PropertyWebLog::whereBetween('created_at', [$startDate, $finishDate])
|
||
->where('web_id', $propertyWeb)
|
||
->groupBy('country_code')
|
||
->select('country_code', DB::raw('count(id) count'))
|
||
->get()->toArray();
|
||
|
||
$propertyWebLogCountryIds = pickItemFromArray('country_code', $propertyWebLogRaw);
|
||
$propertyWebLogCountry = Country::whereIn('country_code', $propertyWebLogCountryIds)->get()->toArray();
|
||
$propertyWebLogCountry = collect($propertyWebLogCountry);
|
||
|
||
$propertyWebLog = [];
|
||
$propertyWebLogTotal = 0;
|
||
foreach ($propertyWebLogRaw as $propertyWebLogKey => $propertyWebLogValue) {
|
||
|
||
$countryCodeDetail = $propertyWebLogCountry->where('country_code', mb_strtoupper($propertyWebLogValue['country_code']))->first();
|
||
if (empty($countryCodeDetail)) {
|
||
continue;
|
||
}
|
||
|
||
$propertyWebLog[] = [
|
||
'country' => $countryCodeDetail['name'],
|
||
'language_key' => $countryCodeDetail['language_key'],
|
||
'country_code' => $propertyWebLogValue['country_code'],
|
||
'count' => $propertyWebLogValue['count'],
|
||
'formatted' => [
|
||
'value' => $propertyWebLogValue['count'],
|
||
'country' => $propertyWebLogValue['country_code'],
|
||
'country_name' => $countryCodeDetail['name'],
|
||
]
|
||
];
|
||
|
||
}
|
||
|
||
$propertyWebLog = collect($propertyWebLog)->sortByDesc('count')->toArray();
|
||
$propertyWebLog = array_values($propertyWebLog);
|
||
|
||
$propertyWebLogTotal = collect($propertyWebLog)->sum('count');
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => [
|
||
'total' => $propertyWebLogTotal,
|
||
'country' => $propertyWebLog
|
||
],
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function guestDemographic(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$propertyChannel = PropertyChannel::whereIn('channel_category_id', [2, 3])->get(['id'])->sortBy('id')->toArray();
|
||
$propertyChannelIds = pickItemFromArray('id', $propertyChannel);
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->timestamp;
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->timestamp;
|
||
$propertyBooking = Booking::whereBetween('created_at', [$startDate, $finishDate])
|
||
->where('status', 1)
|
||
->whereIn('channel_id', $propertyChannelIds)
|
||
->where('property_id', $params['property_id'])
|
||
->get(['id'])->sortBy('id')->toArray();
|
||
$propertyBookingIds = pickItemFromArray('id', $propertyBooking);
|
||
|
||
|
||
$bookingRoomPax = BookingRoomPax::
|
||
whereIn('booking_id', $propertyBookingIds)
|
||
->get()->toArray();
|
||
$bookingRoomPax = collect($bookingRoomPax);
|
||
|
||
$guestDemographic = [];
|
||
|
||
|
||
$totalPax = $bookingRoomPax->count();
|
||
|
||
$guestDemographic['all'] = $totalPax;
|
||
|
||
//Gender
|
||
$guestDemographic['gender'] = [];
|
||
if (!empty($totalPax)) {
|
||
$guestDemographic['gender'] = [
|
||
'male' => [
|
||
'title' => 'Male',
|
||
'count' => $bookingRoomPax->where('gender', 'M')->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPax->where('gender', 'M')->count() / $totalPax * 100),
|
||
],
|
||
'female' => [
|
||
'title' => 'Female',
|
||
'count' => $bookingRoomPax->where('gender', 'F')->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPax->where('gender', 'F')->count() / $totalPax * 100),
|
||
]
|
||
];
|
||
}
|
||
|
||
|
||
//Type
|
||
$guestDemographic['type'] = [];
|
||
if (!empty($totalPax)) {
|
||
$guestDemographic['type'] = [
|
||
'adult' => [
|
||
'title' => 'Adult',
|
||
'count' => $bookingRoomPax->where('type', 'ADT')->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPax->where('type', 'ADT')->count() / $totalPax * 100),
|
||
],
|
||
'child' => [
|
||
'title' => 'Child',
|
||
'count' => $bookingRoomPax->where('type', 'CHD')->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPax->where('type', 'CHD')->count() / $totalPax * 100),
|
||
]
|
||
];
|
||
}
|
||
|
||
|
||
//Citizen
|
||
$guestDemographic['citizen'] = [];
|
||
if (!empty($totalPax)) {
|
||
$bookingRoomPaxGroupedCitizen = $bookingRoomPax->groupBy('citizen')->map->count()->toArray();
|
||
arsort($bookingRoomPaxGroupedCitizen);
|
||
|
||
$paxGroupedCitizenCountry = Country::whereIn('country_code', array_keys($bookingRoomPaxGroupedCitizen))->get()->toArray();
|
||
$paxGroupedCitizenCountry = collect($paxGroupedCitizenCountry);
|
||
|
||
foreach ($bookingRoomPaxGroupedCitizen as $bookingRoomPaxGroupedCitizenCode => $bookingRoomPaxGroupedCitizenCount) {
|
||
|
||
$countryCodeDetail = $paxGroupedCitizenCountry->where('country_code', mb_strtoupper($bookingRoomPaxGroupedCitizenCode))->first();
|
||
|
||
$guestDemographic['citizen'][mb_strtolower($bookingRoomPaxGroupedCitizenCode)] = [
|
||
'country' => fillOnUndefined($countryCodeDetail, 'name', $bookingRoomPaxGroupedCitizenCode),
|
||
'language_key' => fillOnUndefined($countryCodeDetail, 'language_key', $bookingRoomPaxGroupedCitizenCode),
|
||
'country_code' => mb_strtolower($bookingRoomPaxGroupedCitizenCode),
|
||
'count' => $bookingRoomPaxGroupedCitizenCount,
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxGroupedCitizenCount / $totalPax * 100),
|
||
];
|
||
}
|
||
}
|
||
|
||
//Age
|
||
$guestDemographic['age'] = [];
|
||
if (!empty($totalPax)) {
|
||
$bookingRoomPaxAges = $bookingRoomPax->map(function ($value, $key) {
|
||
$value['age'] = Carbon::parse($value['birth_date'])->diffInYears(Carbon::createFromTimestamp($value['created_at']));
|
||
return $value;
|
||
});
|
||
|
||
|
||
$guestDemographic['age'] = [
|
||
'0-12' => [
|
||
'title' => '0-12 Age',
|
||
'count' => $bookingRoomPaxAges->where('age', '>=', 0)->where('age', '<', 12)->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxAges->where('age', '>=', 0)->where('age', '<', 12)->count() / $totalPax * 100),
|
||
],
|
||
'12-18' => [
|
||
'title' => '12-18 Age',
|
||
'count' => $bookingRoomPaxAges->where('age', '>=', 12)->where('age', '<', 18)->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxAges->where('age', '>=', 12)->where('age', '<', 18)->count() / $totalPax * 100),
|
||
],
|
||
'18-36' => [
|
||
'title' => '18-36 Age',
|
||
'count' => $bookingRoomPaxAges->where('age', '>=', 18)->where('age', '<', 36)->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxAges->where('age', '>=', 18)->where('age', '<', 36)->count() / $totalPax * 100),
|
||
],
|
||
'36-60' => [
|
||
'title' => '36-60 Age',
|
||
'count' => $bookingRoomPaxAges->where('age', '>=', 36)->where('age', '<', 60)->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxAges->where('age', '>=', 36)->where('age', '<', 60)->count() / $totalPax * 100),
|
||
],
|
||
'60+' => [
|
||
'title' => '60+ Age',
|
||
'count' => $bookingRoomPaxAges->where('age', '>=', 60)->count(),
|
||
'percentage' => moneyDoubleFormatDecimal($bookingRoomPaxAges->where('age', '>=', 60)->count() / $totalPax * 100),
|
||
],
|
||
];
|
||
}
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $guestDemographic
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function topChannel(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$defaultCurrency = 'TRY';
|
||
$bookingEngineBaseCurrency = PropertyChannelMapping::where('status', 1)
|
||
->where('channel_id', 1)
|
||
->where('property_id', $params['property_id'])
|
||
->first()->toArray();
|
||
|
||
if (!empty($bookingEngineBaseCurrency)) {
|
||
$defaultCurrency = $bookingEngineBaseCurrency['currency_code'];
|
||
}
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->timestamp;
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->timestamp;
|
||
/*$propertyBooking = Booking::whereBetween('created_at', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->get(['id', 'property_id', 'channel_id', 'total', 'currency_code', 'status'])
|
||
->sortByDesc('id')->toArray();*/
|
||
|
||
$propertyBooking = Booking::whereBetween('created_at', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->where('status', 1)
|
||
->groupBy('channel_id')
|
||
->groupBy('currency_code')
|
||
->select('channel_id', 'currency_code', DB::raw('count(id) count, sum(total) total'))
|
||
->get()->toArray();
|
||
|
||
//Channel Id List
|
||
$channelIds = pickItemFromArray('channel_id', $propertyBooking);
|
||
$channelIds = !empty($channelIds) ? array_values(array_unique($channelIds)) : [];
|
||
$propertyChannel = PropertyChannel::whereIn('id', $channelIds)->get(['id', 'name'])->toArray();
|
||
$propertyChannelCollect = collect($propertyChannel);
|
||
|
||
//Currency Code List
|
||
$currencyCodes = pickItemFromArray('currency_code', $propertyBooking);
|
||
$currencyCodes = !empty($currencyCodes) ? array_values(array_unique($currencyCodes)) : [];
|
||
|
||
|
||
$topChannel = [];
|
||
foreach ($propertyBooking as $booking) {
|
||
|
||
if ($booking['total'] <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$commonCurrencyCodeRate = $this->currencyService->lastExchangeRate($booking['currency_code'], $defaultCurrency);
|
||
|
||
$channelName = $propertyChannelCollect->where('id', $booking['channel_id'])->first();
|
||
if (!empty($channelName)) {
|
||
$channelName = $channelName['name'];
|
||
}
|
||
|
||
$topChannel[$booking['channel_id']] = [
|
||
'name' => $channelName,
|
||
'count' => $booking['count'],
|
||
'total' => $booking['total'],
|
||
'currency_code' => $booking['currency_code'],
|
||
'commonCurrencyTotal' => ($booking['total'] * $commonCurrencyCodeRate['data']),
|
||
'commonCurrencyCode' => $defaultCurrency
|
||
];
|
||
|
||
}
|
||
|
||
$totalChannelOverall = collect($topChannel)->sum('commonCurrencyTotal');
|
||
foreach ($topChannel as $channelId => $channel) {
|
||
$topChannel[$channelId]['total'] = moneyDoubleFormatDecimal($channel['total']);
|
||
$topChannel[$channelId]['commonCurrencyTotal'] = moneyDoubleFormatDecimal($channel['commonCurrencyTotal']);
|
||
$topChannel[$channelId]['percentage'] = moneyDoubleFormatDecimal($channel['commonCurrencyTotal'] / $totalChannelOverall * 100);
|
||
}
|
||
|
||
|
||
$topChannel = collect($topChannel)->sortByDesc('commonCurrencyTotal')->toArray();
|
||
$topChannel = array_values($topChannel);
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $topChannel
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function todayCheckin(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$todayCheckin = 0;
|
||
$today = Carbon::now()->startOfDay()->toDateString();
|
||
$todayCheckin = Booking::where('checkin_date', $today)->where('property_id', $params['property_id'])->count();
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $todayCheckin
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function todayCheckout(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$todayCheckOut = 0;
|
||
$today = Carbon::now()->startOfDay()->toDateString();
|
||
$todayCheckOut = Booking::where('checkout_date', $today)->where('property_id', $params['property_id'])->count();
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $todayCheckOut
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function lengthOfStay(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateTimeString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateTimeString();
|
||
|
||
$lengthOfStay = 0;
|
||
$lengthOfStay = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->pluck('length_of_stay')->avg();
|
||
|
||
$lengthOfStay = moneyDoubleFormatDecimal($lengthOfStay);
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $lengthOfStay
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function lengthOfBooking(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateTimeString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateTimeString();
|
||
|
||
$lengthOfBooking = 0;
|
||
$lengthOfBooking = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->pluck('length_of_booking')->avg();
|
||
|
||
$lengthOfBooking = moneyDoubleFormatDecimal($lengthOfBooking);
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $lengthOfBooking
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function totalBooking(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$defaultCurrency = 'TRY';
|
||
$bookingEngineBaseCurrency = PropertyChannelMapping::where('status', 1)
|
||
->where('channel_id', 1)
|
||
->where('property_id', $params['property_id'])
|
||
->first()->toArray();
|
||
|
||
if (!empty($bookingEngineBaseCurrency)) {
|
||
$defaultCurrency = $bookingEngineBaseCurrency['currency_code'];
|
||
}
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateTimeString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateTimeString();
|
||
|
||
$propertyBooking = 0;
|
||
$propertyBooking = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->groupBy('currency_code')
|
||
->select('currency_code', DB::raw('count(id) count, sum(total) total'))
|
||
->get()->toArray();
|
||
|
||
|
||
$totalBooking = [
|
||
'totalCount' => 0,
|
||
'totalRevenue' => 0,
|
||
'currencyCode' => $defaultCurrency
|
||
];
|
||
|
||
foreach ($propertyBooking as $booking) {
|
||
|
||
if ($booking['total'] <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$commonCurrencyCodeRate = $this->currencyService->lastExchangeRate($booking['currency_code'], $defaultCurrency);
|
||
$totalBooking['totalRevenue'] += ($booking['total'] * $commonCurrencyCodeRate['data']);
|
||
$totalBooking['totalCount'] += $booking['count'];
|
||
|
||
}
|
||
|
||
$totalBooking['totalRevenue'] = moneyDoubleFormatDecimal($totalBooking['totalRevenue']);
|
||
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $totalBooking
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function averageDailyRate(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$defaultCurrency = 'TRY';
|
||
$bookingEngineBaseCurrency = PropertyChannelMapping::where('status', 1)
|
||
->where('channel_id', 1)
|
||
->where('property_id', $params['property_id'])
|
||
->first()->toArray();
|
||
|
||
if (!empty($bookingEngineBaseCurrency)) {
|
||
$defaultCurrency = $bookingEngineBaseCurrency['currency_code'];
|
||
}
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateTimeString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateTimeString();
|
||
|
||
$averageDailyRate = [
|
||
'averageDailyRate' => 0,
|
||
'currencyCode' => $defaultCurrency
|
||
];
|
||
|
||
$propertyBooking = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->select('id')
|
||
->get()->toArray();
|
||
$propertyBookingIds = pickItemFromArray('id', $propertyBooking);
|
||
|
||
$bookingRoom = BookingRoom::whereIn('booking_id', $propertyBookingIds)
|
||
->select('id', 'booking_id', 'checkin_date', 'checkout_date', 'total', 'currency_code')
|
||
->get()->toArray();
|
||
|
||
$exchangeCurrencyList = collect($bookingRoom)->unique('currency_code')->pluck('currency_code')->toArray();
|
||
|
||
foreach ($exchangeCurrencyList as $currencyCode) {
|
||
if ($currencyCode == $defaultCurrency) {
|
||
$commonCurrencyCodeRate[$currencyCode] = 1;
|
||
} else {
|
||
$lastExchangeRate = $this->currencyService->lastExchangeRate($currencyCode, $defaultCurrency);
|
||
$commonCurrencyCodeRate[$currencyCode] = $lastExchangeRate['data'];
|
||
}
|
||
}
|
||
|
||
$averageDailyRateList = [];
|
||
foreach ($bookingRoom as $perRoom) {
|
||
$diffInDays = Carbon::parse($perRoom['checkout_date'])->diffInDays(Carbon::parse($perRoom['checkin_date']));
|
||
$totalExchangeAmount = ($perRoom['total'] * $commonCurrencyCodeRate[$perRoom['currency_code']]);
|
||
$averageDailyRateList[] = $totalExchangeAmount / $diffInDays;
|
||
}
|
||
|
||
|
||
$averageDailyRate['averageDailyRate'] = moneyDoubleFormatDecimal(collect($averageDailyRateList)->average());
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $averageDailyRate
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function totalPax(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$defaultCurrency = 'TRY';
|
||
$bookingEngineBaseCurrency = PropertyChannelMapping::where('status', 1)
|
||
->where('channel_id', 1)
|
||
->where('property_id', $params['property_id'])
|
||
->first()->toArray();
|
||
|
||
if (!empty($bookingEngineBaseCurrency)) {
|
||
$defaultCurrency = $bookingEngineBaseCurrency['currency_code'];
|
||
}
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateTimeString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateTimeString();
|
||
|
||
$propertyBooking = 0;
|
||
$propertyBooking = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->groupBy('currency_code')
|
||
->select('currency_code', DB::raw('count(id) count, sum(total) total'))
|
||
->get()->toArray();
|
||
|
||
|
||
$totalPax = [
|
||
'totalPaxCount' => 0,
|
||
'totalPaxRevenue' => 0,
|
||
'averageRevenuePerPax' => 0,
|
||
'currencyCode' => $defaultCurrency
|
||
];
|
||
|
||
foreach ($propertyBooking as $booking) {
|
||
|
||
if ($booking['total'] <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$commonCurrencyCodeRate = $this->currencyService->lastExchangeRate($booking['currency_code'], $defaultCurrency);
|
||
$totalPax['totalPaxRevenue'] += ($booking['total'] * $commonCurrencyCodeRate['data']);
|
||
|
||
}
|
||
|
||
$totalPax['totalPaxRevenue'] = moneyDoubleFormatDecimal($totalPax['totalPaxRevenue']);
|
||
|
||
$bookingIds = vwBookingSummaryAll::whereBetween('time', [$startDate, $finishDate])
|
||
->where('property_id', $params['property_id'])
|
||
->pluck('id')->toArray();
|
||
|
||
$bookingRoom = BookingRoom::whereIn('booking_id', $bookingIds)
|
||
->groupBy('occupancy_code')
|
||
->select('occupancy_code', DB::raw('count(id) count'))
|
||
->get()->toArray();
|
||
|
||
foreach ($bookingRoom as $bookingRoomPax) {
|
||
|
||
$adultCount = substr_count($bookingRoomPax['occupancy_code'], 'A');
|
||
$childCount = substr_count($bookingRoomPax['occupancy_code'], 'C');
|
||
|
||
$totalPax['totalPaxCount'] += (($adultCount + $childCount) * $bookingRoomPax['count']);
|
||
|
||
}
|
||
|
||
if($totalPax['totalPaxCount'] > 0) {
|
||
$totalPax['averageRevenuePerPax'] = moneyDoubleFormatDecimal($totalPax['totalPaxRevenue'] / $totalPax['totalPaxCount']);
|
||
}
|
||
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => $totalPax
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
public function channelForecast(array $params = [], $columns = ["*"])
|
||
{
|
||
$response = ['status' => false, 'message' => '', 'data' => null];
|
||
|
||
try {
|
||
|
||
$startDate = Carbon::parse($params['start_date'])->startOfDay()->toDateString();
|
||
$finishDate = Carbon::parse($params['finish_date'])->endOfDay()->toDateString();
|
||
|
||
//Burada mutlaka 2 kontrol eklenecke,
|
||
// 1. bitiş, başlangıçtan büyük olamazi
|
||
// 2. max 6 aylık yani 180 günlük veri çekilebilir
|
||
|
||
|
||
$relatingDates = [];
|
||
$dateDiff = Carbon::parse($startDate)->diffInDays(Carbon::parse($finishDate));
|
||
for ($i = 0; $i < ($dateDiff + 1); $i++) {
|
||
$currentDate = Carbon::parse($startDate)->addDays($i)->toDateString();
|
||
$relatingDates[] = $currentDate;
|
||
}
|
||
|
||
$period = [];
|
||
$periodModel = 'daily';
|
||
if (Carbon::parse($startDate)->month != Carbon::parse($finishDate)->month) {
|
||
$periodModel = 'monthly';
|
||
} elseif (Carbon::parse($startDate)->diffInDays(Carbon::parse($finishDate)) > 30) {
|
||
$periodModel = 'monthly';
|
||
}
|
||
|
||
$propertyBooking = Booking::where('status', 1)
|
||
->where('checkin_date', '<=', $finishDate)
|
||
->where('checkout_date', '>=', $startDate)
|
||
->where('property_id', $params['property_id'])
|
||
//->where('id',11825)
|
||
->with('bookingRoomSummary')
|
||
->select('id', 'channel_id', 'checkin_date', 'checkout_date', 'total', 'status')
|
||
->get()->toArray();
|
||
|
||
//dd($propertyBooking);
|
||
|
||
//Channel Id List
|
||
$channelIds = pickItemFromArray('channel_id', $propertyBooking);
|
||
$channelIds = !empty($channelIds) ? array_values(array_unique($channelIds)) : [];
|
||
$propertyChannel = PropertyChannel::whereIn('id', $channelIds)->get(['id', 'name'])->toArray();
|
||
$propertyChannelCollect = collect($propertyChannel);
|
||
|
||
$bookingChannelForecast = [];
|
||
$bookingChannelForecastTotal = [];
|
||
foreach ($propertyBooking as $booking) {
|
||
|
||
if ($booking['total'] <= 0) {
|
||
continue;
|
||
}
|
||
|
||
$channelName = $propertyChannelCollect->where('id', $booking['channel_id'])->first();
|
||
if (!empty($channelName)) {
|
||
$channelName = $channelName['name'];
|
||
}
|
||
|
||
foreach ($booking['booking_room_summary'] as $bookingRoom) {
|
||
|
||
$checkInDate = $bookingRoom['checkin_date'];
|
||
$checkOutDate = $bookingRoom['checkout_date'];
|
||
$dateDiff = Carbon::parse($checkOutDate)->diffInDays(Carbon::parse($checkInDate));
|
||
|
||
for ($i = 0; $i < $dateDiff; $i++) {
|
||
$date = Carbon::parse($checkInDate)->addDays($i)->toDateString();
|
||
|
||
if(!in_array($date,$relatingDates)) {
|
||
continue;
|
||
}
|
||
|
||
|
||
if (!isset($bookingChannelForecast[$booking['channel_id']]['total'])) {
|
||
$bookingChannelForecast[$booking['channel_id']]['id'] = $booking['channel_id'];
|
||
$bookingChannelForecast[$booking['channel_id']]['title'] = $channelName;
|
||
$bookingChannelForecast[$booking['channel_id']]['total'] = 0;
|
||
$bookingChannelForecast[$booking['channel_id']]['percentage'] = 0;
|
||
}
|
||
|
||
if (!isset($bookingChannelForecast[$booking['channel_id']]['data'][$date])) {
|
||
$bookingChannelForecast[$booking['channel_id']]['data'][$date] = 0;
|
||
}
|
||
|
||
if (!isset($bookingChannelForecastTotal[$date])) {
|
||
$bookingChannelForecastTotal[$date] = 0;
|
||
}
|
||
|
||
|
||
$bookingChannelForecast[$booking['channel_id']]['data'][$date]++;
|
||
$bookingChannelForecast[$booking['channel_id']]['total']++;
|
||
$bookingChannelForecastTotal[$date]++;
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
$totalRoom = collect($bookingChannelForecast)->sum('total');
|
||
|
||
$dateDiff = Carbon::parse($startDate)->diffInDays(Carbon::parse($finishDate));
|
||
for ($i = 0; $i < ($dateDiff + 1); $i++) {
|
||
$currentDate = Carbon::parse($startDate)->addDays($i)->toDateString();
|
||
foreach ($bookingChannelForecast as $channelId => $channel) {
|
||
foreach ($channel['data'] as $date => $count) {
|
||
|
||
if (!isset($bookingChannelForecast[$channelId]['data'][$currentDate])) {
|
||
$bookingChannelForecast[$channelId]['data'][$currentDate] = 0;
|
||
}
|
||
|
||
if (!isset($bookingChannelForecastTotal[$currentDate])) {
|
||
$bookingChannelForecastTotal[$currentDate] = 0;
|
||
}
|
||
|
||
|
||
$period[$currentDate] = $currentDate;
|
||
$bookingChannelForecast[$channelId]['percentage'] = moneyDoubleFormatDecimal($bookingChannelForecast[$channelId]['total'] / $totalRoom * 100);
|
||
|
||
ksort($bookingChannelForecast[$channelId]['data']);
|
||
ksort($period);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if ($periodModel == 'monthly') {
|
||
|
||
$period = [];
|
||
foreach ($bookingChannelForecast as $channelId => $channel) {
|
||
foreach ($channel['data'] as $date => $count) {
|
||
|
||
$currentMonth = Carbon::parse($date)->format('Y-m');
|
||
$period[$currentMonth] = $currentMonth;
|
||
|
||
if (!isset($bookingChannelForecast[$channelId]['data'][$currentMonth])) {
|
||
$bookingChannelForecast[$channelId]['data'][$currentMonth] = 0;
|
||
}
|
||
|
||
|
||
if (!isset($bookingChannelForecastTotal[$currentMonth])) {
|
||
$bookingChannelForecastTotal[$currentMonth] = 0;
|
||
}
|
||
|
||
|
||
$bookingChannelForecast[$channelId]['data'][$currentMonth] += $bookingChannelForecast[$channelId]['data'][$date];
|
||
$bookingChannelForecastTotal[$currentMonth] += $bookingChannelForecast[$channelId]['data'][$date];
|
||
|
||
unset($bookingChannelForecast[$channelId]['data'][$date]);
|
||
unset($bookingChannelForecastTotal[$date]);
|
||
ksort($bookingChannelForecast[$channelId]['data']);
|
||
ksort($bookingChannelForecast);
|
||
ksort($period);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
$bookingChannelForecast = collect($bookingChannelForecast)->sortBy('title')->toArray();
|
||
$bookingChannelForecast = array_values($bookingChannelForecast);
|
||
|
||
$propertyChannel = collect($propertyChannel)->sortBy('name')->pluck('name')->toArray();
|
||
|
||
$period = is_array($period) ? array_values($period) : [];
|
||
|
||
ksort($bookingChannelForecastTotal);
|
||
|
||
$response = [
|
||
'status' => true,
|
||
'data' => [
|
||
'title' => 'Forecast - '.$startDate . ' / ' . $finishDate . ' (' . ucfirst($periodModel) . ')',
|
||
'period' => $period,
|
||
'channel' => $propertyChannel,
|
||
'forecast' => $bookingChannelForecast,
|
||
'forecastTotal' => $bookingChannelForecastTotal
|
||
]
|
||
];
|
||
|
||
} catch (ApiErrorException $e) {
|
||
$response['message'] = $e->getMessage();
|
||
} catch (Exception $e) {
|
||
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
|
||
Log::error($message);
|
||
$response['message'] = $e->getMessage();
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
|
||
}
|