Merge branch 'get-transactions-from-production' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into fix-account-statement-issue

# Conflicts:
#	app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php
This commit is contained in:
JiaSheng
2023-09-14 23:40:54 +08:00
14 changed files with 383 additions and 28 deletions
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class AmountExceed implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '>', $value);
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class AmountShort implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '<', $value);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class CreatedAfterOrEqual implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('created_at', '>=', Carbon::parse($value));
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class CreatedBeforeOrEqual implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('created_at', '<=', Carbon::parse($value));
}
}
@@ -13,6 +13,8 @@ use App\Models\StatementTransaction;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class CreateBankStatementTransactionOwnersProcessor
@@ -48,7 +50,7 @@ class CreateBankStatementTransactionOwnersProcessor
// Shipping Portal Sales
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 2);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 2, PaymentMethodType::WALLET);
foreach ($creditTransactions as $creditTransaction) {
if($creditTransaction['owner_type'] === Wallet::class) continue;
$transaction->owners()->firstOrCreate([
@@ -72,7 +74,7 @@ class CreateBankStatementTransactionOwnersProcessor
]);
}
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 5);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 5, null);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
@@ -191,25 +193,26 @@ class CreateBankStatementTransactionOwnersProcessor
}
private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) {
$dateRange = $this->getDateRange($date, 4);
$query = $model::whereIn('status', $statuses)
->where(function ($query) use ($ownerType, $paymentMethod, $type) {
if ($ownerType) {
$query->where('owner_type', $ownerType);
}
$dateRange = $this->getDateRange($date, 4);
if (App::environment(['production'])) {
$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 ($paymentMethod) {
$query->where('payment_method', '!=', $paymentMethod);
}
if ($type) {
$query->where('type', $type);
}
})
->whereDate('created_at', '>=', $dateRange['start_date'])
->whereDate('created_at', '<=', $dateRange['end_date'])
->where('amount', '>', ($amount - 0.05))
->where('amount', '<', ($amount + 0.05));
if ($type) {
$query->where('type', $type);
}
})
->whereDate('created_at', '>=', $dateRange['start_date'])
->whereDate('created_at', '<=', $dateRange['end_date'])
->where('amount', '>', ($amount - 0.05))
->where('amount', '<', ($amount + 0.05));
if ($query->count() > 1) {
$transactions = clone $query;
@@ -241,7 +244,6 @@ class CreateBankStatementTransactionOwnersProcessor
});
}
if ($ownerType === Wallet::class) {
$transactions = $transactions->whereHasMorph('owner', [Wallet::class], function ($q1) use ($keywords) {
return $q1->whereHasMorph('owner', [Company::class], function ($company) use($keywords) {
@@ -266,24 +268,60 @@ class CreateBankStatementTransactionOwnersProcessor
}
}
return $query->get();
return $query->get();
} else {
$result = $this->getTransactionsFromExchange($amount, $dateRange, $type, $ownerType, $paymentMethod);
$transactionsId = Arr::pluck($result, 'owner_id');
$query = $model::whereIn('id', $transactionsId);
return $query->get();
}
}
private function getTransactionsFromShippingPortal($amount, $dateRange, $type){
private function getTransactionsFromExchange($amount, $dateRange, $type, $ownerType, $paymentMethod){
$url = 'https://exchange.cief-malaysia.com/public/api/v1/transactions/mappable/query';
return $this->getFromExchange($url, $amount, $dateRange, $type, $ownerType, $paymentMethod);
}
private function getFromExchange($url, $amount, $dateRange, $type, $ownerType, $paymentMethod){
$paymentMethodFilter = "";
if ($paymentMethod) {
$paymentMethodFilter = ',"payment_method_not_in":['.$paymentMethod.']';
}
$ownerType = addslashes($ownerType);
try{
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2,3],"owner_type":"'. $ownerType . '"' . $paymentMethodFilter.',"type":'.$type.',"created_after_or_equal":"'.$dateRange['start_date'].'","created_before_or_equal":"'.$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 getTransactionsFromShippingPortal($amount, $dateRange, $type, $paymentMethod){
$url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query';
return $this->getFromShippingPortal($amount, $dateRange, $url, $type);
return $this->getFromShippingPortal($amount, $dateRange, $url, $type, $paymentMethod);
}
private function getGroupsFromShippingPortal($amount, $dateRange, $type){
private function getGroupsFromShippingPortal($amount, $dateRange, $type, $paymentMethod){
$url = 'https://izyim.cief-malaysia.com/public/api/v1/groups/query';
return $this->getFromShippingPortal($amount, $dateRange, $url, $type);
return $this->getFromShippingPortal($amount, $dateRange, $url, $type, $paymentMethod);
}
private function getFromShippingPortal($amount, $dateRange, $url, $type){
private function getFromShippingPortal($amount, $dateRange, $url, $type, $paymentMethod){
$paymentMethodFilter = "";
if ($paymentMethod) {
$paymentMethodFilter = ',"payment_method_not_in":['.$paymentMethod.']';
}
try{
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url.'?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).',"type_in:"['.$type.']}');
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2]'.$paymentMethodFilter.',"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).',"type_in":['.$type.']}');
$body = $response->getBody();
$data = json_decode($body, true);
$payload = $data['payload'];
@@ -0,0 +1,49 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Http\Resources\MappableTransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListMappableTransactionsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Transactions',
'message' => 'You have successfully retrieved a list of transactions'
];
}
/** @var ListsTransactions */
private $listsTransactions;
/**
* ListTransactionsLogic constructor.
* @param ListsTransactions $listsTransactions
*/
public function __construct(ListsTransactions $listsTransactions)
{
$this->listsTransactions = $listsTransactions;
}
public function logic(Request $request) : JsonResponse
{
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters')));
return $this->collectionResponse(MappableTransactionResource::collection($query));
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\ListMappableTransactionsLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListMappableTransactionsController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function list(Request $request, ListMappableTransactionsLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
+6 -1
View File
@@ -51,6 +51,10 @@ class Kernel extends HttpKernel
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'apipub' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
@@ -71,6 +75,7 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'valid.token' => ValidateToken::class
'valid.token' => ValidateToken::class,
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
];
}
@@ -0,0 +1,56 @@
<?php
namespace App\Http\Middleware;
use App\Models\PersonalAccessTokens;
use Closure;
use Illuminate\Http\Request;
class TokenCheckerMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
//Method 1: Token pass via query parameter
// Check if the api_key query parameter is present
if (!$request->query('api-key')) {
return response()->json(['message' => 'Invalid API key.'], 401);
}
// Check if the api_key is valid
$apiKey = $request->query('api-key');
$personalAccessToken = PersonalAccessTokens::where('token', $apiKey)->first();
if (!$personalAccessToken) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $next($request);
//Method 2: Token pass via request header
/*
$authHeader = $request->header('Authorization');
if (preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
$token = $matches[1];
// validate the token here
$personalAccessToken = PersonalAccessToken::where('token', $token)->first();
if (!$personalAccessToken) {
return response()->json(['error' => 'Unauthorized'], 401);
}
// if the token is valid, you can attach it to the request
$request->attributes->add(['bearerToken' => $token]);
return $next($request);
}
return response()->json(['error' => 'Unauthorized'], 401);
*/
}
}
@@ -0,0 +1,37 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Wallet;
use Illuminate\Http\Resources\Json\JsonResource;
class MappableTransactionResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$reference = null;
if($this->type === TransactionType::TOP_UP) {
$reference = $this->owner->owner->reference;
}
if($this->type === TransactionType::PAYMENT && $this->owner !== Wallet::class){
$reference = $this->owner->marking;
}
return [
'status' => 'success',
'system' => 'EXCHANGE',
'type' => $this->type,
'owner_type' => $this->owner_type,
'owner_id'=> $this->id,
'owner_reference'=> $reference,
];
}
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App\Models;
class PersonalAccessTokens extends AbstractModel
{
protected $table = 'personal_access_tokens';
}
+17
View File
@@ -46,6 +46,8 @@ class RouteServiceProvider extends ServiceProvider
$this->mapWebRoutes();
$this->mapApiPubRoutes();
//
}
@@ -77,4 +79,19 @@ class RouteServiceProvider extends ServiceProvider
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
/**
* Define the "apipub" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiPubRoutes()
{
Route::prefix('public/api')
->middleware('apipub')
->namespace($this->namespace)
->group(base_path('routes/apipub.php'));
}
}
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePersonalAccessTokensTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->bigIncrements('id');
// $table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('personal_access_tokens');
}
}
+9
View File
@@ -0,0 +1,9 @@
<?php
use Illuminate\Support\Facades\Route;
Route::group(['middleware' => 'apipub', 'prefix' => 'v1', 'as' => 'apipub.'], function () {
Route::group(['middleware' => 'token.check'], function () {
Route::get('transactions/mappable/query', 'Transactions\ListMappableTransactionsController@list')->name('transaction.mappable.list');
});
});