From e1e52f78fb318984f3197247b9703897c55a3a0f Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Sat, 10 May 2025 15:12:56 +0700 Subject: [PATCH] ``` feat(sync-logs): tambah fitur sinkronisasi log biaya kartu - Menambahkan route, controller, model, dan migration untuk fitur baru `sync-logs`. - Mengganti referensi `BiayaKartuController` menjadi `SyncLogsController`. - Menyediakan halaman untuk menampilkan data log sinkronisasi dengan filter, pencarian, dan pagination. - Menambahkan kemampuan melihat detail proses sinkronisasi langsung dari modal. - Memperbarui `module.json` dengan item menu baru untuk fitur log sinkronisasi. - Menghapus `BiayaKartuController` yang sudah tidak digunakan lagi. ``` Signed-off-by: Daeng Deni Mardaeni --- app/Http/Controllers/BiayaKartuController.php | 29 -- app/Http/Controllers/SyncLogsController.php | 126 +++++++ app/Models/KartuSyncLog.php | 119 ++++++ ...10_133532_create_kartu_sync_logs_table.php | 48 +++ module.json | 27 +- resources/views/sync-logs/index.blade.php | 347 ++++++++++++++++++ routes/breadcrumbs.php | 5 + routes/web.php | 9 +- 8 files changed, 678 insertions(+), 32 deletions(-) delete mode 100644 app/Http/Controllers/BiayaKartuController.php create mode 100644 app/Http/Controllers/SyncLogsController.php create mode 100644 app/Models/KartuSyncLog.php create mode 100644 database/migrations/2025_05_10_133532_create_kartu_sync_logs_table.php create mode 100644 resources/views/sync-logs/index.blade.php diff --git a/app/Http/Controllers/BiayaKartuController.php b/app/Http/Controllers/BiayaKartuController.php deleted file mode 100644 index 2bf45cf..0000000 --- a/app/Http/Controllers/BiayaKartuController.php +++ /dev/null @@ -1,29 +0,0 @@ -handle(); - - // Alternatif jika Anda ingin menjalankannya secara asinkron - // GenerateBiayaAtmCsvJob::dispatch(); - // return response()->json(['message' => 'Proses pembuatan file CSV sedang berjalan di background']); - - return response()->download($filename)->deleteFileAfterSend(true); - - } - } diff --git a/app/Http/Controllers/SyncLogsController.php b/app/Http/Controllers/SyncLogsController.php new file mode 100644 index 0000000..3476b7e --- /dev/null +++ b/app/Http/Controllers/SyncLogsController.php @@ -0,0 +1,126 @@ +has('search') && !empty($request->get('search'))) { + $search = $request->get('search'); + $query->where(function ($q) use ($search) { + $q->where('periode', 'LIKE', "%$search%") + ->orWhere('sync_notes', 'LIKE', "%$search%") + ->orWhere('csv_notes', 'LIKE', "%$search%") + ->orWhere('ftp_notes', 'LIKE', "%$search%") + ->orWhere('file_name', 'LIKE', "%$search%"); + }); + } + + // Apply filter for sync status if provided + if ($request->has('is_sync') && $request->get('is_sync') !== '') { + $query->where('is_sync', $request->get('is_sync') == '1'); + } + + // Apply filter for CSV status if provided + if ($request->has('is_csv') && $request->get('is_csv') !== '') { + $query->where('is_csv', $request->get('is_csv') == '1'); + } + + // Apply filter for FTP status if provided + if ($request->has('is_ftp') && $request->get('is_ftp') !== '') { + $query->where('is_ftp', $request->get('is_ftp') == '1'); + } + + // Apply sorting if provided + if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) { + $order = $request->get('sortOrder'); + $column = $request->get('sortField'); + $query->orderBy($column, $order); + } else { + // Default sort by created_at descending + $query->orderBy('created_at', 'desc'); + } + + // Get the total count of records + $totalRecords = $query->count(); + + // Apply pagination if provided + if ($request->has('page') && $request->has('size')) { + $page = $request->get('page'); + $size = $request->get('size'); + $offset = ($page - 1) * $size; + + $query->skip($offset)->take($size); + } + + // Get the filtered count of records + $filteredRecords = $query->count(); + + // Get the data for the current page + $data = $query->get(); + + // Calculate the page count + $pageCount = ceil($filteredRecords / ($request->get('size') ?: 1)); + + // Calculate the current page number + $currentPage = $request->get('page') ?: 1; + + // Return the response data as a JSON object + return response()->json([ + 'draw' => $request->get('draw'), + 'recordsTotal' => $totalRecords, + 'recordsFiltered' => $filteredRecords, + 'pageCount' => $pageCount, + 'page' => $currentPage, + 'totalCount' => $totalRecords, + 'data' => $data, + ]); + } + + /** + * Format file size to human readable format + */ + private function formatSize($bytes) + { + $units = ['B', 'KB', 'MB', 'GB', 'TB']; + + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + + $bytes /= pow(1024, $pow); + + return round($bytes, 2) . ' ' . $units[$pow]; + } + + public function show($id){ + $syncLog = KartuSyncLog::find($id); + $csvSize = $this->formatSize(File::size($syncLog->csv_path)); + $ftpSize = $this->formatSize(File::size($syncLog->ftp_path)); + + return response()->json($syncLog, 200, ['Content-Type' => 'application/json'], JSON_PRETTY_PRINT); + } +} diff --git a/app/Models/KartuSyncLog.php b/app/Models/KartuSyncLog.php new file mode 100644 index 0000000..365b102 --- /dev/null +++ b/app/Models/KartuSyncLog.php @@ -0,0 +1,119 @@ + + */ + protected $fillable = [ + 'periode', + 'is_sync', + 'is_csv', + 'is_ftp', + 'sync_at', + 'csv_at', + 'ftp_at', + 'sync_notes', + 'csv_notes', + 'ftp_notes', + 'total_records', + 'success_records', + 'failed_records', + 'file_path', + 'file_name', + 'ftp_destination', + ]; + + /** + * Atribut yang harus diubah menjadi tipe native. + * + * @var array + */ + protected $casts = [ + 'is_sync' => 'boolean', + 'is_csv' => 'boolean', + 'is_ftp' => 'boolean', + 'sync_at' => 'datetime', + 'csv_at' => 'datetime', + 'ftp_at' => 'datetime', + 'total_records' => 'integer', + 'success_records' => 'integer', + 'failed_records' => 'integer', + ]; + + /** + * Scope untuk mendapatkan log berdasarkan periode + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @param string $periode Format: YYYY-MM + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeByPeriode($query, $periode) + { + return $query->where('periode', $periode); + } + + /** + * Scope untuk mendapatkan log yang sudah sync + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeSynced($query) + { + return $query->where('is_sync', true); + } + + /** + * Scope untuk mendapatkan log yang sudah membuat CSV + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeCsvGenerated($query) + { + return $query->where('is_csv', true); + } + + /** + * Scope untuk mendapatkan log yang sudah upload FTP + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeFtpUploaded($query) + { + return $query->where('is_ftp', true); + } + + /** + * Scope untuk mendapatkan log yang belum selesai prosesnya + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeIncomplete($query) + { + return $query->where(function ($q) { + $q->where('is_sync', false) + ->orWhere('is_csv', false) + ->orWhere('is_ftp', false); + }); + } +} diff --git a/database/migrations/2025_05_10_133532_create_kartu_sync_logs_table.php b/database/migrations/2025_05_10_133532_create_kartu_sync_logs_table.php new file mode 100644 index 0000000..d20e8a6 --- /dev/null +++ b/database/migrations/2025_05_10_133532_create_kartu_sync_logs_table.php @@ -0,0 +1,48 @@ +id(); + $table->string('periode')->comment('Periode sinkronisasi (format: YYYY-MM)'); + $table->boolean('is_sync')->default(false)->comment('Status sinkronisasi data'); + $table->boolean('is_csv')->default(false)->comment('Status pembuatan file CSV'); + $table->boolean('is_ftp')->default(false)->comment('Status upload ke FTP'); + $table->timestamp('sync_at')->nullable()->comment('Waktu sinkronisasi'); + $table->timestamp('csv_at')->nullable()->comment('Waktu pembuatan CSV'); + $table->timestamp('ftp_at')->nullable()->comment('Waktu upload FTP'); + $table->text('sync_notes')->nullable()->comment('Catatan sinkronisasi'); + $table->text('csv_notes')->nullable()->comment('Catatan pembuatan CSV'); + $table->text('ftp_notes')->nullable()->comment('Catatan upload FTP'); + $table->integer('total_records')->default(0)->comment('Jumlah total rekaman'); + $table->integer('success_records')->default(0)->comment('Jumlah rekaman berhasil'); + $table->integer('failed_records')->default(0)->comment('Jumlah rekaman gagal'); + $table->string('file_path')->nullable()->comment('Path file CSV yang dihasilkan'); + $table->string('file_name')->nullable()->comment('Nama file CSV yang dihasilkan'); + $table->string('ftp_destination')->nullable()->comment('Tujuan upload FTP'); + $table->timestamps(); + + // Indeks untuk pencarian cepat + $table->index('periode'); + $table->index(['is_sync', 'is_csv', 'is_ftp']); + }); + } + + /** + * Reverse the migrations. + */ + public function down() + : void + { + Schema::dropIfExists('kartu_sync_logs'); + } + }; diff --git a/module.json b/module.json index 1de580a..02fc16a 100644 --- a/module.json +++ b/module.json @@ -77,6 +77,31 @@ "roles": [] } ], - "system": [] + "system": [ + { + "title": "Logs", + "path": "logs", + "icon": "ki-filled ki-tablet-text-down text-lg text-primary", + "classes": "", + "attributes": [], + "permission": "", + "roles": [ + "administrator" + ], + "sub": [ + { + "title": "Log Biaya Kartu", + "path": "sync-logs", + "icon": "ki-filled ki-credit-cart text-lg", + "classes": "", + "attributes": [], + "permission": "", + "roles": [ + "administrator" + ] + } + ] + } + ] } } diff --git a/resources/views/sync-logs/index.blade.php b/resources/views/sync-logs/index.blade.php new file mode 100644 index 0000000..5e41a11 --- /dev/null +++ b/resources/views/sync-logs/index.blade.php @@ -0,0 +1,347 @@ + +@extends('layouts.main') + +@section('breadcrumbs') + {{ Breadcrumbs::render(request()->route()->getName()) }} +@endsection + +@section('content') +
+
+
+

