566 lines
24 KiB
PHP
566 lines
24 KiB
PHP
<?php
|
|
|
|
|
|
namespace App\Services\APIs\CustomerAPIs;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use App\Models\CustomerFavouriteRestaurant;
|
|
use App\Models\IamPrincipal;
|
|
use App\Models\IamPrincipalRestaurantRole;
|
|
use App\Models\ManageRestaurant;
|
|
use App\Models\RedeemRestaurant;
|
|
use App\Helpers\onesignalhelper;
|
|
use App\Models\RestaurantTimeInterval;
|
|
use App\Models\TimeInterval;
|
|
use Carbon\Carbon;
|
|
use Exception;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
use App\Jobs\FetchOperatingHours;
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Promise;
|
|
use GuzzleHttp\Promise\Utils;
|
|
|
|
|
|
|
|
class RestaurantApiServices
|
|
{
|
|
public function getCoordinates($customerIamId)
|
|
{
|
|
try {
|
|
// $perPage = request()->get('per_page', 10000);
|
|
|
|
$restaurants = ManageRestaurant::with('closedRestaurant')
|
|
->select(
|
|
'id',
|
|
'name',
|
|
'image',
|
|
'address',
|
|
'short_id',
|
|
'latitude',
|
|
'longtitude'
|
|
)
|
|
->where('is_active', '1')->get();
|
|
|
|
$client = new Client();
|
|
$promises = [];
|
|
$googlePlaceApiKey = config('constants.googlePlaces.api_key');
|
|
|
|
foreach ($restaurants as &$restaurant) {
|
|
$restaurant['image'] = ListingImageUrl('restaurant_images', $restaurant['image']);
|
|
$isFavourite = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->where('restaurant_xid', $restaurant['id'])
|
|
->exists();
|
|
$restaurant['is_favourite'] = $isFavourite;
|
|
|
|
$cacheKey = 'restaurant_hours_' . $restaurant['name'];
|
|
if (Cache::has($cacheKey)) {
|
|
$restaurant['operating_hours'] = Cache::get($cacheKey);
|
|
} else {
|
|
// Prepare the first request to get the place_id
|
|
$promises[$restaurant['name']] = $client->getAsync('https://maps.googleapis.com/maps/api/place/findplacefromtext/json', [
|
|
'query' => [
|
|
'fields' => 'place_id',
|
|
'input' => $restaurant['name'],
|
|
'inputtype' => 'textquery',
|
|
'key' => $googlePlaceApiKey
|
|
]
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Execute all the first requests concurrently
|
|
$results = Utils::settle($promises)->wait();
|
|
|
|
$detailPromises = [];
|
|
foreach ($restaurants as &$restaurant) {
|
|
if (isset($results[$restaurant['name']]['value'])) {
|
|
$response = $results[$restaurant['name']]['value'];
|
|
$placeData = json_decode($response->getBody(), true);
|
|
|
|
if (isset($placeData['candidates'][0]['place_id'])) {
|
|
$placeId = $placeData['candidates'][0]['place_id'];
|
|
|
|
// Prepare the second request to get the operating hours
|
|
$detailPromises[$restaurant['name']] = $client->getAsync('https://maps.googleapis.com/maps/api/place/details/json', [
|
|
'query' => [
|
|
'fields' => 'opening_hours',
|
|
'place_id' => $placeId,
|
|
'key' => $googlePlaceApiKey
|
|
]
|
|
]);
|
|
} else {
|
|
$restaurant['operating_hours'] = "N/A";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Execute all the second requests concurrently
|
|
$detailResults = Utils::settle($detailPromises)->wait();
|
|
|
|
foreach ($restaurants as &$restaurant) {
|
|
if (isset($detailResults[$restaurant['name']]['value'])) {
|
|
$response = $detailResults[$restaurant['name']]['value'];
|
|
$data = json_decode($response->getBody(), true);
|
|
if (isset($data['result']['opening_hours']['weekday_text'])) {
|
|
$hours = $data['result']['opening_hours']['weekday_text'];
|
|
Cache::put('restaurant_hours_' . $restaurant['name'], $hours, now()->addHours(24));
|
|
$restaurant['operating_hours'] = $hours;
|
|
} else {
|
|
$restaurant['operating_hours'] = "N/A";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return jsonResponseWithSuccessMessage(__('auth.data_fetched_successfully'), $restaurants, 200);
|
|
} catch (Exception $ex) {
|
|
Log::error('Restaurant Get service failed : ' . $ex->getMessage());
|
|
return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
public function addToFavourite($customerIamId, $request)
|
|
{
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$restaurant = ManageRestaurant::where('short_id', $request->id)->where('is_active', '1')->first();
|
|
if (!$restaurant) {
|
|
return jsonResponseWithErrorMessage(__('auth.restaurant_data_not_found'), 404);
|
|
}
|
|
|
|
$existingFavourite = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->where('restaurant_xid', $restaurant->id)
|
|
->first();
|
|
|
|
if ($existingFavourite) {
|
|
return jsonResponseWithErrorMessage(__('auth.restaurant_already_favourite'), 409);
|
|
}
|
|
|
|
$favRestaurant = new CustomerFavouriteRestaurant();
|
|
$favRestaurant->principal_xid = $customerIamId;
|
|
$favRestaurant->restaurant_xid = $restaurant->id;
|
|
$favRestaurant->save();
|
|
|
|
DB::commit();
|
|
|
|
return jsonResponseWithSuccessMessage(__('auth.data_updated_successfully'), 200);
|
|
} catch (\Exception $ex) {
|
|
DB::rollBack();
|
|
Log::error('Favourite Restaurant service failed: ' . $ex->getMessage());
|
|
return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function listFavRestaurant($customerIamId)
|
|
{
|
|
try {
|
|
$list = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)->get()->toArray();
|
|
$customerFavouriteRestaurants = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->pluck('restaurant_xid')
|
|
->toArray();
|
|
|
|
$restaurants = ManageRestaurant::with('operatingHours')->where('is_active', '1')->whereIn('id', $customerFavouriteRestaurants)->get();
|
|
|
|
foreach ($restaurants as &$res) {
|
|
$res['image'] = ListingImageUrl('restaurant_images', $res['image']);
|
|
}
|
|
|
|
return jsonResponseWithSuccessMessage(__('auth.data_updated_successfully'), $restaurants, 200);
|
|
} catch (Exception $ex) {
|
|
Log::error('List of Favourite Restaurant service failed : ' . $ex->getMessage());
|
|
return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
//
|
|
public function DetailRestaurant($customerIamId, $id)
|
|
{
|
|
try {
|
|
$rest = ManageRestaurant::select('id', 'short_id', 'name', 'description', 'restaurant_id', 'address', 'image', 'bio', 'try_on_1', 'try_on_2', 'try_on_3', 'try_on_4', 'exclusion', 'latitude', 'longtitude', 'state_xid')
|
|
->where('short_id', $id)
|
|
->where('is_active', '1')
|
|
->first();
|
|
|
|
if ($rest) {
|
|
$rest->image = ListingImageUrl('restaurant_images', $rest->image);
|
|
|
|
$isFavourite = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->where('restaurant_xid', $rest->id)
|
|
->exists();
|
|
|
|
$rest->is_favourite = $isFavourite;
|
|
|
|
$redeem = RedeemRestaurant::where('iam_principal_xid', $customerIamId)
|
|
->where('manage_restaurants_xid', $rest->id)
|
|
->where('is_redeem', "1")
|
|
->first();
|
|
|
|
$restTime = RestaurantTimeInterval::where('manage_restaurants_xid', $rest->id)->first();
|
|
$restTimeHours = $restTime->time_hours;
|
|
|
|
// Initialize Guzzle HTTP client
|
|
$client = new Client();
|
|
$googlePlaceApiKey = config('constants.googlePlaces.api_key');
|
|
|
|
// Cache key for operating hours
|
|
$cacheKey = 'restaurant_hours_' . $rest->name;
|
|
if (Cache::has($cacheKey)) {
|
|
$rest->operating_hours = Cache::get($cacheKey);
|
|
} else {
|
|
// Prepare the first request to get the place_id
|
|
$placeResponse = $client->get('https://maps.googleapis.com/maps/api/place/findplacefromtext/json', [
|
|
'query' => [
|
|
'fields' => 'place_id',
|
|
'input' => $rest->name,
|
|
'inputtype' => 'textquery',
|
|
'key' => $googlePlaceApiKey
|
|
]
|
|
]);
|
|
$placeData = json_decode($placeResponse->getBody(), true);
|
|
|
|
if (isset($placeData['candidates'][0]['place_id'])) {
|
|
$placeId = $placeData['candidates'][0]['place_id'];
|
|
|
|
// Prepare the second request to get the operating hours
|
|
$detailResponse = $client->get('https://maps.googleapis.com/maps/api/place/details/json', [
|
|
'query' => [
|
|
'fields' => 'opening_hours',
|
|
'place_id' => $placeId,
|
|
'key' => $googlePlaceApiKey
|
|
]
|
|
]);
|
|
$detailData = json_decode($detailResponse->getBody(), true);
|
|
|
|
if (isset($detailData['result']['opening_hours']['weekday_text'])) {
|
|
$hours = $detailData['result']['opening_hours']['weekday_text'];
|
|
Cache::put($cacheKey, $hours, now()->addHours(24));
|
|
$rest->operating_hours = $hours;
|
|
} else {
|
|
$rest->operating_hours = "N/A";
|
|
}
|
|
} else {
|
|
$rest->operating_hours = "N/A";
|
|
}
|
|
}
|
|
|
|
if ($redeem) {
|
|
$rest->is_Redeemed = true;
|
|
$rest->redeem_date = \Carbon\Carbon::parse($redeem->redeem_date)->addHours($restTimeHours)->toDateTimeString();
|
|
} else {
|
|
$rest->is_Redeemed = false;
|
|
$rest->redeem_date = null;
|
|
}
|
|
}
|
|
|
|
if (!$rest) {
|
|
return jsonResponseWithErrorMessage(__('auth.restaurant_data_not_found'), 404);
|
|
}
|
|
|
|
return jsonResponseWithSuccessMessage(__('auth.data_fetched_successfully'), $rest, 200);
|
|
} catch (Exception $e) {
|
|
Log::error("Error fetching restaurant data: " . $e->getMessage());
|
|
return jsonResponseWithErrorMessage(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function removeFromFavourite($customerIamId, $request)
|
|
{
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$restaurant = ManageRestaurant::where('short_id', $request->id)->where('is_active', '1')->first();
|
|
if (!$restaurant) {
|
|
return jsonResponseWithErrorMessage(__('auth.restaurant_data_not_found'), 404);
|
|
}
|
|
|
|
$existingFavourite = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->where('restaurant_xid', $restaurant->id)
|
|
->first();
|
|
if (!$existingFavourite) {
|
|
return jsonResponseWithErrorMessage(__('auth.data_not_found'), 404);
|
|
}
|
|
if ($existingFavourite) {
|
|
$existingFavourite->delete();
|
|
}
|
|
DB::commit();
|
|
|
|
return jsonResponseWithSuccessMessage(__('auth.data_updated_successfully'), 200);
|
|
} catch (\Exception $ex) {
|
|
DB::rollBack();
|
|
Log::error('Favourite Restaurant service failed: ' . $ex->getMessage());
|
|
return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
|
|
public function searchFromFavourite($customerIamId, $request)
|
|
{
|
|
try {
|
|
$customerFavouriteRestaurants = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->pluck('restaurant_xid')
|
|
->toArray();
|
|
|
|
$restaurantsQuery = ManageRestaurant::with('operatingHours')
|
|
->where('is_active', '1')
|
|
->whereIn('id', $customerFavouriteRestaurants);
|
|
|
|
$searchData = $request->input('search_data');
|
|
|
|
if (!empty($searchData)) {
|
|
$restaurantsQuery->where(function ($query) use ($searchData) {
|
|
$query->where('name', 'like', "%$searchData%")
|
|
->orWhere('description', 'like', "%$searchData%")
|
|
->orWhere('address', 'like', "%$searchData%")
|
|
->orWhereHas('state', function ($stateQuery) use ($searchData) {
|
|
$stateQuery->where('name', 'like', "%$searchData%");
|
|
});
|
|
});
|
|
}
|
|
|
|
$restaurants = $restaurantsQuery->get();
|
|
foreach ($restaurants as &$res) {
|
|
$res['image'] = ListingImageUrl('restaurant_images', $res['image']);
|
|
}
|
|
|
|
|
|
return jsonResponseWithSuccessMessageApi(__('auth.restaurant_search'), $restaurants, 200);
|
|
} catch (Exception $ex) {
|
|
Log::error('Search from favourite restaurant service failed: ' . $ex->getMessage());
|
|
return response()->json([
|
|
'message' => __('auth.something_went_wrong')
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
|
|
public function redeemRestaurant($customerIamId, $request)
|
|
{
|
|
try {
|
|
$restaurantId = $request->id;
|
|
|
|
$restaurant = ManageRestaurant::with('operatingHours')->where('short_id', $restaurantId)->first();
|
|
if (!$restaurant) {
|
|
return jsonResponseWithErrorMessageApi(__('auth.restaurant_not_found'), 404);
|
|
}
|
|
|
|
// Check if the restaurant has already been redeemed
|
|
$restaurantExist = RedeemRestaurant::where('manage_restaurants_xid', $restaurant->id)
|
|
->where('iam_principal_xid', $customerIamId)
|
|
->where('is_redeem', 1)
|
|
->first();
|
|
|
|
|
|
if ($restaurantExist) {
|
|
return jsonResponseWithErrorMessageApi(__('auth.restaurant_already_redeemed'), 403);
|
|
}
|
|
|
|
$stateLimitation = TimeInterval::where('manage_state_xid', $restaurant->state_xid)->first();
|
|
$stateMaxLimitation = $stateLimitation ? $stateLimitation->quantity : 0;
|
|
$stateMaxIntervalLimitation = $stateLimitation ? $stateLimitation->time_interval : "month";
|
|
|
|
$restaurantLimitation = RestaurantTimeInterval::where('manage_restaurants_xid', $restaurant->id)->first();
|
|
$restaurantMaxLimitation = $restaurantLimitation ? $restaurantLimitation->quantity : 0;
|
|
$restaurantMaxIntervalLimitation = $restaurantLimitation ? $restaurantLimitation->time_interval : "month";
|
|
|
|
|
|
// Calculate the state interval start date
|
|
$stateIntervalStartDate = $this->calculateIntervalStartDate($stateMaxIntervalLimitation);
|
|
|
|
// Count the redeems within the state interval
|
|
$redeemCountState = RedeemRestaurant::where('state_xid', $restaurant->state_xid)
|
|
->where('iam_principal_xid', $customerIamId)
|
|
->count();
|
|
|
|
if ($redeemCountState >= $stateMaxLimitation) {
|
|
return jsonResponseWithErrorMessageApi(__('auth.state_limit_reached'), 403);
|
|
}
|
|
|
|
// Calculate the restaurant interval start date
|
|
$restaurantIntervalStartDate = $this->calculateIntervalStartDate($restaurantMaxIntervalLimitation);
|
|
|
|
// Count the redeems within the restaurant interval
|
|
$redeemCountRestaurant = RedeemRestaurant::where('manage_restaurants_xid', $restaurant->id)
|
|
->where('is_redeem', 1)
|
|
->where('iam_principal_xid', $customerIamId)
|
|
->count();
|
|
|
|
if ($redeemCountRestaurant >= $restaurantMaxLimitation) {
|
|
return jsonResponseWithErrorMessageApi(__('auth.restaurant_limit_reached'), 403);
|
|
}
|
|
|
|
// Get the last redeem time
|
|
$lastRedeem = RedeemRestaurant::where('iam_principal_xid', $customerIamId)
|
|
->where('state_xid', $restaurant->state_xid)
|
|
->where('is_redeem', 1)
|
|
->orderBy('redeem_date', 'desc')
|
|
->first();
|
|
|
|
$restTime = RestaurantTimeInterval::select('time_hours')->where('manage_restaurants_xid', $restaurant->id)->first();
|
|
$stateTime = TimeInterval::select('time_hours')->where('manage_state_xid', $restaurant->state_xid)->first();
|
|
|
|
$restTimeHours = $restTime ? $restTime->time_hours : 0;
|
|
$stateTimeHours = $stateTime ? $stateTime->time_hours : 0;
|
|
|
|
|
|
|
|
if ($lastRedeem) {
|
|
$lastRedeemTime = Carbon::parse($lastRedeem->redeem_date);
|
|
$currentTime = Carbon::now();
|
|
|
|
$stateAllowedRedeemTime = $lastRedeemTime->copy()->addHours($stateTimeHours);
|
|
$restAllowedRedeemTime = $lastRedeemTime->copy()->addHours($restTimeHours);
|
|
|
|
if ($currentTime < $stateAllowedRedeemTime) {
|
|
$remainingTime = $currentTime->diff($stateAllowedRedeemTime);
|
|
$hours = $remainingTime->h;
|
|
$minutes = $remainingTime->i;
|
|
return jsonResponseWithErrorMessageApi(__('auth.redeem_not_allowed_yet') . " {$hours} hours and {$minutes} minutes remaining.", 403);
|
|
}
|
|
|
|
if ($currentTime < $restAllowedRedeemTime) {
|
|
$remainingTime = $currentTime->diff($restAllowedRedeemTime);
|
|
$hours = $remainingTime->h;
|
|
$minutes = $remainingTime->i;
|
|
return jsonResponseWithErrorMessageApi(__('auth.redeem_not_allowed_yet') . " {$hours} hours and {$minutes} minutes remaining.", 403);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Create a new redeem entry if it doesn't exist
|
|
$redeemRestaurant = new RedeemRestaurant();
|
|
$redeemRestaurant->iam_principal_xid = $customerIamId;
|
|
$redeemRestaurant->manage_restaurants_xid = $restaurant->id;
|
|
$redeemRestaurant->state_xid = $restaurant->state_xid;
|
|
$redeemRestaurant->is_redeem = 1; // Redeem restaurant
|
|
$redeemRestaurant->redeem_date = now();
|
|
$redeemRestaurant->is_redeemption_undone = 0;
|
|
$redeemRestaurant->redeemption_undone_date = null;
|
|
$redeemRestaurant->save();
|
|
|
|
$imagePath = ListingImageUrl('restaurant_images', $restaurant->image);
|
|
|
|
$customerTitle = "Your Redemption was successful for " . $restaurant->name;
|
|
$customerMessage = $restaurant->name . " Voucher Redeemed Successfully";
|
|
$customerContentType = 'Voucher_Redemption';
|
|
$customerImageUrl = $imagePath;
|
|
|
|
$customerData = IamPrincipal::where('id', $customerIamId)
|
|
->where('notification_status', 1)
|
|
->where('principal_type_xid', 3)
|
|
->first();
|
|
|
|
$restaurants = IamPrincipalRestaurantRole::select('id', 'principal_xid')
|
|
->where('restaurant_xid', $restaurant->id)
|
|
->get();
|
|
|
|
foreach ($restaurants as $restaurantRole) {
|
|
$restUser = IamPrincipal::where('id', $restaurantRole->principal_xid)
|
|
->where('notification_status', 1)
|
|
->where('principal_type_xid', 4)
|
|
->first();
|
|
|
|
if ($restUser) {
|
|
$restImagePath = ListingImageUrl('restaurant_images', $restaurant->image);
|
|
$restTitle = "New redemption for " . $restaurant->name;
|
|
$restMessage = $restaurant->name . " new voucher Redeemed Successfully";
|
|
$restContent_type = 'Voucher_Redemption';
|
|
$restImageUrl = $restImagePath;
|
|
|
|
// Sending notification to restaurant
|
|
onesignalhelper::restSendNotificationApi(
|
|
$restUser->one_signal_player_id,
|
|
$restTitle,
|
|
$restMessage,
|
|
$restContent_type,
|
|
$restImageUrl,
|
|
$id = null
|
|
);
|
|
onesignalhelper::StoreNotificationDetails($restUser->id, $restContent_type, $restTitle, $restImageUrl);
|
|
}
|
|
}
|
|
|
|
if ($customerData) {
|
|
// Sending notification to customer
|
|
onesignalhelper::sendNotificationApi(
|
|
$customerData->one_signal_player_id,
|
|
$customerTitle,
|
|
$customerMessage,
|
|
$customerContentType,
|
|
$customerImageUrl,
|
|
$id = null
|
|
);
|
|
onesignalhelper::StoreNotificationDetails($customerData->id, $customerContentType, $customerTitle, $customerImageUrl);
|
|
}
|
|
|
|
return jsonResponseWithSuccessMessageApi(__('success.restaurant_redeem'), $redeemRestaurant, 200);
|
|
} catch (Exception $ex) {
|
|
Log::error('Restaurant Redeem service failed: ' . $ex->getMessage());
|
|
return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
|
|
}
|
|
}
|
|
|
|
private function calculateIntervalStartDate($interval)
|
|
{
|
|
$now = Carbon::now();
|
|
|
|
switch ($interval) {
|
|
case 'day':
|
|
return $now->copy()->subDay();
|
|
case 'week':
|
|
return $now->copy()->subWeek();
|
|
case 'month':
|
|
default:
|
|
return $now->copy()->subMonth();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function searchRestaurant($customerIamId, $request)
|
|
{
|
|
try {
|
|
$restaurantsQuery = ManageRestaurant::with(['operatingHours', 'state'])
|
|
->where('is_active', '1');
|
|
|
|
$searchData = $request->input('search_data');
|
|
|
|
if (!empty($searchData)) {
|
|
$restaurantsQuery->where(function ($query) use ($searchData) {
|
|
$query->where('name', 'like', "%$searchData%")
|
|
->orWhere('description', 'like', "%$searchData%")
|
|
->orWhere('address', 'like', "%$searchData%")
|
|
->orWhereHas('state', function ($stateQuery) use ($searchData) {
|
|
$stateQuery->where('name', 'like', "%$searchData%");
|
|
});
|
|
});
|
|
}
|
|
|
|
$restaurants = $restaurantsQuery->get();
|
|
|
|
foreach ($restaurants as &$res) {
|
|
$res['image'] = ListingImageUrl('restaurant_images', $res['image']);
|
|
$res['is_favourite'] = CustomerFavouriteRestaurant::where('principal_xid', $customerIamId)
|
|
->where('restaurant_xid', $res->id)
|
|
->exists();
|
|
}
|
|
|
|
return jsonResponseWithSuccessMessageApi(__('auth.restaurant_search'), $restaurants, 200);
|
|
} catch (Exception $ex) {
|
|
Log::error('Search from restaurant service failed: ' . $ex->getMessage());
|
|
return response()->json([
|
|
'message' => __('auth.something_went_wrong')
|
|
], 500);
|
|
}
|
|
}
|
|
}
|