Files
api-extranetwork/app/Http/Controllers/V1/ReputationManagementController.php
ExtraNetwork e5c4b6aa13 first commit
2026-05-12 17:04:54 +03:00

571 lines
28 KiB
PHP

<?php
namespace App\Http\Controllers\V1;
use App\Core\Service\ReputationManagementService;
use App\Exceptions\ApiErrorException;
use App\Http\Controllers\Controller;
use App\Jobs\PropertyReviewServiceJob;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Exception;
class ReputationManagementController extends Controller
{
private $params;
private $reputationManagementService;
public function __construct(
ReputationManagementService $reputationManagementService
)
{
$this->params = Input::all();
$this->params = $this->params['params'];
$this->reputationManagementService = $reputationManagementService;
}
public function getChannel(Request $request)
{
$response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
try {
$criteria = [
'criteria' => [
['field' => 'status', 'condition' => '=', 'value' => 1],
]
];
$reputationManagementChannel = $this->reputationManagementService->selectChannel($criteria, ['id', 'name', 'logo', 'parameter', 'logo']);
$reputationManagementChannel = $reputationManagementChannel['status'] == 'success' && !empty($reputationManagementChannel['data']) ? $reputationManagementChannel['data'] : [];
$reputationManagementMappingCriteria = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $this->params['property_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['fetchStatus'],
];
$reputationManagementMapping = $this->reputationManagementService->selectChannelMapping($reputationManagementMappingCriteria);
$reputationManagementMapping = $reputationManagementMapping['status'] == 'success' && !empty($reputationManagementMapping['data']) ? $reputationManagementMapping['data'] : [];
$reputationManagementMappingCollect = collect($reputationManagementMapping);
$reputationManagementList = [];
foreach ($reputationManagementChannel as $reputationManagementChannelKey => $reputationManagementChannel) {
$reputationManagementMapping = $reputationManagementMappingCollect->where('channel_id', $reputationManagementChannel['id'])->first();
$reputationManagementDetail = null;
$isSelected = $reputationManagementMapping ? true : false;
if ($reputationManagementMapping) {
$reputationManagementDetail = [
'fetchStatus' => $reputationManagementMapping['fetch_status'],
'parameterArray' => $reputationManagementMapping['parameterArray']
];
}
$reputationManagementList[] = [
//'code' => $webComponent['code'],
'id' => $reputationManagementChannel['id'],
'name' => $reputationManagementChannel['name'],
'logo' => $reputationManagementChannel['logo'],
'logoUrl' => $reputationManagementChannel['logoUrl'],
'parameterArray' => $reputationManagementChannel['parameterArray'],
'is_selected' => $isSelected,
'channelDetail' => $reputationManagementDetail
];
}
$response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $reputationManagementList];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$response['statusCode'] = 400;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
$response['statusCode'] = 500;
}
return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);
}
public function syncChannel(Request $request)
{
$response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
try {
$criteria = [
'criteria' => [
['field' => 'id', 'condition' => '=', 'value' => $this->params['channel_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'firstRow' => true
];
$reputationManagementChannel = $this->reputationManagementService->selectChannel($criteria, ['id', 'name', 'logo', 'parameter', 'logo']);
$reputationManagementChannel = $reputationManagementChannel['status'] == 'success' && !empty($reputationManagementChannel['data']) ? $reputationManagementChannel['data'] : [];
if (empty($reputationManagementChannel)) {
throw new ApiErrorException(lang('Channel data not found'));
}
//Parameter Check
if (!empty($this->params['channelDetail'])) {
$parameterCheck = array_diff(array_keys($reputationManagementChannel['parameterArray']), array_keys($this->params['channelDetail']['parameter']));
if (!empty($parameterCheck)) {
throw new ApiErrorException(lang('Missing or incorrect parameter'));
}
}
$reputationManagementChannelMappingCriteria = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => fillOnUndefined($this->params, 'property_id')],
['field' => 'channel_id', 'condition' => '=', 'value' => fillOnUndefined($this->params, 'channel_id')],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'firstRow' => true
];
$reputationManagementChannelMapping = $this->reputationManagementService->selectChannelMapping($reputationManagementChannelMappingCriteria);
$reputationManagementChannelMapping = $reputationManagementChannelMapping['status'] == 'success' && !empty($reputationManagementChannelMapping['data']) ? $reputationManagementChannelMapping['data'] : [];
//Parameter Check
DB::beginTransaction();
if ($reputationManagementChannelMapping) {
//Remove
if (empty($this->params['channelDetail'])) {
$syncReputationManagementChannelMapping = $this->reputationManagementService->deleteChannelMapping($reputationManagementChannelMapping['id']);
if ($syncReputationManagementChannelMapping['status'] != 'success') {
throw new Exception('api-unknown_error');
}
} else {
//Update
$updateParam = [
'property_id' => fillOnUndefined($this->params, 'property_id'),
'channel_id' => fillOnUndefined($this->params, 'channel_id'),
'parameter' => fillOnUndefined($this->params['channelDetail'], 'parameter') ? json_encode($this->params['channelDetail']['parameter']) : null,
'fetch_status' => fillOnUndefined($reputationManagementChannelMapping, 'fetch_status'),
'updated_by' => $request->auth->id,
];
$syncReputationManagementChannelMapping = $this->reputationManagementService->updateChannelMapping($reputationManagementChannelMapping['id'], $updateParam);
if ($syncReputationManagementChannelMapping['status'] != 'success') {
throw new ApiErrorException($syncReputationManagementChannelMapping['message']);
}
}
} else {
$createParam = [
'property_id' => fillOnUndefined($this->params, 'property_id'),
'channel_id' => fillOnUndefined($this->params, 'channel_id'),
'parameter' => fillOnUndefined($this->params['channelDetail'], 'parameter') ? json_encode($this->params['channelDetail']['parameter']) : null,
'fetch_status' => 3,
'status' => 1,
'created_by' => $request->auth->id,
];
$syncReputationManagementChannelMapping = $this->reputationManagementService->createChannelMapping($createParam);
if ($syncReputationManagementChannelMapping['status'] != 'success') {
throw new ApiErrorException($syncReputationManagementChannelMapping['message']);
}
//First Fetch Review
dispatch(new PropertyReviewServiceJob($createParam['property_id'], $createParam['channel_id']));
}
$response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => null];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$response['statusCode'] = 400;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
$response['statusCode'] = 500;
}
if ($response['status']) {
DB::commit();
} else {
DB::rollBack();
}
return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);
}
public function getReview(Request $request)
{
$response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
try {
$propertyReviewCriteria = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $this->params['property_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['channel', 'channel', 'categoryMapping.category'],
'orderBy' => [
['field' => 'review_date', 'value' => 'DESC']
],
];
if (isset($this->params['filter']) && !empty(isset($this->params['filter']))) {
if (isset($this->params['filter']['channel_id'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['filter']['channel_id']];
}
if (isset($this->params['filter']['start_date'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '>', 'value' => $this->params['filter']['start_date']];
}
if (isset($this->params['filter']['end_date'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '<=', 'value' => $this->params['filter']['end_date']];
}
if (isset($this->params['filter']['sentiment'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'sentiment', 'condition' => '=', 'value' => $this->params['filter']['sentiment']];
}
if (isset($this->params['filter']['keyword'])) {
$propertyReviewCriteria['whereOr'][] = ['field' => 'author', 'condition' => 'LIKE', 'value' => '%' . $this->params['filter']['keyword'] . '%'];
$propertyReviewCriteria['whereOr'][] = ['field' => 'title', 'condition' => 'LIKE', 'value' => '%' . $this->params['filter']['keyword'] . '%'];
$propertyReviewCriteria['whereOr'][] = ['field' => 'review', 'condition' => 'LIKE', 'value' => '%' . $this->params['filter']['keyword'] . '%'];
}
}
//Just Last 1 Year
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '>', 'value' => Carbon::now()->subYear()->toDateString()];
$propertyReviewCriteriaCount = $propertyReviewCriteria;
$propertyReviewCriteriaCount['count'] = true;
$propertyReviewCount = $this->reputationManagementService->select($propertyReviewCriteriaCount, ['id']);
$propertyReviewCriteria['skip'] = fillOnUndefined($this->params, 'page', 0) ? ($this->params['page'] - 1) : 0;
$propertyReviewCriteria['take'] = fillOnUndefined($this->params, 'per_page', 20);
$propertyReviewCriteria['skip'] = $propertyReviewCriteria['skip'] * $propertyReviewCriteria['take'];
$column = ['id', 'property_id', 'channel_id', 'author', 'title', 'review', 'review_date', 'rating', 'top_rating', 'score', 'sentiment', 'language'];
$propertyReview = $this->reputationManagementService->select($propertyReviewCriteria, $column);
$propertyReview = $propertyReview['status'] == 'success' && !empty($propertyReview['data']) ? $propertyReview['data'] : [];
$propertyReviewList = [
'total' => $propertyReviewCount['data'],
'page' => $this->params['page'],
'count' => count($propertyReview),
'review' => $propertyReview
];
$response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyReviewList];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$response['statusCode'] = 400;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
$response['statusCode'] = 500;
}
return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);
}
public function getReviewStatistics(Request $request)
{
$response = ['status' => false, 'message' => '', 'data' => null, 'statusCode' => 500];
try {
$propertyReviewCriteria = [
'criteria' => [
['field' => 'property_id', 'condition' => '=', 'value' => $this->params['property_id']],
['field' => 'status', 'condition' => '=', 'value' => 1],
],
'with' => ['channel', 'channel', 'categoryMapping.category', 'keywordMapping'],
'orderBy' => [
['field' => 'review_date', 'value' => 'DESC']
],
];
if (isset($this->params['filter']) && !empty(isset($this->params['filter']))) {
if (isset($this->params['filter']['channel_id'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'channel_id', 'condition' => '=', 'value' => $this->params['filter']['channel_id']];
}
if (isset($this->params['filter']['start_date'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '>', 'value' => $this->params['filter']['start_date']];
}
if (isset($this->params['filter']['end_date'])) {
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '<=', 'value' => $this->params['filter']['end_date']];
}
}
//Just Last 1 Year
$propertyReviewCriteria['criteria'][] = ['field' => 'review_date', 'condition' => '>', 'value' => Carbon::now()->subYear()->toDateString()];
$column = ['id', 'property_id', 'channel_id', 'review_date', 'rating', 'top_rating', 'score', 'sentiment', 'language'];
$propertyReview = $this->reputationManagementService->select($propertyReviewCriteria, $column);
$propertyReview = $propertyReview['status'] == 'success' && !empty($propertyReview['data']) ? $propertyReview['data'] : [];
$propertyReviewStatistics['reviewScore'] = collect($propertyReview)->average('score');
$propertyReviewStatistics['reviewScore'] = (float)number_format($propertyReviewStatistics['reviewScore'], 2, '.', '');
$reviewSentimentGroup = collect($propertyReview)->groupBy('sentiment')->map->count();
$reviewSentimentGroup = $reviewSentimentGroup ? $reviewSentimentGroup->toArray() : null;
$reviewSentiment['positive'] = isset($reviewSentimentGroup[1]) ? $reviewSentimentGroup[1] : 0;
$reviewSentiment['negative'] = isset($reviewSentimentGroup[0]) ? $reviewSentimentGroup[0] : 0;
$propertyReviewStatistics['reviewScoreBySystem'] = null;
if (($reviewSentiment['positive'] + $reviewSentiment['negative']) > 0) {
$propertyReviewStatistics['reviewScoreBySystem'] = $reviewSentiment['positive'] / ($reviewSentiment['positive'] + $reviewSentiment['negative']) * 100;
$propertyReviewStatistics['reviewScoreBySystem'] = (float)number_format($propertyReviewStatistics['reviewScoreBySystem'], 2, '.', '');
}
//$reviewCategoryScoreBySystem
$reviewCategoryMapping = [];
$reviewCategoryScoreBySystem = [];
$reviewKeywordScoreBySystem = [];
foreach ($propertyReview as $review) {
foreach ($review['category_mapping'] as $reviewCategory) {
if (!isset($reviewCategoryScoreBySystem[$reviewCategory['category_id']])) {
$reviewCategoryScoreBySystem[$reviewCategory['category_id']][0] = 0;
$reviewCategoryScoreBySystem[$reviewCategory['category_id']][1] = 0;
}
$reviewCategoryScoreBySystem[$reviewCategory['category_id']][$reviewCategory['sentiment']]++;
$reviewCategoryMapping[$reviewCategory['category_id']]['name'] = $reviewCategory['category']['name'];
$reviewCategoryMapping[$reviewCategory['category_id']]['score'][$review['review_date']] = $review['score'];
if (!isset($reviewCategoryMapping[$reviewCategory['category_id']]['sentimentScore'][Carbon::parse($review['review_date'])->format('Y-m')])) {
$reviewCategoryMapping[$reviewCategory['category_id']]['sentimentScore'][Carbon::parse($review['review_date'])->format('Y-m')][0] = 0;
$reviewCategoryMapping[$reviewCategory['category_id']]['sentimentScore'][Carbon::parse($review['review_date'])->format('Y-m')][1] = 0;
}
$reviewCategoryMapping[$reviewCategory['category_id']]['sentimentScore'][Carbon::parse($review['review_date'])->format('Y-m')][$reviewCategory['sentiment']]++;
}
foreach ($review['keyword_mapping'] as $reviewKeyword) {
if (!isset($reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])])) {
$reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])]['positive'] = 0;
$reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])]['negative'] = 0;
$reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])]['keyword'] = $reviewKeyword['keyword'];
}
if ($reviewKeyword['sentiment'] == 1) {
$reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])]['positive']++;
} elseif ($reviewKeyword['sentiment'] == 0) {
$reviewKeywordScoreBySystem[md5($reviewKeyword['keyword'])]['negative']++;
}
}
}
$propertyReviewCategoryCriteria = [
'criteria' => [
['field' => 'status', 'condition' => '=', 'value' => 1],
]
];
$propertyReviewCategory = $this->reputationManagementService->selectCategory($propertyReviewCategoryCriteria);
$propertyReviewCategory = $propertyReviewCategory['status'] == 'success' ? $propertyReviewCategory['data'] : [];
$propertyReviewCategoryScore = [];
foreach ($propertyReviewCategory as $reviewCategory) {
if (empty($reviewCategoryScoreBySystem)) {
continue;
}
if (isset($reviewCategoryScoreBySystem[$reviewCategory['id']]) && array_sum($reviewCategoryScoreBySystem[$reviewCategory['id']]) < 5) {
continue;
}
$propertyReviewCategoryScore[$reviewCategory['id']] = [
'name' => $reviewCategory['name'],
'language_key' => $reviewCategory['language_key'],
];
$propertyReviewCategoryScore[$reviewCategory['id']]['score'] = null;
if (isset($reviewCategoryScoreBySystem[$reviewCategory['id']])) {
$propertyReviewCategoryScore[$reviewCategory['id']]['score'] = (float)number_format($reviewCategoryScoreBySystem[$reviewCategory['id']][1] / array_sum($reviewCategoryScoreBySystem[$reviewCategory['id']]) * 100, 2, '.', '');
$propertyReviewCategoryScore[$reviewCategory['id']]['positive'] = $reviewCategoryScoreBySystem[$reviewCategory['id']][1];
$propertyReviewCategoryScore[$reviewCategory['id']]['negative'] = $reviewCategoryScoreBySystem[$reviewCategory['id']][0];
$propertyReviewCategoryScore[$reviewCategory['id']]['total'] = array_sum($reviewCategoryScoreBySystem[$reviewCategory['id']]);
krsort($reviewCategoryMapping[$reviewCategory['id']]['score']);
$propertyReviewCategoryScore[$reviewCategory['id']]['scoreLastNumber'] = array_slice($reviewCategoryMapping[$reviewCategory['id']]['score'], 0, 10);
//Group By Month
/*$propertyReviewCategoryGroupScore = [];
foreach ($reviewCategoryMapping[$reviewCategory['id']]['score'] as $reviewDateTime => $reviewScore) {
$propertyReviewCategoryGroupScore[Carbon::parse($reviewDateTime)->format('m-Y')][] = $reviewScore;
}
$propertyReviewCategoryGroupScoreAverage = [];
foreach ($propertyReviewCategoryGroupScore as $reviewPeriod => $reviewPeriodScore) {
$propertyReviewCategoryGroupScoreAverage[$reviewPeriod] = round(collect($reviewPeriodScore)->avg());
}*/
//Group By Month
//Group By Month
ksort($reviewCategoryMapping[$reviewCategory['id']]['sentimentScore']);
$propertyReviewCategoryGroupScoreAverage = [];
foreach ($reviewCategoryMapping[$reviewCategory['id']]['sentimentScore'] as $reviewPeriod => $reviewPeriodScore) {
$categorySentimentScore = (float)number_format($reviewPeriodScore[1] / array_sum($reviewPeriodScore) * 100, 2, '.', '');
if ($categorySentimentScore <= 0) {
continue;
}
$propertyReviewCategoryGroupScoreAverage[$reviewPeriod] = round($categorySentimentScore);
}
//Group By Month
$propertyReviewCategoryScore[$reviewCategory['id']]['scoreMonthlyGroup'] = $propertyReviewCategoryGroupScoreAverage;
$propertyReviewCategoryScore[$reviewCategory['id']]['scoreMonthlyGroupAverage'] = (float)number_format(collect($propertyReviewCategoryGroupScoreAverage)->average(), 2, '.', '');
}
}
$propertyReviewStatistics['reviewCategoryScoreBySystem'] = array_values($propertyReviewCategoryScore);
//$reviewCategoryScoreBySystem
foreach ($reviewKeywordScoreBySystem as $reviewKeywordKey => $reviewKeyword) {
if (($reviewKeyword['positive'] + $reviewKeyword['negative']) < 3) {
unset($reviewKeywordScoreBySystem[$reviewKeywordKey]);
continue;
}
if (isset($reviewKeywordScoreBySystem[$reviewKeywordKey])) {
$reviewKeywordScoreBySystem[$reviewKeywordKey]['score'] = (float)number_format($reviewKeywordScoreBySystem[$reviewKeywordKey]['positive'] / array_sum($reviewKeywordScoreBySystem[$reviewKeywordKey]) * 100, 2, '.', '');
}
}
$propertyReviewStatistics['reviewKeywordScoreBySystem'] = array_values($reviewKeywordScoreBySystem);
//Dashboard Summary
$propertyReviewStatistics['dashboard'] = [];
$currentWeekStart = Carbon::now()->startOfWeek(Carbon::MONDAY)->toDateString();
$currentWeekFinish = Carbon::now()->addWeek()->startOfWeek(Carbon::MONDAY)->toDateString();
//TOTAL
$totalReview = count($propertyReview);
$extraReviewCount = collect($propertyReview)->where('review_date', '>', $currentWeekStart)->count();
$propertyReviewStatistics['dashboard'] ['total'] = [
'count' => $totalReview,
'extraReviewCount' => $extraReviewCount
];
//POSITIVE
$totalReviewPositive = collect($propertyReview)->where('sentiment', 1)->count();
$extraPositiveReviewCount = collect($propertyReview)->where('review_date', '>', $currentWeekStart)->where('sentiment', 1)->count();
$propertyReviewStatistics['dashboard'] ['positive'] = [
'count' => $totalReviewPositive,
'extraReviewCount' => $extraPositiveReviewCount
];
//NEGATIVE
$totalReviewNegative = collect($propertyReview)->where('sentiment', '!=', 1)->count();
$extraNegativeReviewCount = collect($propertyReview)->where('review_date', '>', $currentWeekStart)->where('sentiment', '!=', 1)->count();
$propertyReviewStatistics['dashboard'] ['negative'] = [
'count' => $totalReviewNegative,
'extraReviewCount' => $extraNegativeReviewCount
];
//BEST
$bestReview = collect($propertyReviewCategoryScore)->sortByDesc('positive')->first();
$propertyReviewStatistics['dashboard'] ['best'] = [
'name' => $bestReview['name'],
'language_key' => $bestReview['language_key'],
'score' => $bestReview['score'],
'positive' => $bestReview['positive'],
'negative' => $bestReview['negative'],
'total' => $bestReview['total'],
];
$response = ['status' => 1, 'statusCode' => 200, 'message' => null, 'data' => $propertyReviewStatistics];
} catch (ApiErrorException $e) {
$response['message'] = implode(', ', $e->getMessageArr());
$response['statusCode'] = 400;
} catch (Exception $e) {
$message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage();
Log::error($message);
$response['message'] = $e->getMessage();
$response['statusCode'] = 500;
}
return apiResponse($response['status'], $response['message'], $response['data'], $response['statusCode']);
}
}