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 Modules\Webstatement\Jobs\ProcessAccountDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessArrangementDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessAtmTransactionJob;
|
||||
use Modules\Webstatement\Jobs\ProcessBillDetailDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessCategoryDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessCompanyDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessCustomerDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessDataCaptureDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessFtTxnTypeConditionJob;
|
||||
use Modules\Webstatement\Jobs\ProcessFundsTransferDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessStmtEntryDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessStmtNarrFormatDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessStmtNarrParamDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessTellerDataJob;
|
||||
use Modules\Webstatement\Jobs\ProcessTransactionDataJob;
|
||||
|
||||
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){
|
||||
try {
|
||||
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) {
|
||||
return response()->json(['error' => $e->getMessage()], 500);
|
||||
}
|
||||
@@ -119,10 +180,10 @@ class MigrasiController extends Controller
|
||||
// Get all directories (periods) in the SFTP disk
|
||||
$allDirectories = $disk->directories();
|
||||
|
||||
$this->processTransactionData(['_parameter']);
|
||||
$this->processStmtNarrParamData(['_parameter']);
|
||||
$this->processStmtNarrFormatData(['_parameter']);
|
||||
|
||||
//$this->processTransactionData(['_parameter']);
|
||||
//$this->processStmtNarrParamData(['_parameter']);
|
||||
//$this->processStmtNarrFormatData(['_parameter']);
|
||||
//$this->ProcessFtTxnTypeConditioData(['_parameter']);
|
||||
|
||||
// Filter out the _parameter folder
|
||||
$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);
|
||||
}
|
||||
|
||||
$this->processCustomerData(['20250519']);
|
||||
$this->processAccountData(['20250519']);
|
||||
$this->processArrangementData($periods);
|
||||
$this->processBillDetailData($periods);
|
||||
$this->processFundsTransferData($periods);
|
||||
$this->processStmtEntryData($periods);
|
||||
$this->ProcessCategoryData($periods);
|
||||
|
||||
//$this->processCustomerData($periods);
|
||||
//$this->processAccountData($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']);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ namespace Modules\Webstatement\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
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
|
||||
{
|
||||
@@ -12,7 +16,164 @@ class WebstatementController extends Controller
|
||||
*/
|
||||
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();
|
||||
$rowCount = 0;
|
||||
|
||||
while (($row = fgetcsv($handle, 0, ";")) !== false) {
|
||||
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||
$rowCount++;
|
||||
|
||||
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\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Webstatement\Models\StmtEntry;
|
||||
use Modules\Webstatement\Models\TempStmtEntry;
|
||||
|
||||
class ProcessStmtEntryDataJob implements ShouldQueue
|
||||
@@ -67,18 +68,18 @@
|
||||
$handle = fopen($tempFilePath, "r");
|
||||
|
||||
if ($handle !== false) {
|
||||
$headers = (new TempStmtEntry())->getFillable();
|
||||
$headers = (new StmtEntry())->getFillable();
|
||||
$rowCount = 0;
|
||||
|
||||
while (($row = fgetcsv($handle, 0, "/")) !== false) {
|
||||
while (($row = fgetcsv($handle, 0, "~")) !== false) {
|
||||
$rowCount++;
|
||||
|
||||
if (count($headers) === count($row)) {
|
||||
$data = array_combine($headers, $row);
|
||||
try {
|
||||
if (isset($data['_id']) && $data['_id'] !== '_id') {
|
||||
TempStmtEntry::updateOrCreate(
|
||||
['_id' => $data['_id']],
|
||||
if ($data['stmt_entry_id'] !== 'stmt_entry_id') {
|
||||
StmtEntry::updateOrCreate(
|
||||
['stmt_entry_id' => $data['stmt_entry_id']],
|
||||
$data
|
||||
);
|
||||
$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');
|
||||
}
|
||||
|
||||
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('/stmt-entries/{accountNumber}', [MigrasiController::class, 'getStmtEntryByAccount']);
|
||||
Route::get('/', [WebstatementController::class, 'index'])->name('webstatement.index');
|
||||
|
||||
Reference in New Issue
Block a user