getCawanganReport(); } public function getSummaryLaporanPelangganBaru(Request $request) { $startDate = $request->startDate; $endDate = $request->endDate; // Get active branch DBs from helper $active_cawangan_db_connection = Helper::getActiveCawanganDbConnection(); // Fetch branch details with mysql info $cawangan_available = Cawangan::select('kodcaw', 'details_caw', 'mysql') ->whereIn('mysql', $active_cawangan_db_connection) ->get(); $active_cawangan_db_connection = array_column($cawangan_available->toArray(), 'mysql'); $active_cawangan_detail = $cawangan_available->map(function ($c) { return [ 'kodcaw' => $c->kodcaw, 'details_caw' => $c->details_caw, ]; })->values()->toArray(); // Iterate through each branch and get data $response = array_map(function ($db_connection, $cawangan_detail) use ($request) { // Pass the required parameters to the service constructor $reportRingkasanHarianService = new ReportRingkasanHarianService($cawangan_detail['kodcaw'], $request); // Get the customer count from the service $bilangan_customer_baru = $reportRingkasanHarianService->getCustomerSummary(); // Call public method // Return the response return [ 'kodcaw' => $cawangan_detail['kodcaw'], 'details_caw' => $cawangan_detail['details_caw'], 'total_pelanggan_baru' => $bilangan_customer_baru, ]; }, $active_cawangan_db_connection, $active_cawangan_detail); return response()->json($response); } // public function getSummaryLaporanPelangganAktif(Request $request) // { // $startDate = $request->startDate; // $endDate = $request->endDate; // // Dapatkan senarai cawangan aktif // $active_cawangan_db_connection = Helper::getActiveCawanganDbConnection(); // // Dapatkan maklumat cawangan // $cawangan_available = Cawangan::select('kodcaw', 'details_caw', 'mysql') // ->whereIn('mysql', $active_cawangan_db_connection) // ->get(); // $active_cawangan_detail = $cawangan_available->map(function ($c) { // return [ // 'kodcaw' => $c->kodcaw, // 'details_caw' => $c->details_caw, // 'mysql' => $c->mysql, // ]; // })->toArray(); // $response = array_map(function ($cawangan) use ($startDate, $endDate) { // $db_connection = $cawangan['mysql']; // $total_aktif = Gadai::on($db_connection) // ->where(function ($query) use ($startDate) { // $query->where('sttebus', '') // ->where('t_update', '>=', $startDate); // }) // ->where('t_gadai', '<=', $endDate) // ->distinct('nokp') // ->count('nokp'); // return [ // 'kodcaw' => $cawangan['kodcaw'], // 'details_caw' => $cawangan['details_caw'], // 'total_pelanggan_aktif' => $total_aktif, // ]; // }, $active_cawangan_detail); // return response()->json($response); // } public function getSummaryLaporanPelangganAktif(Request $request) { $startDate = $request->startDate; $endDate = $request->endDate; $active_cawangan = Cawangan::select('kodcaw', 'details_caw', 'mysql') ->whereIn('mysql', Helper::getActiveCawanganDbConnection()) ->get(); $response = $active_cawangan->map(function ($cawangan) use ($startDate, $endDate) { $db = $cawangan->mysql; // Ambil nokp dari Gadai $nokp_gadai = DB::connection($db)->table('gadai') ->whereBetween('t_gadai', [$startDate, $endDate]) ->pluck('nokp') ->toArray(); // Ambil nokp dari Tebus $nokp_tebus = DB::connection($db)->table('tebus as t') ->join('gadai as g', 't.norujukan', '=', 'g.norujukan') ->whereBetween('t.t_tebus', [$startDate, $endDate]) ->pluck('g.nokp') ->toArray(); // Gabung semua nokp $semua_nokp = collect(array_merge($nokp_gadai, $nokp_tebus)) ->filter(fn($item) => !empty($item)) ->unique() ->values(); if ($semua_nokp->isEmpty()) { // Jika array kosong, kita kembalikan hasil kosong $pelanggan_aktif = collect(); } else { $pelanggan_aktif = Customer::on($db) ->where(function ($query) use ($semua_nokp) { $query->whereIn('kpbaru', $semua_nokp) ->orWhereIn('kplama', $semua_nokp); }) ->get(['nama', 'kpbaru', 'kplama']) ->toArray();; } return [ 'kodcaw' => $cawangan->kodcaw, 'details_caw' => $cawangan->details_caw, 'total_pelanggan_aktif' => count($semua_nokp), ]; }); return response()->json($response); } public function getActiveCawanganConnections() { $cawangan_details = Cawangan::select(['details_caw', 'mysql'])->get(); $cawangan_details = $cawangan_details->filter(fn($x) => !in_array(strtolower($x->details_caw), config('report.excluded_cawangan'))); $connection_active_cawangan = Helper::getActiveCawanganDbConnection(); return collect($cawangan_details->filter(fn($x) => in_array($x->mysql, $connection_active_cawangan))); } public function getSummaryLaporanDataPelanggan(Request $request) { $year = $request->year; if (!$year) { return response()->json(['error' => 'Sila pilih tahun'], 400); } $startOfYear = Carbon::create($year, 1, 1)->startOfDay(); $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); Carbon::setLocale('ms'); // 1️⃣ Ambil semua pelanggan tahun ini $pelanggan = Customer::whereYear('tarikhdaftar', $year) ->select('id','nama','kpbaru','kplama','t_lahir','jantina', 'kodkerja','poskod','kodcaw','tarikhdaftar','tujuangadai','nopelanggan') ->get(); $connections = $this->getActiveCawanganConnections(); // Ambil semua pekerjaan & poskod sekali untuk map cepat $pekerjaanAll = Pekerjaan::pluck('keterangan','kodkerja'); $poskodAll = Poskod::with('daerah')->get()->keyBy('poskod'); // 2️⃣ Ambil semua nokp pelanggan $nokps = $pelanggan->map(fn($p) => $p->kpbaru ?? $p->kplama)->filter()->values(); // 3️⃣ Ambil semua transaksi gadai + tebus untuk nokp tu dari semua cawangan $allTransaksi = collect(); foreach ($connections as $conn) { $data = DB::connection($conn->mysql) ->table('gadai as g') ->leftJoin('tebus as t', 'g.norujukan', '=', 't.norujukan') ->leftJoin('lelong as l', 'g.norujukan', '=', 'l.norujukan') ->whereIn('g.nokp', $nokps) ->whereBetween('g.t_gadai', [$startOfYear, $endOfYear]) // ⬅️ dalam tahun sahaja ->select( 'g.nokp', 'g.norujukan', 'g.t_gadai', 't.t_tebus', 'g.pinjaman', 'g.upah12', 'g.tempoh', 'l.t_lelong', 'g.sttebus', ) ->get(); $allTransaksi = $allTransaksi->concat($data); } // 4️⃣ Group by nokp $transGrouped = $allTransaksi->groupBy('nokp'); // 5️⃣ Ambil semua norujukan transaksi online $onlineNorujukan = TransactionOnline::pluck('norujukan')->unique()->values(); // 6️⃣ Map pelanggan $result = $pelanggan->map(function($row) use ($transGrouped, $onlineNorujukan, $pekerjaanAll, $poskodAll, $year) { $nokp = $row->kpbaru ?? $row->kplama ?? null; $tempohData = $transGrouped->get($nokp, collect()); // Norujukan pelanggan spesifik $norujukanPelanggan = $tempohData->pluck('norujukan')->unique()->values(); // Cara Bayaran // $caraBayaran = $norujukanPelanggan->intersect($onlineNorujukan)->isNotEmpty() ? 'Online' : 'Kaunter'; $adaOnline = $norujukanPelanggan->contains(fn($nr) => isset($onlineNorujukan[$nr])); $caraBayaran = $adaOnline ? 'Online' : 'Kaunter'; if ($adaOnline) { \Log::info("Pelanggan {$row->nama} ({$nokp}): Bayaran Online - YA"); } // Bilangan transaksi $bilTransaksi = $tempohData->count(); // Bilangan Belum tebus $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); $bilOutstanding = $tempohData ->filter(function ($row) use ($endOfYear) { // masih belum tebus langsung if (empty($row->sttebus)) { return true; } // dah tebus, tapi tebus selepas hujung tahun return Carbon::parse($row->t_tebus)->gt($endOfYear); }) ->count(); // Bilangan tebus $bilTebus = $tempohData->whereNotNull('t_tebus')->count(); // Jumlah pinjaman $jumlahPinjaman = $tempohData->sum('pinjaman'); // Jumlah ujrah ikut tempoh surat $jumlahUjrah = $tempohData->reduce(function ($carry, $trx) { if (!$trx->upah12 || !$trx->tempoh) return $carry; return $carry + ($trx->upah12 / 12 * $trx->tempoh); }, 0); // Tarikh mula & tamat $tarikhMula = $tempohData->min('t_gadai'); $tarikhTamat = $tempohData->max('t_tebus'); $tarikhLelong = $tempohData->max('t_lelong'); // Tempoh Pajakan if (!$tarikhMula) { $tempohPajakan = '-'; } elseif (!$tarikhTamat || $tarikhMula == $tarikhTamat) { $tempohPajakan = Carbon::parse($tarikhMula)->translatedFormat('M Y'); } else { $tempohPajakan = Carbon::parse($tarikhMula)->translatedFormat('M Y') . ' - ' . Carbon::parse($tarikhTamat)->translatedFormat('M Y'); } // Hari sejak transaksi terakhir $hariTempohPajakan = $tarikhMula ? Carbon::parse($tarikhMula)->diffInDays($tarikhTamat ? Carbon::parse($tarikhTamat) : Carbon::now()) : null; // Tujuan gadai $tujuangadai = $row->tujuangadai ?: '-'; // Status aktif: ada transaksi dalam tahun tu $now = Carbon::now(); $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); $startOfYear = Carbon::create($year, 1, 1)->startOfDay(); $statusAktif = $tempohData->contains(function ($trx) use ($startOfYear, $endOfYear) { if (!$trx->t_gadai) return false; $tGadai = Carbon::parse($trx->t_gadai); $tTebus = $trx->t_tebus ? Carbon::parse($trx->t_tebus) : null; // SAG wujud dalam tahun laporan return $tGadai->lte($endOfYear) && ( is_null($tTebus) || // belum ditebus $tTebus->gte($startOfYear) // ditebus dalam / selepas tahun ); }); // Umur $umur = $row->t_lahir ? Carbon::parse($row->t_lahir)->age : null; // Pekerjaan $pekerjaan = $row->kodkerja ? ($pekerjaanAll[ltrim($row->kodkerja,'0')] ?? 'Lain-lain') : '-'; // Daerah / lokasi $lokasi = $row->poskod && isset($poskodAll[$row->poskod]) ? $poskodAll[$row->poskod]->daerah->namadaerah ?? 'Lain-lain' : 'Lain-lain'; return [ 'cawangan' => $row->kodcaw ?? '-', 'nama' => $row->nama, 'nopelanggan' => $row->nopelanggan, 'nokp' => $nokp ?? '-', 'tarikhdaftar' => Carbon::parse($row->tarikhdaftar)->format('d-m-Y'), 'umur' => $umur, 'jantina' => $row->jantina ?? '-', 'pekerjaan' => $pekerjaan, 'daerah' => $lokasi, 'tempoh_pajakan' => $tempohPajakan, 'tarikh_mula' => $tarikhMula ? Carbon::parse($tarikhMula)->format('d-m-Y') : null, 'tarikh_tamat' => $tarikhTamat ? Carbon::parse($tarikhTamat)->format('d-m-Y') : null, 'hari_sejak_transaksi' => $hariTempohPajakan, 'bil_transaksi' => $bilTransaksi, 'bil_outstanding' => $bilOutstanding, 'bil_tebus' => $bilTebus, 'jumlah_pinjaman' => $jumlahPinjaman, 'norujukan' => $norujukanPelanggan, 'jumlah_ujrah' => $jumlahUjrah, 'tujuan_gadai' => $tujuangadai, 'status_aktif' => $statusAktif ? 'AKTIF' : 'TIDAK AKTIF', 'cara_bayaran' => $caraBayaran, 'tarikh_lelong' => $tarikhLelong ? Carbon::parse($tarikhLelong)->format('d-m-Y') : null, ]; }); return response()->json([ 'year' => $year, 'summary' => [ 'total_pelanggan' => $result->count(), 'jumlah_cawangan' => $result->pluck('cawangan')->unique()->count(), ], 'pelanggan' => $result->values(), ], 200); } private function formatTempohPajakan($start, $end) { if (!$start || !$end) { return '-'; } $mula = Carbon::parse($start); $tamat = Carbon::parse($end); if ($mula->year === $tamat->year) { return $mula->translatedFormat('M') . ' – ' . $tamat->translatedFormat('M Y'); } return $mula->translatedFormat('M Y') . ' – ' . $tamat->translatedFormat('M Y'); } public function getSummaryLaporanDataPelangganBycaw(Request $request) { $year = $request->year; if (!$year) { return response()->json(['error' => 'Sila pilih tahun'], 400); } // =============================== // INPUT CAWANGAN (MULTIPLE) // =============================== $cawangan = $request->input('cawangan', []); if (!is_array($cawangan)) { $cawangan = [$cawangan]; } $startOfYear = Carbon::create($year, 1, 1)->startOfDay(); $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); Carbon::setLocale('ms'); // =============================== // 1️⃣ AMBIL PELANGGAN (FILTER CAWANGAN) // =============================== $pelangganQuery = Customer::whereYear('tarikhdaftar', $year); if (!empty($cawangan)) { $pelangganQuery->whereIn('kodcaw', $cawangan); } $pelanggan = $pelangganQuery ->select( 'id','nama','kpbaru','kplama','t_lahir','jantina', 'kodkerja','poskod','kodcaw','tarikhdaftar', 'tujuangadai','nopelanggan' ) ->get(); if ($pelanggan->isEmpty()) { return response()->json([ 'year' => $year, 'summary' => [ 'total_pelanggan' => 0, 'jumlah_cawangan' => 0, ], 'pelanggan' => [] ], 200); } // =============================== // 2️⃣ CONNECTION CAWANGAN // =============================== $connections = $this->getActiveCawanganConnections(); // =============================== // 3️⃣ MASTER DATA // =============================== $pekerjaanAll = Pekerjaan::pluck('keterangan', 'kodkerja'); $poskodAll = Poskod::with('daerah')->get()->keyBy('poskod'); // =============================== // 4️⃣ NOKP PELANGGAN // =============================== $nokps = $pelanggan ->map(fn($p) => $p->kpbaru ?? $p->kplama) ->filter() ->values(); // =============================== // 5️⃣ TRANSAKSI GADAI / TEBUS // =============================== $allTransaksi = collect(); foreach ($connections as $conn) { $data = DB::connection($conn->mysql) ->table('gadai as g') ->leftJoin('tebus as t', 'g.norujukan', '=', 't.norujukan') ->leftJoin('lelong as l', 'g.norujukan', '=', 'l.norujukan') ->whereIn('g.nokp', $nokps) ->whereBetween('g.t_gadai', [$startOfYear, $endOfYear]) ->select( 'g.nokp', 'g.norujukan', 'g.t_gadai', 't.t_tebus', 'g.pinjaman', 'g.upah12', 'g.tempoh', 'l.t_lelong', 'g.sttebus' ) ->get(); $allTransaksi = $allTransaksi->concat($data); } $transGrouped = $allTransaksi->groupBy('nokp'); // =============================== // 6️⃣ NORUJUKAN BAYARAN ONLINE // =============================== $onlineNorujukan = TransactionOnline::pluck('norujukan')->unique(); // =============================== // 7️⃣ MAP DATA PELANGGAN // =============================== $result = $pelanggan->map(function ($row) use ( $transGrouped, $onlineNorujukan, $pekerjaanAll, $poskodAll, $year ) { $nokp = $row->kpbaru ?? $row->kplama; $tempohData = $transGrouped->get($nokp, collect()); $norujukanPelanggan = $tempohData->pluck('norujukan')->unique(); // Cara Bayaran $adaOnline = $norujukanPelanggan ->intersect($onlineNorujukan) ->isNotEmpty(); $caraBayaran = $adaOnline ? 'Online' : 'Kaunter'; // Bilangan $bilTransaksi = $tempohData->count(); $bilOutstanding = $tempohData->filter(function ($row) use ($year) { $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); if (empty($row->sttebus)) return true; return Carbon::parse($row->t_tebus)->gt($endOfYear); })->count(); $bilTebus = $tempohData->whereNotNull('t_tebus')->count(); // Jumlah $jumlahPinjaman = $tempohData->sum('pinjaman'); $jumlahUjrah = $tempohData->reduce(function ($carry, $trx) { if (!$trx->upah12 || !$trx->tempoh) return $carry; return $carry + ($trx->upah12 / 12 * $trx->tempoh); }, 0); // Tarikh $tarikhMula = $tempohData->min('t_gadai'); $tarikhTamat = $tempohData->max('t_tebus'); $tarikhLelong = $tempohData->max('t_lelong'); // Tempoh Pajakan if (!$tarikhMula) { $tempohPajakan = '-'; } elseif (!$tarikhTamat || $tarikhMula == $tarikhTamat) { $tempohPajakan = Carbon::parse($tarikhMula)->translatedFormat('M Y'); } else { $tempohPajakan = Carbon::parse($tarikhMula)->translatedFormat('M Y') . ' - ' . Carbon::parse($tarikhTamat)->translatedFormat('M Y'); } // Hari sejak transaksi terakhir $hariTempohPajakan = $tarikhMula ? Carbon::parse($tarikhMula)->diffInDays($tarikhTamat ? Carbon::parse($tarikhTamat) : Carbon::now()) : null; // Tujuan gadai $tujuangadai = $row->tujuangadai ?: '-'; // Status aktif: ada transaksi dalam tahun tu $now = Carbon::now(); // Status Aktif $startOfYear = Carbon::create($year, 1, 1)->startOfDay(); $endOfYear = Carbon::create($year, 12, 31)->endOfDay(); $statusAktif = $tempohData->contains(function ($trx) use ($startOfYear, $endOfYear) { if (!$trx->t_gadai) return false; $tGadai = Carbon::parse($trx->t_gadai); $tTebus = $trx->t_tebus ? Carbon::parse($trx->t_tebus) : null; return $tGadai->lte($endOfYear) && (is_null($tTebus) || $tTebus->gte($startOfYear)); }); // Umur $umur = $row->t_lahir ? Carbon::parse($row->t_lahir)->age : null; // Pekerjaan $pekerjaan = $row->kodkerja ? ($pekerjaanAll[ltrim($row->kodkerja, '0')] ?? 'Lain-lain') : '-'; // Daerah $lokasi = $row->poskod && isset($poskodAll[$row->poskod]) ? ($poskodAll[$row->poskod]->daerah->namadaerah ?? 'Lain-lain') : 'Lain-lain'; return [ 'cawangan' => $row->kodcaw, 'nama' => $row->nama, 'nopelanggan' => $row->nopelanggan, 'nokp' => $nokp, 'tarikhdaftar' => Carbon::parse($row->tarikhdaftar)->format('d-m-Y'), 'umur' => $umur, 'jantina' => $row->jantina, 'pekerjaan' => $pekerjaan, 'daerah' => $lokasi, 'tempoh_pajakan' => $tempohPajakan, 'tarikh_mula' => $tarikhMula ? Carbon::parse($tarikhMula)->format('d-m-Y') : null, 'tarikh_tamat' => $tarikhTamat ? Carbon::parse($tarikhTamat)->format('d-m-Y') : null, 'hari_sejak_transaksi' => $hariTempohPajakan, 'bil_transaksi' => $bilTransaksi, 'bil_outstanding' => $bilOutstanding, 'bil_tebus' => $bilTebus, 'jumlah_pinjaman' => $jumlahPinjaman, 'jumlah_ujrah' => $jumlahUjrah, 'tujuan_gadai' => $tujuangadai, 'cara_bayaran' => $caraBayaran, 'status_aktif' => $statusAktif ? 'AKTIF' : 'TIDAK AKTIF', 'tarikh_lelong' => $tarikhLelong ? Carbon::parse($tarikhLelong)->format('d-m-Y') : null, ]; }); $result = $result->sortBy('cawangan')->values(); return response()->json([ 'year' => $year, 'cawangan' => $cawangan, 'summary' => [ 'total_pelanggan' => $result->count(), 'jumlah_cawangan' => $result->pluck('cawangan')->unique()->count(), ], 'pelanggan' => $result, ], 200); } }