feat(webstatement): tambahkan pengaturan ekspor dan optimasi fungsionalitas print statement

- **Pembaruan pada `ExportStatementPeriodJob`:**
  - Menambahkan atribut baru `toCsv` untuk mendukung validasi sebelum proses ekspor CSV.
  - Menyesuaikan method `__construct` untuk menerima parameter tambahan `toCsv`.
  - Menambahkan validasi ekspor CSV dengan conditional check pada `toCsv` sebelum menjalankan `exportToCsv`.
  - Memperbaiki logika di `getTotalEntryCount` menggunakan `booking_date` untuk query lebih akurat.
  - Menambahkan logging terperinci pada proses penghitungan jumlah entri untuk meningkatkan debugging.

- **Integrasi Log Print Statement:**
  - Mengupdate status kolom `is_generated` pada model `PrintStatementLog` setelah entri diproses.
  - Menambahkan mekanisme pembaruan data log print statement melalui validasi entry statement.

- **Peningkatan pada Controller `PrintStatementController`:**
  - Memampukan proses ekspor otomatis jika statement tidak tersedia dengan metode baru `printStatementRekening`.
  - Menambahkan parameter `stmt_sent_type` untuk log print pada proses pencatatan data.
  - Mengimplementasikan pemrosesan period statement melalui job `ExportStatementPeriodJob`.

- **Perubahan pada UI/Blade `statements/index`:**
  - Menambahkan opsi pemilihan multiple untuk tipe laporan `stmt_sent_type`.
  - Mengupdate dan merapikan komponen form untuk input branch, akun, email, dan periode laporan.
  - Menambahkan kolom baru `is_generated` pada tabel untuk menampilkan status log hasil pembuatan laporan.

- **Pembaruan pada Datatable dan Skrip Frontend:**
  - Menambahkan render visual dengan badge untuk status `is_generated`.
  - Memperbaiki dan mengoptimalkan element HTML untuk datatable termasuk pagination dan search.
  - Menambahkan konfirmasi aksi dengan Ajax untuk retry pembuatan laporan jika diperlukan.

- **Optimisasi dan Refactor:**
  - Menggunakan group import pada controller untuk meningkatkan keterbacaan.
  - Memperbaiki alignment dan indentasi pada beberapa file blade.
  - Menghapus kode yang tidak digunakan atau redundan seperti conditional unprocessed data.

Dengan perubahan ini, sistem print statement lebih fleksibel, mencatat log lebih baik, dan mendukung fitur tracking pengeluaran laporan.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
Daeng Deni Mardaeni
2025-07-08 17:40:11 +07:00
parent a3060322f9
commit 65b846f0c7
3 changed files with 246 additions and 102 deletions

View File

