mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 04:23:55 +00:00
Mapping of bank statement records with exchange and shipping portal + UI to edit the details
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class DateIn implements Filter
|
||||
{
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param $value
|
||||
* @return Builder|mixed
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
return $builder->whereIn('date', $value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class HasAccountStatementId implements Filter
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
return $builder->whereHas('statementTransaction', function ($query) use ($value) {
|
||||
$query->where('account_statement_id', $value);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class PayFor implements Filter
|
||||
{
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param $value
|
||||
* @return Builder|mixed
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
return $builder->where('pay_for', $value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class PayForIn implements Filter
|
||||
{
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param $value
|
||||
* @return Builder|mixed
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
return $builder->whereIn('pay_for', $value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Jobs;
|
||||
|
||||
use App\Classes\Modules\Accounting\Processors\CreateBankStatementDetailsProcessor;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Models\AccountStatement;
|
||||
|
||||
class CreateBankStatementDetails implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/** @var AccountStatement $statement*/
|
||||
private $statement;
|
||||
|
||||
/**
|
||||
* CreateBankStatementDetails constructor.
|
||||
* @param AccountStatement $statement
|
||||
*/
|
||||
public function __construct(AccountStatement $statement)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\ControllersLogic;
|
||||
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Modules\Accounting\Services\ListsBankStatementDetails;
|
||||
use App\Http\Resources\BankStatementDetailResource;
|
||||
use ErrorException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ListBankStatementDetailsLogic extends AbstractControllerLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification():array {
|
||||
return [
|
||||
'title' => '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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\ControllersLogic;
|
||||
|
||||
|
||||
use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Modules\Accounting\Services\UpdatesBankStatementDetails;
|
||||
use App\Classes\Modules\Accounting\Services\FetchesBankStatementDetails;
|
||||
use App\Classes\Modules\Accounting\Standards\Rules\CanUpdateCompany;
|
||||
use App\Classes\Modules\Accounting\DataTransferObjects\BankStatementDetailObject;
|
||||
use App\Http\Resources\BankStatementDetailResource;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use ErrorException;
|
||||
|
||||
class UpdateBankStatementDetailLogic extends AbstractControllerLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function notification():array {
|
||||
return [
|
||||
'title' => '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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\DataTransferObjects;
|
||||
|
||||
use App\Classes\General\Interfaces\DataTransferObject;
|
||||
|
||||
class BankStatementDetailObject implements DataTransferObject
|
||||
{
|
||||
/** @var string */
|
||||
private $pay_for;
|
||||
|
||||
/** @var string */
|
||||
private $system_references;
|
||||
|
||||
// /** @var int|null */
|
||||
// private $type;
|
||||
|
||||
|
||||
/**
|
||||
* BankStatementDetailObject constructor.
|
||||
* @param string $pay_for
|
||||
* @param string $system_references
|
||||
* @param int|null $type
|
||||
*/
|
||||
public function __construct(string $pay_for, string $system_references)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\Processors;
|
||||
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\PaymentMethodType;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Models\AccountStatement;
|
||||
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 Illuminate\Support\Facades\Log;
|
||||
use DateTime;
|
||||
|
||||
class CreateBankStatementDetailsProcessor
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $transactions
|
||||
* @return true
|
||||
* @throws \App\Classes\Exceptions\MalformedRequestException
|
||||
*/
|
||||
public function execute(AccountStatement $statement) {
|
||||
|
||||
$transactions = $statement->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 = '<table><tr><th>'.implode('</th><th>', $headers).'</th></tr>';
|
||||
$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,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\Services;
|
||||
|
||||
|
||||
use App\Classes\General\Eloquent\AbstractFetchRecord;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\StatementTransactionsDetail;
|
||||
|
||||
class FetchesBankStatementDetails extends AbstractFetchRecord
|
||||
{
|
||||
|
||||
/** @var StatementTransactionsDetail */
|
||||
private $repository;
|
||||
|
||||
|
||||
/**
|
||||
* FetchesBankStatementDetails constructor.
|
||||
* @param StatementTransactionsDetail $repository
|
||||
*/
|
||||
public function __construct(StatementTransactionsDetail $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
*/
|
||||
public function getRepository(): Builder
|
||||
{
|
||||
return $this->repository->newQuery();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\Services;
|
||||
|
||||
use App\Classes\General\Eloquent\AbstractListRecord;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\StatementTransactionsDetail;
|
||||
|
||||
class ListsBankStatementDetails extends AbstractListRecord
|
||||
{
|
||||
|
||||
/** @var StatementTransactionsDetail */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* ListsBankStatementDetails constructor.
|
||||
* @param StatementTransactionsDetail $repository
|
||||
*/
|
||||
public function __construct(StatementTransactionsDetail $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Builder
|
||||
*/
|
||||
public function getRepository(): Builder
|
||||
{
|
||||
return $this->repository->newQuery();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\Modules\Accounting\Services;
|
||||
|
||||
use App\Classes\General\Eloquent\AbstractUpdateRecord;
|
||||
use App\Classes\Modules\Accounting\DataTransferObjects\BankStatementDetailObject;
|
||||
use App\Models\StatementTransactionsDetail;
|
||||
|
||||
class UpdatesBankStatementDetails extends AbstractUpdateRecord
|
||||
{
|
||||
|
||||
/**
|
||||
* @param StatementTransactionsDetail $model
|
||||
* @param BankStatementDetailsObject $object
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
* @throws \App\Classes\Exceptions\MalformedRequestException
|
||||
*/
|
||||
public function execute(StatementTransactionsDetail $model, BankStatementDetailObject $object)
|
||||
{
|
||||
$model->system_references = $object->getSystemReferences();
|
||||
$model->pay_for = $object->getPayFor();
|
||||
|
||||
return $this->handler($model);
|
||||
}
|
||||
}
|
||||
@@ -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 = '<table><tr><th>'.implode('</th><th>', $headers).'</th></tr>';
|
||||
$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 .= '<tr>
|
||||
<td>'.$date->format('d-m-Y').'</td>
|
||||
<td>branch</td>
|
||||
<td>'.$description.'</td>
|
||||
<td>'.$credit.'</td>
|
||||
<td>'.$debit.'</td>
|
||||
<td>'.$row['pay_for'].'</td>
|
||||
<td>'.$system.'</td>
|
||||
<td>'.$systemReference.'</td>
|
||||
<td>'.$row['remarkreferences'].'</td>
|
||||
<td>'.$multiple.'</td>
|
||||
<td>'.$matches.'</td>
|
||||
<td>'.$systemAmount.'</td>
|
||||
</tr>';
|
||||
|
||||
//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 .= '</table>';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class BankStatementDetailResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $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,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class StatementTransactionsDetail extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'date',
|
||||
'statement_transactions_id',
|
||||
// 'description',
|
||||
// 'credit',
|
||||
// 'debit',
|
||||
'pay_for',
|
||||
'system_references',
|
||||
// 'remark_references',
|
||||
// 'is_multiple',
|
||||
// 'is_matches',
|
||||
'system_amounts',
|
||||
];
|
||||
|
||||
public function statementTransaction()
|
||||
{
|
||||
return $this->belongsTo(StatementTransaction::class, 'statement_transactions_id', 'id');
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'base_url' => 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'),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateStatementTransactionsDetailsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('statement_transactions_details', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<validation-wrapper-component :validator="$v.pay_for">
|
||||
<label>Pay For</label>
|
||||
<input type="text" class="form-control" v-model="pay_for" >
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<validation-wrapper-component :validator="$v.system_references">
|
||||
<label>System References</label>
|
||||
<input type="text" class="form-control" v-model="system_references" >
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group row">
|
||||
<label>Date: {{ item.date }}</label>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label>Transaction Description 1: {{ item.transaction_description_1 }}</label>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label>Transaction Description 2: {{ item.transaction_description_2 }}</label>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label>Transaction Description 3: {{ item.transaction_description_3 }}</label>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label>Transaction Description 4: {{ item.transaction_description_4 }}</label>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label>Transaction Description 5: {{ item.transaction_description_5 }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col p-r-5">
|
||||
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
|
||||
</div>
|
||||
<div class="col p-l-5">
|
||||
<div data-dismiss="modal" class="btn btn-sm btn-success btn-block b-rad-none" @click="submitForm()">Update</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
// import ModalFormHandler from '../../../general/mixins/modalFormHandler';
|
||||
import { required } from "vuelidate/lib/validators";
|
||||
// import FormHandler from '../../../general/mixins/formHandler';
|
||||
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
error: '',
|
||||
pay_for: "",
|
||||
system_references: ""
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pay_for = this.item.pay_for,
|
||||
this.system_references = this.item.system_references
|
||||
},
|
||||
validations: {
|
||||
pay_for: { required },
|
||||
system_references: { required }
|
||||
},
|
||||
watch: {
|
||||
'data': function() {
|
||||
this.pay_for = this.item.pay_for;
|
||||
this.system_references = this.item.system_references;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submitForm(){
|
||||
this.parameters = {pay_for : this.pay_for, system_references: this.system_references};
|
||||
this.item.pay_for = this.pay_for;
|
||||
this.item.system_references = this.system_references;
|
||||
this.submit(this.route('api.accounting.statement.details.update', this.data.id), 'put', this.section, true, true);
|
||||
},
|
||||
successHandler(){
|
||||
// this.closeModal();
|
||||
// this.formHandler('');
|
||||
},
|
||||
},
|
||||
mixins: [componentHandler]
|
||||
}
|
||||
</script>
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="row h-100 parentContainer">
|
||||
<div class="col-12" style="min-height: 20px;">
|
||||
<loading-component style="height: 20px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div id="accordion">
|
||||
<div class="card">
|
||||
<div class="card-header" id="headingOne">
|
||||
<h5 class="mb-0">
|
||||
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
||||
Filters
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
|
||||
<div class="card-group" style="margin-bottom: 0px;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Pay For</h3>
|
||||
<div class="card-tools">
|
||||
<div class="form-check" v-for="(match, index) in matches">
|
||||
<input class="form-check-input" type="checkbox" :value="match" :id="'match'+index" v-model="selected.matches">
|
||||
<label class="form-check-label" :for="'match' + index">
|
||||
{{ match }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="margin-top: 0px">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Date</h3>
|
||||
<div class="form-check" v-for="(day, index) in days" :key="day">
|
||||
<input class="form-check-input" type="checkbox" :id="'day'+index" :value="day" v-model="selected.days">
|
||||
<label class="form-check-label" :for="'day'+index">
|
||||
{{ day }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mb-2">
|
||||
<button type="button" class="btn btn-sm btn-primary" @click="fetchList(true)">
|
||||
<i class="fa fa-plus-square"></i>
|
||||
Filter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 v-if="$store.getters.getListData(section)[0] !== undefined" class="card-title">{{ $store.getters.getListData(section)[0].account_name }} - {{ $store.getters.getListData(section)[0].account_number }},{{ $store.getters.getListData(section)[0].account_type }} </h3><br/>
|
||||
<h3 v-if="$store.getters.getListData(section)[0] !== undefined" class="card-title">{{ new Date($store.getters.getListData(section)[0].account_statement_date_from).toDateString() }} -> {{ new Date($store.getters.getListData(section)[0].account_statement_date_to).toDateString() }}</h3>
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body table-responsive p-0">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Date</th>
|
||||
<th>Description 1</th>
|
||||
<th>Pay For</th>
|
||||
<th>System References</th>
|
||||
<th>Amount</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-show="!isLoading">
|
||||
<tr v-for="item in $store.getters.getListData(section)" :key="item.id">
|
||||
<td>{{item.id}}</td>
|
||||
<td>{{item.date}}</td>
|
||||
<td>{{item.transaction_description_1 | truncate(30, '...')}}</td>
|
||||
<td>{{item.pay_for}}</td>
|
||||
<td>{{item.system_references}}</td>
|
||||
<td>{{item.amount}}</td>
|
||||
<td>
|
||||
<a href="#">
|
||||
<i class="fa fa-edit blue requestModal" data-type="editSingleItem" @click="editModal({item})"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<div class="card-footer">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="editSingleItem">
|
||||
<edit-single-item-in-list-component v-if="data != null" :data="data" :section="'editSingleItem'" class="text-left"></edit-single-item-in-list-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<pagination-component :section="section" class="mb-5" ref="pagination"></pagination-component>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import EditSingleItemInListComponent from "../../accounting/elements/EditSingleItemInListComponent";
|
||||
export default {
|
||||
components: {EditSingleItemInListComponent},
|
||||
props: {
|
||||
statement: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
data: null,
|
||||
|
||||
section: 'statementTransactionsDetails',
|
||||
isLoading: false,
|
||||
|
||||
matches: ['exchange', 'shipping', 'none'],
|
||||
selected: {
|
||||
matches: [],
|
||||
days: []
|
||||
},
|
||||
|
||||
filters: {'per_page': 10, order_by: {column: 'id', DESC: true}, 'has_account_statement_id': this.statement},
|
||||
page: 1,
|
||||
|
||||
days: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pendingQueue () {
|
||||
return this.$store.getters.isInCompleteQueue(this.section);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
pendingQueue(inComplete, oldValue){
|
||||
if(inComplete){
|
||||
this.fetchList();
|
||||
}
|
||||
},
|
||||
selected: {
|
||||
handler: function () {
|
||||
//this.filters = {'per_page': 10, order_by: {column: 'id', DESC: true}};
|
||||
|
||||
//pay_for
|
||||
if(this.selected.matches.toString() != ""){
|
||||
const newArr = this.selected.matches.slice();
|
||||
const index = newArr.indexOf('none');
|
||||
if(index > -1){
|
||||
newArr.splice(index, 1, '');
|
||||
}
|
||||
const newObject = {pay_for_in: newArr};
|
||||
this.filters = {...this.filters, ...newObject};
|
||||
}
|
||||
else{
|
||||
delete this.filters.pay_for_in;
|
||||
}
|
||||
|
||||
//date
|
||||
if(this.selected.days.toString() != ""){
|
||||
const newArr = this.selected.days.slice();
|
||||
const newObject = {date_in: newArr};
|
||||
this.filters = {...this.filters, ...newObject};
|
||||
}
|
||||
else{
|
||||
delete this.filters.date_in;
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.setDecoratorDefault();
|
||||
this.$store.dispatch('updateListQueue', {'name': this.section, 'page': 1, 'filters': this.filters});
|
||||
},
|
||||
methods: {
|
||||
fetchList(isUpdate = false){
|
||||
this.isLoading = true;
|
||||
if(!isUpdate){
|
||||
let listDecorators = this.$store.getters.getListDetails(this.section);
|
||||
this.page = listDecorators.page;
|
||||
}
|
||||
this.submit(route('api.accounting.statement.details', this.statement) + '?page=' + this.page + '&filters=' + JSON.stringify(this.filters), 'get', this.section, false, false);
|
||||
},
|
||||
successHandler(response){
|
||||
this.$store.dispatch('completeList', {'name': this.section, 'data': response.payload.data});
|
||||
this.$refs.pagination.makePagination(response.payload.meta, response.payload.links + '&filters=' + JSON.stringify(this.filters));
|
||||
this.generateDays();
|
||||
this.isLoading = false;
|
||||
},
|
||||
editModal(param){
|
||||
this.data = param.item;
|
||||
},
|
||||
generateDays(){
|
||||
if(this.$store.getters.getListData(this.section)[0] !== undefined)
|
||||
{
|
||||
const startDate = new Date(this.$store.getters.getListData(this.section)[0].account_statement_date_from);
|
||||
const endDate = new Date(this.$store.getters.getListData(this.section)[0].account_statement_date_to);
|
||||
const days = [];
|
||||
for (let d = startDate; d <= endDate; d.setDate(d.getDate() + 1)) {
|
||||
const formattedDate = this.formatDate(d);
|
||||
days.push(formattedDate);
|
||||
}
|
||||
this.days = days;
|
||||
}
|
||||
},
|
||||
formatDate(date) {
|
||||
const year = date.getFullYear();
|
||||
const month = ('0' + (date.getMonth() + 1)).slice(-2);
|
||||
const day = ('0' + date.getDate()).slice(-2);
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,8 @@
|
||||
@extends('layouts.base_portal')
|
||||
@section('inner_content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<statement-transactions-details-component :statement="{{$statement}}"></statement-transactions-details-component>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -78,7 +78,7 @@
|
||||
<td>{{ $statement->begin_balance }}</td>
|
||||
<td>{{ $statement->end_balance }}</td>
|
||||
<td>
|
||||
<a href="{{ route('statements.show', $statement) }}" class="btn btn-primary btn-sm">View</a>
|
||||
<a href="{{ route('statements.transactions.details', $statement) }}" class="btn btn-primary btn-sm">View</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group(['prefix' => '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');
|
||||
});
|
||||
});
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user