first init
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Dashboard\Services\PKJ;
|
||||
|
||||
use Modules\Dashboard\Services\DashboardService;
|
||||
use Modules\Dashboard\Repositories\Contracts\PKJDashboardRepositoryInterface;
|
||||
use Modules\PKJAssetEntitlement\Entities\PKJAssetEntitlement;
|
||||
use Modules\PKJAssetHolding\Entities\PKJAssetHolding;
|
||||
use Modules\PKJRepair\Entities\PKJRepair;
|
||||
use Modules\PKJReport\Entities\PKJReport;
|
||||
use App\Services\VisibilityService;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class PKJDashboardService extends DashboardService
|
||||
{
|
||||
protected PKJDashboardRepositoryInterface $pkjDashboardRepository;
|
||||
|
||||
public function __construct(
|
||||
VisibilityService $visibilityService,
|
||||
PKJDashboardRepositoryInterface $pkjDashboardRepository
|
||||
) {
|
||||
parent::__construct($visibilityService);
|
||||
$this->pkjDashboardRepository = $pkjDashboardRepository;
|
||||
}
|
||||
/**
|
||||
* Get total PKJ assets
|
||||
*/
|
||||
public function getTotalAssets(array $filters = [], $user = null): int
|
||||
{
|
||||
return $this->pkjDashboardRepository->getTotalHoldings($filters, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get operational PKJ assets (BP status)
|
||||
*/
|
||||
public function getOperationalAssets(array $filters = [], $user = null): int
|
||||
{
|
||||
$holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('BP', $filters, $user);
|
||||
return $holdings['pagination']['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get under repair PKJ assets (TBDG status)
|
||||
*/
|
||||
public function getUnderRepairAssets(array $filters = [], $user = null): int
|
||||
{
|
||||
$holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('TBDG', $filters, $user);
|
||||
return $holdings['pagination']['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maintenance due PKJ assets (BDG status)
|
||||
*/
|
||||
public function getMaintenanceDueAssets(array $filters = [], $user = null): int
|
||||
{
|
||||
$holdings = $this->pkjDashboardRepository->getHoldingsBySpecificStatus('BDG', $filters, $user);
|
||||
return $holdings['pagination']['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active PKJ repairs
|
||||
*/
|
||||
public function getActiveRepairs(array $filters = []): int
|
||||
{
|
||||
$dateRange = $this->getDateRange($filters);
|
||||
|
||||
return PKJRepair::query()
|
||||
->whereBetween('created_at', [$dateRange['from'], $dateRange['to']])
|
||||
->where('status', 'active')
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pending PKJ reports
|
||||
*/
|
||||
public function getPendingReports(array $filters = []): int
|
||||
{
|
||||
$dateRange = $this->getDateRange($filters);
|
||||
|
||||
return PKJReport::query()
|
||||
->whereBetween('created_at', [$dateRange['from'], $dateRange['to']])
|
||||
->where('status', 'pending')
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ entitlement vs holdings pie chart
|
||||
*/
|
||||
public function getEntitlementVsHoldingsPieChart(array $filters = [], $user = null): array
|
||||
{
|
||||
$totalEntitlement = $this->pkjDashboardRepository->getTotalEntitlement($filters, $user);
|
||||
$totalHoldings = $this->pkjDashboardRepository->getTotalHoldings($filters, $user);
|
||||
|
||||
$data = [
|
||||
[
|
||||
'name' => 'Perjawatan',
|
||||
'value' => $totalEntitlement,
|
||||
'percentage' => ($totalEntitlement + $totalHoldings) > 0 ? round(($totalEntitlement / ($totalEntitlement + $totalHoldings)) * 100, 2) : 0
|
||||
],
|
||||
[
|
||||
'name' => 'Pegangan',
|
||||
'value' => $totalHoldings,
|
||||
'percentage' => ($totalEntitlement + $totalHoldings) > 0 ? round(($totalHoldings / ($totalEntitlement + $totalHoldings)) * 100, 2) : 0
|
||||
]
|
||||
];
|
||||
|
||||
return $this->formatPieChartData(
|
||||
'Perjawatan vs Pegangan PKJ',
|
||||
$data,
|
||||
'', // No drill-down
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ holdings status breakdown pie chart
|
||||
*/
|
||||
public function getHoldingsStatusBreakdownPieChart(array $filters = [], $user = null): array
|
||||
{
|
||||
$statusCounts = $this->pkjDashboardRepository->getHoldingsByStatus($filters, $user);
|
||||
|
||||
// Map status codes to readable names
|
||||
$statusNames = [
|
||||
'BP' => 'Baik dalam Perhatian',
|
||||
'BDG' => 'Boleh Digunakan',
|
||||
'TBDG' => 'Tidak Boleh Digunakan',
|
||||
'BT' => 'Boleh Tembak',
|
||||
'BG' => 'Baik Guna'
|
||||
];
|
||||
|
||||
$data = [];
|
||||
foreach ($statusCounts as $status) {
|
||||
$statusName = $statusNames[$status['status']] ?? $status['status'];
|
||||
$data[] = [
|
||||
'name' => $statusName,
|
||||
'value' => $status['count'],
|
||||
'percentage' => 0 // Will be calculated after total
|
||||
];
|
||||
}
|
||||
|
||||
// Calculate percentages
|
||||
$total = array_sum(array_column($data, 'value'));
|
||||
foreach ($data as &$item) {
|
||||
$item['percentage'] = $total > 0 ? round(($item['value'] / $total) * 100, 2) : 0;
|
||||
}
|
||||
|
||||
return $this->formatPieChartData(
|
||||
'PKJ Status Pegangan',
|
||||
$data,
|
||||
'', // No drill-down
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ monthly trends chart
|
||||
*/
|
||||
public function getMonthlyTrendsChart(array $filters = [], $user = null): array
|
||||
{
|
||||
$monthlyData = $this->pkjDashboardRepository->getMonthlyTrends($filters, $user);
|
||||
|
||||
$categories = [];
|
||||
$data = [];
|
||||
|
||||
foreach ($monthlyData as $trend) {
|
||||
$categories[] = Carbon::createFromFormat('Y-m', $trend['month'])->format('M Y');
|
||||
$data[] = $trend['total_reports'];
|
||||
}
|
||||
|
||||
return $this->formatBarChartData(
|
||||
'Trend Bulanan PKJ 2025',
|
||||
[
|
||||
['name' => 'Laporan', 'data' => $data]
|
||||
],
|
||||
$categories
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ holdings by category bar chart
|
||||
*/
|
||||
public function getHoldingsByCategoryBarChart(array $filters = [], $user = null): array
|
||||
{
|
||||
$categoryData = $this->pkjDashboardRepository->getHoldingsByCategory($filters, $user);
|
||||
|
||||
$categories = [];
|
||||
$categoryIds = [];
|
||||
$data = [];
|
||||
|
||||
foreach ($categoryData as $category) {
|
||||
$categories[] = $category['category_name'];
|
||||
$categoryIds[] = (int) $category['category_id'];
|
||||
$data[] = (int) $category['total_holding'];
|
||||
}
|
||||
|
||||
$chartData = $this->formatBarChartData(
|
||||
'Pegangan PKJ Mengikut Kategori',
|
||||
[
|
||||
['name' => 'Jumlah Pegangan', 'data' => $data]
|
||||
],
|
||||
$categories
|
||||
);
|
||||
|
||||
// Add category IDs to the chart data for drill-down functionality
|
||||
$chartData['category_ids'] = $categoryIds;
|
||||
|
||||
return $chartData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ category metrics bar chart (drill-down)
|
||||
*/
|
||||
public function getCategoryMetricsBarChart(int $categoryId, array $filters = [], $user = null): array
|
||||
{
|
||||
$metrics = $this->pkjDashboardRepository->getCategoryMetrics($categoryId, $filters, $user);
|
||||
|
||||
$categories = ['KEUPAYAAN (%)', 'KESIAGAAN (%)', 'SERVISIBILITI (%)'];
|
||||
$data = [
|
||||
$metrics['keupayaan'],
|
||||
$metrics['kesiagaan'],
|
||||
$metrics['servisibiliti']
|
||||
];
|
||||
|
||||
$chartData = $this->formatBarChartData(
|
||||
'Metrik Kategori PKJ',
|
||||
[
|
||||
['name' => 'Metrics', 'data' => $data]
|
||||
],
|
||||
$categories
|
||||
);
|
||||
|
||||
// Add category information to the response
|
||||
$chartData['category_id'] = $metrics['category_id'];
|
||||
$chartData['category_name'] = $metrics['category_name'];
|
||||
|
||||
return $chartData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PKJ category status breakdown pie chart (drill-down)
|
||||
*/
|
||||
public function getCategoryStatusBreakdownPieChart(int $categoryId, array $filters = [], $user = null): array
|
||||
{
|
||||
$breakdown = $this->pkjDashboardRepository->getCategoryStatusBreakdown($categoryId, $filters, $user);
|
||||
|
||||
// Map status codes to readable names
|
||||
$statusNames = [
|
||||
'BP' => 'Baik dalam Perhatian',
|
||||
'BDG' => 'Boleh Digunakan',
|
||||
'TBDG' => 'Tidak Boleh Digunakan',
|
||||
'BT' => 'Boleh Tembak',
|
||||
'TBT' => 'Tidak Boleh Tembak',
|
||||
'BG' => 'Baik Guna',
|
||||
'TBG' => 'Tidak Baik Guna',
|
||||
];
|
||||
|
||||
$data = [];
|
||||
foreach ($breakdown['status_breakdown'] as $status) {
|
||||
$statusCode = $status['status'];
|
||||
|
||||
// In the breakdown, status_code is null when the asset has no status (DB column is NULL).
|
||||
if ($statusCode === null || $statusCode === '') {
|
||||
$statusName = 'Status Tidak Diketahui';
|
||||
} else {
|
||||
$statusName = $statusNames[$statusCode] ?? $statusCode;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'name' => $statusName,
|
||||
'value' => $status['count'],
|
||||
'percentage' => 0, // Will be calculated after total
|
||||
'status_code' => $statusCode // null when DB status column is NULL (Belum Diberi Status)
|
||||
];
|
||||
}
|
||||
|
||||
// Calculate percentages
|
||||
$total = array_sum(array_column($data, 'value'));
|
||||
foreach ($data as &$item) {
|
||||
$item['percentage'] = $total > 0 ? round(($item['value'] / $total) * 100, 2) : 0;
|
||||
}
|
||||
|
||||
$chartData = $this->formatPieChartData(
|
||||
'PKJ Status Pegangan Mengikut Kategori',
|
||||
$data,
|
||||
'/v1/dashboard/pkj/category/' . $categoryId . '/status-details',
|
||||
['status']
|
||||
);
|
||||
|
||||
// Add category information to the response
|
||||
$chartData['category_id'] = $breakdown['category_id'];
|
||||
$chartData['category_name'] = $breakdown['category_name'];
|
||||
|
||||
return $chartData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unit ID column name for PKJ
|
||||
*/
|
||||
protected function getUnitIdColumn(): string
|
||||
{
|
||||
return 'pkj_asset_holdings.unit_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get asset model class for PKJ
|
||||
*/
|
||||
protected function getAssetModelClass(): string
|
||||
{
|
||||
return PKJAssetHolding::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repair model class for PKJ
|
||||
*/
|
||||
protected function getRepairModelClass(): string
|
||||
{
|
||||
return PKJRepair::class;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user