ultimatepos/Modules/ManagementTools/Services/ExecutiveCockpit/HoldingComparisonService.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),
],
];
}
}