mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 04:23:55 +00:00
update on ambank csv file format
This commit is contained in:
@@ -24,10 +24,11 @@ class ImportAmbankStatementLogic extends AbstractControllerLogic
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification():array {
|
||||
protected function notification(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'Import Ambank Statement Transactions Details',
|
||||
'message' => 'You have successfully updated the Ambank Statement Transactions Details'
|
||||
'message' => 'You have successfully imported the Ambank Statement Transactions Details'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -37,178 +38,147 @@ class ImportAmbankStatementLogic extends AbstractControllerLogic
|
||||
* @return JsonResponse
|
||||
* @throws MalformedRequestException
|
||||
*/
|
||||
public function logic(Request $request) : JsonResponse
|
||||
public function logic(Request $request): JsonResponse
|
||||
{
|
||||
$requiredHeaders = ['Date', 'Time', 'Description', 'Recipient Reference', 'Other Payment Details', 'Transfer Type', 'Inward Amount', 'Outward Amount', 'Balance'];
|
||||
|
||||
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
|
||||
|
||||
foreach ($object->getFiles() as $file){
|
||||
foreach ($object->getFiles() as $file) {
|
||||
$collection = Excel::toCollection(null, json_decode($file)->file_info->original->file, null, null, true);
|
||||
|
||||
$statementDetailRows = $collection->first()->slice(0,13);
|
||||
// check whether the csv is format we expect for
|
||||
foreach ($collection as $sheet_no => $sheet) {
|
||||
$header_mapping_result = [];
|
||||
foreach ($sheet as $row_no => $row) {
|
||||
if ($row[0] !== $requiredHeaders[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$dateInfoKey = $this->findInfoIndexFromExcelCollection($statementDetailRows, "STATEMENT DATE");
|
||||
$statementDateRange = trim(explode(':', $this->extractInfoFromExcelCollection($statementDetailRows[$dateInfoKey])[0])[1]);
|
||||
$dateFrom = trim(explode('-', $statementDateRange)[0]);
|
||||
$dateTo = trim(explode('-', $statementDateRange)[1]);
|
||||
$dateFrom = carbon::createFromFormat('d/m/Y', $dateFrom);
|
||||
$dateTo = carbon::createFromFormat('d/m/Y', $dateTo);
|
||||
$dateTo = carbon::parse($dateTo);
|
||||
$totalDebitKey = $this->findInfoIndexFromExcelCollection($statementDetailRows, "TOTAL DEBIT");
|
||||
$totalDebit = $this->extractInfoFromExcelCollection($statementDetailRows[$totalDebitKey])[1];
|
||||
$totalCreditKey = $this->findInfoIndexFromExcelCollection($statementDetailRows, "TOTAL CREDIT");
|
||||
$totalCredit = $this->extractInfoFromExcelCollection($statementDetailRows[$totalCreditKey])[1];
|
||||
$totalTransactions = $totalDebit + $totalCredit;
|
||||
$beginBalanceKey = $this->findInfoIndexFromExcelCollection($statementDetailRows, "OPENING BALANCE");
|
||||
$beginBalance = ((float) str_replace(',', '', $this->extractInfoFromExcelCollection($statementDetailRows[$beginBalanceKey])[1]));
|
||||
$endBalanceKey = $this->findInfoIndexFromExcelCollection($statementDetailRows, "CLOSING BALANCE");
|
||||
$endBalance = ((float) str_replace(',', '', $this->extractInfoFromExcelCollection($statementDetailRows[$endBalanceKey])[1]));
|
||||
foreach ($requiredHeaders as $col_no => $header) {
|
||||
if ($row[$col_no] !== $header) {
|
||||
$header_mapping_result[$col_no] = false;
|
||||
} else {
|
||||
$header_mapping_result[$col_no] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($header_mapping_result) === 9) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($header_mapping_result) === 0 || in_array(false, $header_mapping_result)) {
|
||||
throw new MalformedRequestException("Sheet {$sheet_no} format is not correct");
|
||||
}
|
||||
}
|
||||
|
||||
$data_start_from = $sheet->search(function ($row, $key) {
|
||||
return $row[0] === 'Date';
|
||||
}) + 1;
|
||||
$data_end_at = $sheet->keys()->last();
|
||||
$descending = true;
|
||||
|
||||
for ($i = $data_end_at; $i > 0; $i--) {
|
||||
$parse_date = Carbon::createFromFormat('d/m/Y', $sheet[$i][0]);
|
||||
if ($parse_date && $parse_date->format('d/m/Y') === $sheet[$i][0]) {
|
||||
$data_end_at = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Carbon::createFromFormat('d/m/Y', $sheet[$data_start_from][0]) > Carbon::createFromFormat('d/m/Y', $sheet[$data_end_at][0])) {
|
||||
$descending = true;
|
||||
} else {
|
||||
$descending = false;
|
||||
}
|
||||
|
||||
$date_from = Carbon::createFromFormat('d/m/Y', $sheet[$descending ? $data_end_at : $data_start_from][0])->format('Y-m-d');
|
||||
$date_to = Carbon::createFromFormat('d/m/Y', $sheet[$descending ? $data_start_from : $data_end_at][0])->format('Y-m-d');
|
||||
$total_rows = abs($data_end_at - $data_start_from) + 1;
|
||||
$begin_balance = floatval($sheet[$descending ? $data_end_at : $data_start_from][8]);
|
||||
$end_balance = floatval($sheet[$descending ? $data_start_from : $data_end_at][8]);
|
||||
$total_debit = 0;
|
||||
$total_credit = 0;
|
||||
|
||||
$account = StatementAccount::where('number', 8881040198515)->first();
|
||||
|
||||
if (!$account) {
|
||||
throw new Exception("Statement Account for CIEF LITE not found.");
|
||||
throw new Exception("Statement Account for AMBANK not found.");
|
||||
}
|
||||
|
||||
$statement = AccountStatement::whereDate('date_from', $dateFrom)
|
||||
->whereDate('date_to', $dateTo)
|
||||
->where('total_amount', $totalTransactions)
|
||||
->where('begin_balance', $beginBalance)
|
||||
->where('end_balance', $endBalance)
|
||||
$statement = AccountStatement::whereDate('date_from', $date_from)
|
||||
->whereDate('date_to', $date_to)
|
||||
->where('total_rows', $total_rows)
|
||||
->where('begin_balance', $begin_balance)
|
||||
->where('end_balance', $end_balance)
|
||||
->first();
|
||||
|
||||
|
||||
if(!$statement){
|
||||
if (!$statement) {
|
||||
$statement = new AccountStatement([
|
||||
'date_from' => $dateFrom,
|
||||
'date_to' => $dateTo,
|
||||
'total_amount' => $totalTransactions,
|
||||
'begin_balance' => $beginBalance,
|
||||
'end_balance' => $endBalance,
|
||||
'statement_account_id' => $account->id,
|
||||
'date_from' => $date_from,
|
||||
'date_to' => $date_to,
|
||||
'total_rows' => $total_rows,
|
||||
'begin_balance' => $begin_balance,
|
||||
'end_balance' => $end_balance,
|
||||
]);
|
||||
$statement->save();
|
||||
}
|
||||
|
||||
$account->statements()->save($statement);
|
||||
|
||||
$collection->map(function ($sheet, $key) use ($statement) {
|
||||
if ($key === 0) {
|
||||
$headerColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11), "DATE");
|
||||
$dateColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11)[$headerColumnKey], "DATE");
|
||||
$descriptionColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11)[$headerColumnKey], "TRANSACTION");
|
||||
$debitColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11)[$headerColumnKey], "DEBIT");
|
||||
$creditColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11)[$headerColumnKey], "CREDIT");
|
||||
$balanceColumnKey = $this->findInfoIndexFromExcelCollection($sheet->slice(11)[$headerColumnKey], "BALANCE");
|
||||
} else {
|
||||
if (strpos($sheet->first()->first(), "DATE") === false) {
|
||||
return;
|
||||
}
|
||||
$headerColumnKey = $this->findInfoIndexFromExcelCollection($sheet, "DATE");
|
||||
$dateColumnKey = $this->findInfoIndexFromExcelCollection($sheet[$headerColumnKey], "DATE");
|
||||
$descriptionColumnKey = $this->findInfoIndexFromExcelCollection($sheet[$headerColumnKey], "TRANSACTION");
|
||||
$debitColumnKey = $this->findInfoIndexFromExcelCollection($sheet[$headerColumnKey], "DEBIT");
|
||||
$creditColumnKey = $this->findInfoIndexFromExcelCollection($sheet[$headerColumnKey], "CREDIT");
|
||||
$balanceColumnKey = $this->findInfoIndexFromExcelCollection($sheet[$headerColumnKey], "BALANCE");
|
||||
}
|
||||
|
||||
$sheet->slice($headerColumnKey + 1)->map(function ($row, $index) use (
|
||||
$statement,
|
||||
$sheet,
|
||||
$dateColumnKey,
|
||||
$descriptionColumnKey,
|
||||
$debitColumnKey,
|
||||
$creditColumnKey,
|
||||
$balanceColumnKey,
|
||||
$key)
|
||||
{
|
||||
// if date or balance is null or empty, skip the row
|
||||
if (!$row[$dateColumnKey] || !$row[$balanceColumnKey]) {
|
||||
return;
|
||||
foreach ($collection as $sheet_no => $sheet) {
|
||||
foreach ($sheet as $row_no => $row) {
|
||||
if ($row_no < $data_start_from || $row_no > $data_end_at) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$postingDate = carbon::createFromFormat('dM', trim($row[$dateColumnKey]));
|
||||
$posting_date = Carbon::createFromFormat('d/m/Y', $row[0])->format('Y-m-d');
|
||||
$posting_time = Carbon::parse($row[1])->format('H:i:s');
|
||||
$transaction_description = trim($row[2]);
|
||||
$transaction_description_2 = trim($row[3]);
|
||||
$transaction_description_3 = trim($row[4]);
|
||||
$transaction_description_4 = trim($row[5]);
|
||||
$inward_amount = floatval(trim($row[6]));
|
||||
$outward_amount = floatval(trim($row[7]));
|
||||
$amount = $inward_amount == 0 ? $outward_amount : $inward_amount;
|
||||
|
||||
$description = trim($row[$descriptionColumnKey]);
|
||||
|
||||
$nextRow = $sheet[$index + 1];
|
||||
|
||||
if (!$nextRow[$dateColumnKey] && $nextRow[$descriptionColumnKey]) {
|
||||
$nextRowInfoArr = $this->extractInfoFromExcelCollection($nextRow);
|
||||
foreach ($nextRowInfoArr as $col) {
|
||||
if ($col) {
|
||||
$description .= ' '. $col;
|
||||
}
|
||||
}
|
||||
if ($inward_amount == 0) {
|
||||
$total_debit += 1;
|
||||
} else {
|
||||
$total_credit += 1;
|
||||
}
|
||||
|
||||
$descriptionArr = explode(',', $description);
|
||||
$balance = floatval(trim($row[8]));
|
||||
|
||||
$transactionDescription = array_key_exists(0, $descriptionArr) ? trim($descriptionArr[0]) : "";
|
||||
$description2 = array_key_exists(1, $descriptionArr) ? trim($descriptionArr[1]) : "";
|
||||
$description3 = array_key_exists(2, $descriptionArr) ? trim($descriptionArr[2]) : "";
|
||||
$description4 = array_key_exists(3, $descriptionArr) ? trim($descriptionArr[3]) : "";
|
||||
$description5 = array_key_exists(4, $descriptionArr) ? trim($descriptionArr[4]) : "";
|
||||
|
||||
if (count($descriptionArr) > 5) {
|
||||
for ($i = 5; $i < count($descriptionArr); $i++) {
|
||||
$description5 = array_key_exists($i, $descriptionArr) ? $description5 . " " . trim($descriptionArr[$i]) : $description5;
|
||||
}
|
||||
}
|
||||
|
||||
$amount = $row[$creditColumnKey] ? ((float) str_replace(',', '', trim($row[$creditColumnKey]))) : (-((float) str_replace(',', '', $row[$debitColumnKey])));
|
||||
$endBalance = ((float) str_replace(',', '', $row[$balanceColumnKey]));
|
||||
$transaction = new StatementTransaction([
|
||||
'posting_date' => $postingDate,
|
||||
'transaction_description' => $transactionDescription,
|
||||
'transaction_description_2' => $description2,
|
||||
'transaction_description_3' => $description3,
|
||||
'transaction_description_4' => $description4,
|
||||
'transaction_description_5' => $description5,
|
||||
'amount' => $amount,
|
||||
'end_balance' => $endBalance,
|
||||
]);
|
||||
|
||||
// Check if the transaction already exists for this statement
|
||||
$existingTransaction = StatementTransaction::whereDate('posting_date', $postingDate)
|
||||
// Check if the transaction already exists for any statement
|
||||
$existingTransaction = StatementTransaction::where('posting_date', ($posting_date . ' ' . $posting_time))
|
||||
->where('amount', $amount)
|
||||
->where('transaction_description', $transactionDescription)
|
||||
->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?",[$endBalance])
|
||||
->where('transaction_description', $transaction_description)
|
||||
->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?", [$balance])
|
||||
->first();
|
||||
|
||||
if (!$existingTransaction) {
|
||||
$statement->transactions()->save($transaction);
|
||||
}
|
||||
|
||||
return $transaction;
|
||||
});
|
||||
});
|
||||
if (!$existingTransaction) {
|
||||
$transaction = new StatementTransaction([
|
||||
'account_statement_id' => $statement->id,
|
||||
'posting_date' => $posting_date . ' ' . $posting_time,
|
||||
'transaction_description' => $transaction_description,
|
||||
'transaction_description_2' => $transaction_description_2,
|
||||
'transaction_description_3' => $transaction_description_3,
|
||||
'transaction_description_4' => $transaction_description_4,
|
||||
'amount' => $amount,
|
||||
'end_balance' => $balance,
|
||||
]);
|
||||
|
||||
$transaction->save();
|
||||
}
|
||||
}
|
||||
|
||||
$statement->total_amount = $total_debit ?: $total_credit;
|
||||
$statement->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->response([]);
|
||||
}
|
||||
|
||||
private function findInfoIndexFromExcelCollection($collection, $keyword)
|
||||
{
|
||||
foreach ($collection as $key => $row) {
|
||||
if ($row instanceof Collection) {
|
||||
$infoArr = $this->extractInfoFromExcelCollection($row);
|
||||
foreach ($infoArr as $info) {
|
||||
if (str_contains(strtolower($info), strtolower($keyword))) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (str_contains(strtolower($row), strtolower($keyword))) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// return an array with information of the row start from 0 index
|
||||
private function extractInfoFromExcelCollection($collection)
|
||||
{
|
||||
return array_values(array_filter($collection->toArray()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,10 @@ export default {
|
||||
} else if (this.statementType.includes('LITE')) {
|
||||
this.submit(this.route('api.accounting.statement.import.cief.lite'), 'post', this.section, true, false)
|
||||
}
|
||||
}
|
||||
},
|
||||
errorHandler(error){
|
||||
this.formHandler(error.message);
|
||||
},
|
||||
},
|
||||
mixins: [formHandler]
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
url: '#',
|
||||
autoQueue: false,
|
||||
processQueue: false,
|
||||
acceptedFiles: 'image/*, application/*',
|
||||
acceptedFiles: 'image/*, application/*, text/csv',
|
||||
uploadMultiple: true,
|
||||
clickable: '.select-btn',
|
||||
previewTemplate: '<div class="row m-l-0 m-r-0 align-items-center m-t-5 m-b-5 bg-master-lightest text-left p-t-10 p-b-10 "> <div class="col-auto p-r-0"> <img data-dz-thumbnail style="width: 35px; height: 35px;" /> </div> <div class="col"> <div class="row m-b-5"> <div class="col"> <div class="dz-filename fs-8 bold"><span data-dz-name></span></div> </div> </div> <div class="row"> <div class="col"> <div class="dz-size muted light fs-10" data-dz-size></div> </div> </div> </div> <div class="col-auto"><i class="fs-16 fa fa-times-circle pointer hint-text" data-dz-remove></i></div> </div>'
|
||||
|
||||
Reference in New Issue
Block a user