503 lines
21 KiB
PHP
503 lines
21 KiB
PHP
<?php
|
|
|
|
namespace Modules\Internal\Http\Controllers\Api;
|
|
|
|
use App\Helpers\Helper;
|
|
use App\Models\Corporate;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
|
|
|
class PrimayanMedicareController extends Controller
|
|
{
|
|
/**
|
|
* List transactions for Primayan Medicare (corporate code: PRAY)
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$limit = $request->has('per_page') ? $request->input('per_page') : 10;
|
|
|
|
$corporate = Corporate::where('code', 'PRAY')->first();
|
|
|
|
if (!$corporate) {
|
|
return response()->json([
|
|
'message' => 'Corporate Primayan Medicare (PRAY) not found',
|
|
'data' => []
|
|
], 404);
|
|
}
|
|
|
|
// Subquery to aggregate amounts from request_log_benefits
|
|
$subQueryAmount = DB::table('request_log_benefits')
|
|
->select('request_log_id',
|
|
DB::raw('SUM(amount_incurred) as total_incurred'),
|
|
DB::raw('SUM(amount_approved) as total_approved'),
|
|
DB::raw('SUM(excess_paid) as total_excess'))
|
|
->whereNull('deleted_at')
|
|
->groupBy('request_log_id');
|
|
|
|
$query = DB::table('claim_requests')
|
|
->join('members', 'claim_requests.member_id', '=', 'members.id')
|
|
->join('corporate_employees', 'corporate_employees.member_id', '=', 'members.id')
|
|
->leftJoin('organizations', 'claim_requests.organization_id', '=', 'organizations.id')
|
|
->leftJoin('claims', 'claim_requests.claim_id', '=', 'claims.id')
|
|
->leftJoin('request_logs', 'claim_requests.request_log_id', '=', 'request_logs.id')
|
|
->leftJoinSub($subQueryAmount, 'log_amounts', function ($join) {
|
|
$join->on('request_logs.id', '=', 'log_amounts.request_log_id');
|
|
})
|
|
->leftJoin('plans', 'claims.plan_id', '=', 'plans.id')
|
|
->leftJoin('benefits', 'claims.benefit_id', '=', 'benefits.id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->whereNull('corporate_employees.deleted_at')
|
|
->whereNull('claim_requests.deleted_at')
|
|
->when($request->input('search'), function ($query, $search) {
|
|
$query->where(function ($query) use ($search) {
|
|
$query->orWhere('members.name', 'like', "%" . $search . "%")
|
|
->orWhere('members.member_id', 'like', "%" . $search . "%")
|
|
->orWhere('claim_requests.code', 'like', "%" . $search . "%")
|
|
->orWhere('request_logs.code', 'like', "%" . $search . "%")
|
|
->orWhere('claims.code', 'like', "%" . $search . "%")
|
|
->orWhere('corporate_employees.nik', 'like', "%" . $search . "%");
|
|
});
|
|
})
|
|
->when($request->input('start_date'), function ($query, $start_date) {
|
|
$query->where('claim_requests.created_at', '>=', $start_date);
|
|
})
|
|
->when($request->input('end_date'), function ($query, $end_date) {
|
|
$query->where('claim_requests.created_at', '<=', $end_date . ' 23:59:59');
|
|
})
|
|
->when($request->input('status'), function ($query, $status) {
|
|
if ($status !== 'all') {
|
|
$query->where('claim_requests.status', $status);
|
|
}
|
|
})
|
|
->when($request->input('provider_id'), function ($query, $provider_id) {
|
|
if ($provider_id !== 'all') {
|
|
$query->where('claim_requests.organization_id', $provider_id);
|
|
}
|
|
})
|
|
->select(
|
|
'claim_requests.id',
|
|
'claim_requests.code as request_code',
|
|
'claim_requests.status',
|
|
'claim_requests.created_at as request_date',
|
|
'claim_requests.service_code',
|
|
'request_logs.log_type',
|
|
'claims.code as claim_code',
|
|
'request_logs.code as log_code',
|
|
DB::raw('COALESCE(log_amounts.total_incurred, claims.amount_incurred, 0) as amount_incurred'),
|
|
DB::raw('COALESCE(log_amounts.total_approved, claims.amount_approved, 0) as amount_approved'),
|
|
DB::raw('COALESCE(claims.amount_not_approved, 0) as amount_not_approved'),
|
|
DB::raw('COALESCE(log_amounts.total_excess, claims.excess_paid, 0) as excess_paid'),
|
|
'claims.benefit_code',
|
|
'claims.benefit_desc',
|
|
'members.name as member_name',
|
|
'members.member_id as member_number',
|
|
'members.birth_date',
|
|
'members.gender',
|
|
'corporate_employees.nik',
|
|
'corporate_employees.branch_code',
|
|
'organizations.name as provider_name',
|
|
'plans.code as plan_code',
|
|
'benefits.code as benefit_code_ref'
|
|
)
|
|
->orderBy('claim_requests.created_at', 'desc');
|
|
|
|
$results = $query->paginate($limit)->appends($request->all());
|
|
|
|
// Get Providers for filter
|
|
$providers = DB::table('claim_requests')
|
|
->join('members', 'claim_requests.member_id', '=', 'members.id')
|
|
->join('corporate_employees', 'corporate_employees.member_id', '=', 'members.id')
|
|
->join('organizations', 'claim_requests.organization_id', '=', 'organizations.id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->whereNull('claim_requests.deleted_at')
|
|
->select('organizations.id', 'organizations.name')
|
|
->groupBy('organizations.id', 'organizations.name')
|
|
->get();
|
|
|
|
return Helper::responseJson([
|
|
'results' => Helper::paginateResources($results),
|
|
'providers' => $providers,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Export transactions to Excel
|
|
*/
|
|
public function export(Request $request)
|
|
{
|
|
$corporate = Corporate::where('code', 'PRAY')->first();
|
|
|
|
if (!$corporate) {
|
|
return response()->json([
|
|
'message' => 'Corporate Primayan Medicare (PRAY) not found',
|
|
], 404);
|
|
}
|
|
|
|
$exportType = $request->input('export_type', 'list');
|
|
|
|
if ($exportType === 'summary') {
|
|
return $this->exportSummary($corporate);
|
|
}
|
|
|
|
// Subquery to aggregate amounts from request_log_benefits
|
|
$subQueryAmount = DB::table('request_log_benefits')
|
|
->select('request_log_id',
|
|
DB::raw('SUM(amount_incurred) as total_incurred'),
|
|
DB::raw('SUM(amount_approved) as total_approved'),
|
|
DB::raw('SUM(excess_paid) as total_excess'))
|
|
->whereNull('deleted_at')
|
|
->groupBy('request_log_id');
|
|
|
|
$results = DB::table('claim_requests')
|
|
->join('members', 'claim_requests.member_id', '=', 'members.id')
|
|
->join('corporate_employees', 'corporate_employees.member_id', '=', 'members.id')
|
|
->leftJoin('organizations', 'claim_requests.organization_id', '=', 'organizations.id')
|
|
->leftJoin('claims', 'claim_requests.claim_id', '=', 'claims.id')
|
|
->leftJoin('request_logs', 'claim_requests.request_log_id', '=', 'request_logs.id')
|
|
->leftJoinSub($subQueryAmount, 'log_amounts', function ($join) {
|
|
$join->on('request_logs.id', '=', 'log_amounts.request_log_id');
|
|
})
|
|
->leftJoin('plans', 'claims.plan_id', '=', 'plans.id')
|
|
->leftJoin('benefits', 'claims.benefit_id', '=', 'benefits.id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->whereNull('corporate_employees.deleted_at')
|
|
->whereNull('claim_requests.deleted_at')
|
|
->when($request->input('search'), function ($query, $search) {
|
|
$query->where(function ($query) use ($search) {
|
|
$query->orWhere('members.name', 'like', "%" . $search . "%")
|
|
->orWhere('members.member_id', 'like', "%" . $search . "%")
|
|
->orWhere('claim_requests.code', 'like', "%" . $search . "%")
|
|
->orWhere('request_logs.code', 'like', "%" . $search . "%")
|
|
->orWhere('claims.code', 'like', "%" . $search . "%")
|
|
->orWhere('corporate_employees.nik', 'like', "%" . $search . "%");
|
|
});
|
|
})
|
|
->when($request->input('start_date'), function ($query, $start_date) {
|
|
$query->where('claim_requests.created_at', '>=', $start_date);
|
|
})
|
|
->when($request->input('end_date'), function ($query, $end_date) {
|
|
$query->where('claim_requests.created_at', '<=', $end_date . ' 23:59:59');
|
|
})
|
|
->when($request->input('status'), function ($query, $status) {
|
|
if ($status !== 'all') {
|
|
$query->where('claim_requests.status', $status);
|
|
}
|
|
})
|
|
->when($request->input('provider_id'), function ($query, $provider_id) {
|
|
if ($provider_id !== 'all') {
|
|
$query->where('claim_requests.organization_id', $provider_id);
|
|
}
|
|
})
|
|
->select(
|
|
'claim_requests.id',
|
|
'claim_requests.code as request_code',
|
|
'claim_requests.status',
|
|
'claim_requests.created_at as request_date',
|
|
'claim_requests.service_code',
|
|
'request_logs.log_type',
|
|
'claims.code as claim_code',
|
|
'request_logs.code as log_code',
|
|
DB::raw('COALESCE(log_amounts.total_incurred, claims.amount_incurred, 0) as amount_incurred'),
|
|
DB::raw('COALESCE(log_amounts.total_approved, claims.amount_approved, 0) as amount_approved'),
|
|
DB::raw('COALESCE(claims.amount_not_approved, 0) as amount_not_approved'),
|
|
DB::raw('COALESCE(log_amounts.total_excess, claims.excess_paid, 0) as excess_paid'),
|
|
'claims.benefit_code',
|
|
'claims.benefit_desc',
|
|
'members.name as member_name',
|
|
'members.member_id as member_number',
|
|
'members.birth_date',
|
|
'members.gender',
|
|
'corporate_employees.nik',
|
|
'corporate_employees.branch_code',
|
|
'organizations.name as provider_name',
|
|
'plans.code as plan_code',
|
|
'benefits.code as benefit_code_ref'
|
|
)
|
|
->orderBy('claim_requests.created_at', 'desc')
|
|
->get();
|
|
|
|
$fileName = 'PrimayanMedicare-List-' . now()->format('Y-m-d_H-i-s') . '.xlsx';
|
|
$filePath = storage_path('app/public/temp/' . $fileName);
|
|
|
|
if (!is_dir(storage_path('app/public/temp'))) {
|
|
mkdir(storage_path('app/public/temp'), 0755, true);
|
|
}
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
$serviceCodeMap = [
|
|
'OP' => 'Outpatient',
|
|
'IP' => 'Inpatient',
|
|
'DE' => 'Dental',
|
|
'MA' => 'Maternal',
|
|
'GL' => 'Optical',
|
|
'MCU' => 'Medical Check Up',
|
|
'MEDIVAC' => 'Medical Emergency Evacuation',
|
|
];
|
|
|
|
$headers = [
|
|
'No',
|
|
'Code Claim / Code LOG',
|
|
'Member Name',
|
|
'Member Number',
|
|
'NIK',
|
|
'Birth Date',
|
|
'Gender',
|
|
'Plan',
|
|
'Benefit',
|
|
'Service',
|
|
'Tipe LOG',
|
|
'Provider',
|
|
'Request Date',
|
|
'Amount Incurred',
|
|
'Amount Approved',
|
|
'Amount Not Approved',
|
|
'Excess Paid',
|
|
'Status',
|
|
];
|
|
|
|
$sheet->fromArray($headers, null, 'A1');
|
|
$sheet->getStyle('A1:R1')->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
]
|
|
]);
|
|
|
|
$rowIndex = 2;
|
|
$no = 1;
|
|
|
|
$logTypeMap = [
|
|
'reference' => 'Rujukan',
|
|
'prescription' => 'Resep',
|
|
'consultation' => 'Konsultasi',
|
|
];
|
|
|
|
foreach ($results as $item) {
|
|
$logTypeName = $logTypeMap[$item->log_type] ?? $item->log_type ?? '-';
|
|
|
|
$rowData = [
|
|
$no++,
|
|
($item->claim_code && $item->log_code)
|
|
? $item->claim_code . ' / ' . $item->log_code
|
|
: ($item->claim_code ?? $item->log_code ?? $item->request_code ?? '-'),
|
|
$item->member_name ?? '-',
|
|
$item->member_number ?? '-',
|
|
$item->nik ?? '-',
|
|
$item->birth_date ?? '-',
|
|
$item->gender ?? '-',
|
|
$item->plan_code ?? '-',
|
|
$item->benefit_name ?? $item->benefit_desc ?? '-',
|
|
$item->service_code ?? '-',
|
|
$logTypeName,
|
|
$item->provider_name ?? '-',
|
|
$item->request_date ?? '-',
|
|
(int)($item->amount_incurred ?? 0),
|
|
(int)($item->amount_approved ?? 0),
|
|
(int)($item->amount_not_approved ?? 0),
|
|
(int)($item->excess_paid ?? 0),
|
|
$item->status ?? '-',
|
|
];
|
|
|
|
$sheet->fromArray($rowData, null, 'A' . $rowIndex);
|
|
$rowIndex++;
|
|
}
|
|
|
|
foreach (range('A', 'R') as $col) {
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save($filePath);
|
|
|
|
return Helper::responseJson([
|
|
'file_name' => 'Primayan Medicare List ' . now()->format('Y-m-d H:i:s'),
|
|
'file_url' => Storage::disk('public')->url('temp/' . $fileName),
|
|
]);
|
|
}
|
|
|
|
private function exportSummary($corporate)
|
|
{
|
|
// Get all branch codes
|
|
$branches = DB::table('corporate_employees')
|
|
->where('corporate_id', $corporate->id)
|
|
->whereNull('deleted_at')
|
|
->select('branch_code')
|
|
->groupBy('branch_code')
|
|
->get();
|
|
|
|
$fileName = 'PrimayanMedicare-Summary-' . now()->format('Y-m-d_H-i-s') . '.xlsx';
|
|
$filePath = storage_path('app/public/temp/' . $fileName);
|
|
|
|
if (!is_dir(storage_path('app/public/temp'))) {
|
|
mkdir(storage_path('app/public/temp'), 0755, true);
|
|
}
|
|
|
|
$codeRSMap = [
|
|
'AI' => 'ABI', 'BB' => 'PHBB', 'BT' => 'PHBT', 'BU' => 'PHBU',
|
|
'BW' => 'PHBW', 'CI' => 'PHPC', 'CO' => 'FABS', 'DE' => 'PHDE',
|
|
'EV' => 'PHEV', 'HE' => 'PHHE', 'KG' => 'PHKG', 'KI' => 'KMI',
|
|
'KR' => 'PHKA', 'KV' => 'KAVA', 'LM' => 'LMS', 'LY' => 'LYNAS',
|
|
'MK' => 'PHMA', 'MS' => 'EYEQU', 'PF' => 'FMC', 'PS' => 'PHPK',
|
|
'PY' => 'PHBP', 'RA' => 'PHRA', 'SB' => 'PHSB', 'SF' => 'SFI',
|
|
'SG' => 'PHSM', 'SM' => 'SIM', 'SO' => 'PHSW', 'SS' => 'SAS',
|
|
'TG' => 'PHTA', 'UP' => 'UKRIDA', 'WS' => 'WEST'
|
|
];
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
|
|
// Header Date Range (Row 1)
|
|
$dateRange = now()->startOfMonth()->format('j F') . ' - ' . now()->format('j F Y');
|
|
$sheet->setCellValue('A1', strtoupper($dateRange));
|
|
$sheet->mergeCells('A1:B1');
|
|
$sheet->getStyle('A1')->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
]
|
|
]);
|
|
|
|
// Table Headers (Row 3)
|
|
$headers = ['Code RS', 'Branch Code', 'Total Benefit', 'Deposit 10%', 'Pemakaian Benefit Obat & Rujukan', 'Pemakaian Telekonsultasi', 'Sisa Deposit'];
|
|
$sheet->fromArray($headers, null, 'A3');
|
|
$sheet->getStyle('A3:G3')->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
],
|
|
'fill' => [
|
|
'fillType' => Fill::FILL_SOLID,
|
|
'startColor' => [
|
|
'rgb' => 'C6E0B4'
|
|
]
|
|
],
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => Border::BORDER_THIN,
|
|
]
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
]
|
|
]);
|
|
|
|
$row = 4;
|
|
foreach ($branches as $branch) {
|
|
$branchCode = $branch->branch_code ?? '-';
|
|
$codeRS = $codeRSMap[$branchCode] ?? '-';
|
|
|
|
$totalDeposit = DB::table('corporate_employees')
|
|
->join('member_plans', 'corporate_employees.member_id', '=', 'member_plans.member_id')
|
|
->join('plans', 'member_plans.plan_id', '=', 'plans.id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->where(function($query) use ($branchCode) {
|
|
if ($branchCode === '-') {
|
|
$query->whereNull('corporate_employees.branch_code')->orWhere('corporate_employees.branch_code', '');
|
|
} else {
|
|
$query->where('corporate_employees.branch_code', $branchCode);
|
|
}
|
|
})
|
|
->whereNull('corporate_employees.deleted_at')
|
|
->whereNull('member_plans.deleted_at')
|
|
->sum(DB::raw('CAST(plans.limit_rules as UNSIGNED)'));
|
|
|
|
$deposit10 = $totalDeposit * 0.1;
|
|
|
|
$usageMedicines = DB::table('request_log_medicines')
|
|
->join('request_logs', 'request_log_medicines.request_log_id', '=', 'request_logs.id')
|
|
->join('corporate_employees', 'request_logs.member_id', '=', 'corporate_employees.member_id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->where(function($query) use ($branchCode) {
|
|
if ($branchCode === '-') {
|
|
$query->whereNull('corporate_employees.branch_code')->orWhere('corporate_employees.branch_code', '');
|
|
} else {
|
|
$query->where('corporate_employees.branch_code', $branchCode);
|
|
}
|
|
})
|
|
->whereIn('request_logs.log_type', ['prescription', 'reference'])
|
|
->sum('request_log_medicines.price');
|
|
|
|
$consultationCount = DB::table('request_logs')
|
|
->join('corporate_employees', 'request_logs.member_id', '=', 'corporate_employees.member_id')
|
|
->where('corporate_employees.corporate_id', $corporate->id)
|
|
->where(function($query) use ($branchCode) {
|
|
if ($branchCode === '-') {
|
|
$query->whereNull('corporate_employees.branch_code')
|
|
->orWhere('corporate_employees.branch_code', '');
|
|
} else {
|
|
$query->where('corporate_employees.branch_code', $branchCode);
|
|
}
|
|
})
|
|
->where('request_logs.log_type', 'consultation')
|
|
->count();
|
|
|
|
$usageConsultation = $consultationCount * 11100;
|
|
$remainingDeposit = $deposit10 - $usageMedicines - $usageConsultation;
|
|
|
|
$sheet->setCellValue('A' . $row, $codeRS);
|
|
$sheet->setCellValue('B' . $row, $branchCode);
|
|
$sheet->setCellValue('C' . $row, $totalDeposit);
|
|
$sheet->setCellValue('D' . $row, $deposit10);
|
|
$sheet->setCellValue('E' . $row, $usageMedicines);
|
|
$sheet->setCellValue('F' . $row, $usageConsultation);
|
|
$sheet->setCellValue('G' . $row, $remainingDeposit);
|
|
|
|
// Number format with thousand separator
|
|
$sheet->getStyle('C' . $row . ':G' . $row)->getNumberFormat()->setFormatCode('#,##0');
|
|
|
|
$row++;
|
|
}
|
|
|
|
$lastRow = $row - 1;
|
|
foreach (range('A', 'G') as $col) {
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
|
|
$sheet->getStyle('A3:G' . $lastRow)->applyFromArray([
|
|
'borders' => [
|
|
'allBorders' => [
|
|
'borderStyle' => Border::BORDER_THIN,
|
|
'color' => ['rgb' => '000000']
|
|
]
|
|
]
|
|
]);
|
|
|
|
$sheet->freezePane('A4');
|
|
|
|
$sheet->setCellValue('E1', '=SUM(E4:E' . $lastRow . ')');
|
|
$sheet->setCellValue('F1', '=SUM(F4:F' . $lastRow . ')');
|
|
$sheet->getStyle('E1:F1')
|
|
->getNumberFormat()
|
|
->setFormatCode('#,##0');
|
|
$sheet->getStyle('E1:F1')->applyFromArray([
|
|
'font' => [
|
|
'bold' => true,
|
|
'size' => 12,
|
|
],
|
|
'alignment' => [
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
]
|
|
]);
|
|
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save($filePath);
|
|
|
|
return Helper::responseJson([
|
|
'file_name' => $fileName,
|
|
'file_url' => Storage::disk('public')->url('temp/' . $fileName),
|
|
]);
|
|
}
|
|
}
|