Merge remote-tracking branch 'origin/feature/primaya' into staging

This commit is contained in:
R
2026-02-26 08:35:27 +07:00
2136 changed files with 33387 additions and 7827 deletions

0
app/Builders/MemberBuilder.php Executable file → Normal file
View File

0
app/Console/Kernel.php Executable file → Normal file
View File

0
app/Events/ChatMessageSent.php Executable file → Normal file
View File

0
app/Events/ClaimApproved.php Executable file → Normal file
View File

0
app/Events/ClaimDeclined.php Executable file → Normal file
View File

0
app/Events/ClaimPaid.php Executable file → Normal file
View File

0
app/Events/ClaimPostpone.php Executable file → Normal file
View File

0
app/Events/ClaimReceived.php Executable file → Normal file
View File

0
app/Events/ClaimRequested.php Executable file → Normal file
View File

0
app/Exceptions/Handler.php Executable file → Normal file
View File

0
app/Exceptions/ImportRowException.php Executable file → Normal file
View File

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Exports;
use App\Exports\Sheets\Invoices\VOPSheet;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use App\Exports\Sheets\UsersSheet;
use App\Exports\Sheets\OrdersSheet;
class ReportExport implements WithMultipleSheets
{
protected array $filters;
public function __construct(array $filters = [])
{
$this->filters = $filters;
}
public function sheets(): array
{
return [
new VOPSheet($this->filters),
];
}
}

View File

@@ -0,0 +1,349 @@
<?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;
}
}

0
app/Helpers/DuitkuHelper.php Executable file → Normal file
View File

0
app/Helpers/Helper.php Executable file → Normal file
View File

0
app/Http/Controllers/Api/AuthController.php Executable file → Normal file
View File

0
app/Http/Controllers/Api/OLDLMS/ClaimController.php Executable file → Normal file
View File

View File

0
app/Http/Controllers/Api/OLDLMS/PaymentController.php Executable file → Normal file
View File

0
app/Http/Controllers/Controller.php Executable file → Normal file
View File

0
app/Http/Controllers/GeneratedDocumentController.php Executable file → Normal file
View File

3
app/Http/Kernel.php Executable file → Normal file
View File

@@ -67,11 +67,12 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'linksehat.old.auth' => \App\Http\Middleware\LinksehatOldAuthMiddleware::class,
'corporate.key' => \Modules\Primaya\Http\Middleware\CheckCorporateKey::class,
// Role
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
}

23
app/Http/Middleware/Authenticate.php Executable file → Normal file
View File

@@ -21,12 +21,21 @@ class Authenticate extends Middleware
}
}
public function handle($request, Closure $next, ...$guards)
{
if (Auth::guard('sanctum')->guest()) {
return response()->json(['error' => 'Bearer Authorization is required'], 401);
}
// public function handle($request, Closure $next, ...$guards)
// {
// // Kalau tidak ada guard dikirim dari route
// if (empty($guards)) {
// $guards = [null];
// }
return parent::handle($request, $next, ...$guards);
}
// foreach ($guards as $guard) {
// if (Auth::guard($guard)->check()) {
// return $next($request);
// }
// }
// return response()->json([
// 'error' => 'Unauthorized'
// ], 401);
// }
}

0
app/Http/Middleware/EncryptCookies.php Executable file → Normal file
View File

0
app/Http/Middleware/LinksehatOldAuthMiddleware.php Executable file → Normal file
View File

View File

0
app/Http/Middleware/RedirectIfAuthenticated.php Executable file → Normal file
View File

0
app/Http/Middleware/TrimStrings.php Executable file → Normal file
View File

0
app/Http/Middleware/TrustHosts.php Executable file → Normal file
View File

0
app/Http/Middleware/TrustProxies.php Executable file → Normal file
View File

0
app/Http/Middleware/VerifyCsrfToken.php Executable file → Normal file
View File

0
app/Http/Resources/MemberDataTableResource.php Executable file → Normal file
View File

0
app/Http/Resources/MemberListResource.php Executable file → Normal file
View File

0
app/Http/Resources/OLDLMS/MemberLimitResource.php Executable file → Normal file
View File

0
app/Http/Resources/OLDLMS/MemberResource.php Executable file → Normal file
View File

0
app/Imports/PlansImport.php Executable file → Normal file
View File

0
app/Jobs/ProcessImport.php Executable file → Normal file
View File

0
app/Jobs/TestJob.php Executable file → Normal file
View File

0
app/Listeners/LogClaimJournal.php Executable file → Normal file
View File

0
app/Listeners/NotifyClaimRequested.php Executable file → Normal file
View File

0
app/Listeners/ProcessChatMessage.php Executable file → Normal file
View File

0
app/Models/Address.php Executable file → Normal file
View File

0
app/Models/Appointment.php Executable file → Normal file
View File

