-Merge branch 'master' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into import-ambank-cief-lite-statement

-update import ambank statement logic
This commit is contained in:
JiaSheng
2023-12-08 19:53:09 +08:00
5 changed files with 222 additions and 157 deletions
@@ -14,6 +14,7 @@ use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
@@ -44,19 +45,24 @@ class ImportAmbankStatementLogic extends AbstractControllerLogic
foreach ($object->getFiles() as $file){
$collection = Excel::toCollection(null, json_decode($file)->file_info->original->file, null, null, true);
$statementDetails = $collection->first();
$statementDetailRows = $collection->first()->slice(0,13);
$statementDateRange = trim(explode(':', $statementDetails[3][0])[1]);
$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);
$totalDebit = $statementDetails[7][7];
$totalCredit = $statementDetails[8][7];
$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;
$beginBalance = ((float) str_replace(',', '', $statementDetails[6][10]));
$endBalance = ((float) str_replace(',', '', $statementDetails[9][10]));
$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]));
$account = StatementAccount::where('number', 8881040198515)->first();
@@ -86,140 +92,123 @@ class ImportAmbankStatementLogic extends AbstractControllerLogic
$collection->map(function ($sheet, $key) use ($statement) {
if ($key === 0) {
$sheet->slice(13)->map(function ($row, $index) use ($statement, $sheet, $key) {
if (!$row[0] || !$row[11]) {
return;
}
$postingDate = carbon::createFromFormat('dM', trim($row[0]));
$description = trim($row[1]);
$nextRow = $sheet->slice(13)[$index + 1];
if (!$nextRow[0] && $nextRow[1]) {
foreach ($nextRow as $col) {
if ($col) {
$description .= ' '. $col;
}
}
}
$descriptionArr = explode(',', $description);
$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 = $description5 . array_key_exists($i, $descriptionArr) ? trim($descriptionArr[$i]) : "";
}
}
$amount = $row[9] ? ((float) str_replace(',', '', trim($row[9]))) : (-((float) str_replace(',', '', $row[8])));
$endBalance = ((float) str_replace(',', '', $row[11]));
$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)
->where('amount', $amount)
->where('transaction_description', $transactionDescription)
->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?",[$endBalance])
->first();
if (!$existingTransaction) {
$statement->transactions()->save($transaction);
}
return $transaction;
});
$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;
}
$extraColumn = 0;
if (count($sheet->first()) > 7 && $sheet->first()[7]) {
$extraColumn = 1;
$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;
}
$sheet->slice(1)->map(function ($row, $index) use ($statement, $sheet, $extraColumn, $key) {
if (!$row[0] || !$row[6 + $extraColumn]) {
return;
}
$postingDate = carbon::createFromFormat('dM', trim($row[$dateColumnKey]));
$postingDate = carbon::createFromFormat('dM', trim($row[0]));
$description = trim($row[$descriptionColumnKey]);
$description = trim($row[1]);
$nextRow = $sheet[$index + 1];
$nextRow = $sheet->slice(1)[$index + 1];
if (!$nextRow[0] && $nextRow[1]) {
foreach ($nextRow as $col) {
if ($col) {
$description .= ' '. $col;
}
if (!$nextRow[$dateColumnKey] && $nextRow[$descriptionColumnKey]) {
$nextRowInfoArr = $this->extractInfoFromExcelCollection($nextRow);
foreach ($nextRowInfoArr as $col) {
if ($col) {
$description .= ' '. $col;
}
}
}
$descriptionArr = explode(',', $description);
$descriptionArr = explode(',', $description);
$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 = $description5 . array_key_exists($i, $descriptionArr) ? trim($descriptionArr[$i]) : "";
}
$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[5 + $extraColumn] ? ((float) str_replace(',', '', trim($row[5 + $extraColumn]))) : (-((float) str_replace(',', '', $row[4 + $extraColumn])));
$endBalance = ((float) str_replace(',', '', $row[6 + $extraColumn]));
$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,
]);
$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)
->where('amount', $amount)
->where('transaction_description', $transactionDescription)
->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?",[$endBalance])
->first();
// Check if the transaction already exists for this statement
$existingTransaction = StatementTransaction::whereDate('posting_date', $postingDate)
->where('amount', $amount)
->where('transaction_description', $transactionDescription)
->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?",[$endBalance])
->first();
if (!$existingTransaction) {
$statement->transactions()->save($transaction);
}
if (!$existingTransaction) {
$statement->transactions()->save($transaction);
}
return $transaction;
});
}
return $transaction;
});
});
}
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()));
}
}
@@ -39,7 +39,8 @@ class ExportsImportedInvoiceMappeds implements FromQuery, WithHeadings, WithHead
'Net Total',
'Cancelled',
'Mapped Status',
'Mapped Reference No'
'Mapped Reference No',
'MapPayment Received Date'
];
}
@@ -72,6 +73,7 @@ class ExportsImportedInvoiceMappeds implements FromQuery, WithHeadings, WithHead
Arr::get($data,'cancelled'),
Arr::get($data,'mapped_status'),
Arr::get($data,'mapped_result_reference'),
Arr::get($data,'payment_received_date'),
];
}
@@ -15,8 +15,11 @@ use Illuminate\Support\Facades\Log;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Models\StatementTransaction;
use App\Models\Company;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Events\AfterSheet;
class ExportsReceiptTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
class ExportsReceiptTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, WithEvents, WithCustomStartCell
{
use Exportable;
@@ -28,37 +31,101 @@ class ExportsReceiptTransactions implements FromQuery, WithHeadings, WithHeading
$this->request = $request;
}
public function startCell(): string
{
return 'A2';
}
public function registerEvents(): array {
return [
AfterSheet::class => function(AfterSheet $event) {
$sheet = $event->sheet;
$sheet->mergeCells('A1:A1');
$sheet->setCellValue('A1', '"');
$sheet->mergeCells('M1:Y1');
$sheet->setCellValue('M1', "Payment Detail Column");
$sheet->mergeCells('Z1:AB1');
$sheet->setCellValue('Z1', "Knock Off Detail");
$styleArray = [
'alignment' => [
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
],
];
$cellRange = 'A1:AB1';
$event->sheet->getDelegate()->getStyle($cellRange)->applyFromArray($styleArray);
},
];
}
public function headings(): array
{
$header = [
'DocNo',
'DocDate',
'DebtorCode',
'Description',
'DocNo2',
'ProjNo',
'DeptNo',
'CurrencyCode',
'ToHomeRate',
'ToDebtorRate',
'Note',
'PaymentMethod',
'ChequeNo',
'PaymentAmt',
'BankCharge',
'ToBankRate',
'BankChargeTaxType',
'BankChargeTaxRefNo',
'BankChargeProjNo',
'BankChargeDeptNo',
'PaymentBy',
'FloatDay',
'IsRCHQ',
'RCHQDate',
'KnockOffDocType',
'KnockOffDocNo',
'KnockOffAmt',
'',
[
' ',
'(20 chars)',
'(Date: dd/MM/yyyy)',
'(12 chars)',
'(40 chars)',
'(25 chars)',
'(10 chars)',
'(10 chars)',
'(5 chars)',
'(Number, use System Currency Rate Decimal)',
'(Number, use System Currency Rate Decimal)',
'(Rich Text)',
'(20 chars)',
'(20 chars)',
'(Number, use System Currency Decimal)',
'(Number, use System Currency Decimal)',
'(Number, use System Currency Rate Decimal)',
'(14 chars)',
'(30 chars)',
'(10 chars)',
'(10 chars)',
'(20 chars)',
'(Integer)',
'(Boolean. Indicate T for stock control or F for non stock control)',
'(Returned Cheque Date: dd/MM/yyyy)',
'(2 chars, RI for Invoice, RD for D/N)',
'',
'(Number, use System Currency Decimal)',
],
[
'DocNo',
'DocDate',
'DebtorCode',
'Description',
'DocNo2',
'ProjNo',
'DeptNo',
'CurrencyCode',
'ToHomeRate',
'ToDebtorRate',
'Note',
'PaymentMethod',
'ChequeNo',
'PaymentAmt',
'BankCharge',
'ToBankRate',
'BankChargeTaxType',
'BankChargeTaxRefNo',
'BankChargeProjNo',
'BankChargeDeptNo',
'PaymentBy',
'FloatDay',
'IsRCHQ',
'RCHQDate',
'KnockOffDocType',
'KnockOffDocNo',
'KnockOffAmt',
'',
]
];
return $header;
}
@@ -102,7 +169,7 @@ class ExportsReceiptTransactions implements FromQuery, WithHeadings, WithHeading
'<<New>>',
Carbon::parse($transaction->posting_date)->format('d/m/Y'),
($company ? $company->debtor : null),
$transaction->transaction_description,
'Payment for '.$transaction->transaction_description,
'',
'',
'',
@@ -40,18 +40,22 @@ class ImportStatementInvoiceController
if (str_starts_with($row['shipping_info'], 'TOPUP')) {
// find in exchange first, if cannont then find in izyim
foreach (['exchange','izyim'] as $system) {
$returnReference = $this->mappingTopUp($row, $system);
[$returnReference, $transactionDate] = $this->mappingTopUp($row, $system);
if ($returnReference) {
// $row['mapped_result_reference'] = $data['owner_reference'];
// $row['payment_received_date'] = date('Y-m-d', strtotime($data['created_at']));
$row['mapped_result_reference'] = $returnReference;
$row['payment_received_date'] = $transactionDate ? date('d-m-Y', strtotime($transactionDate)) : null;
$row['mapped_status'] = 'success';
return $row;
}
}
}
$returnReference = $this->mappingExchange($row);
[$returnReference, $transactionDate] = $this->mappingExchange($row);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['payment_received_date'] = date('d-m-Y', strtotime($transactionDate));
$row['mapped_status'] = 'success';
return $row;
}
@@ -88,6 +92,7 @@ class ImportStatementInvoiceController
$data = [];
foreach ($excelRows as $row) {
$row['mapped_result_reference'] = null;
$row['payment_received_date'] = null;
$row['mapped_status'] = 'failed';
$row['date'] = in_array(gettype($row['date']), ['integer', 'double']) ? $this->changeExcelDate($row['date']) : date('Y-m-d', strtotime($row['date']));
@@ -144,7 +149,8 @@ class ImportStatementInvoiceController
private function mappingTopUp(Array $row, String $system) {
try {
if ($data = (App()->make(ChecksBillNumber::class))->execute($row['shipping_info'], $system)) {
if ($system == 'izyim' && isset($data['owner_reference'])) return $data['owner_reference'];
// if ($system == 'izyim' && isset($data['owner_reference'])) return $data;
if ($system == 'izyim' && isset($data['owner_reference'])) return [$data['owner_reference'], null];
if ($system == 'exchange') return $this->updateTransactionOwnerReference($data, $row['doc_no']);
}
@@ -168,7 +174,7 @@ class ImportStatementInvoiceController
if ($transaction && $transaction->count() > 0) {
return $this->updateTransactionOwnerReference($transaction, $row['doc_no']);
}
return false;
return [false, false];
}
public function updateTransactionOwnerReference($transaction, String $docNo) {
@@ -178,9 +184,9 @@ class ImportStatementInvoiceController
'invoice_reference'=>$docNo,
'status'=>ApprovalStatus::COMPLETED
]);
return $transactionOwner->owner_reference;
return [$transactionOwner->owner_reference, $transaction->created_at];
}
return false;
return [false, false];
}
public function changeExcelDate($date)
@@ -39,6 +39,7 @@
<td>{{item.cancelled}}</td>
<td>{{item.mapped_status}}</td>
<td>{{item.mapped_result_reference}}</td>
<td>{{item.payment_received_date}}</td>
</tr>
</tbody>
</table>
@@ -101,7 +102,7 @@
},
appendComponentTableHeader() {
if (this.section == 'importInvoiceMapping') {
this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No'];
this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No','Payment Received Date'];
} else {
this.tableHeaders = ['No','OR No','Date','Creditor Code','Creditor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No'];
}