Untitled
unknown
plain_text
a year ago
24 kB
5
Indexable
<?php namespace App\Imports\ImportDeposit; use App\Contracts\BankStatementItemRepositoryContract; use App\Contracts\CompanyImportedDepositRepositoryContract; use App\Imports\ImportDeposit\Contracts\BCABankImportDepositContract; use App\Services\ValidateImportDepositService; use App\Services\BankFormatService; use App\Support\BridgenoteTraitCollection; use App\Models\BankStatement; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Maatwebsite\Excel\Excel; use Illuminate\Support\Carbon; #[\AllowDynamicProperties] class BCABankImportDeposit extends BankImportDeposit implements BCABankImportDepositContract { private const BEGIN_LINE_CSV = 7; private const REGEX_D_M_Y_FORMAT = "/^\b\d{1,2}[-\/]\d{1,2}[-\/]\d{2,4}\b$/"; private const REGEX_D_M_FORMAT = "/^\b\d{1,2}[-\/]\d{1,2}\b$/"; private const AMOUNT_MAX = 9999999999999.99; private const AMOUNT_MIN = -9999999999999.99; private const EXCEL_SYMBOL_SLIP_DATE = 'A'; private const EXCEL_CELL_PERIOD = 'A5'; private const EXCEL_SYMBOL_AMOUNT = 'D'; private const EXCEL_SYMBOL_REMARK = 'B'; private const COLUMN_SAVE_ERRORS = 'G'; private $bankStatementItemRepository; private $lengthBankStatementItemsRemarks; private $lengthBankStatementItemsDefault; private $validateImportDepositService; private $companyImportedDepositRepository; private $dataFormFileCSV; private $bankFormatService; private $termBeginMonth; private $termEndMonth; private $countryId; public function __construct ( BankStatementItemRepositoryContract $bankStatementItemRepository, BankFormatService $bankFormatService, CompanyImportedDepositRepositoryContract $companyImportedDepositRepository ) { $this->bankStatementItemRepository = $bankStatementItemRepository; $this->bankFormatService = $bankFormatService; $this->companyImportedDepositRepository = $companyImportedDepositRepository; $this->termBeginMonth = session('selectedterm_beginmonth'); $this->termEndMonth = session('selectedterm_endmonth'); $this->countryId = session('selectedcompany_country_id'); } private function setSheet($reader, $uploadedFile) { $this->sheet = $reader->load($uploadedFile)->getActiveSheet(); } private function getSheet() { return $this->sheet; } private function setDataFromBankStatement() { $bank_id = session('import_deposit_bank_id'); $deposit_type_id = session('import_deposit_deposit_type_id'); // get bank_statement $bank_statement = $this->bankFormatService->getBankStatementsBankIdAndByDepositType($bank_id, $deposit_type_id); if (empty($bank_statement)) { return response()->json(['result' => false, 'error_message' => __('messages.1088'), 'show_message' => true]); } if ($bank_statement instanceof BankStatement) { $data_begin_line = $bank_statement->data_begin_line; $data_begin_row = $bank_statement->data_begin_row; $data_begin_excelsymbol = $bank_statement->data_begin_excelsymbol; $data_end_excelsymbol = $bank_statement->data_end_excelsymbol; } $this->line_start = $data_begin_line; $this->line_end = $data_begin_row; $this->data_start_excel = $data_begin_excelsymbol; $this->data_end_excel = $data_end_excelsymbol; } private function validateLineExcel($line) { $errors_of_line = []; // slip_date $dateTime = $this->getSheet()->getCell(self::EXCEL_SYMBOL_SLIP_DATE . $line)->getFormattedValue(); // check format DM or MD $existDate = preg_match(self::REGEX_D_M_FORMAT, $dateTime); if ($existDate) { $dataDate = [ 'slip_date' => $dateTime, 'period' => $this->sheet->getCell(self::EXCEL_CELL_PERIOD)->getValue(), ]; $dateTime = $this->getSlipDate($dataDate); } $slip_date = !empty($dateTime) ? date('d-m-Y', strtotime($dateTime)) : ''; $errors_of_line[] = $this->validateSlipDate($slip_date); // debit/credit $amount = $this->getCreditDebit($line); $errors_of_line[] = $this->validateByReceiptAndPayment($amount['credit'], $amount['debit']); //remark $remarks = $this->getDataRemarkExcel($line); if (!$this->isRemarks($remarks)) { $errors_of_line[] = trans('labels.60-B-37', ['length' => $this->lengthBankStatementItemsRemarks]); } return implode(",", array_filter($errors_of_line)); } private function getCreditDebit($line) { $dataAmount = $this->getSheet()->getCell(self::EXCEL_SYMBOL_AMOUNT . $line)->getValue(); $receiptValue = ''; $paymentValue = ''; if (!empty($dataAmount)) { $amount = explode(' ', $dataAmount); if (!empty($amount[1]) && $amount[1] == 'CR') { $receiptValue = $amount[0]; } if (!empty($amount[1]) && $amount[1] == 'DB') { $paymentValue = $amount[0]; } } return [ 'credit' => $receiptValue, 'debit' => $paymentValue, ]; } public function getDataRemarkExcel($line) { return $this->getSheet()->getCell(self::EXCEL_SYMBOL_REMARK . $line)->getValue(); } private function validateContentExcelFile() { $messages_errors = []; $is_errors_excel = false; $highestRow = $this->getSheet()->getHighestDataRow() - ($this->hasFooter() ? 4 : 0); for ($line = $this->line_start; $line <= $highestRow; $line++) { $message = $this->validateLineExcel($line); $messages_errors[] = array('line' => $line, 'message' => $message); if (!empty($message)) { $is_errors_excel = true; } } if ($is_errors_excel) { return array('valid' => false, 'list_errors' => $messages_errors); } return array('valid' => true); } private function saveLegerWithDataOfExcel() { DB::beginTransaction(); try { $data_import_deposit = []; $highestRow = $this->getSheet()->getHighestDataRow() - ($this->hasFooter() ? 4 : 0); for ($line = $this->line_start; $line <= $highestRow; $line++) { $data_import_deposit[] = $this->getDataExcelByRow($line); } $this->companyImportedDepositRepository->insert($data_import_deposit); DB::commit(); return true; } catch (\Exception $e) { DB::rollback(); Log::alert('Error:' . print_r($e->getLine() . $e->getMessage(), true), ['file' => __FILE__, 'line' => __LINE__]); return false; } } private function getDataExcelByRow($line) { $import_deposit = $this->dataInsertDefault(); $slip_date = $this->getSheet()->getCell(self::EXCEL_SYMBOL_SLIP_DATE . $line)->getFormattedValue(); $import_deposit['slip_date'] = date('Y-m-d', strtotime($slip_date)); // debit/credit $amount = $this->getCreditDebit($line); $receiptAmount = BridgenoteTraitCollection::getParseFloat($amount['credit'], $this->countryId); if($receiptAmount) { $import_deposit['is_receipt'] = 1; $import_deposit['amount'] = $receiptAmount; } $paymentAmount = BridgenoteTraitCollection::getParseFloat($amount['debit'], $this->countryId); if($paymentAmount) { $import_deposit['is_receipt'] = 0; $import_deposit['amount'] = $paymentAmount; } $remarks = $this->getDataRemarkExcel($line); $import_deposit['remarks'] = trim($remarks); return $import_deposit; } public function uploadBCABankExcel($request) { $this->lengthBankStatementItemsRemarks = $this->bankStatementItemRepository->getMaxLengBankStatementItemByItemType(2); $this->lengthBankStatementItemsDefault = $this->bankStatementItemRepository->getMaxLengBankStatementItemByItemType(99); $uploadedFile = $request->file('uploader'); try { $reader = $this->readExcelFile($uploadedFile); } catch (\Exception $e) { Log::alert('Error Read Excel File:' . print_r($e->getLine(), true), ['file' => __FILE__, 'line' => __LINE__]); return response()->json(['result' => false, 'error_message' => [$e->getMessage()], 'show_message' => true]); } $this->setSheet($reader, $uploadedFile); $this->setDataFromBankStatement(); $this->validateImportDepositService = new ValidateImportDepositService($uploadedFile, $this->getSheet(), 1); $validPhysicalExcelFile = $this->validateImportDepositService->validatePhysicalExcelFile(); if (!$validPhysicalExcelFile['valid']) { return response()->json(['result' => $validPhysicalExcelFile['valid'], 'error_message' => $validPhysicalExcelFile['list_errors'], 'show_message' => true]); } $validContentExcelFile = $this->validateContentExcelFile(); if (!$validContentExcelFile['valid']) { return $this->makeFileErrorsValidExcel($validContentExcelFile['list_errors'], $uploadedFile); } /** * saveLegerWithDataOfExcel */ $saveLegerSuccess = $this->saveLegerWithDataOfExcel(); if ($saveLegerSuccess) { return response()->json(['success' => true, 'result' => true, 'messages' => __('messages.187'), 200]); } return response()->json(['success' => false, 'result' => false, 'show_message' => true, 'error_message' => array(__('messages.1')), 200]); } private function makeFileErrorsValidExcel($messages, $uploadedFile) { $origin_filename = $uploadedFile->getClientOriginalName(); $target_dir = "/tmp/uploads/importdeposit/"; if (!file_exists($target_dir)) { mkdir($target_dir, 0755, true); } $tmp_file = $uploadedFile->move($target_dir, 'errors_' . $origin_filename); $filename = $tmp_file->getFileName(); $column_name_errors = self::COLUMN_SAVE_ERRORS; try { $reader = $this->readExcelFile($tmp_file); $spreadsheet = $reader->load($tmp_file); $highestRow = $this->getSheet()->getHighestDataRow() - ($this->hasFooter() ? 4 : 0); for ($line = $this->line_start; $line <= $highestRow; $line++) { foreach ($messages as $message) { $cell_name = $column_name_errors . $message['line']; $spreadsheet->getActiveSheet()->setCellValue($cell_name, $message['message']); } } $extension = \PhpOffice\PhpSpreadsheet\IOFactory::identify($tmp_file); if ($extension === Excel::XLS) { $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet); } if ($extension === Excel::XLSX) { $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); } if (!empty($writer)) { $writer->save($filename); } $data = file_get_contents($filename); $response = ['is_errors_excel' => true, 'name' => $filename, 'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," . base64_encode($data)]; return response()->json($response); } catch (\Exception $e) { Log::alert('Error:' . print_r($e->getLine() . $e->getMessage(), true), ['file' => __FILE__, 'line' => __LINE__]); } } public function uploadBCABankCsv($request) { $this->lengthBankStatementItemsRemarks = $this->bankStatementItemRepository->getMaxLengBankStatementItemByItemType(2); $this->lengthBankStatementItemsDefault = $this->bankStatementItemRepository->getMaxLengBankStatementItemByItemType(99); $uploadedFile = $request->file('uploader'); $this->validateImportDepositService = new ValidateImportDepositService($uploadedFile, null, 1); $validPhysicalCsvFile = $this->validateImportDepositService->validatePhysicalCsvFile(); if (!$validPhysicalCsvFile['valid']) { return response()->json([ 'result' => $validPhysicalCsvFile['valid'], 'error_message' => $validPhysicalCsvFile['list_errors'], 'show_message' => true, ]); } try { $this->dataFormFileCSV = $this->getDataFromCsvFile($uploadedFile); } catch (\Exception $e) { Log::alert('Error: Read file errors!!! '.print_r($e->getLine() . ' ' . $e->getMessage(), true), ['file' => __FILE__, 'line' => __LINE__]); return response()->json(['success' => false, 'result' => false, 'show_message' => true, 'error_message' => array(__('messages.1088')), 200]); } $fileCsvErrors = $this->validateDataCSV(); if ($fileCsvErrors) { try { return $this->makeFileErrorsValidCSV($uploadedFile); } catch (\Exception $ex) { Log::alert('Error: Write file errors!!! '.print_r($ex->getLine() . ' ' . $ex->getMessage(), true), ['file' => __FILE__, 'line' => __LINE__]); return response()->json(['success' => false, 'result' => false, 'show_message' => true, 'error_message' => array(__('messages.1')), 200]); } } /*save data*/ $saveLegerSuccess = $this->saveLegerWithDataOfCsv(); if ($saveLegerSuccess) { return response()->json(['success' => true, 'result' => true, 'messages' => __('messages.187'), 200]); } return response()->json(['success' => false, 'result' => false, 'show_message' => true, 'error_message' => array(__('messages.1')), 200]); } private function getDataFromCsvFile($uploadedFile) { $allData = []; $import_deposit = []; $this->dataOriginCsv = []; $row = 1; $handle = fopen($uploadedFile, "r"); while (($data = fgetcsv($handle, 1000, ",")) !== false) { if($row == 5) { $import_deposit['period'] = $data[0]; } $import_deposit['slip_date'] = isset($data[0]) ? $data[0] : ''; $import_deposit['remarks'] = isset($data[1]) ? $data[1] : ''; $import_deposit['receipt'] = ''; $import_deposit['payment'] = ''; if (isset($data[3])) { $amount = explode(' ', $data[3]); if (!empty($amount[1]) && $amount[1] == 'CR') { $import_deposit['receipt'] = $amount[0]; } if (!empty($amount[1]) && $amount[1] == 'DB') { $import_deposit['payment'] = $amount[0]; } } if($row < self::BEGIN_LINE_CSV + 1) { $import_deposit['slip_date'] = ''; } else { $import_deposit['slip_date'] = !empty($import_deposit['slip_date']) ? $this->getSlipDate($import_deposit) : ''; } $row++; array_push($allData, $import_deposit); array_push($this->dataOriginCsv, $data); } fclose($handle); return $allData; } private function validateDataCSV() { $fileCsvErrors = false; foreach ($this->dataFormFileCSV as $line => &$data) { if($line < self::BEGIN_LINE_CSV) { continue; } if ($this->isIgnoredLineEmptyCsv($data)) { continue; } // validate date $data['errors'] = array(); array_push($data['errors'], $this->validateSlipDate($data['slip_date'])); // validate remark if (!$this->isRemarks($data['remarks'])) { array_push($data['errors'], __('labels.60-B-37', ['length' => $this->lengthBankStatementItemsRemarks])); } // debit/credit array_push($data['errors'], $this->validateByReceiptAndPayment(trim($data['receipt']), trim($data['payment']))); if (empty(array_filter($data['errors']))) { unset($data['errors']); } else { $fileCsvErrors = true; } } return $fileCsvErrors; } private function validateSlipDate($dateTime): string { $messages = []; // validate null if (empty(trim($dateTime))) { return trans('labels.60-B-33'); } else { // validate format $regularExp = preg_match(self::REGEX_D_M_Y_FORMAT, $dateTime); if (!$regularExp) { array_push($messages, trans('labels.60-B-34')); } } $date = date('Y-m-d', bn_strtotime($dateTime)); if ($date < $this->termBeginMonth || $date > $this->termEndMonth) { array_push($messages, trans('labels.60-B-36')); } return implode(",", array_filter($messages)); } private function isRemarks($remarks): bool { return strlen((string) $remarks) <= $this->lengthBankStatementItemsRemarks; } private function validateByReceiptAndPayment($reciept, $payment) { $messages = []; if (empty($reciept) && empty($payment)) { return trans('labels.60-B-38'); } $reciept = BridgenoteTraitCollection::getParseFloat($reciept, $this->countryId); $payment = BridgenoteTraitCollection::getParseFloat($payment, $this->countryId); if (!empty($reciept) && ($reciept >= self::AMOUNT_MAX || $reciept <= self::AMOUNT_MIN)) { array_push($messages, trans('labels.60-B-40')); } if (!empty($payment) && ($payment >= self::AMOUNT_MAX || $payment <= self::AMOUNT_MIN)) { array_push($messages, trans('labels.60-B-42')); } return implode(",", array_filter($messages)); } private function getSlipDate($data) { if (!empty($data['period'])) { preg_match_all("/\d{2}\/\d{2}\/\d{4}/", $data['period'], $match); $period = $match[0]; $startYear = date('Y', bn_strtotime($period[0])); $endYear = date('Y', bn_strtotime($period[1])); $slip_date = $data['slip_date'] . '/' . $startYear; $format = 'd/m/Y'; if( Carbon::createFromFormat($format, $slip_date) < Carbon::createFromFormat($format, $period[0]) || Carbon::createFromFormat($format, $slip_date) > Carbon::createFromFormat($format, $period[1]) ) { $slip_date = $data['slip_date'] . '/' . $endYear; } return $slip_date; } } private function makeFileErrorsValidCSV($uploadedFile) { $number_max = count($this->dataFormFileCSV); for ($i = 0; $i < $number_max; $i++) { if (isset($this->dataFormFileCSV[$i]['errors'])) { $string_errors = implode(",", array_filter($this->dataFormFileCSV[$i]['errors'])); array_push($this->dataOriginCsv[$i], trim($string_errors)); } } $delimiter = "\t"; $target_dir = "/tmp/uploads/importdeposit/"; if (!file_exists($target_dir)) { mkdir($target_dir, 0755, true); } $origin_filename = $uploadedFile->getClientOriginalName(); // write file errors. $filename = 'errors_' . $origin_filename; $errors_file = fopen($target_dir . $filename, "w"); foreach ($this->dataOriginCsv as $line) { fputcsv($errors_file, $line, $delimiter); } fclose($errors_file); $data = file_get_contents($target_dir . $filename); $response = array( 'is_errors_excel' => true, 'name' => $filename, 'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($data) //mime type of used format ); return response()->json($response); } private function saveLegerWithDataOfCsv() { $import_deposit = $this->dataInsertDefault(); DB::beginTransaction(); try { $data_import_deposit = []; foreach ($this->dataFormFileCSV as $line => $data) { if($line < self::BEGIN_LINE_CSV) { continue; } if ($this->isIgnoredLineEmptyCsv($data)) { continue; } $import_deposit['slip_date'] = date('Y-m-d', bn_strtotime($data['slip_date'])); $import_deposit['remarks'] = trim($data['remarks']); $receipt = trim($data['receipt']); $receiptAmount = BridgenoteTraitCollection::getParseFloat($receipt, $this->countryId); if($receiptAmount) { $import_deposit['is_receipt'] = 1; $import_deposit['amount'] = $receiptAmount; } $payment = trim($data['payment']); $paymentAmount = BridgenoteTraitCollection::getParseFloat($payment, $this->countryId); if($paymentAmount) { $import_deposit['is_receipt'] = 0; $import_deposit['amount'] = $paymentAmount; } array_push($data_import_deposit, $import_deposit); } $this->companyImportedDepositRepository->insert($data_import_deposit); DB::commit(); return true; } catch (\Exception $e) { DB::rollback(); Log::alert('Error:' . print_r($e->getLine() . $e->getMessage(), true), ['file' => __FILE__, 'line' => __LINE__]); return false; } } private function dataInsertDefault() { return [ 'company_id' => session('selectedcompany_id'), 'account_title_id' =>session('import_deposit_account_id'), 'detailed_id' => session('import_deposit_detail_account_id'), 'created_person_name' => session('person_name'), 'update_user_id' => session('account_id'), 'created_at' => now(), 'updated_at' => now(), ]; } private function isIgnoredLineEmptyCsv($data): bool { if (empty($data['slip_date']) && empty($data['remarks']) && empty($data['receipt']) && empty($data['payment'])) { return true; } return false; } private function hasFooter() { $sheet = $this->getSheet(); $lastRow = $sheet->getHighestDataRow(); // Check if footer keywords are present in the last few rows for ($i = $lastRow; $i > $lastRow - 5; $i--) { $rowData = $sheet->rangeToArray("A$i:Z$i", null, true, true, true); foreach ($rowData as $row) { // Check if any column contains the footer keywords if ( strpos($row['A'], 'Saldo Awal') !== false || strpos($row['A'], 'Mutasi Debet') !== false || strpos($row['A'], 'Mutasi Kredit') !== false || strpos($row['A'], 'Saldo Akhir') !== false ) { return true; // Footer found } } } return false; // Footer not found } }
Editor is loading...
Leave a Comment