@@ -2,20 +2,20 @@
namespace Modules\Webstatement\Http\Controllers; namespace Modules\Webstatement\Http\Controllers;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\{Auth, DB, Log, Mail, Storage};
use Illuminate\Support\Facades\DB; use Modules\Basicdata\Models\Branch;
use Illuminate\Support\Facades\Log; use Modules\Webstatement\{
use Illuminate\Support\Facades\Mail; Http\Requests\PrintStatementRequest,
use Illuminate\Support\Facades\Storage; Mail\StatementEmail,
use Modules\Basicdata\Models\Branch; Models\PrintStatementLog,
use Modules\Webstatement\Http\Requests\PrintStatementRequest; Models\AccountBalance,
use Modules\Webstatement\Mail\StatementEmail; Jobs\ExportStatementPeriodJob
use Modules\Webstatement\Models\PrintStatementLog; };
use ZipArchive; use ZipArchive;
class PrintStatementController extends Controller class PrintStatementController extends Controller
{ {
@@ -51,6 +51,7 @@
$validated['processed_accounts'] = 0; $validated['processed_accounts'] = 0;
$validated['success_count'] = 0; $validated['success_count'] = 0;
$validated['failed_count'] = 0; $validated['failed_count'] = 0;
$validated['stmt_sent_type'] = implode(',', $request->input('stmt_sent_type'));
// Create the statement log // Create the statement log
$statement = PrintStatementLog::create($validated); $statement = PrintStatementLog::create($validated);
@@ -65,7 +66,9 @@
// Process statement availability check // Process statement availability check
$this->checkStatementAvailability($statement); $this->checkStatementAvailability($statement);
if(!$statement->is_available){
$this->printStatementRekening($statement->account_number,$statement->period_from,$statement->period_to,$statement->stmt_sent_type);
}
DB::commit(); DB::commit();
return redirect()->route('statements.index') return redirect()->route('statements.index')
@@ -383,6 +386,7 @@
'period_to' => $item->is_period_range ? $item->period_to : null, 'period_to' => $item->is_period_range ? $item->period_to : null,
'authorization_status' => $item->authorization_status, 'authorization_status' => $item->authorization_status,
'is_available' => $item->is_available, 'is_available' => $item->is_available,
'is_generated' => $item->is_generated,
'is_downloaded' => $item->is_downloaded, 'is_downloaded' => $item->is_downloaded,
'created_at' => dateFormat($item->created_at, 1, 1), 'created_at' => dateFormat($item->created_at, 1, 1),
'created_by' => $item->user->name ?? 'N/A', 'created_by' => $item->user->name ?? 'N/A',
@@ -588,4 +592,65 @@
return "statement_{$accountNumber}_{$statement->period_from}.pdf"; return "statement_{$accountNumber}_{$statement->period_from}.pdf";
} }
function printStatementRekening($accountNumber, $period, $periodTo = null, $stmtSentType = null) {
$period = $period ?? date('Ym');
$balance = AccountBalance::where('account_number', $accountNumber)
->when($period === '202505', function($query) {
return $query->where('period', '>=', '20250512')
->orderBy('period', 'asc');
}, function($query) use ($period) {
// Get balance from last day of previous month
$firstDayOfMonth = Carbon::createFromFormat('Ym', $period)->startOfMonth();
$lastDayPrevMonth = $firstDayOfMonth->copy()->subDay()->format('Ymd');
return $query->where('period', $lastDayPrevMonth);
})
->first()
->actual_balance ?? '0.00';
$clientName = 'client1';
try {
\Log::info("Starting statement export for account: {$accountNumber}, period: {$period}, client: {$clientName}");
// Validate inputs
if (empty($accountNumber) || empty($period) || empty($clientName)) {
throw new \Exception('Required parameters missing');
}
// Dispatch the job
$job = ExportStatementPeriodJob::dispatch($accountNumber, $period, $balance, $clientName);
\Log::info("Statement export job dispatched successfully", [
'job_id' => $job->job_id ?? null,
'account' => $accountNumber,
'period' => $period,
'client' => $clientName
]);
return response()->json([
'success' => true,
'message' => 'Statement export job queued successfully',
'data' => [
'job_id' => $job->job_id ?? null,
'account_number' => $accountNumber,
'period' => $period,
'client_name' => $clientName
]
]);
} catch (\Exception $e) {
\Log::error("Failed to export statement", [
'error' => $e->getMessage(),
'account' => $accountNumber,
'period' => $period
]);
return response()->json([
'success' => false,
'message' => 'Failed to queue statement export job',
'error' => $e->getMessage()
]);
}
}
} }

View File

