first commit
This commit is contained in:
255
app/Core/Service/PropertySummaryService.php
Normal file
255
app/Core/Service/PropertySummaryService.php
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Core\Service;
|
||||
|
||||
|
||||
use App\Core\Repository\Booking\BookingRepository;
|
||||
use App\Core\Repository\Property\PropertyRepository;
|
||||
use App\Core\Repository\PropertySummary\PropertySummaryRepository;
|
||||
use App\Exceptions\ApiErrorException;
|
||||
use App\Models\CurrencyRates;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PropertySummaryService
|
||||
{
|
||||
private $countryRepository;
|
||||
|
||||
public function __construct(
|
||||
PropertyRepository $propertyRepository,
|
||||
BookingRepository $bookingRepository,
|
||||
PropertySummaryRepository $propertySummaryRepository
|
||||
)
|
||||
{
|
||||
$this->propertyRepository = $propertyRepository;
|
||||
$this->bookingRepository = $bookingRepository;
|
||||
$this->propertySummaryRepository = $propertySummaryRepository;
|
||||
|
||||
$commissionChannelCategoryMapping = [
|
||||
2 => 'commission_offline',
|
||||
3 => 'commission',
|
||||
4 => 'commission_channel',
|
||||
];
|
||||
|
||||
$this->commissionChannelCategoryMapping = $commissionChannelCategoryMapping;
|
||||
|
||||
$this->exchangeCurrencyCode = 'EUR';
|
||||
}
|
||||
|
||||
public function calculatePeriodCommission($propertyId, $type, $periodStartDate, $periodFinishDate)
|
||||
{
|
||||
|
||||
$propertyDetailCriteria = [
|
||||
'criteria' => [
|
||||
['field' => 'id', 'condition' => '=', 'value' => $propertyId],
|
||||
//['field' => 'status', 'condition' => '=', 'value' => 1],
|
||||
],
|
||||
'with' => ['propertyBookingEngines.channel'],
|
||||
'firstRow' => true
|
||||
];
|
||||
|
||||
$propertyDetail = $this->propertyRepository->findByCriteria($propertyDetailCriteria);
|
||||
|
||||
$propertyCreateTime = Carbon::parse($propertyDetail['invoice_start_date'])->toDateString();
|
||||
|
||||
if ($propertyCreateTime > $periodFinishDate) {
|
||||
throw new ApiErrorException('Property not ready for transaction: ' . $propertyCreateTime . ' - ' . $propertyDetail['name']);
|
||||
}
|
||||
|
||||
$channelBaseCommission = [];
|
||||
foreach ($propertyDetail['property_booking_engines'] as $propertyBookingEngine) {
|
||||
|
||||
$commissionRateParam = isset($this->commissionChannelCategoryMapping[$propertyBookingEngine['channel']['channel_category_id']]) ? $this->commissionChannelCategoryMapping[$propertyBookingEngine['channel']['channel_category_id']] : 'commission';
|
||||
$commissionRateRate = $propertyDetail[$commissionRateParam];
|
||||
|
||||
|
||||
$bookingListCriteria = [
|
||||
'criteria' => [
|
||||
['field' => 'property_id', 'condition' => '=', 'value' => $propertyBookingEngine['property_id']],
|
||||
['field' => 'channel_id', 'condition' => '=', 'value' => $propertyBookingEngine['channel_id']],
|
||||
['field' => 'status', 'condition' => '=', 'value' => 1],
|
||||
],
|
||||
'whereIn' =>
|
||||
[
|
||||
['field' => 'status', 'value' => [1, 3]]
|
||||
]
|
||||
];
|
||||
|
||||
if ($type == 1) {
|
||||
$bookingListCriteria['criteria'][] = ['field' => 'checkout_date', 'condition' => '>=', 'value' => $periodStartDate];
|
||||
$bookingListCriteria['criteria'][] = ['field' => 'checkout_date', 'condition' => '<', 'value' => $periodFinishDate];
|
||||
}
|
||||
|
||||
if ($type == 2) {
|
||||
$bookingListCriteria['criteria'][] = ['field' => 'reservation_time', 'condition' => '>=', 'value' => Carbon::parse($periodStartDate, 'UTC')->timestamp];
|
||||
$bookingListCriteria['criteria'][] = ['field' => 'reservation_time', 'condition' => '<', 'value' => Carbon::parse($periodFinishDate, 'UTC')->timestamp];
|
||||
}
|
||||
|
||||
$bookingList = $this->bookingRepository->findByCriteria($bookingListCriteria, ['id', 'property_id', 'channel_id', 'total', 'currency_code', 'checkin_date', 'checkout_date']);
|
||||
|
||||
$bookingListCollect = collect($bookingList)->groupBy('currency_code')->map(function ($group) {
|
||||
return [
|
||||
'total' => $group->sum('total')
|
||||
];
|
||||
});
|
||||
|
||||
$bookingListCollect = $bookingListCollect ? $bookingListCollect->toArray() : [];
|
||||
|
||||
$exchangeRate = 1;
|
||||
$exchangeRateOriginal = 1;
|
||||
$exchangeRateDate = Carbon::parse($periodStartDate)->lastOfMonth()->toDateString();
|
||||
foreach ($bookingListCollect as $bookingCurrency => $bookingTotal) {
|
||||
|
||||
if ($bookingCurrency != $this->exchangeCurrencyCode) {
|
||||
$exchangeRateCheck = CurrencyRates::where('currency_code', $bookingCurrency)
|
||||
->where('exc_currency_code', $this->exchangeCurrencyCode)
|
||||
->where('date', $exchangeRateDate)
|
||||
->first();
|
||||
|
||||
if ($exchangeRateCheck) {
|
||||
$exchangeRateCheck = $exchangeRateCheck->toArray();
|
||||
|
||||
} else {
|
||||
$exchangeRateCheck = CurrencyRates::where('currency_code', $bookingCurrency)
|
||||
->where('exc_currency_code', $this->exchangeCurrencyCode)
|
||||
->where('date', '<', $exchangeRateDate)
|
||||
->orderBy('date', 'DESC')
|
||||
->first()->toArray();
|
||||
}
|
||||
|
||||
$exchangeRate = $exchangeRateCheck['rate'];
|
||||
$exchangeRateDate = $exchangeRateCheck['date'];
|
||||
|
||||
}
|
||||
|
||||
$bookingTotalWithExchange = $bookingTotal['total'] * $exchangeRate;
|
||||
$bookingCommissionWithExchange = $bookingTotalWithExchange * $commissionRateRate / 100;
|
||||
|
||||
$channelBaseCommission[$propertyBookingEngine['channel_id']][$bookingCurrency] = [
|
||||
'count' => count($bookingList),
|
||||
'total' => (float)number_format($bookingTotal['total'], '4', '.', ''),
|
||||
'exchangeRate' => $exchangeRate,
|
||||
'exchangeRateDate' => $exchangeRateDate,
|
||||
'exchangeData' => [
|
||||
'total' => (float)number_format($bookingTotalWithExchange, '4', '.', ''),
|
||||
'commission' => (float)number_format($bookingCommissionWithExchange, '4', '.', ''),
|
||||
'commissionRate' => $commissionRateRate,
|
||||
'currencyCode' => $this->exchangeCurrencyCode,
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
$channelBaseCount = 0;
|
||||
$channelBaseTotal = 0;
|
||||
$channelBaseTotalCommission = 0;
|
||||
foreach ($channelBaseCommission as $channelBase) {
|
||||
$channelBaseValue = reset($channelBase);
|
||||
$channelBaseCount += $channelBaseValue['count'];
|
||||
$channelBaseTotal += $channelBaseValue['exchangeData']['total'];
|
||||
$channelBaseTotalCommission += $channelBaseValue['exchangeData']['commission'];
|
||||
}
|
||||
|
||||
$commission = [
|
||||
'channelBaseCount' => $channelBaseCount,
|
||||
'channelBaseTotal' => $channelBaseTotal,
|
||||
'channelBaseTotalCommission' => $channelBaseTotalCommission,
|
||||
];
|
||||
|
||||
return $commission;
|
||||
}
|
||||
|
||||
|
||||
public function summaryWithPeriod($propertyId, $period, $type)
|
||||
{
|
||||
$response = ['status' => -1, 'message' => '', 'data' => null];
|
||||
|
||||
$periodStartDate = Carbon::parse($period . '-01')->toDateString();
|
||||
$periodFinishDate = Carbon::parse($periodStartDate)->addMonth()->firstOfMonth()->toDateString();
|
||||
|
||||
|
||||
try {
|
||||
|
||||
$propertyDetailCriteria = [
|
||||
'criteria' => [
|
||||
['field' => 'id', 'condition' => '=', 'value' => $propertyId],
|
||||
//['field' => 'status', 'condition' => '=', 'value' => 1],
|
||||
],
|
||||
'with' => ['propertyBookingEngines.channel'],
|
||||
'firstRow' => true
|
||||
];
|
||||
|
||||
$propertyDetail = $this->propertyRepository->findByCriteria($propertyDetailCriteria);
|
||||
|
||||
if (!$propertyDetail) {
|
||||
throw new ApiErrorException('Property not found');
|
||||
}
|
||||
|
||||
|
||||
$conditions = [
|
||||
'type' => $type,
|
||||
'commission' => $propertyDetail['commission'],
|
||||
'commission_payment' => $propertyDetail['commission_payment'],
|
||||
'commission_offline' => $propertyDetail['commission_offline'],
|
||||
'commission_channel' => $propertyDetail['commission_channel'],
|
||||
];
|
||||
|
||||
$periodCommission = $this->calculatePeriodCommission($propertyId, $type, $periodStartDate, $periodFinishDate);
|
||||
|
||||
$propertySummaryCreateParam = [
|
||||
'property_id' => $propertyId,
|
||||
'period' => $period,
|
||||
'count' => $periodCommission['channelBaseCount'],
|
||||
'commission' => (float)number_format($periodCommission['channelBaseTotalCommission'], '2', '.', ''),
|
||||
'total' => (float)number_format($periodCommission['channelBaseTotal'], '2', '.', ''),
|
||||
'currency' => $this->exchangeCurrencyCode,
|
||||
'type' => $type,
|
||||
'status' => 1,
|
||||
];
|
||||
|
||||
|
||||
$propertySummaryCheckCriteria = [
|
||||
'criteria' => [
|
||||
['field' => 'property_id', 'condition' => '=', 'value' => $propertyId],
|
||||
['field' => 'period', 'condition' => '=', 'value' => $period],
|
||||
['field' => 'type', 'condition' => '=', 'value' => $type],
|
||||
],
|
||||
'firstRow' => true
|
||||
];
|
||||
|
||||
$propertySummaryCheck = $this->propertySummaryRepository->findByCriteria($propertySummaryCheckCriteria);
|
||||
|
||||
if ($propertySummaryCheck) {
|
||||
$propertySummaryCreate = $this->propertySummaryRepository->update($propertySummaryCheck['id'], $propertySummaryCreateParam);
|
||||
} else {
|
||||
$propertySummaryCreate = $this->propertySummaryRepository->create($propertySummaryCreateParam);
|
||||
}
|
||||
|
||||
if ($propertySummaryCreate['status'] != 'success') {
|
||||
throw new ApiErrorException($propertySummaryCreate['message']);
|
||||
}
|
||||
|
||||
|
||||
$response = [
|
||||
'status' => true,
|
||||
'data' => $propertySummaryCreate['data'],
|
||||
];
|
||||
|
||||
|
||||
} 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 output($response);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user