350 lines
10 KiB
PHP
350 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Exports\Sheets\Invoices;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use PhpOffice\PhpSpreadsheet\Cell\{
|
|
Cell,
|
|
DataType,
|
|
StringValueBinder
|
|
};
|
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
use Maatwebsite\Excel\Concerns\{
|
|
FromCollection,
|
|
WithHeadings,
|
|
WithMapping,
|
|
WithTitle,
|
|
WithCustomValueBinder,
|
|
WithEvents
|
|
};
|
|
use Maatwebsite\Excel\Events\AfterSheet;
|
|
|
|
class VOPSheet extends StringValueBinder implements
|
|
FromCollection,
|
|
WithHeadings,
|
|
WithMapping,
|
|
WithTitle,
|
|
WithCustomValueBinder,
|
|
WithEvents
|
|
{
|
|
protected array $filters;
|
|
protected int $no = 0;
|
|
protected float $grandTotal = 0;
|
|
|
|
protected array $benefits = [];
|
|
|
|
protected $benefitAmounts;
|
|
|
|
protected bool $benefitInitialized = false;
|
|
|
|
|
|
public function __construct(array $filters = [])
|
|
{
|
|
$this->filters = $filters;
|
|
}
|
|
|
|
public function collection()
|
|
{
|
|
$query = DB::table('invoice_payments')
|
|
->leftJoin('invoice_payment_details', 'invoice_payment_details.invoice_payment_id', '=', 'invoice_payments.id')
|
|
->leftJoin('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id')
|
|
->leftJoin('request_logs', 'request_logs.id', '=', 'claim_requests.request_log_id')
|
|
->leftJoin('organizations', 'organizations.id', '=', 'request_logs.organization_id')
|
|
->leftJoin('members', 'members.id', '=', 'request_logs.member_id')
|
|
->leftJoin('specialities', 'specialities.id', '=', 'request_logs.specialities_id')
|
|
->leftJoin('icd', DB::raw("icd.code"), '=', DB::raw("SUBSTRING_INDEX(request_logs.diagnosis, ',', 1)"))
|
|
->orderBy('request_logs.service_code', 'desc')
|
|
->select(
|
|
'invoice_payments.*',
|
|
'organizations.name as organization_name',
|
|
'members.name as member_name',
|
|
'request_logs.diagnosis as code_diagnosis',
|
|
'request_logs.service_code',
|
|
'request_logs.dppj',
|
|
'specialities.name as specialities_name',
|
|
'request_logs.submission_date as in',
|
|
'request_logs.discharge_date as out',
|
|
'request_logs.code as code_log',
|
|
'members.payor_id',
|
|
'request_logs.nominal as amount',
|
|
'claim_requests.request_log_id',
|
|
'members.member_id as batch_number',
|
|
'request_logs.keterangan',
|
|
'icd.name as diagnosis',
|
|
'request_logs.type_of_member'
|
|
);
|
|
|
|
|
|
if (!empty($this->filters['search'])) {
|
|
$query->where('invoice_number', 'like', '%' . $this->filters['search'] . '%');
|
|
}
|
|
|
|
if (!empty($this->filters['start_date'])) {
|
|
$query->whereDate('invoice_payments.created_at', '>=', $this->filters['start_date']);
|
|
}
|
|
|
|
if (!empty($this->filters['end_date'])) {
|
|
$query->whereDate('invoice_payments.created_at', '<=', $this->filters['end_date']);
|
|
}
|
|
|
|
if (!empty($this->filters['orderBy'])) {
|
|
$query->orderBy(
|
|
$this->filters['orderBy'],
|
|
$this->filters['order'] ?? 'asc'
|
|
);
|
|
}
|
|
|
|
$items = $query->get();
|
|
|
|
// ambil request_log_id
|
|
$requestLogIds = $items
|
|
->pluck('request_log_id')
|
|
->filter()
|
|
->unique()
|
|
->values();
|
|
|
|
// set benefit header (hanya yg dipakai)
|
|
$this->benefits = DB::table('request_log_benefits')
|
|
->join('benefits', 'benefits.id', '=', 'request_log_benefits.benefit_id')
|
|
->whereIn('request_log_benefits.request_log_id', $requestLogIds)
|
|
->select('benefits.id', 'benefits.description')
|
|
->distinct()
|
|
->orderBy('benefits.id')
|
|
->pluck('benefits.description', 'benefits.id')
|
|
->toArray();
|
|
|
|
// 🔥 preload benefit amount SEKALI (anti N+1)
|
|
$this->benefitAmounts = DB::table('request_log_benefits')
|
|
->whereIn('request_log_id', $requestLogIds)
|
|
->get()
|
|
->groupBy('request_log_id');
|
|
|
|
return $items;
|
|
}
|
|
|
|
public function map($item): array
|
|
{
|
|
$this->no++;
|
|
$this->grandTotal += (float) $item->amount_paid;
|
|
$benefitData = $this->getBenefitAmountsWithTotal($item->request_log_id);
|
|
|
|
return array_merge([
|
|
// $this->no,
|
|
(string) $item->invoice_number,
|
|
// (string) $item->payment_number,
|
|
'',
|
|
'',
|
|
'',
|
|
(string) $item->no_reference,
|
|
'',
|
|
'',
|
|
(string) ($item->code_log ?? '-'),
|
|
(string) ($item->payor_id ?? '-'),
|
|
'',
|
|
'',
|
|
(string) ($item->organization_name ?? '-'),
|
|
(string) ($item->member_name ?? '-'),
|
|
(string) ($item->batch_number ?? '-'),
|
|
(string) $benefitData['total'],
|
|
'',
|
|
'',
|
|
],
|
|
$benefitData['amounts'],
|
|
[
|
|
(string) ($item->in ?? '-'),
|
|
(string) ($item->out ?? '-'),
|
|
'',
|
|
(string) ($item->diagnosis ?? '-'),
|
|
(string) ($item->type_of_member ?? '-'), // omt
|
|
(string) ($item->service_code == 'OP' ? 'RJ' : 'RI'),
|
|
'',
|
|
'',
|
|
'',
|
|
(string) ($item->dppj ?? '-'),
|
|
(string) ($item->in ?? '-'),
|
|
(string) ($item->out ?? '-'),
|
|
(string) ($item->specialities_name ?? '-'),
|
|
'Karyawan',
|
|
'',
|
|
'',
|
|
'',
|
|
(string) ($item->keterangan ?? '-'),
|
|
// (string) $item->invoice_date,
|
|
// (string) $item->start_date,
|
|
// (string) $item->end_date,
|
|
// (float) $item->amount_paid,
|
|
// (string) $item->created_at,
|
|
// (string) $item->updated_at,
|
|
]);
|
|
}
|
|
|
|
public function headings(): array
|
|
{
|
|
$this->initBenefits();
|
|
return array_merge([
|
|
// 'No',
|
|
'No Invoice', //ok
|
|
// 'Pembayaran Ke',
|
|
'MONTH', //ok
|
|
'PERIODE SES', //ok
|
|
'SUBMIT INV/SES', //ok
|
|
'REFERENCE', //ok
|
|
'RECEIVED', //ok
|
|
'INV. DATE', //ok
|
|
'CODE', //ok
|
|
'VENDOR', //ok
|
|
'PO', //ok
|
|
'SES', //ok
|
|
'MAIN DESCRIPTION', //ok
|
|
'DESCRIPTION', //ok
|
|
'BN', //ok
|
|
'AMOUNT', //ok
|
|
'WBS', // ok
|
|
'NOTE', // ok
|
|
],
|
|
array_values($this->benefits),
|
|
[ 'DEPARTURE', // ok
|
|
'ARRIVED', // ok
|
|
'TEMPORARY DIAGNOSA', // ok
|
|
'FINAL DIAGNOSA',
|
|
'NOTE (OMT / NON OMT)',
|
|
'RI/RJ', // OK
|
|
'Dept', // OK
|
|
'Cost Center', // OK
|
|
'No.TA', // OK
|
|
'DPJP', // OK
|
|
'IN', // OK
|
|
'OUT', // OK
|
|
'SPECIALIST', // OK
|
|
'Employee', // OK
|
|
'Total Invoice sebelum BPJS', // OK
|
|
'BPJS', // OK
|
|
'Ditanggung Perusahaan', // OK
|
|
'KETERANGAN', // OK
|
|
// 'Tanggal Invoice',
|
|
// 'Start Date',
|
|
// 'End Date',
|
|
// 'Nominal Pembayaran',
|
|
// 'Created At',
|
|
// 'Updated At',
|
|
]);
|
|
}
|
|
|
|
public function title(): string
|
|
{
|
|
return 'VOP & VIP';
|
|
}
|
|
|
|
/**
|
|
* FOOTER: Grand Total
|
|
*/
|
|
public function registerEvents(): array
|
|
{
|
|
return [
|
|
AfterSheet::class => function (AfterSheet $event) {
|
|
// $event->sheet->getStyle('A1:AO1')
|
|
// ->getFont()
|
|
// ->setBold(true);
|
|
|
|
$highestColumn = $event->sheet->getDelegate()->getHighestColumn();
|
|
|
|
$event->sheet->getStyle('A1:' . $highestColumn . '1')
|
|
->getFont()
|
|
->setBold(true);
|
|
|
|
|
|
// $row = $event->sheet->getHighestRow() + 1;
|
|
|
|
// $event->sheet->setCellValue("A{$row}", 'Grand Total');
|
|
// $event->sheet->setCellValue("G{$row}", $this->grandTotal);
|
|
|
|
// // Bold footer
|
|
// $event->sheet->getStyle("A{$row}:G{$row}")
|
|
// ->getFont()
|
|
// ->setBold(true);
|
|
},
|
|
];
|
|
}
|
|
|
|
/**
|
|
* FORCE: object → string
|
|
*/
|
|
public function bindValue(Cell $cell, $value)
|
|
{
|
|
if (is_object($value) || is_array($value)) {
|
|
$value = json_encode($value);
|
|
}
|
|
|
|
$cell->setValueExplicit($value, DataType::TYPE_STRING);
|
|
return true;
|
|
}
|
|
|
|
protected function getBenefitAmountsWithTotal(?int $requestLogId): array
|
|
{
|
|
if (!$requestLogId || !isset($this->benefitAmounts[$requestLogId])) {
|
|
return [
|
|
'amounts' => array_fill(0, count($this->benefits), 0),
|
|
'total' => 0,
|
|
];
|
|
}
|
|
|
|
$rows = $this->benefitAmounts[$requestLogId]
|
|
->pluck('amount_approved', 'benefit_id')
|
|
->toArray();
|
|
|
|
$amounts = [];
|
|
$total = 0;
|
|
|
|
foreach ($this->benefits as $benefitId => $desc) {
|
|
$amount = (float) ($rows[$benefitId] ?? 0);
|
|
$amounts[] = $amount;
|
|
$total += $amount;
|
|
}
|
|
|
|
// 🔥 kalau ini memang mau jadi grand total global
|
|
$this->grandTotal += $total;
|
|
|
|
return [
|
|
'amounts' => $amounts,
|
|
'total' => $total,
|
|
];
|
|
}
|
|
|
|
|
|
protected function initBenefits(): void
|
|
{
|
|
if ($this->benefitInitialized) {
|
|
return;
|
|
}
|
|
|
|
// ambil request_log_id dulu
|
|
$requestLogIds = DB::table('invoice_payments')
|
|
->leftJoin('invoice_payment_details', 'invoice_payment_details.invoice_payment_id', '=', 'invoice_payments.id')
|
|
->leftJoin('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id')
|
|
->whereNotNull('claim_requests.request_log_id')
|
|
->pluck('claim_requests.request_log_id')
|
|
->unique()
|
|
->values();
|
|
|
|
if ($requestLogIds->isEmpty()) {
|
|
$this->benefits = [];
|
|
return;
|
|
}
|
|
|
|
$this->benefits = DB::table('request_log_benefits')
|
|
->join('benefits', 'benefits.id', '=', 'request_log_benefits.benefit_id')
|
|
->whereIn('request_log_benefits.request_log_id', $requestLogIds)
|
|
->select('benefits.id', 'benefits.description')
|
|
->distinct()
|
|
->orderBy('benefits.id')
|
|
->pluck('benefits.description', 'benefits.id')
|
|
->toArray();
|
|
|
|
$this->benefitInitialized = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|