@@ -12,6 +12,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Modules\Webstatement\Models\PrintStatementLog;
use Modules\Webstatement\Models\ProcessedStatement; use Modules\Webstatement\Models\ProcessedStatement;
use Modules\Webstatement\Models\StmtEntry; use Modules\Webstatement\Models\StmtEntry;
use Modules\Webstatement\Models\TempFundsTransfer; use Modules\Webstatement\Models\TempFundsTransfer;
@@ -31,6 +32,7 @@ class ExportStatementPeriodJob implements ShouldQueue
protected $chunkSize = 1000; protected $chunkSize = 1000;
protected $startDate; protected $startDate;
protected $endDate; protected $endDate;
protected $toCsv;
/** /**
* Create a new job instance. * Create a new job instance.
@@ -41,7 +43,7 @@ class ExportStatementPeriodJob implements ShouldQueue
* @param string $client * @param string $client
* @param string $disk * @param string $disk
*/ */
public function __construct(string $account_number, string $period, string $saldo, string $client = '', string $disk = 'local') public function __construct(string $account_number, string $period, string $saldo, string $client = '', string $disk = 'local', bool $toCsv = true)
{ {
$this->account_number = $account_number; $this->account_number = $account_number;
$this->period = $period; $this->period = $period;
@@ -49,6 +51,7 @@ class ExportStatementPeriodJob implements ShouldQueue
$this->disk = $disk; $this->disk = $disk;
$this->client = $client; $this->client = $client;
$this->fileName = "{$account_number}_{$period}.csv"; $this->fileName = "{$account_number}_{$period}.csv";
$this->toCsv = $toCsv;
// Calculate start and end dates based on period // Calculate start and end dates based on period
$this->calculatePeriodDates(); $this->calculatePeriodDates();
@@ -84,8 +87,9 @@ class ExportStatementPeriodJob implements ShouldQueue
Log::info("Date range: {$this->startDate->format('Y-m-d')} to {$this->endDate->format('Y-m-d')}"); Log::info("Date range: {$this->startDate->format('Y-m-d')} to {$this->endDate->format('Y-m-d')}");
$this->processStatementData(); $this->processStatementData();
$this->exportToCsv(); if($this->toCsv){
$this->exportToCsv();
}
Log::info("Export statement period job completed successfully for account: {$this->account_number}, period: {$this->period}"); Log::info("Export statement period job completed successfully for account: {$this->account_number}, period: {$this->period}");
} catch (Exception $e) { } catch (Exception $e) {
Log::error("Error in ExportStatementPeriodJob: " . $e->getMessage()); Log::error("Error in ExportStatementPeriodJob: " . $e->getMessage());
@@ -104,20 +108,28 @@ class ExportStatementPeriodJob implements ShouldQueue
$existingDataCount = $this->getExistingProcessedCount($accountQuery); $existingDataCount = $this->getExistingProcessedCount($accountQuery);
// Only process if data is not fully processed // Only process if data is not fully processed
if ($existingDataCount !== $totalCount) { //if ($existingDataCount !== $totalCount) {
$this->deleteExistingProcessedData($accountQuery); $this->deleteExistingProcessedData($accountQuery);
$this->processAndSaveStatementEntries($totalCount); $this->processAndSaveStatementEntries($totalCount);
} //}
} }
private function getTotalEntryCount(): int private function getTotalEntryCount(): int
{ {
return StmtEntry::where('account_number', $this->account_number) $query = StmtEntry::where('account_number', $this->account_number)
->whereBetween('date_time', [ ->whereBetween('booking_date', [
$this->startDate->format('ymdHi'), $this->startDate->format('Ymd'),
$this->endDate->format('ymdHi') $this->endDate->format('Ymd')
]) ]);
->count();
Log::info("Getting total entry count with query: " . $query->toSql(), [
'bindings' => $query->getBindings(),
'account' => $this->account_number,
'start_date' => $this->startDate->format('Ymd'),
'end_date' => $this->endDate->format('Ymd')
]);
return $query->count();
} }
private function getExistingProcessedCount(array $criteria): int private function getExistingProcessedCount(array $criteria): int
@@ -141,11 +153,11 @@ class ExportStatementPeriodJob implements ShouldQueue
Log::info("Processing {$totalCount} statement entries for account: {$this->account_number}"); Log::info("Processing {$totalCount} statement entries for account: {$this->account_number}");
StmtEntry::with(['ft', 'transaction']) $entry = StmtEntry::with(['ft', 'transaction'])
->where('account_number', $this->account_number) ->where('account_number', $this->account_number)
->whereBetween('date_time', [ ->whereBetween('booking_date', [
$this->startDate->format('ymdHi'), $this->startDate->format('Ymd'),
$this->endDate->format('ymdHi') $this->endDate->format('Ymd')
]) ])
->orderBy('date_time', 'ASC') ->orderBy('date_time', 'ASC')
->orderBy('trans_reference', 'ASC') ->orderBy('trans_reference', 'ASC')
@@ -156,6 +168,16 @@ class ExportStatementPeriodJob implements ShouldQueue
DB::table('processed_statements')->insert($processedData); DB::table('processed_statements')->insert($processedData);
} }
}); });
if($entry){
$printLog = PrintStatementLog::where('account_number', $this->account_number)
->where('period_from', $this->period)
->latest()
->first();
if($printLog){
$printLog->update(['is_generated' => true]);
}
}
} }
private function prepareProcessedData($entries, &$runningBalance, &$globalSequence): array private function prepareProcessedData($entries, &$runningBalance, &$globalSequence): array
@@ -166,14 +188,13 @@ class ExportStatementPeriodJob implements ShouldQueue
$globalSequence++; $globalSequence++;
$runningBalance += (float) $item->amount_lcy; $runningBalance += (float) $item->amount_lcy;
$transactionDate = $this->formatTransactionDate($item);
$actualDate = $this->formatActualDate($item); $actualDate = $this->formatActualDate($item);
$processedData[] = [ $processedData[] = [
'account_number' => $this->account_number, 'account_number' => $this->account_number,
'period' => $this->period, 'period' => $this->period,
'sequence_no' => $globalSequence, 'sequence_no' => $globalSequence,
'transaction_date' => $transactionDate, 'transaction_date' => $item->booking_date,
'reference_number' => $item->trans_reference, 'reference_number' => $item->trans_reference,
'transaction_amount' => $item->amount_lcy, 'transaction_amount' => $item->amount_lcy,
'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C', 'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C',

View File

@@ -11,41 +11,83 @@
<h3 class="card-title">Request Print Stetement</h3> <h3 class="card-title">Request Print Stetement</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
<form action="{{ isset($statement) ? route('statements.update', $statement->id) : route('statements.store') }}" method="POST"> <form
action="{{ isset($statement) ? route('statements.update', $statement->id) : route('statements.store') }}"
method="POST">
@csrf @csrf
@if(isset($statement)) @if (isset($statement))
@method('PUT') @method('PUT')
@endif @endif
<div class="grid grid-cols-1 gap-5"> <div class="grid grid-cols-1 gap-5">
<div class="form-group"> <div class="form-group">
<label class="form-label required" for="branch_code">Branch</label> <label class="form-label required" for="branch_code">Branch</label>
<select class="select tomselect @error('branch_code') is-invalid @enderror" id="branch_code" name="branch_code" required> <select class="select tomselect @error('branch_code') is-invalid @enderror" id="branch_code"
name="branch_code" required>
<option value="">Select Branch</option> <option value="">Select Branch</option>
@foreach($branches as $branch) @foreach ($branches as $branch)
<option value="{{ $branch->code }}" {{ (old('branch_code', $statement->branch_code ?? '') == $branch->code) ? 'selected' : '' }}> <option value="{{ $branch->code }}"
{{ old('branch_code', $statement->branch_code ?? '') == $branch->code ? 'selected' : '' }}>
{{ $branch->name }} {{ $branch->name }}
</option> </option>
@endforeach @endforeach
</select> </select>
@error('branch_code') @error('branch_code')
<div class="invalid-feedback">{{ $message }}</div> <div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label class="form-label required" for="stmt_sent_type">Statement Type</label>
<select class="select tomselect @error('stmt_sent_type') is-invalid @enderror"
id="stmt_sent_type" name="stmt_sent_type[]" multiple required>
<option value="ALL"
{{ in_array('ALL', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
ALL
</option>
<option value="BY.EMAIL"
{{ in_array('BY.EMAIL', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
BY EMAIL
</option>
<option value="BY.MAIL.TO.DOM.ADDR"
{{ in_array('BY.MAIL.TO.DOM.ADDR', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
BY MAIL TO DOM ADDR
</option>
<option value="BY.MAIL.TO.KTP.ADDR"
{{ in_array('BY.MAIL.TO.KTP.ADDR', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
BY MAIL TO KTP ADDR
</option>
<option value="NO.PRINT"
{{ in_array('NO.PRINT', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
NO PRINT
</option>
<option value="PRINT"
{{ in_array('PRINT', old('stmt_sent_type', $statement->stmt_sent_type ?? [])) ? 'selected' : '' }}>
PRINT
</option>
</select>
@error('stmt_sent_type')
<div class="invalid-feedback">{{ $message }}</div>
@enderror @enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label required" for="account_number">Account Number</label> <label class="form-label required" for="account_number">Account Number</label>
<input type="text" class="input form-control @error('account_number') is-invalid @enderror" id="account_number" name="account_number" value="{{ old('account_number', $statement->account_number ?? '') }}" required> <input type="text" class="input form-control @error('account_number') is-invalid @enderror"
id="account_number" name="account_number"
value="{{ old('account_number', $statement->account_number ?? '') }}" required>
@error('account_number') @error('account_number')
<div class="invalid-feedback">{{ $message }}</div> <div class="invalid-feedback">{{ $message }}</div>
@enderror @enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label" for="email">Email</label> <label class="form-label" for="email">Email</label>
<input type="email" class="input form-control @error('email') is-invalid @enderror" id="email" name="email" value="{{ old('email', $statement->email ?? '') }}" placeholder="Optional email for send statement"> <input type="email" class="input form-control @error('email') is-invalid @enderror"
id="email" name="email" value="{{ old('email', $statement->email ?? '') }}"
placeholder="Optional email for send statement">
@error('email') @error('email')
<div class="invalid-feedback">{{ $message }}</div> <div class="invalid-feedback">{{ $message }}</div>
@enderror @enderror
</div> </div>
@@ -53,24 +95,21 @@
<label class="form-label required" for="start_date">Start Date</label> <label class="form-label required" for="start_date">Start Date</label>
<input class="input @error('period_from') border-danger bg-danger-light @enderror" <input class="input @error('period_from') border-danger bg-danger-light @enderror"
type="month" type="month" name="period_from"
name="period_from" value="{{ $statement->period_from ?? old('period_from') }}"
value="{{ $statement->period_from ?? old('period_from') }}" max="{{ date('Y-m', strtotime('-1 month')) }}">
max="{{ date('Y-m', strtotime('-1 month')) }}">
@error('period_from') @error('period_from')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label required" for="end_date">End Date</label> <label class="form-label required" for="end_date">End Date</label>
<input class="input @error('period_to') border-danger bg-danger-light @enderror" <input class="input @error('period_to') border-danger bg-danger-light @enderror" type="month"
type="month" name="period_to" value="{{ $statement->period_to ?? old('period_to') }}"
name="period_to" max="{{ date('Y-m', strtotime('-1 month')) }}">
value="{{ $statement->period_to ?? old('period_to') }}"
max="{{ date('Y-m', strtotime('-1 month')) }}">
@error('period_to') @error('period_to')
<em class="alert text-danger text-sm">{{ $message }}</em> <em class="text-sm alert text-danger">{{ $message }}</em>
@enderror @enderror
</div> </div>
</div> </div>
@@ -85,8 +124,9 @@
</div> </div>
</div> </div>
<div class="col-span-6"> <div class="col-span-6">
<div class="card card-grid min-w-full" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="statement-table" data-api-url="{{ route('statements.datatables') }}"> <div class="min-w-full card card-grid" data-datatable="false" data-datatable-page-size="10"
<div class="card-header py-5 flex-wrap"> data-datatable-state-save="false" id="statement-table" data-api-url="{{ route('statements.datatables') }}">
<div class="flex-wrap py-5 card-header">
<h3 class="card-title"> <h3 class="card-title">
Daftar Statement Request Daftar Statement Request
</h3> </h3>
@@ -96,59 +136,67 @@
<input placeholder="Search Statement" id="search" type="text" value=""> <input placeholder="Search Statement" id="search" type="text" value="">
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="scrollable-x-auto"> <div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true"> <table class="table text-sm font-medium text-gray-700 align-middle table-auto table-border"
data-datatable-table="true">
<thead> <thead>
<tr> <tr>
<th class="w-14"> <th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/> <input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
</th> </th>
<th class="min-w-[100px]" data-datatable-column="id"> <th class="min-w-[100px]" data-datatable-column="id">
<span class="sort"> <span class="sort-label"> ID </span> <span class="sort"> <span class="sort-label"> ID </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="branch_name"> <th class="min-w-[150px]" data-datatable-column="branch_name">
<span class="sort"> <span class="sort-label"> Branch </span> <span class="sort"> <span class="sort-label"> Branch </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="account_number"> <th class="min-w-[150px]" data-datatable-column="account_number">
<span class="sort"> <span class="sort-label"> Account Number </span> <span class="sort"> <span class="sort-label"> Account Number </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="period"> <th class="min-w-[150px]" data-datatable-column="period">
<span class="sort"> <span class="sort-label"> Period </span> <span class="sort"> <span class="sort-label"> Period </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="authorization_status"> <th class="min-w-[150px]" data-datatable-column="authorization_status">
<span class="sort"> <span class="sort-label"> Status </span> <span class="sort"> <span class="sort-label"> Status </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="is_available"> <th class="min-w-[150px]" data-datatable-column="is_available">
<span class="sort"> <span class="sort-label"> Available </span> <span class="sort"> <span class="sort-label"> Available </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[150px]" data-datatable-column="remarks"> <th class="min-w-[150px]" data-datatable-column="is_generated">
<span class="sort"> <span class="sort-label"> Notes </span> <span class="sort"> <span class="sort-label"> Generated </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[180px]" data-datatable-column="created_at"> <th class="min-w-[150px]" data-datatable-column="remarks">
<span class="sort"> <span class="sort-label"> Created At </span> <span class="sort"> <span class="sort-label"> Notes </span>
<span class="sort-icon"> </span> </span> <span class="sort-icon"> </span> </span>
</th> </th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th> <th class="min-w-[180px]" data-datatable-column="created_at">
</tr> <span class="sort"> <span class="sort-label"> Created At </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr>
</thead> </thead>
</table> </table>
</div> </div>
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium"> <div
<div class="flex items-center gap-2"> class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex gap-2 items-center">
Show Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per page <select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select>
per page
</div> </div>
<div class="flex items-center gap-4"> <div class="flex gap-4 items-center">
<span data-datatable-info="true"> </span> <span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true"> <div class="pagination" data-datatable-pagination="true">
</div> </div>
@@ -175,7 +223,7 @@
if (result.isConfirmed) { if (result.isConfirmed) {
$.ajaxSetup({ $.ajaxSetup({
headers: { headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}' 'X-CSRF-TOKEN': '{{ csrf_token() }}'
} }
}); });
@@ -262,12 +310,22 @@
is_available: { is_available: {
title: 'Available', title: 'Available',
render: (item, data) => { render: (item, data) => {
let statusClass = data.is_available ? 'badge badge-light-success' : 'badge badge-light-danger'; let statusClass = data.is_available ? 'badge badge-light-success' :
'badge badge-light-danger';
let statusText = data.is_available ? 'Yes' : 'No'; let statusText = data.is_available ? 'Yes' : 'No';
return `<span class="${statusClass}">${statusText}</span>`; return `<span class="${statusClass}">${statusText}</span>`;
}, },
}, },
remarks : { is_generated: {
title: 'Generated',
render: (item, data) => {
let statusClass = data.is_generated ? 'badge badge-light-success' :
'badge badge-light-danger';
let statusText = data.is_generated ? 'Yes' : 'No';
return `<span class="${statusClass}">${statusText}</span>`;
},
},
remarks: {
title: 'Notes', title: 'Notes',
}, },
created_at: { created_at: {
@@ -315,7 +373,7 @@
let dataTable = new KTDataTable(element, dataTableOptions); let dataTable = new KTDataTable(element, dataTableOptions);
// Custom search functionality // Custom search functionality
searchInput.addEventListener('input', function () { searchInput.addEventListener('input', function() {
const searchValue = this.value.trim(); const searchValue = this.value.trim();
dataTable.search(searchValue, true); dataTable.search(searchValue, true);
}); });