has('per_page') ? $request->input('per_page') : 10; $results = DB::table('invoice_payments') ->when($request->input('search'), function ($query, $search) { $query->where(function ($query) use ($search) { $query->orWhere('invoice_payments.invoice_number', 'like', "%" . $search . "%"); }); }) ->when($request->has('orderBy'), function ($query) use ($request) { $orderBy = $request->orderBy; $direction = $request->order ?? 'asc'; $query->orderBy($orderBy, $direction); }) ->when($request->input('start_date'), function ($query, $start_date) { $query->whereDate('invoice_payments.created_at', '>=', $start_date); }) ->when($request->input('end_date'), function ($query, $end_date) { $query->whereDate('invoice_payments.created_at', '<=', $end_date); }) ->when($request->input('status') , function ($query, $status) { $query->where(function ($query) use ($status) { $query->where('invoice_payments.status', '=', $status); }); }) // ->where('claim_management', '=', 1) ->select( 'invoice_payments.id', 'invoice_payments.invoice_number', 'invoice_payments.start_date', 'invoice_payments.end_date', 'invoice_payments.created_at', 'invoice_payments.status', ) ->groupBy('invoice_payments.invoice_number') ->paginate($limit); return response()->json(Helper::paginateResources($results)); } public function claim(Request $request) { $limit = $request->input('per_page', 10); $results = DB::table('claim_requests') ->leftJoin('request_logs', 'claim_requests.request_log_id', '=', 'request_logs.id') ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') ->leftJoin('invoice_payment_details', function ($join) { $join->on('invoice_payment_details.claim_request_id', '=', 'claim_requests.id') ->where(function ($q) { $q->whereNull('invoice_payment_details.deleted_by') ->orWhere('invoice_payment_details.deleted_by', 0); }); }) ->when($request->filled('search'), function ($query) use ($request) { $search = $request->search; $query->where(function ($q) use ($search) { $q->where('members.name', 'like', "%{$search}%") ->orWhere('claim_requests.code', 'like', "%{$search}%") ->orWhere('request_logs.code', 'like', "%{$search}%") ->orWhere('members.member_id', 'like', "%{$search}%"); }); }) ->when($request->filled('orderBy'), function ($query) use ($request) { $query->orderBy($request->orderBy, $request->order ?? 'asc'); }) ->when($request->filled('start_date'), fn ($q) => $q->where('claim_requests.created_at', '>=', $request->start_date) ) ->when($request->filled('end_date'), fn ($q) => $q->where('claim_requests.created_at', '<=', $request->end_date) ) ->when($request->filled('provider'), fn ($q) => $q->where('request_logs.organization_id', $request->provider) ) ->where('claim_management', 1) ->when($request->input('param') !== 'Edit', function ($query) { $query->whereNotIn('claim_requests.id', function ($q) { $q->select('claim_request_id') ->from('invoice_payment_details') ->where(function ($s) { $s->whereNull('deleted_by') ->orWhere('deleted_by', 0); }); }); }) ->when($request->input('param') === 'Edit', function ($query) use ($request) { $query->where(function ($q) use ($request) { $q->whereNotIn('claim_requests.id', function ($sub) { $sub->select('claim_request_id') ->from('invoice_payment_details') ->where(function ($s) { $s->whereNull('deleted_by') ->orWhere('deleted_by', 0); }); }) ->orWhereIn('claim_requests.id', function ($sub) use ($request) { $sub->select('claim_request_id') ->from('invoice_payment_details') ->where('invoice_payment_id', $request->invoiceID) ->where(function ($s) { $s->whereNull('deleted_by') ->orWhere('deleted_by', 0); }); }); }); }) ->select( 'claim_requests.id', 'request_logs.id AS id_log', 'request_logs.code AS code_log', 'claim_requests.code', 'members.name', 'members.member_id', 'claim_requests.created_at', DB::raw('(SELECT plans.code FROM plans JOIN member_plans ON member_plans.plan_id = plans.id WHERE member_plans.member_id = claim_requests.member_id AND plans.service_code = claim_requests.service_code LIMIT 1 ) AS plan_code'), DB::raw('(SELECT services.description FROM services WHERE services.code = claim_requests.service_code LIMIT 1 ) AS service_code'), DB::raw('(SELECT corporate_policies.code FROM corporate_policies WHERE corporate_policies.id = claim_requests.policy_id LIMIT 1 ) AS corporate_policies'), DB::raw('(SELECT organizations.name FROM organizations WHERE organizations.id = request_logs.organization_id LIMIT 1 ) AS provider'), DB::raw('(SELECT COALESCE(SUM(amount_approved),0) FROM request_log_benefits WHERE request_log_id = request_logs.id AND deleted_by IS NULL ) AS tot_bill'), 'claim_requests.status_claim_management as status' ) ->groupBy('claim_requests.id') ->paginate($limit); return response()->json(Helper::paginateResources($results)); } public function detail($id) { $invoice['invoice_payments'] = DB::table('invoice_payments') ->where('invoice_payments.id', $id) ->select('invoice_payments.*') ->get(); $invoice['invoice_payment_details'] = DB::table('invoice_payment_details') ->leftJoin('claim_requests', 'claim_requests.id', '=', 'invoice_payment_details.claim_request_id') ->leftJoin('request_logs', 'claim_requests.request_log_id','=', 'request_logs.id') ->leftJoin('members', 'request_logs.member_id', '=', 'members.id') ->where('invoice_payment_details.invoice_payment_id', $id) ->where(function ($q) { $q->whereNull('invoice_payment_details.deleted_by') ->orWhere('invoice_payment_details.deleted_by', 0); }) ->select( 'claim_requests.id', 'request_logs.invoice_no', 'request_logs.id AS id_log', 'request_logs.code AS code_log', 'claim_requests.code as code', 'members.name', DB::raw(' (SELECT members.member_id FROM members WHERE members.id = claim_requests.member_id LIMIT 1) AS member_id '), 'request_logs.created_at as submission_date', 'request_logs.submission_date as addmission_date', 'request_logs.discharge_date', // DB::raw(' // (SELECT plans.code FROM plans WHERE plans.id = member_plans.plan_id LIMIT 1) AS plan_code // '), DB::raw(' (SELECT plans.code FROM plans WHERE plans.id IN ( SELECT member_plans.plan_id FROM member_plans WHERE member_plans.member_id = claim_requests.member_id ) AND plans.service_code = claim_requests.service_code) AS plan_code '), DB::raw(' (SELECT services.description FROM services WHERE services.code = claim_requests.service_code LIMIT 1) AS service_code '), DB::raw(' (SELECT corporate_policies.code FROM corporate_policies WHERE corporate_policies.id = claim_requests.policy_id LIMIT 1) AS corporate_policies '), DB::raw(' (SELECT organizations.name FROM organizations WHERE organizations.id = request_logs.organization_id LIMIT 1) AS provider '), DB::raw(' (Select SUM(request_log_benefits.amount_approved) as tot_bill FROM request_log_benefits WHERE request_log_benefits.request_log_id = request_logs.id and deleted_by is null) AS tot_bill '), 'claim_requests.status_claim_management as status', ) ->groupBy('claim_requests.id') ->get(); $payments = DB::table('invoice_payments') ->leftJoin('files', function ($join) { $join->on('files.fileable_id', '=', 'invoice_payments.id') ->where('files.type', 'files-proof-payment') ->whereNull('files.deleted_by') ->orWhere('files.deleted_by', 0); }) ->where('invoice_payments.invoice_number', $invoice['invoice_payments'][0]->invoice_number) ->select( 'invoice_payments.id', 'files.id as file_id', 'invoice_payments.amount_paid', 'invoice_payments.no_reference', 'invoice_payments.payment_number', 'files.path', 'files.source', 'files.original_name' ) ->orderBy('invoice_payments.payment_number', 'asc') ->get() ->map(function ($row) { // default null kalau tidak ada path if (!$row->path) { $row->path = null; // atau bisa $row->url = null return $row; } if ($row->source === 's3') { try { $row->path = Storage::disk('s3')->temporaryUrl( $row->path, now()->addMinutes(60) ); } catch (\Exception $e) { $row->path = Storage::disk('s3')->url($row->path); } } else { $row->path = Storage::disk('public')->url($row->path); } return $row; }); $invoice['files'] = $payments->groupBy('payment_number')->map(function ($group) { return [ 'id' => $group->first()->id, 'amount_paid' => $group->first()->amount_paid, 'no_reference' => $group->first()->no_reference, 'payment_number' => $group->first()->payment_number, 'files' => $group->map(function ($file) { return [ 'file_id' => $file->file_id, 'path' => $file->path, 'original_name' => $file->original_name ]; })->toArray() ]; })->values()->toArray(); if ($invoice['invoice_payments']->isEmpty()) { return response()->json(['message' => 'Invoice tidak ditemukan'], 404); } return response()->json($invoice); } public function create(Request $request) { $data = [ 'invoice_number' => $request->invoice_number, 'invoice_date' => $request->invoice_date, 'start_date' => $request->start_date, 'end_date' => $request->end_date, 'payments' => $request->payments ]; $validator = Validator::make($request->all(), [ 'invoice_number' => 'required', 'invoice_date' => 'required', 'start_date' => 'required', 'end_date' => 'required', 'payments' => 'required', 'invoice_payment_details' => 'required', ], [ 'invoice_number.required' => trans('Validation.required',['attribute' => 'Nomor Invoice']), 'invoice_date.required' => trans('Validation.required',['attribute' => 'Tanggal Invoice']), 'start_date.required' => trans('Validation.required',['attribute' => 'Tanggal Mulai']), 'end_date.required' => trans('Validation.required',['attribute' => 'Tanggal Akhir']), 'payments.required' => trans('Validation.required',['attribute' => 'Jumlah Bayar']), 'invoice_payment_details.required' => trans('Validation.required',['attribute' => 'Nomor Claim']), ]); if ($validator->fails()) { return response()->json(['message' => $validator->errors()], 400); } else { try { DB::beginTransaction(); $invoiceNumber = $request->invoice_number; foreach ($request->payments as $valuePayments) { if($request->param === 'Edit') { $invoiceNumber = DB::table('invoice_payments') ->where('id', $valuePayments['id']) ->value('invoice_number'); } // **Cek apakah invoice_number sudah ada di database** $existingInvoice = DB::table('invoice_payments') ->where('invoice_number', $invoiceNumber) ->where('payment_number', $valuePayments['paymentNumber']) // ->where('amount_paid', $this->normalizeCurrency($valuePayments['amount'])) ->exists(); //Insert if (!$existingInvoice) { $lastInsertedId = DB::table('invoice_payments') ->insertGetId([ 'invoice_number' => $request->invoice_number, 'payment_number' => $valuePayments['paymentNumber'], 'invoice_date' => $request->invoice_date, 'start_date' => $request->start_date, 'end_date' => $request->start_date, 'amount_paid' => $this->normalizeCurrency($valuePayments['amount']), 'no_reference' => $valuePayments['noReference'], 'status' => 'submitted', 'created_by' => auth()->user()->id, 'created_at' => date('Y-m-d H:i:s'), ]); foreach ($request->invoice_payment_details as $value) { // **Cek apakah claim_request_id sudah ada untuk invoice_payment_id ini** $existingClaim = DB::table('invoice_payment_details') ->where('claim_request_id', $value) ->exists(); if (!$existingClaim) { DB::table('invoice_payment_details') ->insert([ 'invoice_payment_id' => $lastInsertedId, 'claim_request_id' => $value, 'created_by' => auth()->user()->id, 'created_at' => date('Y-m-d H:i:s'), ]); } } if (!empty($valuePayments['files']) && is_array($valuePayments['files'])) { foreach ($valuePayments['files'] as $file) { $fileData = File::storeFile('files-proof-payment', $lastInsertedId, $file); File::updateOrCreate([ 'fileable_type' => 'App\Models\InvoicePayment', 'fileable_id' => $lastInsertedId, 'type' => 'files-proof-payment', 'name' => $fileData['name'], 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), 'source' => env('FILESYSTEM_DISK'), 'path' => $fileData['path'], 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, ]); } } } else { //Edit $invoicePaymentId = DB::table('invoice_payments') ->where('invoice_number', $invoiceNumber) ->where('payment_number', $valuePayments['paymentNumber']) ->value('id'); DB::table('invoice_payments') ->where('id', $invoicePaymentId) ->update([ 'invoice_number' => $request->invoice_number, 'invoice_date' => $request->invoice_date, 'start_date' => $request->start_date, 'end_date' => $request->end_date, 'amount_paid' => $this->normalizeCurrency($valuePayments['amount']), 'no_reference' => $valuePayments['noReference'], 'updated_by' => auth()->user()->id, 'updated_at' => date('Y-m-d H:i:s'), ]); $existingClaims = DB::table('invoice_payment_details') ->where('invoice_payment_id', $invoicePaymentId) ->whereNull('deleted_at') // hanya data aktif ->pluck('claim_request_id') ->map(fn($id) => (int)$id) ->toArray(); // pastikan newClaims integer semua $newClaims = array_map('intval', $request->invoice_payment_details); // ============================= // INSERT DATA BARU // ============================= $claimsToInsert = array_diff($newClaims, $existingClaims); if (!empty($claimsToInsert)) { foreach ($claimsToInsert as $claim) { DB::table('invoice_payment_details')->insert([ 'invoice_payment_id' => $invoicePaymentId, 'claim_request_id' => $claim, 'created_by' => auth()->id(), 'created_at' => now(), ]); } } // ============================= // SOFT DELETE DATA YANG DIHAPUS // ============================= $claimsToDelete = array_diff($existingClaims, $newClaims); if (!empty($claimsToDelete)) { DB::table('invoice_payment_details') ->where('invoice_payment_id', $invoicePaymentId) ->whereIn('claim_request_id', $claimsToDelete) ->whereNull('deleted_at') // penting supaya tidak over-update ->update([ 'deleted_by' => auth()->id(), 'deleted_at' => now(), ]); } // Handle existing files $existingFiles = DB::table('files') ->where('files.fileable_id', $invoicePaymentId) ->where('files.type', 'files-proof-payment') ->pluck('id') ->toArray(); $newFiles = []; if (!empty($valuePayments['existingFiles']) && is_array($valuePayments['existingFiles'])) { $newFiles = array_column($valuePayments['existingFiles'], 'file_id'); } $filesToDelete = array_diff($existingFiles, $newFiles); if (!empty($filesToDelete)) { DB::table('files') ->whereIn('id', $filesToDelete) ->update([ 'deleted_by' => auth()->user()->id, 'deleted_at' => now(), ]); } //File New if (!empty($valuePayments['files']) && is_array($valuePayments['files'])) { foreach ($valuePayments['files'] as $file) { $fileData = File::storeFile('files-proof-payment', $invoicePaymentId, $file); File::updateOrCreate([ 'fileable_type' => 'App\Models\InvoicePayment', 'fileable_id' => $invoicePaymentId, 'type' => 'files-proof-payment', 'name' => $fileData['name'], 'original_name' => $file->getClientOriginalName(), 'extension' => $file->getClientOriginalExtension(), 'source' => env('FILESYSTEM_DISK'), 'path' => $fileData['path'], 'created_by' => auth()->user()->id, 'updated_by' => auth()->user()->id, ]); } } } } DB::commit(); return response()->json(['message' => 'Data berhasil disimpan'], 200); } catch (\Exception $e) { DB::rollback(); return response()->json(['message' => $e->getMessage()], 500); } } } function normalizeCurrency($amount) { return (int) preg_replace('/\D/', '', $amount); } public function submitStatus(Request $request) { $request->validate([ 'valueStatus' => 'required|in:submitted,accepted,partial_paid,paid,decline', 'valueID' => 'required|integer|exists:invoice_payments,id', ]); $update = DB::table('invoice_payments') ->where('id', $request->valueID) ->update([ 'status' => $request->valueStatus, 'updated_at' => now(), 'updated_by' => auth()->user()->id, ]); if (!$update) { return response()->json(['message' => 'Data tidak ditemukan atau tidak diperbarui'], 404); } return response()->json(['message' => 'Status berhasil diperbarui']); } public function export(Request $request, ExportExcelService $service) { \Log::info('EXPORT REQUEST', $request->all()); $filters = [ 'search' => $request->input('search'), 'start_date' => $request->input('start_date'), 'end_date' => $request->input('end_date'), 'orderBy' => $request->input('orderBy'), 'order' => $request->input('order', 'asc'), ]; return $service->exportReport($filters, 'Report-Vale-Payment.xlsx'); } public function export3(Request $request) { $start_date = $request->input('start_date') ? $request->input('start_date') : 'all'; $end_date = $request->input('end_date') ? $request->input('end_date') : 'all'; $writer = WriterEntityFactory::createXLSXWriter(); $writer->openToFile(public_path('files/Report-Data-Invoice-Management-'.$start_date.'-'.$end_date.'.xlsx')); $header = [ 'No', 'Nomor Invoice', 'Pembayaran Ke', 'Tanggal Invoice', 'Start Date', 'End Date', 'Nominal Pembayaran', 'Created At', 'Updated At', ]; $style = (new StyleBuilder()) ->setFontBold() // ->setFontSize(15) // ->setFontColor(Color::BLUE) // ->setShouldWrapText() ->setCellAlignment(CellAlignment::LEFT) // ->setBackgroundColor(Color::YELLOW) ->build(); $headerRow = WriterEntityFactory::createRowFromArray($header, $style); $writer->addRow($headerRow); // ============================ $results = DB::table('invoice_payments') // ->leftJoin('member_plans', 'member_plans.member_id', '=', 'members.id') ->when($request->input('search'), function ($query, $search) { $query->where(function ($query) use ($search) { $query->orWhere('invoice_payments.invoice_number', 'like', "%" . $search . "%"); }); }) ->when($request->has('orderBy'), function ($query) use ($request) { $orderBy = $request->orderBy; $direction = $request->order ?? 'asc'; $query->orderBy($orderBy, $direction); }) ->when($request->input('start_date') , function ($query, $start_date) { $query->where(function ($query) use ($start_date) { $query->where('claim_requests.created_at', '>=', $start_date); }); }) ->when($request->input('end_date') , function ($query, $end_date) { $query->where(function ($query) use ($end_date) { $query->where('claim_requests.created_at', '<=', $end_date); }); }) ->select( 'invoice_payments.*') ->get(); $no=0; $gr_total = 0; $header = [ 'No', 'Nomor Invoice', 'Pembayaran Ke', 'Tanggal Invoice', 'Start Date', 'End Date', 'Nominal Pembayaran', 'Created At', 'Updated At', ]; foreach($results as $item) { $gr_total += $item->amount_paid; $no++; $rowData = [ $no, $item->invoice_number, $item->payment_number, $item->invoice_date, $item->start_date, $item->end_date, $item->amount_paid, $item->created_at, $item->updated_at ]; $style = (new StyleBuilder()) //->setFontBold() // ->setFontSize(15) // ->setFontColor(Color::BLUE) // ->setShouldWrapText() ->setCellAlignment(CellAlignment::LEFT) // ->setBackgroundColor(Color::YELLOW) ->build(); $row = WriterEntityFactory::createRowFromArray($rowData, $style); $writer->addRow($row); } $footer = [ 'Grand Total', '', '', '', '', '', $gr_total, '', '', ]; $style = (new StyleBuilder()) ->setFontBold() // ->setFontSize(15) // ->setFontColor(Color::BLUE) // ->setShouldWrapText() ->setCellAlignment(CellAlignment::LEFT) // ->setBackgroundColor(Color::YELLOW) ->build(); $footerRow = WriterEntityFactory::createRowFromArray($footer, $style); $writer->addRow($footerRow); $writer->close(); return Helper::responseJson([ 'file_name' => 'Report-Data-Invoice-Management-'. $start_date.'-'.$end_date, "file_url" => url('files/Report-Data-Invoice-Management-'. $start_date.'-'.$end_date.'.xlsx') ]); } }