refactor(webstatement): simplify and enhance statement export process

- Menghapus logika dan kode terkait pengunduhan, pembuatan, dan pengelolaan file statement yang berlebihan.
- Menambahkan fungsi `listAccount` untuk mendapatkan daftar nomor akun secara langsung.
- Menambahkan fungsi `listPeriod` untuk mengatur daftar periode yang digunakan dalam proses.
- Menambahkan fungsi `getAccountBalance` untuk mengakses saldo akun berdasarkan nomor akun dan periode.
- Mengubah metode `index` menjadi lebih modular, menggunakan fungsi tambahan untuk menyederhanakan pembuatan data dan queue statement.
- Menyederhanakan tanggapan JSON untuk pesan keberhasilan pengajuan job export.
- Mengimpor model `AccountBalance` yang diperlukan untuk fungsi baru.
This commit is contained in:
daengdeni
2025-05-24 08:59:20 +07:00
parent 2e2c8b4b0d
commit a3f2244fee

View File

@@ -9,6 +9,7 @@
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Modules\Webstatement\Jobs\ExportStatementJob; use Modules\Webstatement\Jobs\ExportStatementJob;
use Modules\Webstatement\Models\AccountBalance;
use Modules\Webstatement\Models\StmtEntry; use Modules\Webstatement\Models\StmtEntry;
use Modules\Webstatement\Models\TempFundsTransfer; use Modules\Webstatement\Models\TempFundsTransfer;
use Modules\Webstatement\Models\TempStmtNarrFormat; use Modules\Webstatement\Models\TempStmtNarrFormat;
@@ -21,296 +22,118 @@
*/ */
public function index() public function index()
{ {
$data = [[
'account_number' => '1080425781',
'period' => '2025012',
'saldo' => '23984352604'
],[
'account_number' => '1080425781',
'period' => '2025013',
'saldo' => '13984352604'
]];
$jobIds = []; $jobIds = [];
$data = [];
// Process each data entry foreach ($this->listAccount() as $accountNumber) {
foreach ($data as $entry) { foreach ($this->listPeriod() as $period) {
// Dispatch job for each entry $job = new ExportStatementJob(
$job = new ExportStatementJob( $accountNumber,
$entry['account_number'], $period,
$entry['period'], $this->getAccountBalance($accountNumber, $period)
$entry['saldo'] );
); $jobIds[] = app(Dispatcher::class)->dispatch($job);
$jobIds[] = app(Dispatcher::class)->dispatch($job); $data[] = [
'account_number' => $accountNumber,
'period' => $period
];
}
} }
return response()->json([ return response()->json([
'message' => 'Statement export jobs have been queued', 'message' => 'Statement export jobs have been queued',
'jobs' => array_map(function($index, $jobId) use ($data) { 'jobs' => array_map(function ($index, $jobId) use ($data) {
return [ return [
'job_id' => $jobId, 'job_id' => $jobId,
'account_number' => $data[$index]['account_number'], 'account_number' => $data[$index]['account_number'],
'period' => $data[$index]['period'], 'period' => $data[$index]['period'],
'file_name' => "{$data[$index]['account_number']}_{$data[$index]['period']}.csv" 'file_name' => "{$data[$index]['account_number']}_{$data[$index]['period']}.csv"
]; ];
}, array_keys($jobIds), $jobIds) }, array_keys($jobIds), $jobIds)
]); ]);
} }
/** function listAccount(){
* Download a previously exported statement return [
*/ '1080426085',
public function downloadStatement(Request $request) '1080425781',
{
$account_number = $request->input('account_number', '1080425781');
$period = $request->input('period', '20250512');
$fileName = "{$account_number}_{$period}.csv";
$filePath = "statements/{$fileName}";
if (!Storage::disk('local')->exists($filePath)) { '1081647484',
return response()->json([ '1081647485',
'message' => 'Statement file not found. It may still be processing.'
], 404);
}
return Storage::disk('local')->download($filePath, $fileName, [ '1083123710',
"Content-Type" => "text/csv", '1083123711',
]); '1083123712',
} '1083123713',
'1083123714',
'1083123715',
'1083123716',
'1083123718',
'1083123719',
'1083123721',
'1083123722',
'1083123723',
'1083123724',
'1083123726',
'1083123727',
'1083123728',
'1083123730',
'1083123731',
'1083123732',
'1083123734',
'1083123735',
/** '1086677889',
* Generate statement on-demand and return as download '1086677890',
*/ '1086677891',
public function generateAndDownload(Request $request) '1086677892',
{ '1086677893',
$account_number = $request->input('account_number', '1080425781'); '1086677894',
$period = $request->input('period', '20250512'); '1086677895',
$saldo = $request->input('saldo', '23984352604'); '1086677896',
'1086677897',
$stmt = StmtEntry::with(['ft', 'transaction']) '1080119298',
->where('account_number', $account_number) '1080119361',
->where('booking_date', $period) '1080119425',
->orderBy('date_time', 'ASC') '1080119387',
->orderBy('trans_reference', 'ASC') '1082208069',
->get();
if ($stmt->isEmpty()) { '1085151668',
return response()->json([
'message' => 'No statement data found for the specified account and period.'
], 404);
}
$runningBalance = (float) $saldo; '1085368601',
// Map the data to transform or format specific fields
$mappedData = $stmt->sortBy(['ACTUAL.DATE', 'REFERENCE.NUMBER'])
->map(function ($item, $index) use (&$runningBalance) {
$runningBalance += (float) $item->amount_lcy;
return [
'NO' => 0, // Will be updated later
'TRANSACTION.DATE' => Carbon::createFromFormat('YmdHi', $item->booking_date . substr($item->ft?->date_time ?? '0000000000', 6, 4))
->format('d/m/Y H:i'),
'REFERENCE.NUMBER' => $item->trans_reference,
'TRANSACTION.AMOUNT' => $item->amount_lcy,
'TRANSACTION.TYPE' => $item->amount_lcy < 0 ? 'D' : 'C',
'DESCRIPTION' => $this->generateNarrative($item),
'END.BALANCE' => $runningBalance,
'ACTUAL.DATE' => Carbon::createFromFormat('ymdHi', $item->ft?->date_time ?? '2505120000')
->format('d/m/Y H:i'),
];
})
->values();
// Then apply the sequential numbers '1078333878',
$mappedData = $mappedData->map(function ($item, $index) {
$item['NO'] = $index + 1;
return $item;
});
$csvFileName = $account_number . "_" . $period . ".csv"; '0081272689'
$headers = [
"Content-Type" => "text/csv",
"Content-Disposition" => "attachment; filename={$csvFileName}"
]; ];
$callback = function () use ($mappedData) {
$file = fopen('php://output', 'w');
// Write headers without quotes, using pipe separator
fputs($file, implode('|', array_keys($mappedData[0])) . "\n");
// Write data rows without quotes, using pipe separator
foreach ($mappedData as $row) {
fputs($file, implode('|', $row) . "\n");
}
fclose($file);
};
return response()->stream($callback, 200, $headers);
} }
/** function listPeriod(){
* Generate narrative for a statement entry return [
*/ '20250512',
private function generateNarrative($item) '20250513',
{ '20250514',
$narr = ''; '20250515',
if ($item->transaction && $item->transaction->narr_type) { '20250516',
$narr .= $item->transaction->stmt_narr . ' '; '20250517',
$narr .= $this->getFormatNarrative($item->transaction->narr_type, $item); '20250518',
} else if ($item->transaction) { '20250519',
$narr .= $item->transaction->stmt_narr . ' '; '20250520',
} '20250521',
'20250522'
if ($item->ft && $item->ft->recipt_no) { ];
$narr .= 'Receipt No: ' . $item->ft->recipt_no;
}
return $narr;
} }
/**
* Get formatted narrative based on narrative type function getAccountBalance($accountNumber, $period)
*/
private function getFormatNarrative($narr, $item)
{ {
$narrParam = TempStmtNarrParam::where('_id', $narr)->first(); $accountBalance = AccountBalance::where('account_number', $accountNumber)
->where('period', '<', $period)
->orderBy('period', 'desc')
->first();
if (!$narrParam) { return $accountBalance->actual_balance ?? 0;
return '';
}
$fmt = '';
if ($narrParam->_id == 'FTIN') {
$fmt = 'FT.IN';
} else if ($narrParam->_id == 'FTOUT') {
$fmt = 'FT.IN';
} else {
$fmt = $narrParam->_id;
}
$narrFormat = TempStmtNarrFormat::where('_id', $fmt)->first();
if (!$narrFormat) {
return '';
}
// Get the format string from the database
$formatString = $narrFormat->text_data ?? '';
// Parse the format string
// Split by the separator ']'
$parts = explode(']', $formatString);
$result = '';
foreach ($parts as $index => $part) {
if (empty($part)) {
continue;
}
if ($index === 0) {
// For the first part, take only what's before the '!'
$splitPart = explode('!', $part);
if (count($splitPart) > 0) {
// Remove quotes, backslashes, and other escape characters
$cleanPart = trim($splitPart[0]);
// Remove quotes at the beginning and end
$cleanPart = preg_replace('/^["\'\\\\]+|["\'\\\\]+$/', '', $cleanPart);
// Remove any remaining backslashes
$cleanPart = str_replace('\\', '', $cleanPart);
// Remove any remaining quotes
$cleanPart = str_replace('"', '', $cleanPart);
$result .= $cleanPart;
}
} else {
// For other parts, these are field placeholders
$fieldName = strtolower(str_replace('.', '_', $part));
// Get the corresponding parameter value from narrParam
$paramValue = null;
// Check if the field exists as a property in narrParam
if (property_exists($narrParam, $fieldName)) {
$paramValue = $narrParam->$fieldName;
} else if (isset($narrParam->$fieldName)) {
$paramValue = $narrParam->$fieldName;
}
// If we found a value, add it to the result
if ($paramValue !== null) {
$result .= $paramValue;
} else {
// If no value found, try to use the original field name as a fallback
if ($fieldName != 'recipt_no') {
$result .= $this->getTransaction($item->trans_reference, $fieldName) . ' ';
}
}
}
}
return $result;
}
/**
* Get transaction data by reference and field
*/
private function getTransaction($ref, $field)
{
$trans = TempFundsTransfer::where('ref_no', $ref)->first();
return $trans ? ($trans->$field ?? "") : "";
}
/**
* Queue a statement export job and return job ID
*/
public function queueExport(Request $request)
{
$account_number = $request->input('account_number', '1080425781');
$period = $request->input('period', '20250512');
$saldo = $request->input('saldo', '23984352604');
// Dispatch the job and get the job ID
$job = new ExportStatementJob($account_number, $period, $saldo);
$jobId = app(Dispatcher::class)->dispatch($job);
return response()->json([
'message' => 'Statement export job has been queued',
'job_id' => $jobId,
'account_number' => $account_number,
'period' => $period,
'file_name' => "{$account_number}_{$period}.csv"
]);
}
/**
* Check the status of an export job
*/
public function checkExportStatus(Request $request, $jobId)
{
// Get job status from the queue
$job = DB::table('jobs')
->where('id', $jobId)
->first();
if (!$job) {
// Check if job is completed
$completedJob = DB::table('job_batches')
->where('id', $jobId)
->first();
if ($completedJob) {
return response()->json([
'status' => 'completed',
'message' => 'Export job has been completed'
]);
}
return response()->json([
'status' => 'not_found',
'message' => 'Export job not found'
], 404);
}
return response()->json([
'status' => 'pending',
'message' => 'Export job is still processing'
]);
} }
} }