From 1954cfa63c6445793d7de82b8827acc44de870f0 Mon Sep 17 00:00:00 2001 From: Dillon Date: Tue, 11 Apr 2023 04:14:53 +0800 Subject: [PATCH] Mapping of bank statement records with exchange and shipping portal + UI to edit the details --- .../General/Eloquent/Filters/DateIn.php | 19 ++ .../Filters/HasAccountStatementId.php | 22 ++ .../General/Eloquent/Filters/PayFor.php | 19 ++ .../General/Eloquent/Filters/PayForIn.php | 19 ++ .../Jobs/CreateBankStatementDetails.php | 40 +++ .../ListBankStatementDetailsLogic.php | 52 ++++ .../UpdateBankStatementDetailLogic.php | 68 +++++ .../BankStatementDetailObject.php | 46 +++ .../CreateBankStatementDetailsProcessor.php | 218 +++++++++++++ .../Services/FetchesBankStatementDetails.php | 34 +++ .../Services/ListsBankStatementDetails.php | 32 ++ .../Services/UpdatesBankStatementDetails.php | 25 ++ .../Accounting/BankStatementController.php | 287 +++++++++++++++++- .../Resources/BankStatementDetailResource.php | 37 +++ app/Models/StatementTransaction.php | 9 +- app/Models/StatementTransactionsDetail.php | 30 ++ config/perfexcrm.php | 2 +- ...e_statement_transactions_details_table.php | 43 +++ .../EditSingleItemInListComponent.vue | 90 ++++++ .../StatementTransactionsDetailsComponent.vue | 227 ++++++++++++++ .../bank-statements/details.blade.php | 8 + .../bank-statements/index.blade.php | 2 +- routes/accounting.php | 10 + routes/api.php | 2 + routes/web.php | 4 + 25 files changed, 1326 insertions(+), 19 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/DateIn.php create mode 100644 app/Classes/General/Eloquent/Filters/HasAccountStatementId.php create mode 100644 app/Classes/General/Eloquent/Filters/PayFor.php create mode 100644 app/Classes/General/Eloquent/Filters/PayForIn.php create mode 100644 app/Classes/Jobs/CreateBankStatementDetails.php create mode 100644 app/Classes/Modules/Accounting/ControllersLogic/ListBankStatementDetailsLogic.php create mode 100644 app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php create mode 100644 app/Classes/Modules/Accounting/DataTransferObjects/BankStatementDetailObject.php create mode 100644 app/Classes/Modules/Accounting/Processors/CreateBankStatementDetailsProcessor.php create mode 100644 app/Classes/Modules/Accounting/Services/FetchesBankStatementDetails.php create mode 100644 app/Classes/Modules/Accounting/Services/ListsBankStatementDetails.php create mode 100644 app/Classes/Modules/Accounting/Services/UpdatesBankStatementDetails.php create mode 100644 app/Http/Resources/BankStatementDetailResource.php create mode 100644 app/Models/StatementTransactionsDetail.php create mode 100644 database/migrations/2023_04_07_212512_create_statement_transactions_details_table.php create mode 100644 resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue create mode 100644 resources/assets/vue/components/accounting/sections/StatementTransactionsDetailsComponent.vue create mode 100644 resources/views/pages/accounting/bank-statements/details.blade.php create mode 100644 routes/accounting.php diff --git a/app/Classes/General/Eloquent/Filters/DateIn.php b/app/Classes/General/Eloquent/Filters/DateIn.php new file mode 100644 index 00000000..b1704eb4 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/DateIn.php @@ -0,0 +1,19 @@ +whereIn('date', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/HasAccountStatementId.php b/app/Classes/General/Eloquent/Filters/HasAccountStatementId.php new file mode 100644 index 00000000..05cfe9d8 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasAccountStatementId.php @@ -0,0 +1,22 @@ +whereHas('statementTransaction', function ($query) use ($value) { + $query->where('account_statement_id', $value); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/PayFor.php b/app/Classes/General/Eloquent/Filters/PayFor.php new file mode 100644 index 00000000..b8a2ba75 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/PayFor.php @@ -0,0 +1,19 @@ +where('pay_for', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/PayForIn.php b/app/Classes/General/Eloquent/Filters/PayForIn.php new file mode 100644 index 00000000..3fe98f00 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/PayForIn.php @@ -0,0 +1,19 @@ +whereIn('pay_for', $value); + } + +} diff --git a/app/Classes/Jobs/CreateBankStatementDetails.php b/app/Classes/Jobs/CreateBankStatementDetails.php new file mode 100644 index 00000000..9d12c6ba --- /dev/null +++ b/app/Classes/Jobs/CreateBankStatementDetails.php @@ -0,0 +1,40 @@ +statement = $statement; + } + + public function handle() + { + (App()->make(CreateBankStatementDetailsProcessor::class))->execute($this->statement); + } + + public function delay($delay) + { + // Add delay in seconds to the job + $this->delay = $delay; + return $this; + } +} diff --git a/app/Classes/Modules/Accounting/ControllersLogic/ListBankStatementDetailsLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/ListBankStatementDetailsLogic.php new file mode 100644 index 00000000..10cffba1 --- /dev/null +++ b/app/Classes/Modules/Accounting/ControllersLogic/ListBankStatementDetailsLogic.php @@ -0,0 +1,52 @@ + 'Retrieved Bank Statement Details', + 'message' => 'You have successfully retrieved a Bank Statement Details' + ]; + } + + + /** @var ListsBankStatementDetails */ + private $listsBankStatementDetails; + + /** + * ListBankStatementDetailsLogic constructor. + * @param ListsBankStatementDetails $listsBankStatementDetails + */ + public function __construct(ListsBankStatementDetails $listsBankStatementDetails) + { + $this->listsBankStatementDetails = $listsBankStatementDetails; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $query = $this->listsBankStatementDetails->execute($this->listsBankStatementDetails->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(BankStatementDetailResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php new file mode 100644 index 00000000..bbdeef35 --- /dev/null +++ b/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php @@ -0,0 +1,68 @@ + 'Updated Bank Statement Transactions Details', + 'message' => 'You have successfully updated the Bank Statement Transactions Details' + ]; + } + + // /** @var CanUpdateCompany */ + // private $canUpdateCompany; + + /** @var UpdatesBankStatementDetails */ + private $updatesBankStatementDetails; + + /** @var FetchesBankStatementDetails */ + private $fetchesBankStatementDetails; + + /** + * UpdateBankStatementDetailLogic constructor. + * @param UpdatesBankStatementDetails $updatesBankStatementDetails + * @param FetchesBankStatementDetails $fetchesBankStatementDetails + */ + public function __construct(UpdatesBankStatementDetails $updatesBankStatementDetails, FetchesBankStatementDetails $fetchesBankStatementDetails) + { + $this->updatesBankStatementDetails = $updatesBankStatementDetails; + $this->fetchesBankStatementDetails = $fetchesBankStatementDetails; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $object = new BankStatementDetailObject($request->input('pay_for'), $request->input('system_references')); + + // $this->canUpdateCompany->passes($object); + + $query = $this->fetchesBankStatementDetails->execute(['id' => $request->route('id')]); + + $query = $this->updatesBankStatementDetails->execute($query, $object); + + return $this->resourceResponse(new BankStatementDetailResource($query)); + } + +} diff --git a/app/Classes/Modules/Accounting/DataTransferObjects/BankStatementDetailObject.php b/app/Classes/Modules/Accounting/DataTransferObjects/BankStatementDetailObject.php new file mode 100644 index 00000000..8da675d6 --- /dev/null +++ b/app/Classes/Modules/Accounting/DataTransferObjects/BankStatementDetailObject.php @@ -0,0 +1,46 @@ +pay_for = $pay_for; + $this->system_references = $system_references; + } + + /** + * @return string + */ + public function getPayFor(): string + { + return $this->pay_for; + } + + /** + * @return string + */ + public function getSystemReferences(): string + { + return $this->system_references; + } +} diff --git a/app/Classes/Modules/Accounting/Processors/CreateBankStatementDetailsProcessor.php b/app/Classes/Modules/Accounting/Processors/CreateBankStatementDetailsProcessor.php new file mode 100644 index 00000000..4514682c --- /dev/null +++ b/app/Classes/Modules/Accounting/Processors/CreateBankStatementDetailsProcessor.php @@ -0,0 +1,218 @@ +transactions(); + $transactions = $transactions->get(); + + $headers = [ + 'Date', + 'Bank', + 'Description', + 'Credit', + 'Debit', + 'Pay For', + 'System', + 'System Reference', + 'Human Reference', + 'Multiple', + 'Match?', + 'System Amount' + ]; + + $branches = [ + 0 => 'MBB Cyber', + 1 => 'MBB SS2', + ]; + + $yes = 'Yes'; + $no = 'No'; + + $table = ''; + $count = 0; + + foreach ($transactions as $row) { + $isExist = StatementTransactionsDetail::where('statement_transactions_id', $row->id)->first(); + + if ($isExist) { + continue; + } + + $count++; + $credit = 0.00; + $debit = 0.00; + + $date = new DateTime($row['posting_date']); + $description = $row['transaction_description_2']; + + if($row['amount'] < 0){ + $debit = (float) $row['amount']; + } + else{ + $credit = (float) $row['amount']; + } + + $creditTransactions = []; + $debitTransactions = []; + + $system = []; + $systemReference = null; + $systemAmount = null; + + if($credit){ + $creditTransactions = $this->getTransactions($date, $credit, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction->owner instanceof Booking ? $transaction->owner->marking : $transaction->bill_no; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + + $creditTransactions = $this->getTransactions($date, $credit, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction->owner instanceof Booking ? $transaction->owner->marking : $transaction->bill_no; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + + $creditTransactions = $this->getTransactionsFromShippingPortal($credit, $this->getDateRange($row['posting_date'])); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction['order']['reference']; + $systemAmount[] = $transaction['amount']; + $system[] = 'SHIPPING'; + } + } + + if($debit){ + $debitTransactions = $this->getTransactions($date, $debit, null, null, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], Group::class); + + if(!count($debitTransactions)) { + foreach (['YSN', 'HCK', 'ATVANTIC', 'HIGH HILL'] as $reference){ + if(str_contains($description, $reference)) { + $paymentDate = date('Y-m-d', strtotime('+1 day', strtotime($row['posting_date']))); //$date->addDays(1)->format('Y-m-d'); + + if($reference = 'ATVANTIC'){ + $paymentDate = date('Y-m-d', strtotime($row['posting_date']));//$date->format('Y-m-d'); + } + $issuer = Company::where('name', 'like', '%'.$reference.'%')->get()->pluck('id'); + $debitTransactions = Group::whereIn('issuer', $issuer)->whereDate('created_at', $paymentDate)->get(); + break; + } + } + + } + + foreach ($debitTransactions as $transaction) { + $systemReference[] = $transaction->reference; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + } + + + $multiple = count($creditTransactions) + count($debitTransactions) > 1 ? $yes : $no; + + $systemReference = $systemReference ? implode(',', $systemReference) : null; + $systemAmount = $systemAmount ? implode(',', $systemAmount) : null; + $system = $system ? implode(',', $system) : null; + + $matches = $systemReference == $row['remarkreferences'] ? $yes : $no; + + $statementTransactionsDetail = new StatementTransactionsDetail([ + 'date' => $date, + 'statement_transactions_id' => $row->id, + // 'description' => is_null($description) ? "" : $description, + // 'credit' => $credit, + // 'debit' => $debit, + 'pay_for' => is_null($system) ? "" : $system, + 'system_references' => is_null($systemReference) ? "" : $systemReference, + // 'remark_references' => is_null($row['remarkreferences']) ? "" : $row['remarkreferences'], + // 'is_multiple' => $multiple == "Yes" ? 1 : 0, + // 'is_matches' => $matches == "Yes" ? 1 : 0, + 'system_amounts'=> is_null($systemAmount) ? "" : $systemAmount, + ]); + + $statementTransactionsDetail->save(); + + // if($count == 10){ + // break; + // } + } + } + + private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $model = Transaction::class) { + $query = $model::whereIn('status', $statuses) + ->where(function ($query) use ($ownerType, $paymentMethod, $type) { + if ($ownerType) { + $query->where('owner_type', $ownerType); + } + + if ($paymentMethod) { + $query->where('payment_method', '!=', $paymentMethod); + } + + if ($type) { + $query->where('type', $type); + } + }) + ->whereDate('created_at', $date->format('Y-m-d')) + ->where('amount', '>', ($amount - 0.01)) + ->where('amount', '<', ($amount + 0.01)); + + return $query->get(); + } + + private function getTransactionsFromShippingPortal($amount, $dateRange){ + try{ + + $client = new \GuzzleHttp\Client(); + $response = $client->request('GET', 'https://izyim.cief-malaysia.com/public/api/v1/list?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2],"type":2,"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).'}'); + $body = $response->getBody(); + $data = json_decode($body, true); + $payload = $data['payload']; + $transactions2 = $payload['data']; + return $transactions2; + }catch(\Exception $exception){ + Log::error($exception); + return []; + } + } + + private function getDateRange(string $dateStr) { + // Create a DateTime object from the input string + $date = strtotime($dateStr); + + // Get the first day of the month + $today = date('Y-m-d', $date); + + // Get the first day of the next month + $nextDay = date('Y-m-d', strtotime('+1 day', $date)); + + return [ + 'start_date' => $today, + 'end_date' => $nextDay, + ]; + } +} diff --git a/app/Classes/Modules/Accounting/Services/FetchesBankStatementDetails.php b/app/Classes/Modules/Accounting/Services/FetchesBankStatementDetails.php new file mode 100644 index 00000000..37a3d785 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/FetchesBankStatementDetails.php @@ -0,0 +1,34 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Accounting/Services/ListsBankStatementDetails.php b/app/Classes/Modules/Accounting/Services/ListsBankStatementDetails.php new file mode 100644 index 00000000..2f1290e5 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/ListsBankStatementDetails.php @@ -0,0 +1,32 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Accounting/Services/UpdatesBankStatementDetails.php b/app/Classes/Modules/Accounting/Services/UpdatesBankStatementDetails.php new file mode 100644 index 00000000..2e4ad23c --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/UpdatesBankStatementDetails.php @@ -0,0 +1,25 @@ +system_references = $object->getSystemReferences(); + $model->pay_for = $object->getPayFor(); + + return $this->handler($model); + } +} diff --git a/app/Http/Controllers/Accounting/BankStatementController.php b/app/Http/Controllers/Accounting/BankStatementController.php index d1df6a74..3146e13d 100644 --- a/app/Http/Controllers/Accounting/BankStatementController.php +++ b/app/Http/Controllers/Accounting/BankStatementController.php @@ -2,15 +2,32 @@ namespace App\Http\Controllers\Accounting; +use App\Classes\Jobs\CreateBankStatementDetails; +use App\Classes\Modules\Accounting\ControllersLogic\ListBankStatementDetailsLogic; +use App\Classes\Modules\Accounting\ControllersLogic\UpdateBankStatementDetailLogic; use App\Classes\Modules\Imports\Services\BankStatementImport; -use App\Http\Controllers\Controller; -use DateTime; -use Illuminate\Http\Request; -use Illuminate\Support\Carbon; -use Maatwebsite\Excel\Facades\Excel; +use App\Classes\Modules\Imports\Services\ImportsBankRecord; +use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\PaymentMethodType; +use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\StatementAccount; use App\Models\AccountStatement; use App\Models\StatementTransaction; +use App\Models\Booking; +use App\Models\Company; +use App\Models\Group; +use App\Models\StatementTransactionsDetail; +use App\Models\Transaction; +use App\Models\Wallet; +use App\Http\Controllers\Controller; +use Maatwebsite\Excel\Facades\Excel; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Illuminate\Support\Carbon; +use DateTime; + + +use PhpOffice\PhpSpreadsheet\Shared\Date; class BankStatementController extends Controller { @@ -44,6 +61,7 @@ class BankStatementController extends Controller public function import(Request $request) { + $request->validate([ 'file' => 'required|mimes:csv,txt' ]); @@ -83,17 +101,21 @@ class BankStatementController extends Controller 'end_balance' => $endBalance, ]); - $existingStatement = AccountStatement::where('date_from', $dateFrom) - ->where('date_to', $dateTo) - ->where('statement_account_id', $account->id) - ->first(); + // $existingStatement = AccountStatement::where('date_from', $dateFrom) + // ->where('date_to', $dateTo) + // ->where('statement_account_id', $account->id) + // ->first(); - if ($existingStatement) { - return redirect()->back()->with('error', 'This statement has already been imported.'); - } + // // if ($existingStatement) { + // // return redirect()->back()->with('error', 'This statement has already been imported.'); + // // } $account->statements()->save($statement); + CreateBankStatementDetails::dispatch($statement)->delay(30); + + + // $account = null; $newTransactions = $sheet->map(function ($row) use ($statement, $account) { $transactionRef = $row[15]; $amount = $row[17] !== '-' ? ((float) str_replace(',', '', $row[17])) : (-((float) str_replace(',', '', $row[16]))); @@ -141,13 +163,17 @@ class BankStatementController extends Controller return $transaction; }); + + // dd(json_encode($newTransactions)); return redirect()->back()->with('success', 'Statement imported successfully.')->with('newTransactions', $newTransactions); } public function show(AccountStatement $statement, Request $request) { $transactions = $statement->transactions(); - + // $account = $statement->account(); + // dd(json_encode($account->where('id', '>=', 1)->first())); + // dd(json_encode($transactions->where('id', '>=', 1)->first())); if ($request->get('transaction_filter')) { $transactionFilter = $request->get('transaction_filter'); $transactions = $transactions->where('transaction_description', 'LIKE', "%$transactionFilter%"); @@ -163,9 +189,11 @@ class BankStatementController extends Controller $transactions = $transactions->where('amount', '<=', $toAmountFilter); } - $transactions = $transactions->paginate(100); + // $transactions = $transactions->paginate(100); + $transactions = $transactions->get(); + echo $this->process3_merged($transactions); - return view('pages.accounting.bank-statements.show', compact('statement', 'transactions')); + //return view('pages.accounting.bank-statements.show', compact('statement', 'transactions')); } public function download(AccountStatement $statement) @@ -176,4 +204,233 @@ class BankStatementController extends Controller $csvExporter->build($transactions, ['transaction_date', 'transaction_time', 'posting_date', 'transaction_description', 'transaction_ref', 'debit', 'credit']) ->download($statement->date_from->format('Y-m-d') . '_' . $statement->date_to->format('Y-m-d') . '_statement.csv'); } + + public function fetch(Request $request, ListBankStatementDetailsLogic $logic): JsonResponse + { + return $logic->execute($request); + } + + public function update(Request $request, UpdateBankStatementDetailLogic $logic): JsonResponse + { + return $logic->execute($request); + } + + private function process3_merged($transactions){ + + // $statement = $transactions[0]->statement(); + // dd(json_encode($statement->first())); + + $headers = [ + 'Date', + 'Bank', + 'Description', + 'Credit', + 'Debit', + 'Pay For', + 'System', + 'System Reference', + 'Human Reference', + 'Multiple', + 'Match?', + 'System Amount' + ]; + + $branches = [ + 0 => 'MBB Cyber', + 1 => 'MBB SS2', + ]; + + $yes = 'Yes'; + $no = 'No'; + + $table = '
'.implode('', $headers).'
'; + $count = 0; + + foreach ($transactions as $row) { + $isExist = StatementTransactionsDetail::where('statement_transactions_id', $row->id)->first(); + + if ($isExist) { + continue; + } + + $count++; + $credit = 0.00; + $debit = 0.00; + + // dd(json_encode($row['posting_date'])); + $date = new DateTime($row['posting_date']); + $description = $row['transaction_description_2']; + + if($row['amount'] < 0){ + $debit = (float) $row['amount']; + } + else{ + $credit = (float) $row['amount']; + } + + $creditTransactions = []; + $debitTransactions = []; + + $system = ''; + $systemReference = null; + $systemAmount = null; + + if($credit){ + $creditTransactions = $this->getTransactions($date, $credit, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction->owner instanceof Booking ? $transaction->owner->marking : $transaction->bill_no; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + + $creditTransactions = $this->getTransactions($date, $credit, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction->owner instanceof Booking ? $transaction->owner->marking : $transaction->bill_no; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + + $creditTransactions = $this->getTransactionsFromShippingPortal($credit, $this->getDateRange($row['posting_date'])); + foreach ($creditTransactions as $transaction) { + $systemReference[] = $transaction['order']['reference']; + $systemAmount[] = $transaction['amount']; + $system[] = 'SHIPPING'; + } + } + + if($debit){ + $debitTransactions = $this->getTransactions($date, $debit, null, null, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], Group::class); + + if(!count($debitTransactions)) { + foreach (['YSN', 'HCK', 'ATVANTIC', 'HIGH HILL'] as $reference){ + if(str_contains($description, $reference)) { + $paymentDate = date('Y-m-d', strtotime('+1 day', strtotime($row['posting_date']))); //$date->addDays(1)->format('Y-m-d'); + + if($reference = 'ATVANTIC'){ + $paymentDate = date('Y-m-d', strtotime($row['posting_date']));//$date->format('Y-m-d'); + } + $issuer = Company::where('name', 'like', '%'.$reference.'%')->get()->pluck('id'); + $debitTransactions = Group::whereIn('issuer', $issuer)->whereDate('created_at', $paymentDate)->get(); + break; + } + } + + } + + foreach ($debitTransactions as $transaction) { + $systemReference[] = $transaction->reference; + $systemAmount[] = $transaction->amount; + $system[] = 'EXCHANGE'; + } + } + + + $multiple = count($creditTransactions) + count($debitTransactions) > 1 ? $yes : $no; + + + + + + $systemReference = $systemReference ? implode(',', $systemReference) : null; + $systemAmount = $systemAmount ? implode(',', $systemAmount) : null; + + $matches = $systemReference == $row['remarkreferences'] ? $yes : $no; + + $table .= ' + + + + + + + + + + + + + '; + + //AccountStatement + // $row->statement()->first()->id) + + $statementTransactionsDetail = new StatementTransactionsDetail([ + 'date' => $date, + 'statement_transactions_id' => $row->id, + 'description' => is_null($description) ? "" : $description, + 'credit' => $credit, + 'debit' => $debit, + 'pay_for' => $system, + 'system_references' => is_null($systemReference) ? "" : $systemReference, + 'remark_references' => is_null($row['remarkreferences']) ? "" : $row['remarkreferences'], + 'is_multiple' => $multiple == "Yes" ? 1 : 0, + 'is_matches' => $matches == "Yes" ? 1 : 0, + 'system_amounts'=> is_null($systemAmount) ? "" : $systemAmount, + ]); + + $statementTransactionsDetail->save(); + + if($count == 10){ + break; + } + } + + $table .= '
'.implode('', $headers).'
'.$date->format('d-m-Y').'branch'.$description.''.$credit.''.$debit.''.$row['pay_for'].''.$system.''.$systemReference.''.$row['remarkreferences'].''.$multiple.''.$matches.''.$systemAmount.'
'; + + return $table; + } + + private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $model = Transaction::class) { + $query = $model::whereIn('status', $statuses) + ->where(function ($query) use ($ownerType, $paymentMethod, $type) { + if ($ownerType) { + $query->where('owner_type', $ownerType); + } + + if ($paymentMethod) { + $query->where('payment_method', '!=', $paymentMethod); + } + + if ($type) { + $query->where('type', $type); + } + }) + ->whereDate('created_at', $date->format('Y-m-d')) + ->where('amount', '>', ($amount - 0.01)) + ->where('amount', '<', ($amount + 0.01)); + + return $query->get(); + } + + private function getDateRange(string $dateStr) { + // Create a DateTime object from the input string + $date = strtotime($dateStr); + + // Get the first day of the month + $today = date('Y-m-d', $date); + + // Get the first day of the next month + $nextDay = date('Y-m-d', strtotime('+1 day', $date)); + + return [ + 'start_date' => $today, + 'end_date' => $nextDay, + ]; + } + + private function getTransactionsFromShippingPortal($amount, $dateRange){ + + $client = new \GuzzleHttp\Client(); + $response = $client->request('GET', 'https://izyim.cief-malaysia.com/public/api/v1/list?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2],"type":2,"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).'}'); + $body = $response->getBody(); + $data = json_decode($body, true); + $payload = $data['payload']; + $transactions2 = $payload['data']; + // $filters = [ + // ['field' => 'created_at', 'value' => '2023-03-01 08:07:00'], + // ]; + // $transactions2 = $this->getTransactions3($transactions2, $filters); + return $transactions2; + } + } diff --git a/app/Http/Resources/BankStatementDetailResource.php b/app/Http/Resources/BankStatementDetailResource.php new file mode 100644 index 00000000..5533728c --- /dev/null +++ b/app/Http/Resources/BankStatementDetailResource.php @@ -0,0 +1,37 @@ + $this->id, + 'account_number' => $this->statementTransaction->statement->account->number, + 'account_type' => $this->statementTransaction->statement->account->type, + 'account_name' => $this->statementTransaction->statement->account->name, + 'account_statement_id' => $this->statementTransaction->statement->id, + 'account_statement_date_from' => $this->statementTransaction->statement->date_from, + 'account_statement_date_to' => $this->statementTransaction->statement->date_to, + 'date' => $this->date, + 'description' => $this->description, + 'amount' => $this->statementTransaction->amount, + 'pay_for' => $this->pay_for, + 'system_references' => $this->system_references, + 'transaction_description_1' => $this->statementTransaction->transaction_description, + 'transaction_description_2' => $this->statementTransaction->transaction_description_2, + 'transaction_description_3' => $this->statementTransaction->transaction_description_3, + 'transaction_description_4' => $this->statementTransaction->transaction_description_4, + 'transaction_description_5' => $this->statementTransaction->transaction_description_5, + ]; + } +} diff --git a/app/Models/StatementTransaction.php b/app/Models/StatementTransaction.php index a7c6a589..7d089b65 100644 --- a/app/Models/StatementTransaction.php +++ b/app/Models/StatementTransaction.php @@ -10,7 +10,7 @@ class StatementTransaction extends Model use HasFactory; protected $fillable = [ - 'statement_id', + 'account_statement_id', 'transaction_date', 'posting_date', 'transaction_description', @@ -31,11 +31,16 @@ class StatementTransaction extends Model public function statement() { - return $this->belongsTo(AccountStatement::class, 'statement_id', 'id'); + return $this->belongsTo(AccountStatement::class, 'account_statement_id', 'id'); } public function owner() { return $this->morphTo()->nullable(); } + + public function statementDetail() + { + return $this->hasMany(StatementTransactionsDetail::class); + } } diff --git a/app/Models/StatementTransactionsDetail.php b/app/Models/StatementTransactionsDetail.php new file mode 100644 index 00000000..1a0ee6ba --- /dev/null +++ b/app/Models/StatementTransactionsDetail.php @@ -0,0 +1,30 @@ +belongsTo(StatementTransaction::class, 'statement_transactions_id', 'id'); + } +} diff --git a/config/perfexcrm.php b/config/perfexcrm.php index f67040f5..7644a489 100644 --- a/config/perfexcrm.php +++ b/config/perfexcrm.php @@ -1,7 +1,7 @@ env('PERFEXCRM_BASE_URL', 'http://192.168.1.100:8084'), //cief todo: Update crm api domain here + 'base_url' => env('PERFEXCRM_BASE_URL', 'http://192.168.1.101:8084'), //cief todo: Update crm api domain here 'api_key' => env('PERFEXCRM_API_KEY', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZXhjaGFuZ2Utc2hpcHBpbmciLCJuYW1lIjoiRXhjaGFuZ2UgYW5kIFNoaXBwaW5nIFBvcnRhbCIsIkFQSV9USU1FIjoxNjc1MDg2Mzc4fQ.SGAHWl5stcxQwp55TBGeMRVTdlLeWQIbsvJh5glyVvs'), 'is_enabled' => env('PERFEXCRM_IS_ENABLED', 'true'), ]; diff --git a/database/migrations/2023_04_07_212512_create_statement_transactions_details_table.php b/database/migrations/2023_04_07_212512_create_statement_transactions_details_table.php new file mode 100644 index 00000000..41abbd96 --- /dev/null +++ b/database/migrations/2023_04_07_212512_create_statement_transactions_details_table.php @@ -0,0 +1,43 @@ +id(); + $table->date('date'); + $table->unsignedBigInteger('statement_transactions_id'); + $table->foreign('statement_transactions_id')->references('id')->on('statement_transactions'); + // $table->string('description'); + // $table->decimal('credit', 8, 2); + // $table->decimal('debit', 8, 2); + $table->string('pay_for'); + $table->string('system_references'); + // $table->string('remark_references'); + // $table->boolean('is_multiple')->default(false); + // $table->boolean('is_matches')->default(false); + $table->string('system_amounts'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('statement_transactions_details'); + } +} diff --git a/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue new file mode 100644 index 00000000..b160eeac --- /dev/null +++ b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue @@ -0,0 +1,90 @@ + + + diff --git a/resources/assets/vue/components/accounting/sections/StatementTransactionsDetailsComponent.vue b/resources/assets/vue/components/accounting/sections/StatementTransactionsDetailsComponent.vue new file mode 100644 index 00000000..db9e25e1 --- /dev/null +++ b/resources/assets/vue/components/accounting/sections/StatementTransactionsDetailsComponent.vue @@ -0,0 +1,227 @@ + + diff --git a/resources/views/pages/accounting/bank-statements/details.blade.php b/resources/views/pages/accounting/bank-statements/details.blade.php new file mode 100644 index 00000000..6c0caf8b --- /dev/null +++ b/resources/views/pages/accounting/bank-statements/details.blade.php @@ -0,0 +1,8 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+ +
+
+@endsection diff --git a/resources/views/pages/accounting/bank-statements/index.blade.php b/resources/views/pages/accounting/bank-statements/index.blade.php index b22cec53..2269ad94 100644 --- a/resources/views/pages/accounting/bank-statements/index.blade.php +++ b/resources/views/pages/accounting/bank-statements/index.blade.php @@ -78,7 +78,7 @@ {{ $statement->begin_balance }} {{ $statement->end_balance }} - View + View @endforeach diff --git a/routes/accounting.php b/routes/accounting.php new file mode 100644 index 00000000..acc75e35 --- /dev/null +++ b/routes/accounting.php @@ -0,0 +1,10 @@ + 'accounting', 'as' => 'accounting.', 'namespace' => 'Accounting'], function () { + Route::group(['prefix' => 'statements/{id}', 'as' => 'statement.'], function () { + Route::get('/details', 'BankStatementController@fetch')->name('details'); + Route::put('/details/update', 'BankStatementController@update')->name('details.update'); + }); +}); diff --git a/routes/api.php b/routes/api.php index 6c17a107..9af79578 100644 --- a/routes/api.php +++ b/routes/api.php @@ -54,6 +54,8 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/wallet.php'; + require __DIR__ . '/accounting.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/web.php b/routes/web.php index 0566f5c3..9c06273e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -557,9 +557,13 @@ Route::get('/currency-rate-history', function () { Route::get('/statements', [BankStatementController::class, 'index'])->name('statements.index'); Route::post('/statements/import', [BankStatementController::class, 'import'])->name('statements.import'); +Route::get('/statements/{statement}/details', function ($statement) { + return view('pages.accounting.bank-statements.details', ['statement' => $statement]); +})->name('statements.transactions.details'); Route::get('/statements/{statement}', [BankStatementController::class, 'show'])->name('statements.show'); Route::get('/statements/{statement}/download', 'StatementController@download')->name('statements.download'); Route::get('/bank-record', 'Imports\ImportBankRecordController@import'); +