Compare commits
10 Commits
713c2b1e12
...
d5495d721e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5495d721e | ||
|
|
e511025307 | ||
|
|
285c2409ea | ||
|
|
3c061f40f7 | ||
|
|
def0b037a8 | ||
|
|
39e356e2ff | ||
|
|
fb6fd534d5 | ||
|
|
359cfea905 | ||
|
|
1c8d9a4a8a | ||
|
|
24700c5bd8 |
@@ -8,12 +8,18 @@ use Illuminate\Support\Facades\Storage;
|
|||||||
use Log;
|
use Log;
|
||||||
use Modules\Webstatement\Jobs\ProcessAccountDataJob;
|
use Modules\Webstatement\Jobs\ProcessAccountDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessArrangementDataJob;
|
use Modules\Webstatement\Jobs\ProcessArrangementDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessAtmTransactionJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessBillDetailDataJob;
|
use Modules\Webstatement\Jobs\ProcessBillDetailDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessCategoryDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessCompanyDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessCustomerDataJob;
|
use Modules\Webstatement\Jobs\ProcessCustomerDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessDataCaptureDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessFtTxnTypeConditionJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessFundsTransferDataJob;
|
use Modules\Webstatement\Jobs\ProcessFundsTransferDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessStmtEntryDataJob;
|
use Modules\Webstatement\Jobs\ProcessStmtEntryDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessStmtNarrFormatDataJob;
|
use Modules\Webstatement\Jobs\ProcessStmtNarrFormatDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessStmtNarrParamDataJob;
|
use Modules\Webstatement\Jobs\ProcessStmtNarrParamDataJob;
|
||||||
|
use Modules\Webstatement\Jobs\ProcessTellerDataJob;
|
||||||
use Modules\Webstatement\Jobs\ProcessTransactionDataJob;
|
use Modules\Webstatement\Jobs\ProcessTransactionDataJob;
|
||||||
|
|
||||||
class MigrasiController extends Controller
|
class MigrasiController extends Controller
|
||||||
@@ -102,10 +108,65 @@ class MigrasiController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ProcessFtTxnTypeConditioData($periods){
|
||||||
|
try {
|
||||||
|
ProcessFtTxnTypeConditionJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'FtTxnTypeCondition processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function processStmtEntryData($periods){
|
public function processStmtEntryData($periods){
|
||||||
try {
|
try {
|
||||||
ProcessStmtEntryDataJob::dispatch($periods);
|
ProcessStmtEntryDataJob::dispatch($periods);
|
||||||
return response()->json(['message' => 'Data TempStmtEntry processing job has been successfully']);
|
return response()->json(['message' => 'Stmt Entry processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function ProcessCompanyData($periods){
|
||||||
|
try {
|
||||||
|
ProcessCompanyDataJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'Company processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessDataCaptureData($periods){
|
||||||
|
try {
|
||||||
|
ProcessDataCaptureDataJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'Data Capture processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessCategoryData($periods){
|
||||||
|
try {
|
||||||
|
ProcessCategoryDataJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'Category processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessTellerData($periods){
|
||||||
|
try {
|
||||||
|
ProcessTellerDataJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'Teller processing job has been successfully']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ProcessAtmTransaction($periods){
|
||||||
|
try {
|
||||||
|
ProcessAtmTransactionJob::dispatch($periods);
|
||||||
|
return response()->json(['message' => 'AtmTransaction processing job has been successfully']);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return response()->json(['error' => $e->getMessage()], 500);
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
@@ -119,10 +180,10 @@ class MigrasiController extends Controller
|
|||||||
// Get all directories (periods) in the SFTP disk
|
// Get all directories (periods) in the SFTP disk
|
||||||
$allDirectories = $disk->directories();
|
$allDirectories = $disk->directories();
|
||||||
|
|
||||||
$this->processTransactionData(['_parameter']);
|
//$this->processTransactionData(['_parameter']);
|
||||||
$this->processStmtNarrParamData(['_parameter']);
|
//$this->processStmtNarrParamData(['_parameter']);
|
||||||
$this->processStmtNarrFormatData(['_parameter']);
|
//$this->processStmtNarrFormatData(['_parameter']);
|
||||||
|
//$this->ProcessFtTxnTypeConditioData(['_parameter']);
|
||||||
|
|
||||||
// Filter out the _parameter folder
|
// Filter out the _parameter folder
|
||||||
$periods = array_filter($allDirectories, function($dir) {
|
$periods = array_filter($allDirectories, function($dir) {
|
||||||
@@ -138,12 +199,21 @@ class MigrasiController extends Controller
|
|||||||
return response()->json(['message' => 'No valid period folders found in SFTP storage'], 404);
|
return response()->json(['message' => 'No valid period folders found in SFTP storage'], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->processCustomerData(['20250519']);
|
$this->ProcessCategoryData($periods);
|
||||||
$this->processAccountData(['20250519']);
|
|
||||||
$this->processArrangementData($periods);
|
//$this->processCustomerData($periods);
|
||||||
$this->processBillDetailData($periods);
|
//$this->processAccountData($periods);
|
||||||
$this->processFundsTransferData($periods);
|
|
||||||
$this->processStmtEntryData($periods);
|
//$this->processStmtEntryData($periods);
|
||||||
|
//$this->ProcessDataCaptureData($periods);
|
||||||
|
//$this->processFundsTransferData($periods);
|
||||||
|
$this->ProcessTellerData($periods);
|
||||||
|
$this->ProcessAtmTransaction($periods);
|
||||||
|
|
||||||
|
//$this->processArrangementData($periods);
|
||||||
|
//$this->processBillDetailData($periods);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return response()->json(['message' => 'Data processing job has been successfully']);
|
return response()->json(['message' => 'Data processing job has been successfully']);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ namespace Modules\Webstatement\Http\Controllers;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Modules\Webstatement\Models\StmtEntry;
|
||||||
|
use Modules\Webstatement\Models\TempFundsTransfer;
|
||||||
|
use Modules\Webstatement\Models\TempStmtNarrFormat;
|
||||||
|
use Modules\Webstatement\Models\TempStmtNarrParam;
|
||||||
|
|
||||||
class WebstatementController extends Controller
|
class WebstatementController extends Controller
|
||||||
{
|
{
|
||||||
@@ -12,7 +16,164 @@ class WebstatementController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('webstatement::index');
|
|
||||||
|
$account_number = '1080425781';
|
||||||
|
$period = '20250512';
|
||||||
|
|
||||||
|
$stmt = StmtEntry::with(['ft','transaction'])->where('account_number',$account_number)->where('booking_date',$period)->get();
|
||||||
|
$saldo = '23984352604';
|
||||||
|
$runningBalance = (float) $saldo;
|
||||||
|
|
||||||
|
// 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, // Use $index instead of $item->count()
|
||||||
|
'TRANSACTION.DATE' => \Carbon\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->generateNarative($item),
|
||||||
|
'END.BALANCE' => $runningBalance,
|
||||||
|
'ACTUAL.DATE' => \Carbon\Carbon::createFromFormat('ymdHi', $item->ft?->date_time ?? '2505120000')
|
||||||
|
->format('d/m/Y H:i'),
|
||||||
|
];
|
||||||
|
})->values();
|
||||||
|
|
||||||
|
|
||||||
|
// Then apply the sequential numbers
|
||||||
|
$mappedData = $mappedData->map(function ($item, $index) {
|
||||||
|
$item['NO'] = $index + 1;
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return response()->json($mappedData);
|
||||||
|
|
||||||
|
$csvFileName = $account_number."_".$period.".csv";
|
||||||
|
$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 generateNarative($item){
|
||||||
|
$narr = '';
|
||||||
|
if($item->transaction->narr_type){
|
||||||
|
$narr .= $item->transaction->stmt_narr.' ';
|
||||||
|
$narr .= $this->getFormatNarrative($item->transaction->narr_type,$item);
|
||||||
|
} else {
|
||||||
|
$narr .= $item->transaction->stmt_narr.' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if($item->ft?->recipt_no) {
|
||||||
|
$narr .= 'Receipt No: ' . $item->ft->recipt_no;
|
||||||
|
}
|
||||||
|
return $narr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getFormatNarrative($narr,$item){
|
||||||
|
$narrParam = TempStmtNarrParam::where('_id', $narr)->first();
|
||||||
|
|
||||||
|
if (!$narrParam) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$fmt = '';
|
||||||
|
if($narrParam->_id=='FTIN'){
|
||||||
|
$fmt = 'FT.IN';
|
||||||
|
}elseif($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;
|
||||||
|
} elseif (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).' ';
|
||||||
|
// $result .= "[$fieldName]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getTransaction($ref, $field){
|
||||||
|
$trans = TempFundsTransfer::where('ref_no', $ref)->first();
|
||||||
|
|
||||||
|
return $trans->$field ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
235
app/Jobs/ProcessAtmTransactionJob.php
Normal file
235
app/Jobs/ProcessAtmTransactionJob.php
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\AtmTransaction;
|
||||||
|
|
||||||
|
class ProcessAtmTransactionJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private const PARAMETER_FOLDER = '_parameter';
|
||||||
|
|
||||||
|
// Konstanta untuk nilai-nilai statis
|
||||||
|
private const FILE_EXTENSION = '.ST.ATM.csv';
|
||||||
|
private const CSV_DELIMITER = '~';
|
||||||
|
private const DISK_NAME = 'sftpStatement';
|
||||||
|
private const HEADER_MAP = [
|
||||||
|
'id' => 'transaction_id',
|
||||||
|
'card_acc_id' => 'card_acc_id',
|
||||||
|
'pan_number' => 'pan_number',
|
||||||
|
'txn_type' => 'txn_type',
|
||||||
|
'merchant_id' => 'merchant_id',
|
||||||
|
'txn_amount' => 'txn_amount',
|
||||||
|
'booking_date' => 'booking_date',
|
||||||
|
'trans_ref' => 'trans_ref',
|
||||||
|
'retrieval_ref_no' => 'retrieval_ref_no',
|
||||||
|
'stmt_nos' => 'stmt_nos',
|
||||||
|
'debit_acct_no' => 'debit_acct_no',
|
||||||
|
'credit_acct_no' => 'credit_acct_no',
|
||||||
|
'chrg_amount' => 'chrg_amount',
|
||||||
|
'value_date' => 'value_date',
|
||||||
|
'stan_no' => 'stan_no',
|
||||||
|
'trans_status' => 'trans_status',
|
||||||
|
'proc_code' => 'proc_code'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Pemetaan bidang header ke kolom model
|
||||||
|
protected array $periods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [])
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for ATM transaction data processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stats = $this->processPeriods();
|
||||||
|
|
||||||
|
Log::info("ProcessAtmTransactionJob completed. Total processed: {$stats['processed']}, Total errors: {$stats['errors']}");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("Error in ProcessAtmTransactionJob: " . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process all periods and return statistics
|
||||||
|
*/
|
||||||
|
private function processPeriods(): array
|
||||||
|
{
|
||||||
|
$disk = Storage::disk(self::DISK_NAME);
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the parameter folder
|
||||||
|
if ($period === self::PARAMETER_FOLDER) {
|
||||||
|
Log::info("Skipping " . self::PARAMETER_FOLDER . " folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->processPeriodFile($disk, $period);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single period file
|
||||||
|
*/
|
||||||
|
private function processPeriodFile($disk, string $period): array
|
||||||
|
{
|
||||||
|
$filename = $period . self::FILE_EXTENSION;
|
||||||
|
$filePath = "$period/$filename";
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
Log::info("Processing ATM transaction file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempFilePath = $this->createTempFile($disk, $filePath, $filename);
|
||||||
|
|
||||||
|
$result = $this->processCSVFile($tempFilePath, $filePath);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
if (file_exists($tempFilePath)) {
|
||||||
|
unlink($tempFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Completed processing $filePath. Processed {$result['processed']} records with {$result['errors']} errors.");
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary file for processing
|
||||||
|
*/
|
||||||
|
private function createTempFile($disk, string $filePath, string $filename): string
|
||||||
|
{
|
||||||
|
$tempFilePath = storage_path("app/temp_$filename");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
return $tempFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a CSV file and import data
|
||||||
|
*/
|
||||||
|
private function processCSVFile(string $tempFilePath, string $originalFilePath): array
|
||||||
|
{
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
if ($handle === false) {
|
||||||
|
Log::error("Unable to open file: $originalFilePath");
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the headers from the first row
|
||||||
|
$headerRow = fgetcsv($handle, 0, self::CSV_DELIMITER);
|
||||||
|
if (!$headerRow) {
|
||||||
|
fclose($handle);
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
while (($row = fgetcsv($handle, 0, self::CSV_DELIMITER)) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
if (count($headerRow) !== count($row)) {
|
||||||
|
Log::warning("Row $rowCount in $originalFilePath has incorrect column count. Expected: " . count($headerRow) . ", Got: " . count($row));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->processRow($headerRow, $row, $rowCount, $originalFilePath);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single row from the CSV file
|
||||||
|
*/
|
||||||
|
private function processRow(array $headerRow, array $row, int $rowCount, string $filePath): array
|
||||||
|
{
|
||||||
|
// Combine the header row with the data row
|
||||||
|
$rawData = array_combine($headerRow, $row);
|
||||||
|
|
||||||
|
// Map the raw data to our model fields
|
||||||
|
$data = [];
|
||||||
|
foreach (self::HEADER_MAP as $csvField => $modelField) {
|
||||||
|
$data[$modelField] = $rawData[$csvField] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip header row if it was included in the data
|
||||||
|
if ($data['transaction_id'] === 'id') {
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Format dates if needed
|
||||||
|
/*if (!empty($data['booking_date'])) {
|
||||||
|
$data['booking_date'] = date('Y-m-d H:i:s', strtotime($data['booking_date']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($data['value_date'])) {
|
||||||
|
$data['value_date'] = date('Y-m-d H:i:s', strtotime($data['value_date']));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Create or update the record
|
||||||
|
AtmTransaction::updateOrCreate(
|
||||||
|
['transaction_id' => $data['transaction_id']],
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
|
||||||
|
return ['processed' => 1, 'errors' => 0];
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("Error processing row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
return ['processed' => 0, 'errors' => 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ class ProcessBillDetailDataJob implements ShouldQueue
|
|||||||
$headers = (new TempBillDetail())->getFillable();
|
$headers = (new TempBillDetail())->getFillable();
|
||||||
$rowCount = 0;
|
$rowCount = 0;
|
||||||
|
|
||||||
while (($row = fgetcsv($handle, 0, ";")) !== false) {
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
$rowCount++;
|
$rowCount++;
|
||||||
|
|
||||||
if (count($headers) === count($row)) {
|
if (count($headers) === count($row)) {
|
||||||
|
|||||||
138
app/Jobs/ProcessCategoryDataJob.php
Normal file
138
app/Jobs/ProcessCategoryDataJob.php
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\Category;
|
||||||
|
|
||||||
|
class ProcessCategoryDataJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $periods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [])
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
$disk = Storage::disk('sftpStatement');
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for category data processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the _parameter folder
|
||||||
|
if ($period === '_parameter') {
|
||||||
|
Log::info("Skipping _parameter folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the filename based on the period folder name
|
||||||
|
$filename = "$period.ST.CATEGORY.csv";
|
||||||
|
$filePath = "$period/$filename";
|
||||||
|
|
||||||
|
Log::info("Processing category file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary local copy of the file
|
||||||
|
$tempFilePath = storage_path("app/temp_$filename");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
|
||||||
|
if ($handle !== false) {
|
||||||
|
// Get the headers from the first row
|
||||||
|
$headerRow = fgetcsv($handle, 0, "~");
|
||||||
|
|
||||||
|
// Map the headers to our model fields
|
||||||
|
$headerMap = [
|
||||||
|
'id' => 'id_category',
|
||||||
|
'date_time' => 'date_time',
|
||||||
|
'description' => 'description',
|
||||||
|
'short_name' => 'short_name',
|
||||||
|
'system_ind' => 'system_ind',
|
||||||
|
'record_status' => 'record_status',
|
||||||
|
'co_code' => 'co_code',
|
||||||
|
'curr_no' => 'curr_no',
|
||||||
|
'l_db_cr_ind' => 'l_db_cr_ind',
|
||||||
|
'category_code' => 'category_code'
|
||||||
|
];
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
|
||||||
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
if (count($headerRow) === count($row)) {
|
||||||
|
// Combine the header row with the data row
|
||||||
|
$rawData = array_combine($headerRow, $row);
|
||||||
|
|
||||||
|
// Map the raw data to our model fields
|
||||||
|
$data = [];
|
||||||
|
foreach ($headerMap as $csvField => $modelField) {
|
||||||
|
$data[$modelField] = $rawData[$csvField] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Skip header row if it was included in the data
|
||||||
|
if ($data['id_category'] !== 'id') {
|
||||||
|
// Use firstOrNew instead of updateOrCreate
|
||||||
|
$category = Category::firstOrNew(['id_category' => $data['id_category']]);
|
||||||
|
$category->fill($data);
|
||||||
|
$category->save();
|
||||||
|
$processedCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$errorCount++;
|
||||||
|
Log::error("Error processing Category at row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log::warning("Row $rowCount in $filePath has incorrect column count. Expected: " . count($headerRow) . ", Got: " . count($row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
Log::info("Completed processing $filePath. Processed $processedCount records with $errorCount errors.");
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
unlink($tempFilePath);
|
||||||
|
} else {
|
||||||
|
Log::error("Unable to open file: $filePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Category data processing completed. Total processed: $processedCount, Total errors: $errorCount");
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error('Error in ProcessCategoryDataJob: ' . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
154
app/Jobs/ProcessCompanyDataJob.php
Normal file
154
app/Jobs/ProcessCompanyDataJob.php
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
|
||||||
|
class ProcessCompanyDataJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $periods;
|
||||||
|
protected $filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [], string $filename = "ST.COMPANY.csv")
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
$this->filename = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
$disk = Storage::disk('sftpStatement');
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for company data processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the _parameter folder
|
||||||
|
if ($period === '_parameter') {
|
||||||
|
Log::info("Skipping _parameter folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the filepath based on the period folder name
|
||||||
|
$fileName = "$period.$this->filename";
|
||||||
|
$filePath = "$period/$fileName";
|
||||||
|
|
||||||
|
Log::info("Processing company file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary local copy of the file
|
||||||
|
$tempFilePath = storage_path("app/temp_{$this->filename}");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
|
||||||
|
if ($handle !== false) {
|
||||||
|
// CSV headers from the file
|
||||||
|
$csvHeaders = [
|
||||||
|
'id', 'date_time', 'company_code', 'company_name', 'name_address',
|
||||||
|
'mnemonic', 'customer_company', 'customer_mnemonic', 'company_group',
|
||||||
|
'curr_no', 'co_code', 'l_vendor_atm', 'l_vendor_cpc'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Field mapping from CSV to Branch model
|
||||||
|
$fieldMapping = [
|
||||||
|
'company_code' => 'code',
|
||||||
|
'company_name' => 'name',
|
||||||
|
'name_address' => 'address',
|
||||||
|
'mnemonic' => 'mnemonic',
|
||||||
|
'customer_company' => 'customer_company',
|
||||||
|
'customer_mnemonic' => 'customer_mnemonic',
|
||||||
|
'company_group' => 'company_group',
|
||||||
|
'curr_no' => 'curr_no',
|
||||||
|
'co_code' => 'co_code',
|
||||||
|
'l_vendor_atm' => 'l_vendor_atm',
|
||||||
|
'l_vendor_cpc' => 'l_vendor_cpc'
|
||||||
|
];
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
|
||||||
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
// Skip header row if it exists
|
||||||
|
if ($rowCount === 1 && (strtolower($row[0]) === 'id' || strtolower($row[2]) === 'company_code')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($csvHeaders) === count($row)) {
|
||||||
|
$csvData = array_combine($csvHeaders, $row);
|
||||||
|
|
||||||
|
// Map CSV data to Branch model fields
|
||||||
|
$branchData = [];
|
||||||
|
foreach ($fieldMapping as $csvField => $modelField) {
|
||||||
|
if (isset($csvData[$csvField])) {
|
||||||
|
// Convert string boolean values to actual booleans for boolean fields
|
||||||
|
if (in_array($modelField, ['l_vendor_atm', 'l_vendor_cpc'])) {
|
||||||
|
$branchData[$modelField] = filter_var($csvData[$csvField], FILTER_VALIDATE_BOOLEAN);
|
||||||
|
} else {
|
||||||
|
$branchData[$modelField] = $csvData[$csvField];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!empty($branchData['code'])) {
|
||||||
|
Branch::updateOrCreate(
|
||||||
|
['code' => $branchData['code']],
|
||||||
|
$branchData
|
||||||
|
);
|
||||||
|
$processedCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$errorCount++;
|
||||||
|
Log::error("Error processing Company data at row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log::warning("Row $rowCount in $filePath has incorrect column count. Expected: " . count($csvHeaders) . ", Got: " . count($row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
Log::info("Completed processing $filePath. Processed $processedCount records with $errorCount errors.");
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
unlink($tempFilePath);
|
||||||
|
} else {
|
||||||
|
Log::error("Unable to open file: $filePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Company data processing completed. Total processed: $processedCount, Total errors: $errorCount");
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error('Error in ProcessCompanyDataJob: ' . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
185
app/Jobs/ProcessDataCaptureDataJob.php
Normal file
185
app/Jobs/ProcessDataCaptureDataJob.php
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\DataCapture;
|
||||||
|
|
||||||
|
class ProcessDataCaptureDataJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $periods;
|
||||||
|
protected $filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [], string $filename = "ST.DATA.CAPTURE.csv")
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
$this->filename = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
$disk = Storage::disk('sftpStatement');
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for data capture processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the _parameter folder
|
||||||
|
if ($period === '_parameter') {
|
||||||
|
Log::info("Skipping _parameter folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the filepath based on the period folder name
|
||||||
|
$fileName = "$period.$this->filename";
|
||||||
|
$filePath = "$period/$fileName";
|
||||||
|
|
||||||
|
Log::info("Processing data capture file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary local copy of the file
|
||||||
|
$tempFilePath = storage_path("app/temp_{$this->filename}");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
|
||||||
|
if ($handle !== false) {
|
||||||
|
// CSV headers from the file
|
||||||
|
$csvHeaders = [
|
||||||
|
'id',
|
||||||
|
'account_number',
|
||||||
|
'sign',
|
||||||
|
'amount_lcy',
|
||||||
|
'transaction_code',
|
||||||
|
'their_reference',
|
||||||
|
'narrative',
|
||||||
|
'pl_category',
|
||||||
|
'customer_id',
|
||||||
|
'account_officer',
|
||||||
|
'product_category',
|
||||||
|
'value_date',
|
||||||
|
'currency',
|
||||||
|
'amount_fcy',
|
||||||
|
'exchange_rate',
|
||||||
|
'neg_ref_no',
|
||||||
|
'position_type',
|
||||||
|
'our_reference',
|
||||||
|
'reversal_marker',
|
||||||
|
'exposure_date',
|
||||||
|
'currency_market',
|
||||||
|
'iblc_country',
|
||||||
|
'last_version',
|
||||||
|
'otor_version',
|
||||||
|
'department_code',
|
||||||
|
'dealer_desk',
|
||||||
|
'bank_sort_cde',
|
||||||
|
'cheque_number',
|
||||||
|
'accounting_date',
|
||||||
|
'contingent_acct',
|
||||||
|
'cheq_type',
|
||||||
|
'tfs_reference',
|
||||||
|
'accounting_company',
|
||||||
|
'stmt_no',
|
||||||
|
'curr_no',
|
||||||
|
'inputter',
|
||||||
|
'authoriser',
|
||||||
|
'co_code',
|
||||||
|
'date_time'
|
||||||
|
];
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
|
||||||
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
// Skip header row if it exists
|
||||||
|
if ($rowCount === 1 && strtolower($row[0]) === 'id') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($csvHeaders) === count($row)) {
|
||||||
|
$data = array_combine($csvHeaders, $row);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Format dates if they exist
|
||||||
|
foreach (['value_date', 'exposure_date', 'accounting_date'] as $dateField) {
|
||||||
|
if (!empty($data[$dateField])) {
|
||||||
|
try {
|
||||||
|
$data[$dateField] = date('Y-m-d', strtotime($data[$dateField]));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// If date parsing fails, keep the original value
|
||||||
|
Log::warning("Failed to parse date for $dateField: {$data[$dateField]}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format datetime if it exists
|
||||||
|
if (!empty($data['date_time'])) {
|
||||||
|
try {
|
||||||
|
$data['date_time'] = date('Y-m-d H:i:s', strtotime($data['date_time']));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// If datetime parsing fails, keep the original value
|
||||||
|
Log::warning("Failed to parse datetime for date_time: {$data['date_time']}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($data['id'])) {
|
||||||
|
DataCapture::updateOrCreate(
|
||||||
|
['id' => $data['id']],
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
$processedCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$errorCount++;
|
||||||
|
Log::error("Error processing Data Capture at row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log::warning("Row $rowCount in $filePath has incorrect column count. Expected: " . count($csvHeaders) . ", Got: " . count($row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
Log::info("Completed processing $filePath. Processed $processedCount records with $errorCount errors.");
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
unlink($tempFilePath);
|
||||||
|
} else {
|
||||||
|
Log::error("Unable to open file: $filePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Data capture processing completed. Total processed: $processedCount, Total errors: $errorCount");
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error('Error in ProcessDataCaptureDataJob: ' . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
118
app/Jobs/ProcessFtTxnTypeConditionJob.php
Normal file
118
app/Jobs/ProcessFtTxnTypeConditionJob.php
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\FtTxnTypeCondition;
|
||||||
|
|
||||||
|
class ProcessFtTxnTypeConditionJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $periods;
|
||||||
|
protected $filename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [], string $filename = "ST.FT.TXN.TYPE.CONDITION.csv")
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
$this->filename = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
$disk = Storage::disk('sftpStatement');
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for transaction type condition data processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the _parameter folder
|
||||||
|
/*if ($period === '_parameter') {
|
||||||
|
Log::info("Skipping _parameter folder");
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Construct the filepath based on the period folder name
|
||||||
|
$filePath = "$period/{$this->filename}";
|
||||||
|
|
||||||
|
Log::info("Processing transaction type condition file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary local copy of the file
|
||||||
|
$tempFilePath = storage_path("app/temp_{$this->filename}");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
|
||||||
|
if ($handle !== false) {
|
||||||
|
$headers = ['id', 'date_time', 'transaction_type', 'short_descr', 'txn_code_cr', 'txn_code_dr'];
|
||||||
|
$rowCount = 0;
|
||||||
|
|
||||||
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
// Skip header row if it exists
|
||||||
|
if ($rowCount === 1 && strtolower($row[0]) === 'id') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($headers) === count($row)) {
|
||||||
|
$data = array_combine($headers, $row);
|
||||||
|
try {
|
||||||
|
if (!empty($data['id'])) {
|
||||||
|
FtTxnTypeCondition::updateOrCreate(
|
||||||
|
['id' => $data['id']],
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
$processedCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$errorCount++;
|
||||||
|
Log::error("Error processing Transaction Type Condition at row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log::warning("Row $rowCount in $filePath has incorrect column count. Expected: " . count($headers) . ", Got: " . count($row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
Log::info("Completed processing $filePath. Processed $processedCount records with $errorCount errors.");
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
unlink($tempFilePath);
|
||||||
|
} else {
|
||||||
|
Log::error("Unable to open file: $filePath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Transaction type condition data processing completed. Total processed: $processedCount, Total errors: $errorCount");
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error('Error in ProcessFtTxnTypeConditionJob: ' . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\StmtEntry;
|
||||||
use Modules\Webstatement\Models\TempStmtEntry;
|
use Modules\Webstatement\Models\TempStmtEntry;
|
||||||
|
|
||||||
class ProcessStmtEntryDataJob implements ShouldQueue
|
class ProcessStmtEntryDataJob implements ShouldQueue
|
||||||
@@ -67,18 +68,18 @@
|
|||||||
$handle = fopen($tempFilePath, "r");
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
|
||||||
if ($handle !== false) {
|
if ($handle !== false) {
|
||||||
$headers = (new TempStmtEntry())->getFillable();
|
$headers = (new StmtEntry())->getFillable();
|
||||||
$rowCount = 0;
|
$rowCount = 0;
|
||||||
|
|
||||||
while (($row = fgetcsv($handle, 0, "/")) !== false) {
|
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||||
$rowCount++;
|
$rowCount++;
|
||||||
|
|
||||||
if (count($headers) === count($row)) {
|
if (count($headers) === count($row)) {
|
||||||
$data = array_combine($headers, $row);
|
$data = array_combine($headers, $row);
|
||||||
try {
|
try {
|
||||||
if (isset($data['_id']) && $data['_id'] !== '_id') {
|
if ($data['stmt_entry_id'] !== 'stmt_entry_id') {
|
||||||
TempStmtEntry::updateOrCreate(
|
StmtEntry::updateOrCreate(
|
||||||
['_id' => $data['_id']],
|
['stmt_entry_id' => $data['stmt_entry_id']],
|
||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
$processedCount++;
|
$processedCount++;
|
||||||
|
|||||||
316
app/Jobs/ProcessTellerDataJob.php
Normal file
316
app/Jobs/ProcessTellerDataJob.php
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Webstatement\Models\Teller;
|
||||||
|
|
||||||
|
class ProcessTellerDataJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private const PARAMETER_FOLDER = '_parameter';
|
||||||
|
|
||||||
|
// Konstanta untuk nilai-nilai statis
|
||||||
|
private const FILE_EXTENSION = '.ST.TELLER.csv';
|
||||||
|
private const CSV_DELIMITER = '~';
|
||||||
|
private const DISK_NAME = 'sftpStatement';
|
||||||
|
private const HEADER_MAP = [
|
||||||
|
'id' => 'id_teller',
|
||||||
|
'account_1' => 'account_1',
|
||||||
|
'currency_1' => 'currency_1',
|
||||||
|
'amount_local_1' => 'amount_local_1',
|
||||||
|
'value_date_1' => 'value_date_1',
|
||||||
|
'account_2' => 'account_2',
|
||||||
|
'new_cust_bal' => 'new_cust_bal',
|
||||||
|
'term_type' => 'term_type',
|
||||||
|
'term_id' => 'term_id',
|
||||||
|
'trans_reff' => 'trans_reff',
|
||||||
|
'card_no' => 'card_no',
|
||||||
|
'recipt_no' => 'recipt_no',
|
||||||
|
'transaction_code' => 'transaction_code',
|
||||||
|
'date_time' => 'date_time',
|
||||||
|
'record_status' => 'record_status',
|
||||||
|
'amount_local_2' => 'amount_local_2',
|
||||||
|
'co_code' => 'co_code',
|
||||||
|
'narrative_1' => 'narrative_1',
|
||||||
|
'wic_flag' => 'wic_flag',
|
||||||
|
'wic_cust_type' => 'wic_cust_type',
|
||||||
|
'wic_full_name' => 'wic_full_name',
|
||||||
|
'wic_alias_name' => 'wic_alias_name',
|
||||||
|
'wic_acct_no' => 'wic_acct_no',
|
||||||
|
'wic_id_type' => 'wic_id_type',
|
||||||
|
'wic_id_no' => 'wic_id_no',
|
||||||
|
'wic_npwp' => 'wic_npwp',
|
||||||
|
'wic_nationality' => 'wic_nationality',
|
||||||
|
'wic_ind_birthpl' => 'wic_ind_birthpl',
|
||||||
|
'wic_ind_birthdt' => 'wic_ind_birthdt',
|
||||||
|
'wic_address_id' => 'wic_address_id',
|
||||||
|
'wic_address_cur' => 'wic_address_cur',
|
||||||
|
'wic_city' => 'wic_city',
|
||||||
|
'wic_province' => 'wic_province',
|
||||||
|
'wic_post_code' => 'wic_post_code',
|
||||||
|
'wic_phone' => 'wic_phone',
|
||||||
|
'wic_gender' => 'wic_gender',
|
||||||
|
'wic_marital_sts' => 'wic_marital_sts',
|
||||||
|
'wic_occptn' => 'wic_occptn',
|
||||||
|
'wic_occptn_dur' => 'wic_occptn_dur',
|
||||||
|
'wic_income_avg' => 'wic_income_avg',
|
||||||
|
'wic_cor_name' => 'wic_cor_name',
|
||||||
|
'wic_cor_address' => 'wic_cor_address',
|
||||||
|
'wic_cor_phone' => 'wic_cor_phone',
|
||||||
|
'wic_cor_lgl_typ' => 'wic_cor_lgl_typ',
|
||||||
|
'wic_cor_lic_no' => 'wic_cor_lic_no',
|
||||||
|
'wic_cor_birthpl' => 'wic_cor_birthpl',
|
||||||
|
'wic_cor_birthdt' => 'wic_cor_birthdt',
|
||||||
|
'wic_cor_rel' => 'wic_cor_rel',
|
||||||
|
'wic_party_rel' => 'wic_party_rel',
|
||||||
|
'wic_amount' => 'wic_amount',
|
||||||
|
'wic_amount_type' => 'wic_amount_type',
|
||||||
|
'wic_amtbnk_name' => 'wic_amtbnk_name',
|
||||||
|
'wic_amtbnk_cunm' => 'wic_amtbnk_cunm',
|
||||||
|
'wic_fund_source' => 'wic_fund_source',
|
||||||
|
'wic_fund_use' => 'wic_fund_use',
|
||||||
|
'dr_cr_marker' => 'dr_cr_marker',
|
||||||
|
'charge_code' => 'charge_code',
|
||||||
|
'chrg_amt_local' => 'chrg_amt_local',
|
||||||
|
'charge_category' => 'charge_category',
|
||||||
|
'charge_account' => 'charge_account',
|
||||||
|
'amount_fcy_1' => 'amount_fcy_1',
|
||||||
|
'rate_1' => 'rate_1',
|
||||||
|
'deal_rate' => 'deal_rate',
|
||||||
|
'l_wic_id' => 'l_wic_id',
|
||||||
|
'account_1_co_code' => 'account_1_co_code',
|
||||||
|
'account_2_co_code' => 'account_2_co_code',
|
||||||
|
'l_charge_amt' => 'l_charge_amt',
|
||||||
|
'bl_cust_no' => 'bl_cust_no',
|
||||||
|
'stmt_no' => 'stmt_no',
|
||||||
|
'bil_customer' => 'bil_customer',
|
||||||
|
'value_date_2' => 'value_date_2',
|
||||||
|
'cheq_type' => 'cheq_type',
|
||||||
|
'cheque_number' => 'cheque_number',
|
||||||
|
'inputter' => 'inputter',
|
||||||
|
'authoriser' => 'authoriser',
|
||||||
|
'bil_product' => 'bil_product',
|
||||||
|
'fx_document' => 'fx_document',
|
||||||
|
'fx_purpose' => 'fx_purpose',
|
||||||
|
'narrative_2' => 'narrative_2',
|
||||||
|
'customer_2' => 'customer_2',
|
||||||
|
'l_sms_1' => 'l_sms_1',
|
||||||
|
'l_phone_1' => 'l_phone_1',
|
||||||
|
'kyc_incom_rng' => 'kyc_incom_rng',
|
||||||
|
'wic_rt' => 'wic_rt',
|
||||||
|
'wic_rw' => 'wic_rw',
|
||||||
|
'ktp_kelurahan' => 'ktp_kelurahan',
|
||||||
|
'ktp_kecamatan' => 'ktp_kecamatan',
|
||||||
|
'ktp_provinsi' => 'ktp_provinsi',
|
||||||
|
'wic_jenis_kelam' => 'wic_jenis_kelam',
|
||||||
|
'kyc_sumber_dana' => 'kyc_sumber_dana',
|
||||||
|
'l_manual_risk' => 'l_manual_risk',
|
||||||
|
'l_slip_no' => 'l_slip_no',
|
||||||
|
'dest_bank_id' => 'dest_bank_id',
|
||||||
|
'dr_narrative' => 'dr_narrative',
|
||||||
|
'inter_type' => 'inter_type',
|
||||||
|
'l_va_number' => 'l_va_number',
|
||||||
|
'inter_bank_id' => 'inter_bank_id',
|
||||||
|
'term_narr' => 'term_narr',
|
||||||
|
'currency_2' => 'currency_2',
|
||||||
|
'amount_fcy_2' => 'amount_fcy_2',
|
||||||
|
'rate_2' => 'rate_2',
|
||||||
|
'customer_1' => 'customer_1',
|
||||||
|
'last_version' => 'last_version'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Pemetaan bidang header ke kolom model
|
||||||
|
protected array $periods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct(array $periods = [])
|
||||||
|
{
|
||||||
|
$this->periods = $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
set_time_limit(24 * 60 * 60);
|
||||||
|
|
||||||
|
if (empty($this->periods)) {
|
||||||
|
Log::warning('No periods provided for teller data processing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stats = $this->processPeriods();
|
||||||
|
|
||||||
|
Log::info("ProcessTellerDataJob completed. Total processed: {$stats['processed']}, Total errors: {$stats['errors']}");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("Error in ProcessTellerDataJob: " . $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process all periods and return statistics
|
||||||
|
*/
|
||||||
|
private function processPeriods()
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
$disk = Storage::disk(self::DISK_NAME);
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
foreach ($this->periods as $period) {
|
||||||
|
// Skip the parameter folder
|
||||||
|
if ($period === self::PARAMETER_FOLDER) {
|
||||||
|
Log::info("Skipping " . self::PARAMETER_FOLDER . " folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->processPeriodFile($disk, $period);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single period file
|
||||||
|
*/
|
||||||
|
private function processPeriodFile($disk, string $period)
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
$filename = $period . self::FILE_EXTENSION;
|
||||||
|
$filePath = "$period/$filename";
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
Log::info("Processing teller file: $filePath");
|
||||||
|
|
||||||
|
if (!$disk->exists($filePath)) {
|
||||||
|
Log::warning("File not found: $filePath");
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempFilePath = $this->createTempFile($disk, $filePath, $filename);
|
||||||
|
|
||||||
|
$result = $this->processCSVFile($tempFilePath, $filePath);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
|
||||||
|
// Clean up the temporary file
|
||||||
|
if (file_exists($tempFilePath)) {
|
||||||
|
unlink($tempFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Completed processing $filePath. Processed {$result['processed']} records with {$result['errors']} errors.");
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a temporary file for processing
|
||||||
|
*/
|
||||||
|
private function createTempFile($disk, string $filePath, string $filename)
|
||||||
|
: string
|
||||||
|
{
|
||||||
|
$tempFilePath = storage_path("app/temp_$filename");
|
||||||
|
file_put_contents($tempFilePath, $disk->get($filePath));
|
||||||
|
return $tempFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a CSV file and import data
|
||||||
|
*/
|
||||||
|
private function processCSVFile(string $tempFilePath, string $originalFilePath)
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
$processedCount = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
|
||||||
|
$handle = fopen($tempFilePath, "r");
|
||||||
|
if ($handle === false) {
|
||||||
|
Log::error("Unable to open file: $originalFilePath");
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the headers from the first row
|
||||||
|
$headerRow = fgetcsv($handle, 0, self::CSV_DELIMITER);
|
||||||
|
if (!$headerRow) {
|
||||||
|
fclose($handle);
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
while (($row = fgetcsv($handle, 0, self::CSV_DELIMITER)) !== false) {
|
||||||
|
$rowCount++;
|
||||||
|
|
||||||
|
if (count($headerRow) !== count($row)) {
|
||||||
|
Log::warning("Row $rowCount in $originalFilePath has incorrect column count. Expected: " . count($headerRow) . ", Got: " . count($row));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->processRow($headerRow, $row, $rowCount, $originalFilePath);
|
||||||
|
$processedCount += $result['processed'];
|
||||||
|
$errorCount += $result['errors'];
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'processed' => $processedCount,
|
||||||
|
'errors' => $errorCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a single row from the CSV file
|
||||||
|
*/
|
||||||
|
private function processRow(array $headerRow, array $row, int $rowCount, string $filePath)
|
||||||
|
: array
|
||||||
|
{
|
||||||
|
// Combine the header row with the data row
|
||||||
|
$rawData = array_combine($headerRow, $row);
|
||||||
|
|
||||||
|
// Map the raw data to our model fields
|
||||||
|
$data = [];
|
||||||
|
foreach (self::HEADER_MAP as $csvField => $modelField) {
|
||||||
|
$data[$modelField] = $rawData[$csvField] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip header row if it was included in the data
|
||||||
|
if ($data['id_teller'] === 'id') {
|
||||||
|
return ['processed' => 0, 'errors' => 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$teller = Teller::firstOrNew(['id_teller' => $data['id_teller']]);
|
||||||
|
$teller->fill($data);
|
||||||
|
$teller->save();
|
||||||
|
|
||||||
|
return ['processed' => 1, 'errors' => 0];
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error("Error processing Teller at row $rowCount in $filePath: " . $e->getMessage());
|
||||||
|
return ['processed' => 0, 'errors' => 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
app/Models/AtmTransaction.php
Normal file
45
app/Models/AtmTransaction.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class AtmTransaction extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'transaction_id',
|
||||||
|
'card_acc_id',
|
||||||
|
'pan_number',
|
||||||
|
'txn_type',
|
||||||
|
'merchant_id',
|
||||||
|
'txn_amount',
|
||||||
|
'booking_date',
|
||||||
|
'trans_ref',
|
||||||
|
'retrieval_ref_no',
|
||||||
|
'stmt_nos',
|
||||||
|
'debit_acct_no',
|
||||||
|
'credit_acct_no',
|
||||||
|
'chrg_amount',
|
||||||
|
'value_date',
|
||||||
|
'stan_no',
|
||||||
|
'trans_status',
|
||||||
|
'proc_code',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'booking_date' => 'datetime',
|
||||||
|
'value_date' => 'datetime',
|
||||||
|
'txn_amount' => 'decimal:2',
|
||||||
|
'chrg_amount' => 'decimal:2',
|
||||||
|
];
|
||||||
|
}
|
||||||
24
app/Models/Category.php
Normal file
24
app/Models/Category.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class Category extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_category',
|
||||||
|
'date_time',
|
||||||
|
'description',
|
||||||
|
'short_name',
|
||||||
|
'system_ind',
|
||||||
|
'record_status',
|
||||||
|
'co_code',
|
||||||
|
'curr_no',
|
||||||
|
'l_db_cr_ind',
|
||||||
|
'category_code'
|
||||||
|
];
|
||||||
|
}
|
||||||
74
app/Models/DataCapture.php
Normal file
74
app/Models/DataCapture.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class DataCapture extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Indicates if the model's ID is auto-incrementing.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $incrementing = false;
|
||||||
|
protected $table = 'data_captures';
|
||||||
|
/**
|
||||||
|
* The data type of the auto-incrementing ID.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id',
|
||||||
|
'account_number',
|
||||||
|
'sign',
|
||||||
|
'amount_lcy',
|
||||||
|
'transaction_code',
|
||||||
|
'their_reference',
|
||||||
|
'narrative',
|
||||||
|
'pl_category',
|
||||||
|
'customer_id',
|
||||||
|
'account_officer',
|
||||||
|
'product_category',
|
||||||
|
'value_date',
|
||||||
|
'currency',
|
||||||
|
'amount_fcy',
|
||||||
|
'exchange_rate',
|
||||||
|
'neg_ref_no',
|
||||||
|
'position_type',
|
||||||
|
'our_reference',
|
||||||
|
'reversal_marker',
|
||||||
|
'exposure_date',
|
||||||
|
'currency_market',
|
||||||
|
'iblc_country',
|
||||||
|
'last_version',
|
||||||
|
'otor_version',
|
||||||
|
'department_code',
|
||||||
|
'dealer_desk',
|
||||||
|
'bank_sort_cde',
|
||||||
|
'cheque_number',
|
||||||
|
'accounting_date',
|
||||||
|
'contingent_acct',
|
||||||
|
'cheq_type',
|
||||||
|
'tfs_reference',
|
||||||
|
'accounting_company',
|
||||||
|
'stmt_no',
|
||||||
|
'curr_no',
|
||||||
|
'inputter',
|
||||||
|
'authoriser',
|
||||||
|
'co_code',
|
||||||
|
'date_time'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'amount_lcy' => 'decimal:2',
|
||||||
|
'amount_fcy' => 'decimal:2',
|
||||||
|
'exchange_rate' => 'decimal:6',
|
||||||
|
'value_date' => 'date',
|
||||||
|
'exposure_date' => 'date',
|
||||||
|
'accounting_date' => 'date',
|
||||||
|
'date_time' => 'datetime'
|
||||||
|
];
|
||||||
|
}
|
||||||
61
app/Models/FtTxnTypeCondition.php
Normal file
61
app/Models/FtTxnTypeCondition.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
// use Modules\Webstatement\Database\Factories\FtTxnTypeConditionFactory;
|
||||||
|
|
||||||
|
class FtTxnTypeCondition extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the IDs are auto-incrementing.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public $incrementing = false;
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'ft_txn_type_condition';
|
||||||
|
/**
|
||||||
|
* The primary key for the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
/**
|
||||||
|
* The data type of the auto-incrementing ID.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'id',
|
||||||
|
'date_time',
|
||||||
|
'transaction_type',
|
||||||
|
'short_descr',
|
||||||
|
'txn_code_cr',
|
||||||
|
'txn_code_dr',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'date_time' => 'datetime',
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -56,4 +56,12 @@ class StmtEntry extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Account::class, 'account_number', 'account_number');
|
return $this->belongsTo(Account::class, 'account_number', 'account_number');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ft(){
|
||||||
|
return $this->belongsTo(TempFundsTransfer::class, 'trans_reference', 'ref_no');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function transaction(){
|
||||||
|
return $this->belongsTo(TempTransaction::class, 'transaction_code', 'transaction_code');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
117
app/Models/Teller.php
Normal file
117
app/Models/Teller.php
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Webstatement\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class Teller extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_teller',
|
||||||
|
'account_1',
|
||||||
|
'currency_1',
|
||||||
|
'amount_local_1',
|
||||||
|
'value_date_1',
|
||||||
|
'account_2',
|
||||||
|
'new_cust_bal',
|
||||||
|
'term_type',
|
||||||
|
'term_id',
|
||||||
|
'trans_reff',
|
||||||
|
'card_no',
|
||||||
|
'recipt_no',
|
||||||
|
'transaction_code',
|
||||||
|
'date_time',
|
||||||
|
'record_status',
|
||||||
|
'amount_local_2',
|
||||||
|
'co_code',
|
||||||
|
'narrative_1',
|
||||||
|
'wic_flag',
|
||||||
|
'wic_cust_type',
|
||||||
|
'wic_full_name',
|
||||||
|
'wic_alias_name',
|
||||||
|
'wic_acct_no',
|
||||||
|
'wic_id_type',
|
||||||
|
'wic_id_no',
|
||||||
|
'wic_npwp',
|
||||||
|
'wic_nationality',
|
||||||
|
'wic_ind_birthpl',
|
||||||
|
'wic_ind_birthdt',
|
||||||
|
'wic_address_id',
|
||||||
|
'wic_address_cur',
|
||||||
|
'wic_city',
|
||||||
|
'wic_province',
|
||||||
|
'wic_post_code',
|
||||||
|
'wic_phone',
|
||||||
|
'wic_gender',
|
||||||
|
'wic_marital_sts',
|
||||||
|
'wic_occptn',
|
||||||
|
'wic_occptn_dur',
|
||||||
|
'wic_income_avg',
|
||||||
|
'wic_cor_name',
|
||||||
|
'wic_cor_address',
|
||||||
|
'wic_cor_phone',
|
||||||
|
'wic_cor_lgl_typ',
|
||||||
|
'wic_cor_lic_no',
|
||||||
|
'wic_cor_birthpl',
|
||||||
|
'wic_cor_birthdt',
|
||||||
|
'wic_cor_rel',
|
||||||
|
'wic_party_rel',
|
||||||
|
'wic_amount',
|
||||||
|
'wic_amount_type',
|
||||||
|
'wic_amtbnk_name',
|
||||||
|
'wic_amtbnk_cunm',
|
||||||
|
'wic_fund_source',
|
||||||
|
'wic_fund_use',
|
||||||
|
'dr_cr_marker',
|
||||||
|
'charge_code',
|
||||||
|
'chrg_amt_local',
|
||||||
|
'charge_category',
|
||||||
|
'charge_account',
|
||||||
|
'amount_fcy_1',
|
||||||
|
'rate_1',
|
||||||
|
'deal_rate',
|
||||||
|
'l_wic_id',
|
||||||
|
'account_1_co_code',
|
||||||
|
'account_2_co_code',
|
||||||
|
'l_charge_amt',
|
||||||
|
'bl_cust_no',
|
||||||
|
'stmt_no',
|
||||||
|
'bil_customer',
|
||||||
|
'value_date_2',
|
||||||
|
'cheq_type',
|
||||||
|
'cheque_number',
|
||||||
|
'inputter',
|
||||||
|
'authoriser',
|
||||||
|
'bil_product',
|
||||||
|
'fx_document',
|
||||||
|
'fx_purpose',
|
||||||
|
'narrative_2',
|
||||||
|
'customer_2',
|
||||||
|
'l_sms_1',
|
||||||
|
'l_phone_1',
|
||||||
|
'kyc_incom_rng',
|
||||||
|
'wic_rt',
|
||||||
|
'wic_rw',
|
||||||
|
'ktp_kelurahan',
|
||||||
|
'ktp_kecamatan',
|
||||||
|
'ktp_provinsi',
|
||||||
|
'wic_jenis_kelam',
|
||||||
|
'kyc_sumber_dana',
|
||||||
|
'l_manual_risk',
|
||||||
|
'l_slip_no',
|
||||||
|
'dest_bank_id',
|
||||||
|
'dr_narrative',
|
||||||
|
'inter_type',
|
||||||
|
'l_va_number',
|
||||||
|
'inter_bank_id',
|
||||||
|
'term_narr',
|
||||||
|
'currency_2',
|
||||||
|
'amount_fcy_2',
|
||||||
|
'rate_2',
|
||||||
|
'customer_1',
|
||||||
|
'last_version'
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('ft_txn_type_condition', function (Blueprint $table) {
|
||||||
|
$table->string('id')->primary();
|
||||||
|
$table->dateTime('date_time')->nullable();
|
||||||
|
$table->string('transaction_type')->nullable();
|
||||||
|
$table->string('short_descr')->nullable();
|
||||||
|
$table->string('txn_code_cr')->nullable();
|
||||||
|
$table->string('txn_code_dr')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('ft_txn_type_condition');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('data_captures', function (Blueprint $table) {
|
||||||
|
$table->string('id')->primary();
|
||||||
|
$table->string('account_number')->nullable();
|
||||||
|
$table->string('sign')->nullable();
|
||||||
|
$table->decimal('amount_lcy', 20, 2)->nullable();
|
||||||
|
$table->string('transaction_code')->nullable();
|
||||||
|
$table->string('their_reference')->nullable();
|
||||||
|
$table->text('narrative')->nullable();
|
||||||
|
$table->string('pl_category')->nullable();
|
||||||
|
$table->string('customer_id')->nullable();
|
||||||
|
$table->string('account_officer')->nullable();
|
||||||
|
$table->string('product_category')->nullable();
|
||||||
|
$table->date('value_date')->nullable();
|
||||||
|
$table->string('currency')->nullable();
|
||||||
|
$table->decimal('amount_fcy', 20, 2)->nullable();
|
||||||
|
$table->decimal('exchange_rate', 20, 6)->nullable();
|
||||||
|
$table->string('neg_ref_no')->nullable();
|
||||||
|
$table->string('position_type')->nullable();
|
||||||
|
$table->string('our_reference')->nullable();
|
||||||
|
$table->string('reversal_marker')->nullable();
|
||||||
|
$table->date('exposure_date')->nullable();
|
||||||
|
$table->string('currency_market')->nullable();
|
||||||
|
$table->string('iblc_country')->nullable();
|
||||||
|
$table->string('last_version')->nullable();
|
||||||
|
$table->string('otor_version')->nullable();
|
||||||
|
$table->string('department_code')->nullable();
|
||||||
|
$table->string('dealer_desk')->nullable();
|
||||||
|
$table->string('bank_sort_cde')->nullable();
|
||||||
|
$table->string('cheque_number')->nullable();
|
||||||
|
$table->date('accounting_date')->nullable();
|
||||||
|
$table->string('contingent_acct')->nullable();
|
||||||
|
$table->string('cheq_type')->nullable();
|
||||||
|
$table->string('tfs_reference')->nullable();
|
||||||
|
$table->string('accounting_company')->nullable();
|
||||||
|
$table->string('stmt_no')->nullable();
|
||||||
|
$table->string('curr_no')->nullable();
|
||||||
|
$table->string('inputter')->nullable();
|
||||||
|
$table->string('authoriser')->nullable();
|
||||||
|
$table->string('co_code')->nullable();
|
||||||
|
$table->dateTime('date_time')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('data_captures');
|
||||||
|
}
|
||||||
|
};
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('categories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('id_category')->nullable();
|
||||||
|
$table->string('date_time')->nullable();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->string('short_name')->nullable();
|
||||||
|
$table->string('system_ind')->nullable();
|
||||||
|
$table->string('record_status')->nullable();
|
||||||
|
$table->string('co_code')->nullable();
|
||||||
|
$table->string('curr_no')->nullable();
|
||||||
|
$table->string('l_db_cr_ind')->nullable();
|
||||||
|
$table->string('category_code')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('categories');
|
||||||
|
}
|
||||||
|
};
|
||||||
130
database/migrations/2025_05_21_144332_create_tellers_table.php
Normal file
130
database/migrations/2025_05_21_144332_create_tellers_table.php
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('tellers', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('id_teller')->nullable();
|
||||||
|
$table->string('account_1')->nullable();
|
||||||
|
$table->string('currency_1')->nullable();
|
||||||
|
$table->string('amount_local_1')->nullable();
|
||||||
|
$table->string('value_date_1')->nullable();
|
||||||
|
$table->string('account_2')->nullable();
|
||||||
|
$table->string('new_cust_bal')->nullable();
|
||||||
|
$table->string('term_type')->nullable();
|
||||||
|
$table->string('term_id')->nullable();
|
||||||
|
$table->string('trans_reff')->nullable();
|
||||||
|
$table->string('card_no')->nullable();
|
||||||
|
$table->string('recipt_no')->nullable();
|
||||||
|
$table->string('transaction_code')->nullable();
|
||||||
|
$table->string('date_time')->nullable();
|
||||||
|
$table->string('record_status')->nullable();
|
||||||
|
$table->string('amount_local_2')->nullable();
|
||||||
|
$table->string('co_code')->nullable();
|
||||||
|
$table->text('narrative_1')->nullable();
|
||||||
|
$table->string('wic_flag')->nullable();
|
||||||
|
$table->string('wic_cust_type')->nullable();
|
||||||
|
$table->string('wic_full_name')->nullable();
|
||||||
|
$table->string('wic_alias_name')->nullable();
|
||||||
|
$table->string('wic_acct_no')->nullable();
|
||||||
|
$table->string('wic_id_type')->nullable();
|
||||||
|
$table->string('wic_id_no')->nullable();
|
||||||
|
$table->string('wic_npwp')->nullable();
|
||||||
|
$table->string('wic_nationality')->nullable();
|
||||||
|
$table->string('wic_ind_birthpl')->nullable();
|
||||||
|
$table->string('wic_ind_birthdt')->nullable();
|
||||||
|
$table->string('wic_address_id')->nullable();
|
||||||
|
$table->string('wic_address_cur')->nullable();
|
||||||
|
$table->string('wic_city')->nullable();
|
||||||
|
$table->string('wic_province')->nullable();
|
||||||
|
$table->string('wic_post_code')->nullable();
|
||||||
|
$table->string('wic_phone')->nullable();
|
||||||
|
$table->string('wic_gender')->nullable();
|
||||||
|
$table->string('wic_marital_sts')->nullable();
|
||||||
|
$table->string('wic_occptn')->nullable();
|
||||||
|
$table->string('wic_occptn_dur')->nullable();
|
||||||
|
$table->string('wic_income_avg')->nullable();
|
||||||
|
$table->string('wic_cor_name')->nullable();
|
||||||
|
$table->string('wic_cor_address')->nullable();
|
||||||
|
$table->string('wic_cor_phone')->nullable();
|
||||||
|
$table->string('wic_cor_lgl_typ')->nullable();
|
||||||
|
$table->string('wic_cor_lic_no')->nullable();
|
||||||
|
$table->string('wic_cor_birthpl')->nullable();
|
||||||
|
$table->string('wic_cor_birthdt')->nullable();
|
||||||
|
$table->string('wic_cor_rel')->nullable();
|
||||||
|
$table->string('wic_party_rel')->nullable();
|
||||||
|
$table->string('wic_amount')->nullable();
|
||||||
|
$table->string('wic_amount_type')->nullable();
|
||||||
|
$table->string('wic_amtbnk_name')->nullable();
|
||||||
|
$table->string('wic_amtbnk_cunm')->nullable();
|
||||||
|
$table->string('wic_fund_source')->nullable();
|
||||||
|
$table->string('wic_fund_use')->nullable();
|
||||||
|
$table->string('dr_cr_marker')->nullable();
|
||||||
|
$table->string('charge_code')->nullable();
|
||||||
|
$table->string('chrg_amt_local')->nullable();
|
||||||
|
$table->string('charge_category')->nullable();
|
||||||
|
$table->string('charge_account')->nullable();
|
||||||
|
$table->string('amount_fcy_1')->nullable();
|
||||||
|
$table->string('rate_1')->nullable();
|
||||||
|
$table->string('deal_rate')->nullable();
|
||||||
|
$table->string('l_wic_id')->nullable();
|
||||||
|
$table->string('account_1_co_code')->nullable();
|
||||||
|
$table->string('account_2_co_code')->nullable();
|
||||||
|
$table->string('l_charge_amt')->nullable();
|
||||||
|
$table->string('bl_cust_no')->nullable();
|
||||||
|
$table->string('stmt_no')->nullable();
|
||||||
|
$table->string('bil_customer')->nullable();
|
||||||
|
$table->string('value_date_2')->nullable();
|
||||||
|
$table->string('cheq_type')->nullable();
|
||||||
|
$table->string('cheque_number')->nullable();
|
||||||
|
$table->string('inputter')->nullable();
|
||||||
|
$table->string('authoriser')->nullable();
|
||||||
|
$table->string('bil_product')->nullable();
|
||||||
|
$table->string('fx_document')->nullable();
|
||||||
|
$table->string('fx_purpose')->nullable();
|
||||||
|
$table->text('narrative_2')->nullable();
|
||||||
|
$table->string('customer_2')->nullable();
|
||||||
|
$table->string('l_sms_1')->nullable();
|
||||||
|
$table->string('l_phone_1')->nullable();
|
||||||
|
$table->string('kyc_incom_rng')->nullable();
|
||||||
|
$table->string('wic_rt')->nullable();
|
||||||
|
$table->string('wic_rw')->nullable();
|
||||||
|
$table->string('ktp_kelurahan')->nullable();
|
||||||
|
$table->string('ktp_kecamatan')->nullable();
|
||||||
|
$table->string('ktp_provinsi')->nullable();
|
||||||
|
$table->string('wic_jenis_kelam')->nullable();
|
||||||
|
$table->string('kyc_sumber_dana')->nullable();
|
||||||
|
$table->string('l_manual_risk')->nullable();
|
||||||
|
$table->string('l_slip_no')->nullable();
|
||||||
|
$table->string('dest_bank_id')->nullable();
|
||||||
|
$table->text('dr_narrative')->nullable();
|
||||||
|
$table->string('inter_type')->nullable();
|
||||||
|
$table->string('l_va_number')->nullable();
|
||||||
|
$table->string('inter_bank_id')->nullable();
|
||||||
|
$table->text('term_narr')->nullable();
|
||||||
|
$table->string('currency_2')->nullable();
|
||||||
|
$table->string('amount_fcy_2')->nullable();
|
||||||
|
$table->string('rate_2')->nullable();
|
||||||
|
$table->string('customer_1')->nullable();
|
||||||
|
$table->string('last_version')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('tellers');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
Schema::create('atm_transactions', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('transaction_id')->nullable()->index();
|
||||||
|
$table->string('card_acc_id')->nullable();
|
||||||
|
$table->string('pan_number')->nullable();
|
||||||
|
$table->string('txn_type')->nullable();
|
||||||
|
$table->string('merchant_id')->nullable();
|
||||||
|
$table->string('txn_amount')->nullable();
|
||||||
|
$table->string('booking_date')->nullable();
|
||||||
|
$table->string('trans_ref')->nullable();
|
||||||
|
$table->string('retrieval_ref_no')->nullable();
|
||||||
|
$table->string('stmt_nos')->nullable();
|
||||||
|
$table->string('debit_acct_no')->nullable();
|
||||||
|
$table->string('credit_acct_no')->nullable();
|
||||||
|
$table->string('chrg_amount')->nullable();
|
||||||
|
$table->string('value_date')->nullable();
|
||||||
|
$table->string('stan_no')->nullable();
|
||||||
|
$table->string('trans_status')->nullable();
|
||||||
|
$table->string('proc_code')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
: void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('atm_transactions');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -93,3 +93,4 @@ Route::get('migrasi', [MigrasiController::class, 'index'])->name('migrasi.index'
|
|||||||
Route::get('biaya-kartu', [SyncLogsController::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']);
|
Route::get('/stmt-entries/{accountNumber}', [MigrasiController::class, 'getStmtEntryByAccount']);
|
||||||
|
Route::get('/', [WebstatementController::class, 'index'])->name('webstatement.index');
|
||||||
|
|||||||
Reference in New Issue
Block a user