+ Log Sinkronisasi Data Kartu +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + + +
+ Periode + + + Status Sinkronisasi + + + Waktu Sinkronisasi + + + Status CSV + + + Waktu Pembuatan CSV + + + Status FTP + + + Waktu Upload FTP + + + Total Rekaman + + + Nama File + + + Aksi +
+
+ +
+
+
+ + + +@endsection + +@push('scripts') + +@endpush diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php index c5fec4c..9c88b88 100644 --- a/routes/breadcrumbs.php +++ b/routes/breadcrumbs.php @@ -83,3 +83,8 @@ $trail->parent('home'); $trail->push('Kartu ATM', route('kartu-atm.index')); }); + + Breadcrumbs::for('sync-logs.index', function (BreadcrumbTrail $trail) { + $trail->parent('home'); + $trail->push('Sync Logs Biaya Kartu', route('sync-logs.index')); + }); diff --git a/routes/web.php b/routes/web.php index f202ef6..3ecfc07 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,7 +1,7 @@ group(function () { }); Route::resource('kartu-atm', KartuAtmController::class)->only('index'); + Route::prefix('sync-logs')->name('sync-logs.')->group(function () { + Route::get('datatables', [SyncLogsController::class, 'dataForDatatables'])->name('datatables'); + }); + Route::resource('sync-logs', SyncLogsController::class); + Route::prefix('emailblast')->group(function () { Route::get('/', [EmailBlastController::class, 'index'])->name('emailblast.index'); Route::get('/create', [EmailBlastController::class, 'create'])->name('emailblast.create'); @@ -54,6 +59,6 @@ Route::middleware(['auth'])->group(function () { }); Route::get('migrasi', [MigrasiController::class, 'index'])->name('migrasi.index'); -Route::get('biaya-kartu', [BiayaKartuController::class, 'index'])->name('biaya-kartu.index'); +Route::get('biaya-kartu', [SyncLogsController::class, 'index'])->name('biaya-kartu.index'); Route::get('/stmt-entries/{accountNumber}', [MigrasiController::class, 'getStmtEntryByAccount']);