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:
@@ -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'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user