0
app/Models/AppointmentParticipant.php Executable file → Normal file
View File

0
app/Models/AppointmentType.php Executable file → Normal file
View File

0
app/Models/AuditTrail.php Executable file → Normal file
View File

4
app/Models/Benefit.php Executable file → Normal file
View File

@@ -57,4 +57,8 @@ class Benefit extends Model
// TODO corporate_benefits pivot
]);
}
public function corporateBenefits()
{
return $this->hasMany(CorporateBenefit::class, 'benefit_id');
}
}

0
app/Models/Brand.php Executable file → Normal file
View File

0
app/Models/Category.php Executable file → Normal file
View File

0
app/Models/Channel.php Executable file → Normal file
View File

0
app/Models/City.php Executable file → Normal file
View File

0
app/Models/Claim.php Executable file → Normal file
View File

0
app/Models/ClaimDiagnosis.php Executable file → Normal file
View File

0
app/Models/ClaimEncounter.php Executable file → Normal file
View File

0
app/Models/ClaimHistory.php Executable file → Normal file
View File

0
app/Models/ClaimHistoryCare.php Executable file → Normal file
View File

0
app/Models/ClaimItem.php Executable file → Normal file
View File

0
app/Models/ClaimRequest.php Executable file → Normal file
View File

4
app/Models/Corporate.php Executable file → Normal file
View File

@@ -1,7 +1,7 @@
<?php
namespace App\Models;
use Altek\Accountant\Contracts\Recordable;
use Altek\Accountant\Contracts\Recordable;
use App\Traits\Blameable;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -23,6 +23,8 @@ class Corporate extends Model
'help_text',
'active',
'linking_rules',
'api_key',
'api_secret',
'automatic_linking',
'phone',
'phone_alarm_canter',

0
app/Models/CorporateBenefit.php Executable file → Normal file
View File

0
app/Models/CorporateDivision.php Executable file → Normal file
View File

0
app/Models/CorporateEmployee.php Executable file → Normal file
View File

0
app/Models/CorporateFormularium.php Executable file → Normal file
View File

0
app/Models/CorporateHospital.php Executable file → Normal file
View File

0
app/Models/CorporateManager.php Executable file → Normal file
View File

0
app/Models/CorporatePlan.php Executable file → Normal file
View File

0
app/Models/CorporatePolicy.php Executable file → Normal file
View File

0
app/Models/CorporateService.php Executable file → Normal file
View File

0
app/Models/CorporateServiceConfig.php Executable file → Normal file
View File

0
app/Models/CorporateServiceSpeciality.php Executable file → Normal file
View File

0
app/Models/DailyMonitoring.php Executable file → Normal file
View File

0
app/Models/DiagnosisSecondaryClaimHistoryCare.php Executable file → Normal file
View File

0
app/Models/District.php Executable file → Normal file
View File

0
app/Models/Drug.php Executable file → Normal file
View File

0
app/Models/DrugAtc.php Executable file → Normal file
View File

0
app/Models/DrugCategory.php Executable file → Normal file
View File

0
app/Models/DrugComposition.php Executable file → Normal file
View File

0
app/Models/DrugExternalIdentifier.php Executable file → Normal file
View File

0
app/Models/DrugIdentifier.php Executable file → Normal file
View File

0
app/Models/DrugSellingUnit.php Executable file → Normal file
View File

0
app/Models/DrugUnit.php Executable file → Normal file
View File

0
app/Models/Encounter.php Executable file → Normal file
View File

0
app/Models/EncounterDiagnosis.php Executable file → Normal file
View File

0
app/Models/EncounterParticipant.php Executable file → Normal file
View File

0
app/Models/Exclusion.php Executable file → Normal file
View File

0
app/Models/ExclusionImport.php Executable file → Normal file
View File

0
app/Models/ExclusionRules.php Executable file → Normal file
View File

0
app/Models/Family.php Executable file → Normal file
View File

0
app/Models/File.php Executable file → Normal file
View File

0
app/Models/FilesDoc.php Executable file → Normal file
View File

0
app/Models/FilesMcu.php Executable file → Normal file
View File

0
app/Models/Formularium.php Executable file → Normal file
View File

0
app/Models/FormulariumItem.php Executable file → Normal file
View File

0
app/Models/FormulariumTemplate.php Executable file → Normal file
View File

0
app/Models/GeneratedDocument.php Executable file → Normal file
View File

0
app/Models/Icd.php Executable file → Normal file
View File

0
app/Models/IcdTemplate.php Executable file → Normal file
View File

0
app/Models/Identifier.php Executable file → Normal file
View File

0
app/Models/ImportLog.php Executable file → Normal file
View File

0
app/Models/Ingredient.php Executable file → Normal file
View File

Some files were not shown because too many files have changed in this diff Show More