120 lines
3.7 KiB
PHP
120 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace Modules\ManagementTools\Services\ExecutiveCockpit;
|
|
|
|
use App\Services\Holding\AssignmentQueryScopeService;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class HoldingComparisonService
|
|
{
|
|
public function __construct(
|
|
protected AssignmentQueryScopeService $assignmentScope,
|
|
protected TransactionMetricsQuery $transactionMetrics
|
|
) {}
|
|
|
|
public function compare(
|
|
int $businessId,
|
|
Carbon $startDate,
|
|
Carbon $endDate,
|
|
callable $periodComparison,
|
|
callable $previousPeriodRange
|
|
): array {
|
|
if (! Schema::hasTable('holding_entities')) {
|
|
return ['available' => false, 'entities' => [], 'totals' => []];
|
|
}
|
|
|
|
[$prevStartDate, $prevEndDate] = $previousPeriodRange($startDate, $endDate);
|
|
|
|
$entityQuery = DB::table('holding_entities')
|
|
->where('business_id', $businessId)
|
|
->where('is_active', 1);
|
|
|
|
if (Schema::hasColumn('holding_entities', 'deleted_at')) {
|
|
$entityQuery->whereNull('deleted_at');
|
|
}
|
|
|
|
$allowedEntityIds = $this->assignmentScope->allowedEntityIds();
|
|
if ($allowedEntityIds !== null) {
|
|
$entityQuery->whereIn('id', $allowedEntityIds);
|
|
}
|
|
|
|
$entities = $entityQuery
|
|
->orderBy('name')
|
|
->get(['id', 'name', 'code', 'entity_type', 'meta']);
|
|
|
|
if ($entities->isEmpty()) {
|
|
return ['available' => false, 'entities' => [], 'totals' => []];
|
|
}
|
|
|
|
$entityLocationMap = [];
|
|
$entityIds = [];
|
|
foreach ($entities as $entity) {
|
|
$meta = is_string($entity->meta) ? json_decode($entity->meta, true) : (array) ($entity->meta ?? []);
|
|
$entityLocationMap[(int) $entity->id] = (int) data_get($meta, 'business_location_id', 0);
|
|
$entityIds[] = (int) $entity->id;
|
|
}
|
|
|
|
$currentSales = $this->transactionMetrics->entitySalesBatch(
|
|
$businessId,
|
|
$entityIds,
|
|
$entityLocationMap,
|
|
$startDate,
|
|
$endDate
|
|
);
|
|
$prevSales = $this->transactionMetrics->entitySalesBatch(
|
|
$businessId,
|
|
$entityIds,
|
|
$entityLocationMap,
|
|
$prevStartDate,
|
|
$prevEndDate
|
|
);
|
|
|
|
$rows = [];
|
|
$totalSales = 0.0;
|
|
$totalPrevSales = 0.0;
|
|
|
|
foreach ($entities as $entity) {
|
|
$entityId = (int) $entity->id;
|
|
$locationId = $entityLocationMap[$entityId] ?? 0;
|
|
$sales = (float) ($currentSales[$entityId] ?? 0);
|
|
$prev = (float) ($prevSales[$entityId] ?? 0);
|
|
$comparison = $periodComparison($sales, $prev);
|
|
$totalSales += $sales;
|
|
$totalPrevSales += $prev;
|
|
|
|
$rows[] = [
|
|
'id' => $entityId,
|
|
'name' => $entity->name,
|
|
'code' => $entity->code,
|
|
'entity_type' => $entity->entity_type,
|
|
'location_id' => $locationId ?: null,
|
|
'sales' => $sales,
|
|
'previous_sales' => $prev,
|
|
'comparison' => $comparison,
|
|
'share_pct' => 0.0,
|
|
];
|
|
}
|
|
|
|
usort($rows, fn ($a, $b) => $b['sales'] <=> $a['sales']);
|
|
|
|
foreach ($rows as &$row) {
|
|
$row['share_pct'] = $totalSales > 0
|
|
? round(($row['sales'] / $totalSales) * 100, 1)
|
|
: 0.0;
|
|
}
|
|
unset($row);
|
|
|
|
return [
|
|
'available' => true,
|
|
'entities' => $rows,
|
|
'totals' => [
|
|
'sales' => $totalSales,
|
|
'previous_sales' => $totalPrevSales,
|
|
'comparison' => $periodComparison($totalSales, $totalPrevSales),
|
|
],
|
|
];
|
|
}
|
|
}
|