Merge branches 'regenerate-invoice', 'regenerate-invoice' and 'master' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into regenerate-invoice

This commit is contained in:
edmondlang
2023-09-06 15:27:53 +08:00
641 changed files with 30426 additions and 1747 deletions
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<php>
<ini name="display_errors" value="On" />
<ini name="display_startup_errors" value="On" />
</php>
<phpunit
colors="true"
>
<testsuites>
<testsuite name="dryrun">
<directory suffix="php">./tests/Browser/DryRun/</directory>
</testsuite>
</testsuites>
</phpunit>
+59
View File
@@ -0,0 +1,59 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:X521H/hWdbsG6S/JG0Q/BZgTo1azoV18kzqkqMQSDrQ=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=dusk
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=exchange-test
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
FILESYSTEM_DRIVER="documents"
JWT_SECRET=
JWT_TTL=1440
SHIPPING_URL=http://shipping-portal.test/
MIX_SHIPPING_URL="${SHIPPING_URL}"
BILLPLZ_BASE_URL="https://www.billplz-sandbox.com"
BILLPLZ_API_KEY="0fa4c710-761b-4a7a-a501-c2c2d02643d5"
BILLPLZ_X_SIGNATURE_KEY="S-pbNVthVRsvnPfZlgLwqqOg"
BILLPLZ_COLLECTION_ID="hev2wdjy"
+11
View File
@@ -57,3 +57,14 @@ BILLPLZ_API_KEY="d25c6170-dc00-45cd-b226-d702b957870c"
BILLPLZ_X_SIGNATURE_KEY="S-HdAU6QDubUrMErxJ-PCpgw"
BILLPLZ_COLLECTION_ID="t0cggbdd"
BILLPLZ_WALLET_COLLECTION_ID="t0cggbdd"
PERFEXCRM_BASE_URL=""
PERFEXCRM_API_KEY=""
PERFEXCRM_IS_ENABLED="false"
VOUCHERIFY_APPLICATION_ID=""
VOUCHERIFY_CLIENT_SECRET_KEY=""
VOUCHERIFY_VERSION="v2018-08-01"
VOUCHERIFY_URL="https://as1.api.voucherify.io"
-1
View File
@@ -21,7 +21,6 @@ gox.iml
rebuild_docker.sh
docker/*
db/*
docker-compose.yml
package-lock.json
public/*
/public/*
+16
View File
@@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
"name": "Listen for XDebug on Docker",
"type": "php",
"request": "launch",
"port": 9002,
"pathMappings": {
"/var/www/html": "${workspaceFolder}",
},
"log": true
}]
}
@@ -4,7 +4,8 @@ namespace App\Classes\General\Abstracts;
use App\Classes\Exceptions\ErrorException;
use App\Classes\Exceptions\InternalServerErrorException;
use App\Classes\Jobs\UserRiskAnalysis;
use App\Classes\Modules\Segments\Processors\RiskAnalysisProcessor;
use App\Classes\ValueObjects\Constants\Notifications;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
@@ -13,7 +14,9 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
abstract class AbstractControllerLogic
{
@@ -49,9 +52,12 @@ abstract class AbstractControllerLogic
* @return JsonResponse
*/
public function execute(Request $request) : JsonResponse {
try {
if(Auth::user()){
if(Auth::user()->type === 3) UserRiskAnalysis::dispatch(Auth::user(), $request->header('captcha-token'));
}
DB::beginTransaction();
$response = $this->logic($request);
@@ -61,6 +67,7 @@ abstract class AbstractControllerLogic
return $response;
} catch (ErrorException|GeneralExceptions $exception){
log::error($exception);
return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(),
$exception->getCode() ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler();
@@ -94,4 +101,4 @@ abstract class AbstractControllerLogic
return $this->response(json_decode($collection->response()->getContent(), true));
}
}
}
@@ -6,6 +6,7 @@ namespace App\Classes\General\Eloquent;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log;
abstract class AbstractListRecord extends AbstractGetRecord
{
@@ -23,6 +24,7 @@ abstract class AbstractListRecord extends AbstractGetRecord
return $this->handler($filters);
} catch (QueryException $exception){
log::error($exception);
throw new MalformedRequestException('Unable to fetch the list of records due to unexpected error');
}
@@ -43,4 +45,4 @@ abstract class AbstractListRecord extends AbstractGetRecord
}
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class Code implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('code', '=', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class CompanyIdNotIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereNotIn('company_id', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class CreatedAtBetween implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereBetween('created_at', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class CurrencyRateIdIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereIn('currency_rate_id', $value);
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class DateEnd implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('created_at', '<=', $value);
}
}
@@ -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,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class DateStart implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('created_at', '>=', $value);
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Eloquent\Builder;
class DoesNotHavePurchaseOrderStatusIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDoesntHave('transactions', function($transaction) use($value) {
return $transaction->where('transactions.type', TransactionType::PURCHASE_ORDER)->whereIn('transactions.status', $value);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class DoesNotHaveTransactionType implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDoesntHave('transactions', function($query) use($value) {
return $query->where('transactions.type', $value);
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class EmailLike implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('email', 'LIKE', '%'.$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,44 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\RoleTypes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class HasActiveReward implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){
// $userId = $value !== 1 ? $value : Auth::user()->id;
$userId = $value;
return $builder->where('user_id', $userId)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) {
$query->where('user_id', $userId);
});
}
else{
return $builder->where('user_id', Auth::user()->id)
->where(function ($query) {
$query->whereHas('reward', function ($subquery) {
$subquery->where('is_active', true);
})
->orWhereDoesntHave('reward');
})
->whereDoesntHave('voucher.redemptions.transaction.owner');
}
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Eloquent\Builder;
class HasPaymentStatusIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('transactions', function($query) use($value) {
return $query->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', $value);
});
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Eloquent\Builder;
class HasPurchaseOrderStatusIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('transactions', function($query) use($value) {
return $query->where('transactions.type', TransactionType::PURCHASE_ORDER)->whereIn('transactions.status', $value);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class HasTransactionType implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->has('transactions', function($query) use($value) {
return $query->where('transactions.type', $value);
});
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class HasUsedVoucher implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('user_id', Auth::user()->id)
->where(function ($query) {
$query->whereHas('voucher', function ($subquery) {
$subquery->whereHas('redemptions', function ($subsubquery) {
$subsubquery->whereHas('transaction', function ($subsubsubquery) {
$subsubsubquery->whereHas('owner');
});
});
});
});
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class HasUsedVoucherForAdmin implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
$userId = $value !== 1 ? $value : Auth::user()->id;
return $builder->where('user_id', $userId)
->where(function ($query) use ($userId){
$query->whereHas('voucher', function ($subquery) use ($userId){
$subquery->whereHas('redemptions', function ($subsubquery) use ($userId){
$subsubquery->whereHas('transaction', function ($subsubsubquery) use ($userId){
$subsubsubquery->whereHas('booking', function ($s4query) use ($userId){
$s4query->whereHas('company', function ($s5query) use ($userId) {
$s5query->whereHas('employees', function ($s6query) use ($userId){
$s6query->where('user_id', $userId);
});
});
});
});
});
});
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class IsActive implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('is_active', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class IsMapped implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $value ? $builder->whereHas('owners') : $builder->whereDoesntHave('owners');
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Database\Eloquent\Builder;
class IsMappedWithMultiple implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
$query = $builder->withCount(['owners' => function ($query){
$query->where('status', ApprovalStatus::PENDING_VERIFICATION);
}]);
return $value ? $query->having('owners_count', '>', 1) : $query->having('owners_count', '=', 1);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class MaxAmount implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '<=', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class MinAmount implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '>=', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OwnerId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('owner_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,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class RandomName implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('is_active', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class ReferenceLike implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('reference', 'LIKE', '%'.$value.'%');
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionAccountId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('account', function ($query) use ($value) {
$query->where('statement_accounts.id', $value);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionOwnerStatusIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('owners', function ($query) use ($value) {
return $query->whereIn('statement_transaction_owners.status', $value);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionOwnerTypeIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('owners', function ($query) use ($value) {
return $query->whereIn('type', $value);
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class TransactionId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('transaction_id', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class TypeIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereIn('type', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class UserId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('user_id', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WhereHasSeasonalSegment implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('seasonalSegments');
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WithWallets implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->with('wallets');
}
}
+19 -1
View File
@@ -2,6 +2,7 @@
namespace App\Classes\General;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
@@ -24,4 +25,21 @@ class Helper
return array_slice(get_class_methods($className), 1);
}
}
/**
* @param $log
* @return array
*/
static function debugLogger($log){
if($log && isset($log['message'])){
$message = $log['message'];
$substring = 'No data were found';
if (isset($message)) {
if (strpos($message, $substring) !== false) {
// Log::info('Message exist');
} else {
Log::info($log['message']);
}
}
}
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Classes\General\Interfaces;
use Illuminate\Database\Eloquent\Relations\MorphTo;
interface Notifiable
{
public function subject(): MorphTo;
public function target(): MorphTo;
public function causer(): MorphTo;
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\General\Interfaces;
use Illuminate\Database\Eloquent\Relations\MorphMany;
interface Voucherifiable
{
public function voucherifyEntities(): morphMany;
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\General\Traits;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
trait LogData
{
public static function boot()
{
parent::boot();
static::updating(function($model)
{
$tableName = Str::singular($model->table).'_logs';
$relationshipColumn = Str::singular($model->table).'_id';
$originalData = $model->getRawOriginal();
$originalData[$relationshipColumn] = $originalData['id'];
unset($originalData['id']);
// remove pivot columns
foreach($originalData as $key => $row){
if(str::startsWith($key, 'pivot_')){
unset($originalData[$key]);
}
}
if (!Schema::hasTable($tableName)) {
DB::statement('CREATE TABLE '.$tableName.' LIKE '.$model->table);
$indexs = DB::select('SHOW INDEX FROM '.$tableName.';');
$removedIndexes = [];
foreach ($indexs as $index){
if($index->Column_name === 'id' || in_array($index->Key_name, $removedIndexes)) continue;
DB::statement('ALTER TABLE '.$tableName.' drop index '.$index->Key_name);
$removedIndexes[] = $index->Key_name;
}
DB::statement('ALTER TABLE '.$tableName.' ADD COLUMN `'.$relationshipColumn.'` BIGINT NOT NULL AFTER `id`');
}
DB::table($tableName)->insert($originalData);
});
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
use Voucherify\VoucherifyClient;
use Voucherify\ClientException;
function createVoucherifyClient()
{
$apiID = config('voucherify.application_id');
$apiKey = config('voucherify.client_secret_key');
$apiVersion = config('voucherify.version');
$apiUrl = config('voucherify.url');
return new VoucherifyClient($apiID, $apiKey, $apiVersion, $apiUrl);
}
@@ -0,0 +1,27 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Accounting\Processors\CreateBankStatementTransactionOwnersProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CreateBankStatementTransactionOwners implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
(App()->make(CreateBankStatementTransactionOwnersProcessor::class))->execute();
}
public function delay($delay)
{
// Add delay in seconds to the job
$this->delay = $delay;
return $this;
}
}
@@ -0,0 +1,41 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMLead;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var CreateLeadPerfexCRMObject */
private $createLeadPerfexCRMObject;
/**
* CreatePerfexCRMCustomer constructor.
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
*/
public function __construct(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject)
{
$this->createLeadPerfexCRMObject = $createLeadPerfexCRMObject;
}
public function handle()
{
$lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createLeadPerfexCRMObject->getEmail());
if(!is_null($lead)){
(App()->make(UpdatesPerfexCRMLead::class))->execute($lead, $this->createLeadPerfexCRMObject->getCompanyReference());
}
else{
(App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject);
}
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CreatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var $transaction*/
private $transaction;
/**
* CreatePerfexCRMInvoice constructor.
* @param $transaction
*/
public function __construct($transaction)
{
$this->transaction = $transaction;
}
public function handle()
{
(App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($this->transaction);
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMTaskProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
class CreatePerfexCRMSingleTask implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var FetchesPerfexCRMLead */
private $fetchesPerfexCRMLead;
/** @var CreateTaskPerfexCRMObject */
private $createTaskPerfexCRMObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject
*/
public function __construct(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject)
{
$this->createTaskPerfexCRMObject = $createTaskPerfexCRMObject;
}
public function handle()
{
$lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createTaskPerfexCRMObject->getEmail());
if(!is_null($lead))
{
$this->createTaskPerfexCRMObject->setLeadId($lead->id);
(App()->make(CreatePerfexCRMTaskProcessor::class))->execute($this->createTaskPerfexCRMObject);
}
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Transactions\Processors\GeneratesGroupTransactionsPurchaseOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class GenerateGroupTransactionsPurchaseOrder implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 900;
public function handle()
{
(App()->make(GeneratesGroupTransactionsPurchaseOrder::class))->execute();
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Transactions\Processors\GeneratesGroupTransactionsWhiteForm;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class GenerateGroupTransactionsWhiteForm implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 900;
public function handle()
{
(App()->make(GeneratesGroupTransactionsWhiteForm::class))->execute();
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\GeneratesGroupTransactionsWhiteForm;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class GenerateInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Booking */
private $booking;
/**
* @param Booking $booking
*/
public function __construct(Booking $booking)
{
$this->booking = $booking;
}
public function handle()
{
$this->booking->transactions()->whereIn('transactions.type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->delete();
$this->booking->documents()->whereIn('document_type', [DocumentType::INVOICE, DocumentType::PURCHASE_ORDER, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->delete();
$this->booking->status = ApprovalStatus::APPROVED;
$this->booking->save();
(App()->make(CreateInvoiceTransactionProcessor::class))->execute($this->booking);
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Notifications\PaymentProofUploadedEmail;
use App\Models\Booking;
use App\Models\User;
use App\Models\File;
use App\Models\UserEmailVerification;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendUserPaymentProofUploadedEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var User */
private $user;
/** @var Booking */
private $booking;
/** @var File */
private $file;
/**
* SendUserVerificationEmail constructor.
* @param User $user
* @param UserEmailVerification $attempt
*/
public function __construct(User $user, Booking $booking, File $file)
{
$this->user = $user;
$this->booking = $booking;
$this->file = $file;
}
public function handle()
{
$this->user->notify(new PaymentProofUploadedEmail($this->user, $this->booking, $this->file));
}
}
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Processors\FetchPerfexCRMInvoiceProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\FetchPerfexCRMInvoiceObject;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean;
use App\Classes\ValueObjects\Constants\TransactionType;
class UpdatePerfexCRM implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/** @var */
private $transaction;
/** @var Boolean|null */
private $shouldCreateInvoice;
/**
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @param $transaction
* @param bool|null $shouldCreateInvoice
*/
public function __construct(UpdatePerfexCRMObject $updatePerfexCRMObject, $transaction, ?bool $shouldCreateInvoice = false)
{
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
$this->transaction = $transaction;
$this->shouldCreateInvoice = $shouldCreateInvoice;
}
public function handle()
{
//To use invoice as a reference to decide whether more tasks should be created
$this->updatePerfexCRMObject->setInvoiceId($this->getInvoiceIdOrCreateInvoice());
$result = (App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject);
if($this->transaction != null && $this->shouldCreateInvoice){
$updatePerfexCRMInvoiceObject = new UpdatePerfexCRMInvoiceObject(
$this->updatePerfexCRMObject->getContactEmail(),
$this->updatePerfexCRMObject->getProjectName(),
$result->projectId,
$this->transaction,
true
);
UpdatePerfexCRMInvoice::dispatch($updatePerfexCRMInvoiceObject);
}
}
private function getInvoiceIdOrCreateInvoice(){
if($this->transaction != null){
$fetchPerfexCRMInvoiceObject = new FetchPerfexCRMInvoiceObject(
$this->updatePerfexCRMObject->getContactEmail(),
$this->transaction
);
$invoiceId = (App()->make(FetchPerfexCRMInvoiceProcessor::class))->execute($fetchPerfexCRMInvoiceObject);
return $invoiceId;
}
return 0;
}
}
+101
View File
@@ -0,0 +1,101 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMInvoiceStatus;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
class UpdatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMInvoiceObject */
private $updatePerfexCRMInvoiceObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param UpdatePerfexCRMInvoiceObject $updatePerfexCRMInvoiceObject
*/
public function __construct(UpdatePerfexCRMInvoiceObject $updatePerfexCRMInvoiceObject)
{
$this->updatePerfexCRMInvoiceObject = $updatePerfexCRMInvoiceObject;
}
public function handle()
{
//get the client id
$customer = (App()->make(FetchesPerfexCRMCustomer::class))->execute($this->updatePerfexCRMInvoiceObject->getEmail());
$transaction = $this->updatePerfexCRMInvoiceObject->getTransaction();
//get the invoice id
$invoiceId = 0;
$invoiceStatus = 0;
$number = $transaction->bill_no;
$prefix = "INV-";
//This will remove the prefix if prefix already exist in the string
if (substr($number, 0, strlen($prefix)) == $prefix) {
$number = substr($number, strlen($prefix));
}
$number = 'EXC-'.$number;
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $number);
Log::error(json_encode('UpdatePerfexCRMInvoice debug $number: '.$number));
if(is_null($invoice)){
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction);
if ($result) {
$invoiceId = $result->payload['id'];
} else {
// Log::error(json_encode('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed'));
$log['message'] = 'UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed';
Helper::debugLogger($log);
}
}
else{
$invoiceId = $invoice->id;
$invoiceStatus = $invoice->status;
//This only run when invoice already exist and the invoice does not have a PAID status
if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){
Log::error(json_encode('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId()));
//update invoice
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $this->updatePerfexCRMInvoiceObject->getProjectId());
}
}
//create invoice payment
if($invoiceId != 0 && $invoiceStatus != PerfexCRMInvoiceStatus::PAID){
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject(
$invoiceId,
"$transaction->amount",
$date,
1,
"",
""
);
(App()->make(CreatesPerfexCRMInvoicePayment::class))->execute($invoicePaymentPerfexCRMObject);
}
}
}
+105
View File
@@ -0,0 +1,105 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class UpdatePerfexCRMPrelude implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Transaction */
private $transaction;
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/** @var Boolean|null */
private $shouldCreateInvoice;
/**
* @param Transaction $transaction
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @param bool|null $shouldCreateInvoice
*/
public function __construct(Transaction $transaction, UpdatePerfexCRMObject $updatePerfexCRMObject, ?bool $shouldCreateInvoice = false)
{
$this->transaction = $transaction;
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
$this->shouldCreateInvoice = $shouldCreateInvoice;
}
public function handle()
{
$serviceTypeName = $this->transaction->owner->company->services()->where('id', $this->transaction->owner->service_id)->first()->name;
$booking = $this->transaction->booking;
$bankDetails = $this->generateBankDetails($booking->bank);
$data = [
'amount' => number_format($this->transaction->amount, 2, '.', ''),
'currency' => $this->transaction->currency_id == 1 ? "MYR" : "CNY",
'service_type' => $serviceTypeName,
'bank_details' => $bankDetails,
'link_transfer' => config('app.url').'/transfer/'.$this->transaction->owner->marking,
'link_payments' => config('app.url').'/payments',
'link_autocount_or' => 'https://docs.google.com/spreadsheets/d/1Q3rJBGQ9Bo04HZp5WR9zbLp7pIW2kfDYsabxG7JON-4/edit#gid=2013983170',
];
$result = $this->replacePlaceholders($this->updatePerfexCRMObject->getTasks(), $data);
$this->updatePerfexCRMObject->setTasks($result);
UpdatePerfexCRM::dispatch($this->updatePerfexCRMObject, $this->transaction, $this->shouldCreateInvoice);
}
private function generateBankDetails($bank): array
{
return $this->transaction->owner->service_id == 4 ?
[
'1688_username' => $bank->account_no,
'1688_password' => $bank->holder_name,
'payment_pin' => $bank->bank_branch,
]:
[
'id' => $bank->id,
'type' => $bank->type,
'reference' => $bank->reference,
'bank_name' => $bank->bank_name,
'bank_branch' => $bank->bank_branch,
'holder_name' => $bank->holder_name,
'account_no' => $bank->account_no,
'country_id' => $bank->country_id,
'default' => $bank->default,
'status' => $bank->status,
];
}
function replacePlaceholders($template, $data, $prefix = '')
{
foreach ($template as $key => $value) {
foreach ($data as $dataKey => $dataValue) {
if (is_array($dataValue)) {
$template[$key] = $this->replacePlaceholders($template[$key], $dataValue, $dataKey);
} else {
if ($prefix != '') {
$template[$key] = str_replace('{' .$prefix. "." .$dataKey . '}', $dataValue, $template[$key]);
} else {
$template[$key] = str_replace('{' . $dataKey . '}', $dataValue, $template[$key]);
}
}
}
}
return $template;
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\Segments\Processors\RiskAnalysisProcessor;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class UserRiskAnalysis implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var User */
private $user;
/** @var string */
private $captchaToken;
/**
* UserRiskAnalysis constructor.
* @param User $user
* @param string $captchaToken
*/
public function __construct(User $user, string $captchaToken)
{
$this->user = $user;
$this->captchaToken = $captchaToken;
}
public function handle()
{
(app()->make(RiskAnalysisProcessor::class))->execute($this->user, $this->captchaToken);
}
}
@@ -0,0 +1,283 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction;
use App\Http\Resources\BankStatementTransactionResource;
use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Accounting\Services\FetchesBankStatementDetails;
use App\Classes\Modules\Accounting\Services\ListsBankStatementDetails;
use App\Models\StatementTransactionOwner;
use Illuminate\Support\Collection;
class ApproveDuplicateBankStatementDetailsStatusLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Update Duplicate Bank Statement Details Status',
'message' => 'You have successfully updated the Statement Transation Status'
];
}
/** @var UpdatesBankStatementTransactionOwnerStatus */
private $updatesBankStatementTransactionOwnerStatus;
/**
* @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus
*/
public function __construct(UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus)
{
$this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus;
}
// /**
// * Perform logic for approving or rejecting a statement transaction owner and handle matching records.
// *
// * @param Request $request The request object containing route parameters and data.
// * @return JsonResponse The JSON response indicating the result of the logic.
// */
// public function logic(Request $request): JsonResponse
// {
// // Determine the status based on the 'status' route parameter
// $status = $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED;
//
// // Find the statement transaction owner based on the 'id' route parameter
// $owner = StatementTransactionOwner::find($request->route('id'));
//
// // Execute an update action to change the status of the owner
// $this->updatesBankStatementTransactionOwnerStatus->execute($owner, $status);
//
// // If the status is 'approved', reject all other owners with the same system, owner type, and owner ID
// if ($status === ApprovalStatus::APPROVED) {
// StatementTransactionOwner::where('system', $owner->system)
// ->where('owner_type', $owner->owner_type)
// ->where('owner_id', $owner->owner_id)
// ->where('id', '!=', $owner->id)
// ->update(['status' => ApprovalStatus::REJECTED]);
// }
//
// // Find all siblings (owners with the same statement transaction ID)
// $siblings = StatementTransactionOwner::where('statement_transaction_id', $owner->statement_transaction_id)
// ->where('id', '!=', $owner->id)
// ->get();
//
// // Process each sibling
// foreach ($siblings as $sibling) {
//
// // If the status is 'approved', reject the sibling and save the changes
// if ($status === ApprovalStatus::APPROVED) {
// $sibling->status = ApprovalStatus::REJECTED;
// $sibling->save();
// }
//
// // Find all twins (owners with the same system, owner type, and owner ID)
// $twins = StatementTransactionOwner::where('system', $sibling->system)
// ->where('owner_type', $sibling->owner_type)
// ->where('owner_id', $sibling->owner_id)
// ->where('id', '!=', $sibling->id)
// ->get();
//
// // Process each twin
// foreach ($twins as $twin) {
// // Find all owners with the same statement transaction ID as the twin
// $owners = StatementTransactionOwner::where('statement_transaction_id', $twin->statement_transaction_id)
// ->where('id', '!=', $twin->id)
// ->get();
//
// // If there is only one owner (the twin itself), execute an update action to change its status to 'approved'
// if (count($owners) === 1) {
// $this->updatesBankStatementTransactionOwnerStatus->execute($twin, ApprovalStatus::APPROVED);
// }
// }
// }
//
// // Find all remaining matching owners for the related transaction
// $remainingMatches = StatementTransactionOwner::where('system', $owner->system)
// ->where('owner_type', $owner->owner_type)
// ->where('owner_id', $owner->owner_id)
// ->where('status', ApprovalStatus::PENDING_VERIFICATION) // Consider only pending owners
// ->get();
//
// // Process each remaining match
// foreach ($remainingMatches as $match) {
// // Find all owners with the same statement transaction ID as the match
// $owners = StatementTransactionOwner::where('statement_transaction_id', $match->statement_transaction_id)
// ->where('id', '!=', $match->id)
// ->get();
//
// // If there is only one owner (the match itself), execute an update action to change its status to 'approved'
// if (count($owners) === 1) {
// $this->updatesBankStatementTransactionOwnerStatus->execute($match, ApprovalStatus::APPROVED);
// }
// }
//
// // Return an empty response
// return $this->response([]);
// }
/**
* Perform logic for approving or rejecting a statement transaction owner and handle matching records.
*
* @param Request $request The request object containing route parameters and data.
* @return JsonResponse The JSON response indicating the result of the logic.
*/
public function logic(Request $request): JsonResponse
{
// Determine the approval status
$status = $this->getApprovalStatus($request);
// Find the statement transaction owner
$owner = $this->getOwner($request);
// Update owner status
$this->updateOwnerStatus($owner, $status);
// If the status is 'approved', handle the approval process
if ($status === ApprovalStatus::APPROVED) {
$this->handleApprovedStatus($owner);
}
// Check and approve remaining matches if any
$this->checkAndApproveRemainingMatches($owner);
// Return an empty response
return $this->response([]);
}
private function getApprovalStatus(Request $request): int
{
return $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED;
}
private function getOwner(Request $request): StatementTransactionOwner
{
return StatementTransactionOwner::find($request->route('id'));
}
private function updateOwnerStatus(StatementTransactionOwner $owner, int $status): void
{
$this->updatesBankStatementTransactionOwnerStatus->execute($owner, $status);
}
private function handleApprovedStatus(StatementTransactionOwner $owner): void
{
// Reject all other owners with the same system, owner type, and owner ID
$this->rejectOtherOwners($owner);
// Find all siblings and process them
$siblings = $this->getSiblings($owner);
$this->processSiblings($siblings);
}
private function rejectOtherOwners(StatementTransactionOwner $owner): void
{
StatementTransactionOwner::where('system', $owner->system)
->where('owner_type', $owner->owner_type)
->where('owner_id', $owner->owner_id)
->where('id', '!=', $owner->id)
->update(['status' => ApprovalStatus::REJECTED]);
}
private function getSiblings(StatementTransactionOwner $owner): Collection
{
return StatementTransactionOwner::where('statement_transaction_id', $owner->statement_transaction_id)
->where('id', '!=', $owner->id)
->get();
}
private function processSiblings(Collection $siblings): void
{
foreach ($siblings as $sibling) {
$this->processSibling($sibling);
}
}
private function processSibling(StatementTransactionOwner $sibling): void
{
// Reject the sibling and save the changes
$sibling->status = ApprovalStatus::REJECTED;
$sibling->save();
// Find all twins and process them
$twins = $this->getTwins($sibling);
$this->processTwins($twins);
}
private function getTwins(StatementTransactionOwner $sibling): Collection
{
return StatementTransactionOwner::where('system', $sibling->system)
->where('owner_type', $sibling->owner_type)
->where('owner_id', $sibling->owner_id)
->where('id', '!=', $sibling->id)
->get();
}
private function processTwins(Collection $twins): void
{
foreach ($twins as $twin) {
$this->processTwin($twin);
}
}
private function processTwin(StatementTransactionOwner $twin): void
{
// Find all owners with the same statement transaction ID as the twin
$owners = $this->getOwners($twin);
// If there is only one owner (the twin itself), approve it
if ($owners->count() === 1) {
$this->updateOwnerStatus($twin, ApprovalStatus::APPROVED);
}
}
private function getOwners(StatementTransactionOwner $transactionOwner): Collection
{
return StatementTransactionOwner::where('statement_transaction_id', $transactionOwner->statement_transaction_id)
->where('id', '!=', $transactionOwner->id)
->get();
}
private function checkAndApproveRemainingMatches(StatementTransactionOwner $owner): void
{
// Find all remaining matching owners for the related transaction
$remainingMatches = $this->getRemainingMatches($owner);
// Process each remaining match
foreach ($remainingMatches as $match) {
$this->processRemainingMatch($match);
}
}
private function getRemainingMatches(StatementTransactionOwner $owner): Collection
{
return StatementTransactionOwner::where('system', $owner->system)
->where('owner_type', $owner->owner_type)
->where('owner_id', $owner->owner_id)
->where('status', ApprovalStatus::PENDING_VERIFICATION)
->get();
}
private function processRemainingMatch(StatementTransactionOwner $match): void
{
// Find all owners with the same statement transaction ID as the match
$owners = $this->getOwners($match);
// If there is only one owner (the match itself), approve it
if ($owners->count() === 1) {
$this->updateOwnerStatus($match, ApprovalStatus::APPROVED);
}
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounting\Services\ListsBankStatementTransactions;
use App\Http\Resources\BankStatementTransactionResource;
use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
class GroupApproveStatementTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Group Approve Statement Transaction',
'message' => 'You have successfully approveed a group of Statement Transation'
];
}
/** @var ListsBankStatementTransactions */
private $listsBankStatementTransactions;
/** @var UpdatesBankStatementTransactionOwnerStatus */
private $updatesBankStatementTransactionOwnerStatus;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* @param ListsBankStatementTransactions $listsBankStatementTransactions
* @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(ListsBankStatementTransactions $listsBankStatementTransactions, UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, UpdatesTransactionStatus $updatesTransactionStatus)
{
$this->listsBankStatementTransactions = $listsBankStatementTransactions;
$this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
/**
* @param Request $request
* @return JsonResponse
* @throws MalformedRequestException
*/
public function logic(Request $request): JsonResponse
{
$filters = [
"min_amount" => 0,
"is_mapped" => true,
"is_mapped_with_multiple" => false,
"statement_transaction_owner_type_in" => [1, 2],
"statement_transaction_owner_status_in" => [1]
];
$statementTransactions = $this->listsBankStatementTransactions->execute($filters);
foreach ($statementTransactions as $statementTransaction) {
$owners = $statementTransaction->owners;
if (count($owners)) {
$this->updatesBankStatementTransactionOwnerStatus->execute($owners->first(), ApprovalStatus::APPROVED);
// automatically approve payment if pending verification
// if ($statementTrasactionOwner->owner->type !== StatementTransactionOwnerType::SALES) continue;
// if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION ) {
// $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED);
// }
}
}
return $this->response([]);
}
}
@@ -0,0 +1,147 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\CreateBankStatementTransactionOwners;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\AccountStatement;
use App\Models\StatementAccount;
use App\Models\StatementTransaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Maatwebsite\Excel\Facades\Excel;
class ImportBankStatementLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Import Bank Statement Transactions Details',
'message' => 'You have successfully updated the Bank Statement Transactions Details'
];
}
/**
* @param Request $request
* @return JsonResponse
* @throws MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$files = $request->file('files');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
foreach ($object->getFiles() as $file){
$collection = Excel::toCollection(null, json_decode($file)->file_info->original->file, null, null, true);
$sheet = $collection->first()->skip(1);
$statementDetails = $sheet->first();
$accountNumber = $statementDetails[0];
$accountType = $statementDetails[1];
$accountName = $statementDetails[2];
$accountCurrency = $statementDetails[3];
$dateFrom = carbon::parse(str_replace(' MY (UTC+08:00)', '', $statementDetails[4]));
$dateTo = carbon::parse(str_replace(' MY (UTC+08:00)', '', $statementDetails[5]));
$totalDebit = $statementDetails[6];
$totalCredit = $statementDetails[7];
$beginBalance = $statementDetails[8];
$endBalance = $statementDetails[9];
$account = StatementAccount::updateOrCreate(
['number' => $accountNumber],
[
'type' => $accountType,
'name' => $accountName,
'currency' => $accountCurrency,
]
);
$statement = AccountStatement::where('date_from', $dateFrom)
->where('date_to', $dateTo)
->where('total_amount', $totalDebit ?: $totalCredit,)
->where('begin_balance', $beginBalance)
->where('end_balance', $endBalance)->first();
if(!$statement){
$statement = new AccountStatement([
'date_from' => $dateFrom,
'date_to' => $dateTo,
'total_amount' => $totalDebit ?: $totalCredit,
'begin_balance' => $beginBalance,
'end_balance' => $endBalance,
]);
}
$account->statements()->save($statement);
// CreateBankStatementTransactionOwners::dispatch($statement);
$sheet->map(function ($row) use ($statement, $account) {
$transactionRef = $row[15];
$amount = $row[17] !== '-' ? ((float) str_replace(',', '', $row[17])) : (-((float) str_replace(',', '', $row[16])));
$transactionDate = $row[10] !== '-' ? carbon::parse(str_replace(' MY (UTC+08:00)', '', $row[10]) . $row[11]) : null;
$postingDate = carbon::createFromFormat('d/M/Y H:i', str_replace(' MY (UTC+08:00)', '', $row[12]) . str_replace(' MY (UTC+08:00)', '', $row[13]));
$transactionDescription = is_numeric($row[14]) ? (int) sprintf('%.2f', $row[14]) : $row[14];
$tellerId = $row[19];
$branchChannel = $row[20];
$transactionCode = $row[21];
$endBalance = $row[22];
$description2 = $row[25];
$description3 = $row[26];
$description4 = $row[27];
$description5 = $row[28];
$transaction = new StatementTransaction([
'transaction_ref' => $transactionRef,
'amount' => $amount,
'transaction_date' => $transactionDate,
'posting_date' => $postingDate,
'transaction_description' => $transactionDescription,
'teller_id' => $tellerId,
'branch_channel' => $branchChannel,
'transaction_code' => $transactionCode,
'end_balance' => $endBalance,
'transaction_description_2' => $description2,
'transaction_description_3' => $description3,
'transaction_description_4' => $description4,
'transaction_description_5' => $description5,
]);
// Check if the transaction already exists for this statement
$existingTransaction = StatementTransaction::where('transaction_ref', $transactionRef)
->where('posting_date', $postingDate)
->where('amount', $amount)
->where('transaction_description', $transactionDescription)
->where('teller_id', $tellerId)
->where('branch_channel', $branchChannel)
->where('transaction_code', $transactionCode)
->where('end_balance', $endBalance)
->first();
if (!$existingTransaction) {
$statement->transactions()->save($transaction);
}
return $transaction;
});
}
return $this->response([]);
}
}
@@ -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,53 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounting\Services\ListsBankStatementDetails;
use App\Classes\Modules\Accounting\Services\ListsBankStatementTransactions;
use App\Http\Resources\BankStatementTransactionResource;
use App\Models\StatementTransaction;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListBankStatementTransactionsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Bank Statement Transactions',
'message' => 'You have successfully retrieved a Bank Statement Transactions'
];
}
/** @var ListsBankStatementTransactions */
private $listsBankStatementTransactions;
/**
* @param ListsBankStatementTransactions $listsBankStatementTransactions
*/
public function __construct(ListsBankStatementTransactions $listsBankStatementTransactions)
{
$this->listsBankStatementTransactions = $listsBankStatementTransactions;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->listsBankStatementTransactions->execute($this->listsBankStatementTransactions->deserializeFilters($request->input('filters')));
return $this->collectionResponse(BankStatementTransactionResource::collection($query));
}
}
@@ -0,0 +1,152 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounting\Services\CreatesBankStatementTransactionOwner;
use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction;
use App\Classes\Modules\Accounting\Processors\ListShippingPortalTransactions;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use App\Classes\ValueObjects\Constants\SystemType;
use App\Classes\Modules\Accounting\Processors\ChecksBillNumber;
use App\Classes\ValueObjects\Constants\ShippingTransactionType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Transaction;
use App\Models\Wallet;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
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 FetchesBankStatementTransaction */
private $fetchesBankStatementTransaction;
/** @var ChecksBillNumber */
private $checksBillNumber;
/**
* @param FetchesBankStatementTransaction $fetchesBankStatementTransaction
* @param ChecksBillNumber $checksBillNumber
*/
public function __construct(FetchesBankStatementTransaction $fetchesBankStatementTransaction, ChecksBillNumber $checksBillNumber)
{
$this->fetchesBankStatementTransaction = $fetchesBankStatementTransaction;
$this->checksBillNumber = $checksBillNumber;
}
public function logic(Request $request): JsonResponse
{
$bankStatementTransaction = $this->fetchesBankStatementTransaction->execute(['id' => $request->route('id')]);
$transactionReference = $request->input('transaction_reference');
$systemReference = $request->input('system_references');
$owner_type = $owner_id = $owner_reference = $statementTransactionOwnerType = $system = null;
$salesSystems = ['lite', 'cntr', 'probashi', 'pets'];
$allowedSystems = array_merge($salesSystems, ['exchange', 'izyim']);
if (!in_array($systemReference, $allowedSystems) && !in_array($request->input('pay_for'), ['internal_bank_transfer', 'others'])) {
throw new MalformedRequestException('System Reference not allowed');
}
switch ($request->input('pay_for')) {
case 'sales':
$owner_reference = $transactionReference;
$statementTransactionOwnerType = StatementTransactionOwnerType::SALES;
break;
case 'top_up':
$owner_reference = $transactionReference;
$statementTransactionOwnerType = StatementTransactionOwnerType::WALLET_TOP_UP;
break;
case 'internal_bank_transfer':
$statementTransactionOwnerType = StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_IN;
break;
case 'others':
$owner_reference = $transactionReference;
$statementTransactionOwnerType = StatementTransactionOwnerType::NON_OPERATIONAL;
break;
default:
throw new MalformedRequestException('Transaction Type Not Allowed');
}
if (in_array($systemReference, ['exchange', 'izyim'])) {
$transaction = $this->checksBillNumber->execute($transactionReference, $systemReference);
if (is_array($transaction) && empty($transaction)) {
throw new MalformedRequestException('Transaction Not Found.');
}
if($systemReference === 'exchange') {
$owner_type = Transaction::class;
$owner_id = $transaction->id;
if($transaction->type === TransactionType::TOP_UP) {
$owner_reference = $transaction->owner->owner->reference;
}
if($transaction->type === TransactionType::PAYMENT && $transaction->owner_type === Booking::class) {
$owner_reference = $transaction->owner->marking;
}
}
if($systemReference === 'izyim') {
$transaction = $transaction[0];
$payFor = $request->input('pay_for');
$transactionType = $transaction['type'];
if (($payFor === 'sales' && !in_array($transactionType, [ShippingTransactionType::PAYMENT, ShippingTransactionType::GROUP_PAYMENT]))
|| ($payFor === 'top_up' && !in_array($transactionType, [ShippingTransactionType::TOP_UP, ShippingTransactionType::GROUP_PAYMENT]))) {
throw new MalformedRequestException('Transaction Type does not match.');
}
$owner_type = Transaction::class;
$owner_id = $transaction['owner_id'];
$owner_reference = $transaction['owner_reference'];
}
}
$system = $systemReference != null ? SystemType::SYSTEM_NAMES[$systemReference] : '';
$this->createBankStatementTransactionOwner($bankStatementTransaction, $statementTransactionOwnerType, $system, $owner_type, $owner_id, $owner_reference);
return $this->response([]);
}
private function createBankStatementTransactionOwner($bankStatementTransaction, $statementTransactionOwnerType, $system, $owner_type, $owner_id, $owner_reference)
{
$ownerData = [
'type' => $statementTransactionOwnerType,
'system' => $system,
'owner_type' => $owner_type,
'owner_id' => $owner_id,
'owner_reference' => $owner_reference,
];
$bankStatementTransaction->owners()->firstOrCreate($ownerData);
}
}
@@ -0,0 +1,81 @@
<?php
namespace App\Classes\Modules\Accounting\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction;
use App\Http\Resources\BankStatementTransactionResource;
use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Update Statement Transaction Status',
'message' => 'You have successfully updated the Statement Transation Status'
];
}
/** @var FetchesBankStatementTransaction */
private $fetchesBankStatementTransaction;
/** @var UpdatesBankStatementTransactionOwnerStatus */
private $updatesBankStatementTransactionOwnerStatus;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* UpdateAnnouncementLogic constructor.
* @param FetchesBankStatementTransaction $fetchesBankStatementTransaction
* @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(
FetchesBankStatementTransaction $fetchesBankStatementTransaction,
UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus,
UpdatesTransactionStatus $updatesTransactionStatus
) {
$this->fetchesBankStatementTransaction = $fetchesBankStatementTransaction;
$this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
{
$statementTrasaction = $this->fetchesBankStatementTransaction->execute(['id' => $request->route('id')]);
$statementTrasactionOwner = $statementTrasaction->owners->first();
$this->updatesBankStatementTransactionOwnerStatus->execute($statementTrasactionOwner, $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
// todo-new: approve payments status, need to check the owner(if system is shipping, need to api with shipping portal)
// if ($request->route('status') == 'approve') {
// if ($statementTrasactionOwner->transaction->type === StatementTransactionOwnerType::SALES) {
// if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION) {
// $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED);
// }
// }
// }
return $this->resourceResponse(new BankStatementTransactionResource($statementTrasaction));
}
}
@@ -0,0 +1,137 @@
<?php
namespace App\Classes\Modules\Accounting\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean;
class BankStatementTransactionObject implements DataTransferObject
{
/** @var int */
private $statement_transaction_id;
/** @var int */
private $type;
/** @var string */
private $system;
/** @var string */
private $owner_type;
/** @var int */
private $owner_id;
/** @var string */
private $invoice_reference;
/** @var string */
private $receipt_reference;
/** @var Boolean */
private $is_auto_mapped;
/** @var int|null */
private $status;
/**
* BankStatementDetailObject constructor.
* @param string $pay_for
* @param string $system_references
* @param int|null $type
*/
public function __construct(
$statement_transaction_id,
$type,
$system,
$owner_type,
$owner_id,
$invoice_reference,
$receipt_reference,
$is_auto_mapped,
?int $status = ApprovalStatus::PENDING_VERIFICATION
) {
$this->statement_transaction_id = $statement_transaction_id;
$this->type = $type;
$this->system = $system;
$this->owner_type = $owner_type;
$this->owner_id = $owner_id;
$this->invoice_reference = $invoice_reference;
$this->receipt_reference = $receipt_reference;
$this->is_auto_mapped = $is_auto_mapped;
$this->status = $status;
}
/**
* @return int
*/
public function getStatementTransactionId(): int
{
return $this->statement_transaction_id;
}
/**
* @return int
*/
public function getType(): int
{
return $this->type;
}
/**
* @return string
*/
public function getOwnerType(): string
{
return $this->owner_type;
}
/**
* @return int
*/
public function getOwnerId(): int
{
return $this->owner_id;
}
/**
* @return string
*/
public function getSystem(): string
{
return $this->system;
}
/**
* @return string
*/
public function getInvoiceReference(): string
{
return $this->invoice_reference;
}
/**
* @return string
*/
public function getReceipteReference(): string
{
return $this->receipt_reference;
}
/**
* @return Boolean
*/
public function getIsAutoMapped(): Boolean
{
return $this->is_auto_mapped;
}
/**
* @return int
*/
public function getStatus(): int
{
return $this->status;
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\Modules\Accounting\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class BankStatementTrasactionOwnerObject 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,37 @@
<?php
namespace App\Classes\Modules\Accounting\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class ChecksBillNumber
{
public function execute($bill_no, $system_reference)
{
if ($system_reference == 'izyim') {
try {
$url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query';
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"bill_no":"' . $bill_no . '"}');
$body = $response->getBody();
$data = json_decode($body, true);
$payload = $data['payload'];
return $payload['data'];
} catch (\Exception $exception) {
throw new MalformedRequestException($exception->getMessage());
}
}
if ($system_reference == 'exchange') {
$transaction = Transaction::where('bill_no', $bill_no)->first();
if ($transaction) {
return $transaction;
}
}
// if not found
throw new MalformedRequestException('Bill Number Not Found.');
}
}
@@ -0,0 +1,255 @@
<?php
namespace App\Classes\Modules\Accounting\Processors;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Company;
use App\Models\Group;
use App\Models\StatementTransaction;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class CreateBankStatementTransactionOwnersProcessor
{
/**
* @return void
*/
public function execute() {
$transactions = StatementTransaction::whereDoesntHave('owners', function($query){
return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})->orderBy('posting_date')->get();
// $transactions = StatementTransaction::whereDoesntHave('owners')->where('amount', '<', 0)->get();
foreach ($transactions as $transaction) {
if($transaction->amount > 0){
// Exchange Sales
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
'owner_id'=> $creditTransaction->id,
'owner_reference'=> $creditTransaction->owner->marking,
]);
}
// Shipping Portal Sales
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date), 2);
foreach ($creditTransactions as $creditTransaction) {
if($creditTransaction['owner_type'] === Wallet::class) continue;
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
'owner_id'=> $creditTransaction['owner_id'],
'owner_reference'=> $creditTransaction['owner_reference'],
]);
}
// Exchange Wallet Top Up
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
'owner_id'=> $creditTransaction->id,
'owner_reference'=> $creditTransaction->owner->owner->reference,
]);
}
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date), 5);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
'owner_id'=> $creditTransaction['owner_id'],
'owner_reference'=> $creditTransaction['owner_reference'],
]);
}
// fpx charge refund
if($transaction->transaction_description === 'DUITNOW S/CHRG REFUND'){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE_REFUND
]);
}
// Customer Refund
// INTERNAL_BANK_TRANSFER_IN
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_IN
]);
}
}
if($transaction->amount < 0){
// Supplier Purchase Order Payments
foreach (['YSN', 'HCK', 'ATVANTIC', 'HIGH HILL'] as $reference){
if(str_contains($transaction->transaction_description.' '.$transaction->transaction_description_2.' '.$transaction->transaction_description_3.' '.$transaction->transaction_description_4.' '.$transaction->transaction_description_5 , $reference)) {
$paymentDateStart = $transaction->posting_date->startOfDay()->subDays(1);
$paymentDateEnd = $transaction->posting_date->endOfDay();
if($paymentDateStart->dayOfWeek === Carbon::SUNDAY){
$paymentDateStart->subDays(2);
}
$issuer = Company::where('name', 'like', '%'.$reference.'%')->get()->pluck('id');
$debitTransactions = Group::whereIn('issuer', $issuer)->where('amount', '>=', (($transaction->amount * -1) - 0.01))
->where('amount', '<=', (($transaction->amount * -1) + 0.01))->whereDate('created_at', '>=', $paymentDateStart)->whereDate('created_at', '<=', $paymentDateEnd)->get();
foreach ($debitTransactions as $debitTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SUPPLIER_PAYMENT,
'system' => 'EXCHANGE',
'owner_type' => Group::class,
'owner_id'=> $debitTransaction->id,
'owner_reference'=> $debitTransaction->reference
]);
}
}
}
// Exchange Wallet Withdrawal
$debitTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::DEBIT_NOTE, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
foreach ($debitTransactions as $debitTransaction) {
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_WITHDRAWAL,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
'owner_id'=> $debitTransaction->id,
'owner_reference'=> $debitTransaction->owner->owner->marking,
]);
}
// SALARY
// STATUTORY
if(str_contains($transaction->transaction_description_2, 'PEMBANGUNAN SUMBER') || str_contains($transaction->transaction_description_2, 'HASIL') || str_contains($transaction->transaction_description_2, 'PERTUBUHAN KESELAMAT') || str_contains($transaction->transaction_description_2, 'KUMPULAN WANG SIMPAN')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::STATUTORY
]);
}
// FPX_CHARGE
if($transaction->transaction_description === 'DR DUITNOW S/CHRG' || str_contains($transaction->transaction_description, 'Manual FPX') || str_contains($transaction->transaction_description, 'CMS - DR FPX CHG')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE
]);
}
// BANK_CHARGE
if($transaction->transaction_description === 'CMS - DR CORP CHG' || $transaction->transaction_description === 'MONTHLY PROFIT DEBIT'){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::BANK_CHARGE
]);
}
// CREDIT_CARD_PAYMENT
if(str_contains($transaction->transaction_description_2, 'VISA CARD')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::CREDIT_CARD_PAYMENT
]);
}
// INTERNAL_BANK_TRANSFER_OUT
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE') || str_contains($transaction->transaction_description_2, 'CIEF WORLWIDE') || str_contains($transaction->transaction_description_2, 'IZYIM GLOBAL')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_OUT
]);
}
// non-operational charges
if(str_contains($transaction->transaction_description_2, 'HIRE PURCHASE') || str_contains($transaction->transaction_description_2, 'TENAGA NASIONAL') || str_contains($transaction->transaction_description, 'CABLE CHARGE') || str_contains($transaction->transaction_description_2, 'CTOS DATA SYSTEMS') || str_contains($transaction->transaction_description_2, 'MAXIS')){
$transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::NON_OPERATIONAL
]);
}
}
}
}
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, $type){
$url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query';
return $this->getFromShippingPortal($amount, $dateRange, $url, $type);
}
private function getGroupsFromShippingPortal($amount, $dateRange, $type){
$url = 'https://izyim.cief-malaysia.com/public/api/v1/groups/query';
return $this->getFromShippingPortal($amount, $dateRange, $url, $type);
}
private function getFromShippingPortal($amount, $dateRange, $url, $type){
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.']}');
$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', strtotime('-1 day', $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,35 @@
<?php
namespace App\Classes\Modules\Accounting\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
use \Illuminate\Database\Eloquent\Collection;
class ListShippingPortalTransactions
{
public function execute($filters)
{
try {
$url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query/with-details';
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters=' . json_encode($filters));
$body = $response->getBody();
$data = json_decode($body, true);
$payload = $data['payload'];
return $data['payload']['data'];
} catch (\Exception $exception) {
// dd($exception->getMessage());
throw new MalformedRequestException($exception->getMessage());
// preg_match('/\{.*\}/s', $exception->getMessage(), $matches);
// $jsonError = json_decode($matches[0]);
// Retrieved Transactions failed
// throw new MalformedRequestException($jsonError->title);
}
// if not found
throw new MalformedRequestException('Bill Number Not Found.');
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\Accounting\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounting\DataTransferObjects\BankStatementTransactionObject;
use App\Models\StatementTransactionOwner;
class CreatesBankStatementTransactionOwner extends AbstractUpdateRecord
{
/**
* @param StatementTransactionOwner $model
* @param BankStatementDetailsObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(BankStatementTransactionObject $object)
{
$model = new StatementTransactionOwner();
$model->statement_transaction_id = $object->getStatementTransactionId();
$model->type = $object->getType();
$model->system = $object->getSystem();
$model->owner_type = $object->getOwnerType();
$model->owner_id = $object->getOwnerId();
$model->invoice_reference = $object->getInvoiceReference();
$model->receipt_reference = $object->getReceipteReference();
$model->is_auto_mapped = $object->getIsAutoMapped();
$model->status = $object->getStatus();
return $this->handler($model);
}
}
@@ -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\StatementTransactionOwner;
class FetchesBankStatementDetails extends AbstractFetchRecord
{
/** @var StatementTransactionOwner */
private $repository;
/**
* FetchesBankStatementDetails constructor.
* @param StatementTransactionOwner $repository
*/
public function __construct(StatementTransactionOwner $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\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\StatementTransaction;
class FetchesBankStatementTransaction extends AbstractFetchRecord
{
/** @var StatementTransaction */
private $repository;
/**
* FetchesBankStatementDetails constructor.
* @param StatementTransactionOwner $repository
*/
public function __construct(StatementTransaction $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\StatementTransactionOwner;
class ListsBankStatementDetails extends AbstractListRecord
{
/** @var StatementTransactionOwner */
private $repository;
/**
* ListsBankStatementDetails constructor.
* @param StatementTransactionOwner $repository
*/
public function __construct(StatementTransactionOwner $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\Accounting\Services;
use App\Classes\General\Eloquent\AbstractListRecord;
use App\Models\StatementTransaction;
use Illuminate\Database\Eloquent\Builder;
use App\Models\StatementTransactionOwner;
class ListsBankStatementTransactions extends AbstractListRecord
{
/** @var StatementTransaction */
private $repository;
/**
* ListsBankStatementDetails constructor.
* @param StatementTransaction $repository
*/
public function __construct(StatementTransaction $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\StatementTransactionOwner;
class UpdatesBankStatementDetails extends AbstractUpdateRecord
{
/**
* @param StatementTransactionOwner $model
* @param BankStatementDetailsObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(StatementTransactionOwner $model, BankStatementDetailObject $object)
{
$model->system_references = $object->getSystemReferences();
$model->pay_for = $object->getPayFor();
return $this->handler($model);
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Modules\Accounting\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounting\DataTransferObjects\BankStatementTransactionObject;
use App\Models\StatementTransactionOwner;
class UpdatesBankStatementTransactionOwner extends AbstractUpdateRecord
{
/**
* @param StatementTransactionOwner $model
* @param BankStatementDetailsObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(StatementTransactionOwner $model, BankStatementTransactionObject $object)
{
$model->statement_transaction_id = $object->getStatementTransactionId();
$model->type = $object->getType();
$model->system = $object->getSystem();
$model->owner_type = $object->getOwnerType();
$model->owner_id = $object->getOwnerId();
$model->invoice_reference = $object->getInvoiceReference();
$model->receipt_reference = $object->getReceipteReference();
$model->is_auto_mapped = $object->getIsAutoMapped();
$model->status = $object->getStatus();
return $this->handler($model);
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Modules\Accounting\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\StatementTransactionOwner;
class UpdatesBankStatementTransactionOwnerStatus extends AbstractUpdateRecord
{
/**
* @param StatementTransactionOwner $model
* @param BankStatementDetailsObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(StatementTransactionOwner $model, int $status)
{
$model->status = $status;
return $this->handler($model);
}
}
@@ -10,16 +10,26 @@ use App\Classes\Modules\Accounts\Processors\GenerateEmailVerificationAttemptProc
use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor;
use App\Classes\Modules\Vouchers\Processors\CreateVoucherProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Jobs\CreatePerfexCRMCustomer;
use App\Classes\Modules\Segments\DataTransferObjects\SeasonalSegmentObject;
use App\Models\Company;
use App\Models\Segment;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment;
class CreateCustomerLogic extends AbstractControllerLogic
{
@@ -55,6 +65,18 @@ class CreateCustomerLogic extends AbstractControllerLogic
/** @var GenerateEmailVerificationAttemptProcessor */
private $generateEmailVerificationAttemptProcessor;
/** @var CreatesSeasonalSegment */
private $createsSeasonalSegment;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/** @var NewCustomerToVoucherifyProcessor */
private $newCustomerToVoucherifyProcessor;
/** @var CreateVoucherProcessor */
private $createVoucherProcessor;
/**
* CreateCustomerLogic constructor.
* @param CreateUserProcessor $createUserProcessor
@@ -64,8 +86,13 @@ class CreateCustomerLogic extends AbstractControllerLogic
* @param AssignSegmentProcessor $assignSegmentProcessor
* @param AuthenticationProcessor $authenticationProcessor
* @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor
* @param CreatesSeasonalSegment $createsSeasonalSegment
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
* @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor
* @param CreateVoucherProcessor $createVoucherProcessor
*/
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor)
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor,
CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor)
{
$this->createUserProcessor = $createUserProcessor;
$this->createCompanyProcessor = $createCompanyProcessor;
@@ -74,6 +101,10 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->assignSegmentProcessor = $assignSegmentProcessor;
$this->authenticationProcessor = $authenticationProcessor;
$this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor;
$this->createsSeasonalSegment = $createsSeasonalSegment;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
$this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor;
$this->createVoucherProcessor = $createVoucherProcessor;
}
/**
@@ -87,22 +118,50 @@ class CreateCustomerLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
/** @var User $user */
$user = $this->createUserProcessor->execute($request, RoleTypes::USER, App::environment(['local']) ? ApprovalStatus::APPROVED : ApprovalStatus::PENDING_VERIFICATION);
/** @var Company $company */
$company = $this->createCompanyProcessor->execute($request, BusinessType::IMPORTER, $request->input('type'), ApprovalStatus::PENDING_SUBMISSION);
$company = $this->createCompanyProcessor->execute($request, BusinessType::IMPORTER, $request->input('type') === CompanyType::COMPANY_BUSINESS ? CompanyType::COMPANY_BUSINESS : CompanyType::PERSONAL_BUSINESS, ApprovalStatus::PENDING_SUBMISSION);
$this->createContactProcessor->execute($request, $company);
$Object = new EmploymentObject($company, $user);
$this->assignEmployeeProcessor->execute($Object);
// assign STANDARD_SEGMENT to all new customers
$this->assignSegmentProcessor->execute($company);
$this->generateEmailVerificationAttemptProcessor->execute($user);
// assign other standard segment to all new customers
$otherDefaultSegmentToAdd = Segment::whereIn('name', ['HONEY TRAP NEW REGISTRATION'])->get();
$start_date = Carbon::now();
$end_date = Carbon::now()->addDays(30);
foreach ($otherDefaultSegmentToAdd as $segment) {
$seasonalSegmentObject = new SeasonalSegmentObject($company->id, $segment->id, $start_date, $end_date ?? null);
return $this->response($this->authenticationProcessor->execute($request));
$this->createsSeasonalSegment->execute($seasonalSegmentObject);
$this->assignSegmentProcessor->execute($company, $segment->id);
}
if(config('perfexcrm.is_enabled') == 'true'){
$createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject(
$request->input('name'),
$request->input('email'),
$request->input('phone'),
$request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name'),
$company->reference
);
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
$this->generateEmailVerificationAttemptProcessor->execute($user);
$this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true);
$this->createVoucherProcessor->execute($user, 'WELCOME50%OFF');
return $this->response($this->authenticationProcessor->execute($request, false));
}
}
}
@@ -0,0 +1,61 @@
<?php
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanFetchUser;
use App\Http\Resources\UserCompanyResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchUserByEmailLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved User',
'message' => 'You have successfully retrieved a User by email'
];
}
/** @var CanFetchUser */
private $canFetchUser;
/** @var FetchesUser */
private $fetchesUser;
/**
* FetchUserByEmailLogic constructor.
* @param CanFetchUser $canFetchUser
* @param FetchesUser $fetchesUser
*/
public function __construct(CanFetchUser $canFetchUser, FetchesUser $fetchesCompany)
{
$this->canFetchUser = $canFetchUser;
$this->fetchesUser = $fetchesCompany;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchUser->passes();
$query = $this->fetchesUser->execute(['email' => $request->route('email')]);
return $this->resourceResponse(new UserCompanyResource($query));
}
}
@@ -4,7 +4,7 @@ namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\UpdatesUser;
use App\Classes\Modules\Accounts\Services\UpdatesUserFullName;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanUpdateUser;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
@@ -29,8 +29,8 @@ class UpdateUserLogic extends AbstractControllerLogic
/** @var CanUpdateUser */
private $canUpdateUser;
/** @var UpdatesUser */
private $updatesUser;
/** @var UpdatesUserFullName */
private $updatesUserFullName;
/** @var FetchesUser */
private $fetchesUser;
@@ -41,10 +41,10 @@ class UpdateUserLogic extends AbstractControllerLogic
* @param UpdatesUser $updatesUser
* @param FetchesUser $fetchesUSer
*/
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUser $updatesUser, FetchesUser $fetchesUser)
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUserFullName $updatesUserFullName, FetchesUser $fetchesUser)
{
$this->canUpdateUser = $canUpdateUser;
$this->updatesUser = $updatesUser;
$this->updatesUserFullName = $updatesUserFullName;
$this->fetchesUser = $fetchesUser;
}
@@ -64,7 +64,7 @@ class UpdateUserLogic extends AbstractControllerLogic
$query = $this->fetchesUser->execute(['id' => $request->route('id')]);
$query = $this->updatesUser->execute($query, $object);
$query = $this->updatesUserFullName->execute($query, $object);
return $this->resourceResponse(new UserResource($query));
@@ -0,0 +1,78 @@
<?php
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\UpdatesUser;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanUpdateUser;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use App\Http\Resources\UserResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateUserRoleLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Admin Role',
'message' => 'You have successfully updated the Admin Role'
];
}
/** @var CanUpdateUser */
private $canUpdateUser;
/** @var UpdatesUser */
private $updatesUser;
/** @var FetchesUser */
private $fetchesUser;
/**
* UpdateAddressLogic constructor.
* @param CanUpdateUser $canUpdateUser
* @param UpdatesUser $updatesUser
* @param FetchesUser $fetchesUSer
*/
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUser $updatesUser, FetchesUser $fetchesUser)
{
$this->canUpdateUser = $canUpdateUser;
$this->updatesUser = $updatesUser;
$this->fetchesUser = $fetchesUser;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesUser->execute(['id' => $request->route('id')]);
$object = new UserObject(
$query->name,
$query->email,
$query->password,
$query->password,
$request->input('type'),
$query->status,
);
$this->canUpdateUser->passes($object);
$query = $this->updatesUser->execute($query, $object);
return $this->resourceResponse(new UserResource($query));
}
}
@@ -8,6 +8,9 @@ use App\Classes\Modules\Accounts\Services\AuthenticationRedirect;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken;
use App\Classes\Modules\Accounts\Standards\Rules\CanAuthenticateUser;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor;
use App\Classes\ValueObjects\Constants\Milestones;
use Illuminate\Http\Request;
class AuthenticationProcessor
@@ -28,6 +31,13 @@ class AuthenticationProcessor
/** @var AuthenticationRedirect */
private $authenticationRedirect;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/** @var NewCustomerToVoucherifyProcessor */
private $newCustomerToVoucherifyProcessor;
/**
* AuthenticationProcessor constructor.
* @param CanAuthenticateUser $canAuthenticateUser
@@ -35,14 +45,18 @@ class AuthenticationProcessor
* @param GeneratesAuthenticationToken $generatesAuthenticationToken
* @param FetchesUser $fetchesUser
* @param AuthenticationRedirect $authenticationRedirect
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
* @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor
*/
public function __construct(CanAuthenticateUser $canAuthenticateUser, AuthenticatesUser $authenticatesUser, GeneratesAuthenticationToken $generatesAuthenticationToken, FetchesUser $fetchesUser, AuthenticationRedirect $authenticationRedirect)
public function __construct(CanAuthenticateUser $canAuthenticateUser, AuthenticatesUser $authenticatesUser, GeneratesAuthenticationToken $generatesAuthenticationToken, FetchesUser $fetchesUser, AuthenticationRedirect $authenticationRedirect, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor)
{
$this->canAuthenticateUser = $canAuthenticateUser;
$this->authenticatesUser = $authenticatesUser;
$this->generatesAuthenticationToken = $generatesAuthenticationToken;
$this->fetchesUser = $fetchesUser;
$this->authenticationRedirect = $authenticationRedirect;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
$this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor;
}
@@ -53,7 +67,7 @@ class AuthenticationProcessor
* @throws \App\Classes\Exceptions\AccessUnauthorisedException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request): array {
public function execute(Request $request, bool $isSignIn = true): array {
$object = new AuthenticationCredentialsObject($request->input('email'), $request->input('password'));
@@ -63,8 +77,13 @@ class AuthenticationProcessor
$user = $this->fetchesUser->execute(['email' => $object->getEmail()]);
if($isSignIn){
$this->newCustomerToVoucherifyProcessor->execute(0, $user, false);
}
//cief todo: case study 1
//$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]);
return ['access_token' => $this->generatesAuthenticationToken->execute($user), 'redirect_url' => $this->authenticationRedirect->url($user)];
}
}
}
@@ -65,8 +65,12 @@ class GeneratesAuthenticationToken {
];
if($user->type === RoleTypes::USER) {
/** @var Company $companyModule */
$claims = array_merge($claims, [
'company_id' => $company->id
'company_id' => $company->id,
'company_name' => $company->name,
'company_marking' => $company->reference,
]);
}
@@ -3,7 +3,7 @@
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use App\Models\User;
class UpdatesUser extends AbstractUpdateRecord
@@ -15,9 +15,10 @@ class UpdatesUser extends AbstractUpdateRecord
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(User $model, FullNameObject $object) {
public function execute(User $model, UserObject $object) {
$model->name = $object->getName();
$model->type = $object->getType();
return $this->handler($model);
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Models\User;
class UpdatesUserFullName extends AbstractUpdateRecord
{
/**
* @param User $model
* @param FullNameObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(User $model, FullNameObject $object) {
$model->name = $object->getName();
return $this->handler($model);
}
}
@@ -9,10 +9,12 @@ use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Http\Resources\AddressResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\ValueObjects\Constants\Milestones;
class CreateAddressLogic extends AbstractControllerLogic
{
@@ -39,19 +41,25 @@ class CreateAddressLogic extends AbstractControllerLogic
/** @var CreatesAddress */
private $createsAddress;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/**
* CreateAddressLogic constructor.
* @param CanCreateAddress $canCreateAddress
* @param FetchesDistrict $fetchesDistrict
* @param FetchesCompany $fetchesCompany
* @param CreatesAddress $createsAddress
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
*/
public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompany $fetchesCompany, CreatesAddress $createsAddress)
public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompany $fetchesCompany, CreatesAddress $createsAddress, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor)
{
$this->canCreateAddress = $canCreateAddress;
$this->fetchesDistrict = $fetchesDistrict;
$this->fetchesCompany = $fetchesCompany;
$this->createsAddress = $createsAddress;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
}
/**
@@ -70,10 +78,15 @@ class CreateAddressLogic extends AbstractControllerLogic
$this->canCreateAddress->passes($object);
$query = $this->createsAddress->execute($this->fetchesCompany->execute(['id' => $request->input('company_id')]), $object);
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$query = $this->createsAddress->execute($company, $object);
//cief todo: case study 6
// $user = $company->employees()->first();
// $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_6]);
return $this->resourceResponse(new AddressResource($query));
}
}
}
@@ -11,7 +11,7 @@ use App\Classes\Modules\Announcements\Services\CreatesAnnouncement;
use App\Classes\Modules\Announcements\Processors\AssignAnnouncementToSegmentProcessor;
use App\Http\Resources\AnnouncementResource;
use Carbon\Carbon;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -67,8 +67,8 @@ class CreateAnnouncementLogic extends AbstractControllerLogic
$annoucement_object = new AnnouncementObject(
$request->input('title'),
$request->input('description'),
$request->input('starting_on'),
$request->input('ending_on')
Carbon::createFromFormat('d-m-Y', $request->input('starting_on'))->format('Y-m-d H:i:s'),
Carbon::createFromFormat('d-m-Y', $request->input('ending_on'))->format('Y-m-d H:i:s')
);
$this->canCreateAnnouncement->passes($annoucement_object);
@@ -10,7 +10,7 @@ use App\Classes\Modules\Announcements\Services\FetchesAnnouncement;
use App\Classes\Modules\Announcements\Services\UpdatesAnnouncement;
use App\Http\Resources\AnnouncementResource;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -66,8 +66,8 @@ class UpdateAnnouncementLogic extends AbstractControllerLogic
$annoucement_object = new AnnouncementObject(
$request->input('title'),
$request->input('description'),
$request->input('starting_on'),
$request->input('ending_on')
Carbon::createFromFormat('d-m-Y', $request->input('starting_on'))->format('Y-m-d H:i:s'),
Carbon::createFromFormat('d-m-Y', $request->input('ending_on'))->format('Y-m-d H:i:s')
);
$this->canUpdateAnnouncement->passes($annoucement_object);
@@ -6,8 +6,12 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Banks\Standards\Rules\CanCreateBank;
use App\Classes\Modules\Banks\Services\CreatesBank;
use App\Classes\Modules\Banks\Services\CreatesBankLog;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Http\Resources\BankResource;
use App\Classes\ValueObjects\Constants\Milestones;
use ErrorException;
use Illuminate\Http\JsonResponse;
@@ -32,19 +36,37 @@ class CreateBankLogic extends AbstractControllerLogic
/** @var CreatesBank */
private $createsBank;
/** @var CreatesBankLog */
private $createsBankLog;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/**
* CreateBankLogic constructor.
* @param CanCreateBank $canCreateBank
* @param CreatesBank $createsBank
* @param CreatesBankLog $createsBankLog
* @param FetchesCompany $fetchesCompany
* @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
*/
public function __construct(
CanCreateBank $canCreateBank,
CreatesBank $createsBank
CreatesBank $createsBank,
CreatesBankLog $createsBankLog,
FetchesCompany $fetchesCompany,
CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor
)
{
$this->canCreateBank = $canCreateBank;
$this->createsBank = $createsBank;
$this->createsBankLog = $createsBankLog;
$this->fetchesCompany = $fetchesCompany;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
}
/**
@@ -56,7 +78,6 @@ class CreateBankLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$bank_object = new BankObject($request->input('company_id'), $request->input('account_type'),
$request->input('bank_name'), $request->input('holder_name'), $request->input('account_no'),
$request->input('bank_branch'), $request->input('swift'), $request->input('snap'),
@@ -66,7 +87,14 @@ class CreateBankLogic extends AbstractControllerLogic
$bank = $this->createsBank->execute($bank_object);
// $bankLog = $this->createsBankLog->execute($bank);
//cief todo: case study 4
// $company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
// $user = $company->employees()->first();
// $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_4]);
return $this->resourceResponse(new BankResource($bank));
}
}
}
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Banks\Services\FetchesBank;
use App\Classes\Modules\Banks\Standards\Rules\CanDeleteBank;
use App\Classes\Modules\Banks\Services\DeletesBank;
use App\Classes\Modules\Banks\Services\CreatesBankLog;
use App\Http\Resources\BankResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -33,22 +34,27 @@ class DeleteBankLogic extends AbstractControllerLogic
/** @var FetchesBank */
private $fetchesBank;
/** @var CreatesBankLog */
private $createsBankLog;
/**
* DeleteBankLogic constructor.
* @param CanDeleteBank $canDeleteBank
* @param DeletesBank $deletesBank
* @param FetchesBank $fetchesBank
* @param CreatesBankLog $createsBankLog
*/
public function __construct(
CanDeleteBank $canDeleteBank,
DeletesBank $deletesBank,
FetchesBank $fetchesBank
FetchesBank $fetchesBank,
CreatesBankLog $createsBankLog
)
{
$this->canDeleteBank = $canDeleteBank;
$this->deletesBank = $deletesBank;
$this->fetchesBank = $fetchesBank;
$this->createsBankLog = $createsBankLog;
}
/**
@@ -69,7 +75,9 @@ class DeleteBankLogic extends AbstractControllerLogic
throw new RequestValidationException('You can\'t delete bank account when it set to default');
}
$this->deletesBank->execute($bank);
$bank = $this->deletesBank->execute($bank);
// $bankLog = $this->createsBankLog->execute($bank);
return $this->response([]);
}
@@ -10,6 +10,8 @@ use App\Classes\Modules\Banks\Services\FetchesBank;
use App\Classes\Modules\Banks\Standards\Rules\CanUpdateBank;
use App\Classes\Modules\Banks\Services\UpdatesBank;
use App\Classes\Modules\Banks\Services\CreatesBankLog;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use ErrorException;
@@ -39,21 +41,27 @@ class UpdateBankLogic extends AbstractControllerLogic
/** @var FetchesBank */
private $fetchesBank;
/** @var CreatesBankLog */
private $createsBankLog;
/**
* UpdateBankLogic constructor.
* @param CanUpdateBank $canUpdateBank
* @param UpdatesBank $updatesBank
* @param FetchesBank $fetchesBank
* @param CreatesBankLog $createsBankLog
*/
public function __construct(
CanUpdateBank $canUpdateBank,
UpdatesBank $updatesBank,
FetchesBank $fetchesBank
FetchesBank $fetchesBank,
CreatesBankLog $createsBankLog
)
{
$this->canUpdateBank = $canUpdateBank;
$this->updatesBank = $updatesBank;
$this->fetchesBank = $fetchesBank;
$this->createsBankLog = $createsBankLog;
}
/**
@@ -84,6 +92,8 @@ class UpdateBankLogic extends AbstractControllerLogic
$bank_query = $this->updatesBank->execute($bank, $bankObject);
// $bankLog = $this->createsBankLog->execute($bank_query);
return $this->resourceResponse(new BankResource($bank_query));
}
@@ -6,6 +6,7 @@ use App\Http\Resources\BankResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Banks\Services\FetchesBank;
use App\Classes\Modules\Banks\Services\UpdatesBankStatus;
use App\Classes\Modules\Banks\Services\CreatesBankLog;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -28,18 +29,24 @@ class UpdateBankStatusLogic extends AbstractControllerLogic
/** @var UpdatesBankStatus */
private $updatesBankStatus;
/** @var CreatesBankLog */
private $createsBankLog;
/**
* UpdateBankStatusLogic constructor.
* @param FetchesBank $fetchesBank
* @param UpdatesBankStatus $updatesBankStatus
* @param CreatesBankLog $createsBankLog
*/
public function __construct(
FetchesBank $fetchesBank,
UpdatesBankStatus $updatesBankStatus
UpdatesBankStatus $updatesBankStatus,
CreatesBankLog $createsBankLog
)
{
$this->fetchesBank = $fetchesBank;
$this->updatesBankStatus = $updatesBankStatus;
$this->createsBankLog = $createsBankLog;
}
/**
@@ -55,6 +62,8 @@ class UpdateBankStatusLogic extends AbstractControllerLogic
$bank_query = $this->updatesBankStatus->execute($bank, $request->input('status'));
// $bankLog = $this->createsBankLog->execute($bank_query);
return $this->resourceResponse(new BankResource($bank_query));
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Modules\Banks\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Bank;
use App\Models\BankLog;
class CreatesBankLog extends AbstractUpdateRecord
{
/**
* @param Bank $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Bank $object) {
$model = new BankLog();
$model->bank_id = $object->id;
$model->company_id = $object->company_id;
$model->reference = $object->reference;
$model->bank_name = $object->bank_name;
$model->holder_name = $object->holder_name;
$model->account_no = $object->account_no;
$model->bank_branch = $object->bank_branch;
$model->swift = $object->swift;
$model->snap = $object->snap;
$model->type = $object->type;
$model->country_id = $object->country_id;
return $this->handler($model);
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Billplzs\ControllersLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
@@ -16,6 +17,7 @@ use Illuminate\Http\JsonResponse;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\General\Abstracts\AbstractControllerLogic;
@@ -23,6 +25,7 @@ use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance;
class CallbackBillplzLogic
{
@@ -40,19 +43,28 @@ class CallbackBillplzLogic
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var CreateCashBackTransactionProcessor */
private $createCashBackTransactionProcessor;
/** @var RecalculatesWalletBalance */
private $recalculatesWalletBalance;
/**
* CallbackBillplzLogic constructor.
* @param GetBillplzBill $getBillplzBill
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdatesWalletBalance $updatesWalletBalance
* @param RecalculatesWalletBalance $recalculatesWalletBalance
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance)
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance)
{
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updatesWalletBalance = $updatesWalletBalance;
$this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor;
$this->recalculatesWalletBalance = $recalculatesWalletBalance;
}
@@ -80,26 +92,29 @@ class CallbackBillplzLogic
$status = ApprovalStatus::APPROVED;
}
if($billPlz->state === 'due') {
$status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
}
if($transaction->status !== ApprovalStatus::COMPLETED){
if($transaction->owner instanceof Wallet && $transaction->status !== ApprovalStatus::APPROVED && $status === ApprovalStatus::APPROVED) {
$this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);
}
if($transaction->status !== ApprovalStatus::COMPLETED && $transaction->status !== ApprovalStatus::APPROVED){
$this->updatesTransactionStatus->execute($transaction, $status);
}
if($transaction->owner instanceof Wallet) {
$this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);
}
// if ($transaction->type == TransactionType::PAYMENT) {
// $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction);
// }
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
$marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking;
$marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : (count($transaction->owner->owner->bookings()->get())? $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking: null);
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking, 'transaction' => $transaction, 'status' => $status]);
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking ?? null, 'transaction' => $transaction, 'status' => $status]);
}
}
@@ -4,6 +4,8 @@ namespace App\Classes\Modules\Billplzs\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class CreatesBillplzBill
{
@@ -25,7 +27,7 @@ class CreatesBillplzBill
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->post(config('billplz.base_url').'/api/v3/bills', [
'collection_id' => $wallet ? config('billplz.wallet_collection_id') : config('billplz.collection_id'),
'name' => $name,
'email' => $email,
'email' => App::environment('production') ? $email : 'development@cief-malaysia.com',
'description' => $description,
'amount' => $this->finalizeAmount($amount),
'redirect_url' => route('online_payment.redirect'),
@@ -43,6 +45,7 @@ class CreatesBillplzBill
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
@@ -2,16 +2,16 @@
namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\ApprovesDocument;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\RejectsDocument;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
@@ -26,14 +26,15 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic
* @param ApprovesDocument $approvesDocument
* @param RejectsDocument $rejectsDocument
* @param FetchesDocument $fetchesDocument
* @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
* @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument)
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->approvesDocument = $approvesDocument;
$this->rejectsDocument = $rejectsDocument;
$this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor;
}
/**
@@ -58,6 +59,9 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic
/** @var RejectsDocument */
private $rejectsDocument;
/** @var CreateCashBackTransactionProcessor */
private $createCashBackTransactionProcessor;
/**
* @param Request $request
* @return JsonResponse
@@ -65,7 +69,6 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$status = $request->route('status');
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('payment_id')]);
@@ -74,7 +77,7 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic
$this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
// $this->createInvoiceTransactionProcessor->execute($transaction->booking);
// $this->createCashBackTransactionProcessor->execute($transaction);
return $this->response([]);
}
@@ -64,8 +64,8 @@ class AutoPurchaseOrderFillLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$bookings = Booking::where(function($query){
return $query->whereMonth('created_at', 11)->orWhereMonth('created_at', 12);
$bookings = Booking::where('service_id', '!=', 4)->where(function($query){
return $query->whereMonth('created_at', '=', 03)->whereYear('created_at', 2023);
})->whereDoesntHave('transactions', function($q){
$q->where('type', TransactionType::PURCHASE_ORDER);
$q->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]);
@@ -111,4 +111,4 @@ class AutoPurchaseOrderFillLogic extends AbstractControllerLogic
return $this->response([]);
}
}
}
@@ -13,8 +13,12 @@ use App\Classes\Modules\Bookings\Services\CreatesBooking;
use App\Classes\Modules\Bookings\Services\GeneratesBookingMarking;
use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject;
use App\Classes\Modules\PerfexCRM\Processors\BookingToPerfexCRMProcessor;
use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor;
use App\Classes\ValueObjects\Constants\Milestones;
use App\Http\Resources\BookingResource;
use App\Models\Booking;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -44,19 +48,30 @@ class CreateBookingLogic extends AbstractControllerLogic
/** @var FetchesCompany */
private $fetchesCompany;
/** @var BookingToPerfexCRMProcessor */
private $bookingToPerfexCRMProcessor;
/** @var CheckMilestonesForRewardProcessor */
private $checkMilestonesForRewardProcessor;
/**
* CreateBookingLogic constructor.
* @param CanCreateBooking $canCreateBooking
* @param CreatesBooking $createsBooking
* @param GeneratesBookingMarking $generatesBookingMarking
* @param FetchesCompany $fetchesCompany
* @param BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor
* @param CheckMilestoneForRewardProcessor $checkMilestonesForRewardProcessor
*/
public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany)
public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany, BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor)
{
$this->canCreateBooking = $canCreateBooking;
$this->createsBooking = $createsBooking;
$this->generatesBookingMarking = $generatesBookingMarking;
$this->fetchesCompany = $fetchesCompany;
$this->bookingToPerfexCRMProcessor = $bookingToPerfexCRMProcessor;
$this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor;
}
@@ -75,9 +90,18 @@ class CreateBookingLogic extends AbstractControllerLogic
$this->canCreateBooking->passes($object);
/** @var Booking $booking */
$booking = $this->createsBooking->execute($company, $object);
if(config('perfexcrm.is_enabled') == 'true'){
$this->bookingToPerfexCRMProcessor->execute($booking);
}
//cief todo: case study 5
// $user = $company->employees()->first();
// $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_5]);
return $this->resourceResponse(new BookingResource($booking));
}
}
}

Some files were not shown because too many files have changed in this diff Show More