Update: laravel 8 to 12, php 7.3 to php 8.3, Jenkinsfile, Unit/Feature testing, vapor, docker

This commit is contained in:
Dillon Ngo
2026-04-03 06:10:58 +08:00
parent d376bbeff3
commit 00e796c1a3
142 changed files with 3336 additions and 1104 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
FILESYSTEM_DRIVER="documents"
FILESYSTEM_DISK="documents"
JWT_SECRET=
JWT_TTL=1440
+12
View File
@@ -0,0 +1,12 @@
APP_NAME=Laravel
APP_ENV=testing
APP_KEY=base64:utnZQgraE9iHT+4xCoDP2p7MdQmBweGyP0b6Mp1ksds=
JWT_SECRET=4DlpggxJJeV1nVeHPPf83mSGsoJEmA8bpuSFdFN0VCvwqkE084iYOqoed0q47Ee2
DB_CONNECTION=mysql
DB_HOST=172.18.0.3
DB_PORT=3306
DB_DATABASE=ci_test_exchange
DB_USERNAME=ci
DB_PASSWORD=bi9y@T8r
+3
View File
@@ -6,6 +6,7 @@
**/.idea/
.env
.env.backup
.env.testing.example
.phpunit.result.cache
Homestead.json
Homestead.yaml
@@ -31,3 +32,5 @@ public
.env.production
.env.staging
.env.development
docz/*
.phpunit.cache/
+7
View File
@@ -19,12 +19,19 @@
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>
<script>
setInterval(function() {
window.location.href = "/";
}, 60000); // 60000 ms = 1 minute, 300000 ms = 5 minutes
</script>
</head>
<body>
<div class="content">
<h1>We'll be back soon!</h1>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
<p>&mdash; CIEF EXCHANGE</p>
<a href="/" class="btn">Go Back Home</a>
</div>
</body>
</html>
Vendored
+43 -3
View File
@@ -9,8 +9,8 @@
pipeline {
agent {
docker {
args '--group-add 992 -v /var/run/docker.sock:/var/run/docker.sock'
image '303644228504.dkr.ecr.ap-southeast-1.amazonaws.com/jenkins-pipeline-agent:latest'
args '--network ci-net --group-add 992 -v /var/run/docker.sock:/var/run/docker.sock'
image '303644228504.dkr.ecr.ap-southeast-1.amazonaws.com/jenkins-pipeline-agent-php-8.3:latest'
registryCredentialsId "ecr:ap-southeast-1:aws-ec2-instance-iam-role"
registryUrl "https://303644228504.dkr.ecr.ap-southeast-1.amazonaws.com"
}
@@ -53,6 +53,15 @@ pipeline {
branch: GIT_BRANCH
)
break
case "vapor/test": //cief todo: 137
pusherKeyCredId = 'pusher-test-key'
pusherCluster = 'ap1'
git(
url: 'https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git',
credentialsId: 'gitlab-jenkins-localhost',
branch: GIT_BRANCH
)
break
case "origin/dillon/34-jenkins-vapor":
git(
url: 'https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git',
@@ -84,7 +93,35 @@ pipeline {
stage('Tests') {
steps {
sh 'vendor/bin/phpunit tests/Unit'
// sh 'vendor/bin/phpunit tests/Unit'
sh '''
set -e
export APP_ENV=testing
# export APP_KEY=$(php -r "echo 'base64:'.base64_encode(random_bytes(32));")
# export JWT_SECRET=$(php -r "echo bin2hex(random_bytes(32));")
# Show which PHP binary is used
which php
php -v
# List PHP modules to confirm pdo_mysql
php -m | grep pdo_mysql || echo "pdo_mysql not loaded"
# Show DB environment variables
echo "DB_CONNECTION=$DB_CONNECTION"
echo "DB_HOST=$DB_HOST"
echo "DB_PORT=$DB_PORT"
echo "DB_DATABASE=$DB_DATABASE"
echo "DB_USERNAME=$DB_USERNAME"
# Do NOT echo password in logs
php artisan migrate:fresh --force
vendor/bin/phpunit -c phpunit.ci.xml --group ok_to_run
# vendor/bin/phpunit --filter AuthenticationTest
# vendor/bin/phpunit -c phpunit.ci.xml --filter ListOrderTrackingLogicTest
'''
script{
currentBuild.description = 'Step 4 of 6 Completed'
}
@@ -107,6 +144,9 @@ pipeline {
case "vapor/development":
sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'"
break
case "vapor/test":
sh "vendor/bin/vapor deploy test --message='${gitCommitMessage}'"
break
case "origin/dillon/34-jenkins-vapor":
sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'"
break
@@ -4,7 +4,6 @@ namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class IsNotFullyRefunded implements Filter
{
@@ -19,6 +18,6 @@ class IsNotFullyRefunded implements Filter
return $builder->withSum(['transactions as total_refund_amount' => function($q) {
$q->refunds()->where('status', ApprovalStatus::APPROVED);
}], 'original_amount')
->having('total_refund_amount', '<', DB::raw('original_amount'));
->havingRaw('total_refund_amount < original_amount');
}
}
@@ -3,7 +3,6 @@
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class IsPartialRefund implements Filter
{
@@ -17,9 +16,9 @@ class IsPartialRefund implements Filter
{
return $builder->whereHas('owner', function ($q) use ($value) {
if ($value) {
$q->where('original_amount', '!=', DB::raw('transactions.original_amount'));
$q->whereRaw('original_amount != transactions.original_amount');
} else {
$q->where('original_amount', DB::raw('transactions.original_amount'));
$q->whereRaw('original_amount = transactions.original_amount');
}
});
}
+1 -1
View File
@@ -46,7 +46,7 @@ class SendWelcomeVoucherEmail implements ShouldQueue
{
$currentDatetime = Carbon::now();
$dateToCompare = Carbon::parse($this->voucher->end_date);
if (!$this->user->hasAttribute($this->voucher->code."_EMAIL_COUNT")
if (!$this->user->hasCustomAttribute($this->voucher->code."_EMAIL_COUNT")
&& $this->user->rewards->where('voucher_id', $this->voucher->id)->count() > 0
&& $currentDatetime->isBefore($dateToCompare))
{
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Accounts\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use Illuminate\Validation\Rule;
class UserCreateValidation extends AbstractValidation
{
@@ -29,7 +30,7 @@ class UserCreateValidation extends AbstractValidation
{
return [
'name' => 'required',
'email' => 'required|unique:users',
'email' => ['required', Rule::unique('users')],
'password' => 'required',
];
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Accounts\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Accounts\DataTransferObjects\RegistrationObject;
use Illuminate\Validation\Rule;
class UserRegistrationValidation extends AbstractValidation
{
@@ -32,7 +33,7 @@ class UserRegistrationValidation extends AbstractValidation
{
return [
'name' => 'required',
'email' => 'required|email|max:255|unique:users,email',
'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')],
'password' => 'required|min:6|confirmed',
'type' => 'required',
'status' => 'required'
@@ -56,7 +56,7 @@ class UpdateCompanyLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$object = new CompanyObject($request->input('name'), $request->input('reference'), $request->input('type'));
$object = new CompanyObject($request->input('name'), $request->input('reference'), $request->input('business_type'), $request->input('type'));
$this->canUpdateCompany->passes($object);
@@ -7,6 +7,7 @@ use App\Classes\General\Interfaces\DataTransferObject;
use App\Classes\ValueObjects\Constants\FileType;
use Illuminate\Support\Str;
use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;
class FileObject implements DataTransferObject
{
@@ -28,7 +29,13 @@ class FileObject implements DataTransferObject
*/
public function getData()
{
return in_array($this->getExtension(), ['pdf', 'excel', 'text']) ? $this->data : (new imageManager())->make($this->data);
// intervention/image v2: old
//return in_array($this->getExtension(), ['pdf', 'excel', 'text']) ? $this->data : (new imageManager())->make($this->data);
// intervention/image v3: new
return in_array($this->getExtension(), ['pdf', 'excel', 'text'])
? $this->data
: (new ImageManager(new Driver()))->read($this->data);
}
/**
@@ -66,9 +73,10 @@ class FileObject implements DataTransferObject
*/
public function getDecodedData(): string
{
// intervention/image v3: Use encode()->toDataUri() instead of encode('data-url')->encoded
return in_array($this->getExtension(), ['pdf', 'excel', 'text']) ?
base64_decode((explode('base64,', $this->getData()))[1]) :
$this->getData()->encode('data-url')->encoded;
$this->getData()->encode()->toDataUri();
}
/**
@@ -32,7 +32,8 @@ class ConvertsBase64ToFile
* @return array
* @throws MalformedRequestException
*/
public function convert($files = []){
public function convert($files = [])
{
foreach ($files as $file) {
$object = new FileObject($file);
@@ -48,7 +49,8 @@ class ConvertsBase64ToFile
* @param FileObject $file
* @throws MalformedRequestException
*/
private function generatePDF(FileObject $file){
private function generatePDF(FileObject $file)
{
$filePath = $this->generateFile($file);
$this->updateFiles($file, ['original' => ['file' => $filePath]]);
@@ -58,7 +60,8 @@ class ConvertsBase64ToFile
* @param FileObject $file
* @throws MalformedRequestException
*/
private function generateImage(FileObject $file){
private function generateImage(FileObject $file)
{
$fileInfo = [];
@@ -66,17 +69,21 @@ class ConvertsBase64ToFile
$suffix = $size !== 'original' ? '_' . $size : '';
if ($size !== 'original') {
$thumbnail = $file->getData()->widen($value, function ($constraint) {
// intervention/image v2: old
// $thumbnail = $file->getData()->widen($value, function ($constraint) {
// $constraint->upsize();
// })->heighten($value, function ($constraint) {
// $constraint->upsize();
// });
// $file->setData($thumbnail->encode('data-url')->encoded);
$constraint->upsize();
})->heighten($value, function ($constraint) {
// intervention/image v3: Use scaleDown() instead of widen()/heighten()
// scaleDown() maintains aspect ratio and prevents upsizing by default
$thumbnail = $file->getData()->scaleDown(width: $value, height: $value);
$constraint->upsize();
});
$file->setData($thumbnail->encode('data-url')->encoded);
// intervention/image v3: Use encode()->toDataUri() instead of encode('data-url')->encoded
$file->setData($thumbnail->encode()->toDataUri());
}
@@ -97,15 +104,15 @@ class ConvertsBase64ToFile
* @return string
* @throws MalformedRequestException
*/
private function generateFile(FileObject $file, string $suffix = '') {
private function generateFile(FileObject $file, string $suffix = '')
{
$filesystemDriver = Storage::getDefaultDriver();
if ($filesystemDriver === 's3') {
$filePath = 'documents/' . $this->path . '/' . $file->getFileName() . $suffix . '.' . $file->getExtension();
Storage::put($filePath, $file->getDecodedData(), 's3');
return $filePath;
}
else{
} else {
$filePath = $this->path . '/' . $file->getFileName() . $suffix . '.' . $file->getExtension();
Storage::disk('documents')->put($filePath, $file->getDecodedData());
return $filePath;
@@ -117,7 +124,8 @@ class ConvertsBase64ToFile
* @param array $fileInfo
* @throws MalformedRequestException
*/
private function updateFiles(FileObject $file, array $fileInfo){
private function updateFiles(FileObject $file, array $fileInfo)
{
$this->filesInfo[] = json_encode([
'path' => $this->path,
'filename' => $file->getFileName() . '.' . $file->getExtension(),
@@ -19,14 +19,19 @@ class CreatesFiles extends AbstractUpdateRelationshipRecord
{
$models = [];
// foreach ($object->getFiles() as $file) {
// $model = new File(['file' => $file]);
// $models[] = $this->handler($document->files(), $model);
// }
foreach ($object->getFiles() as $file) {
$model = new File(['file' => $file]);
$fileData = is_string($file) ? json_decode($file, true) : $file;
$model = new File(['file' => $fileData]);
$models[] = $this->handler($document->files(), $model);
}
return $models;
}
}
@@ -20,7 +20,7 @@ class CreatesConstant extends AbstractUpdateRelationshipRecord
$model = new SegmentConstant();
$model->name = $object->getName();
$model->reference = $object->getReference();
$model->detail = json_encode($object->getDetail());
$model->detail = $object->getDetail();
return $this->handler($segment->constants(), $model);
}
@@ -19,7 +19,7 @@ class UpdatesConstant extends AbstractUpdateRecord
{
$model->name = $object->getName();
$model->reference = $object->getReference();
$model->detail = json_encode($object->getDetail());
$model->detail = $object->getDetail();
return $this->handler($model);
}
@@ -6,6 +6,7 @@ use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject;
use App\Classes\Modules\Segments\Standards\Validators\SegmentValidation;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class CanCreateSegment extends AbstractRule
{
@@ -28,7 +29,10 @@ class CanCreateSegment extends AbstractRule
protected function authorized($object): bool
{
// TODO Set Authorization rules
if (!Auth::user()->can('add segment')) {
/** @var \App\Models\User $user */
$user = Auth::user();
if (!$user->can('add segment')) {
return false;
}
@@ -139,8 +139,7 @@ class CreateInvoiceTransactionV2Processor
->complete()
->first();
if(!$purchaseOrder){
//was use for $generateEInvoiceRefund true
if(!$purchaseOrder && $generateEInvoiceRefund){
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
->where('status', ApprovalStatus::PENDING_SUBMISSION)
-121
View File
@@ -1,121 +0,0 @@
<?php
namespace App\Console;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use ZipArchive;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
//Commands Version 2: Laravel Vapor/AWS
$isEnabled = env('COMMANDS_V2_ENABLED', false);
if($isEnabled){
// $schedule->command('dummy-command')
// ->everyFiveMinutes()
// ->withoutOverlapping();
$schedule->command('housekeeping-s3-files-command')
->dailyAt('01:00')
->withoutOverlapping();
$schedule->command('password-reset-token-expriration-check-command')
->everySixHours()
->withoutOverlapping();
$schedule->command('new-user-registration-expire-check-command')
->everySixHours()
->withoutOverlapping();
if(env('APP_ENV') === 'production'){
$schedule->command('email-do-to-vt-command')
->dailyAt('10:00')
->withoutOverlapping();
$schedule->command('seasonal-segmant-company-remove-command')
->dailyAt('01:00')
->withoutOverlapping();
$schedule->command('delete-bulk-download-files-command')
->hourly()
->withoutOverlapping();
$schedule->command('booking-expired-command')
->dailyAt('02:00')
->withoutOverlapping();
// DISABLED BY DEFAULT
// $schedule->command('purchase-order-autofill-command')
// ->dailyAt('03:00')
// ->withoutOverlapping();
// Push company module to Lark
$schedule->command('lark:push-company-module')
->hourly()
->withoutOverlapping();
// Push booking module to Lark
$schedule->command('lark:push-booking-module')
->hourly()
->withoutOverlapping();
}
}
//Commands Version 1: Before Laravel Vapor/AWS
else{
// $schedule->command('inspire')->hourly();
$schedule->command('mail:EmailDoToVTCommand')->dailyAt('10:00')->withoutOverlapping();
$schedule->command('seasonalSegmantCompany:remove')
->dailyAt('01:00')
->appendOutputTo(storage_path().'/logs/soft-delete-seasonal-segmant-company.log')
->withoutOverlapping();
$schedule->command('delete:bulk-download-files')
->hourly()
->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log')
->withoutOverlapping();
$schedule->command('booking:expired')
->dailyAt('02:00')
->appendOutputTo(storage_path().'/logs/expire-booking.log')
->withoutOverlapping();
// $schedule->command('purchaseOrder:autoFill')
// ->dailyAt('03:00')
// ->withoutOverlapping();
}
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
-68
View File
@@ -1,68 +0,0 @@
<?php
namespace App\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* @param \Throwable $exception
* @return void
*
* @throws \Exception
*/
public function report(Throwable $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $exception
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Throwable
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof MaintenanceModeException) {
return response()
->view('pages.errors.maintenance');
}
if ($exception instanceof AuthenticationException) {
return (new ApiResponseObject('Authentication', 'To keep your account secure we need to re-validate your account', HttpStatus::ACCESS_UNAUTHORISED))->handler();
}
return parent::render($request, $exception);
}
}
@@ -22,7 +22,7 @@ class AWSImageUploadController extends Controller
public function imageUploadPost(Request $request)
{
$request->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'image' => 'required|image:allow_svg|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$imageName = time().'.'.$request->image->extension();
@@ -169,7 +169,7 @@ class ImportStatementInvoiceController
}
if ($transaction && $transaction->count() == 0) {
$transaction = Transaction::getReceiverWithJoinStatementTransactionAndOwner($row)->select('transactions.*')->where(DB::raw('FLOOR(statement_transactions.amount)'), floor($row['net_total']))->whereRaw("DATE(posting_date) = '$date'")->first();
$transaction = Transaction::getReceiverWithJoinStatementTransactionAndOwner($row)->select('transactions.*')->whereRaw('FLOOR(statement_transactions.amount) = ?', [floor($row['net_total'])])->whereRaw("DATE(posting_date) = '$date'")->first();
}
if ($transaction && $transaction->count() > 0) {
-85
View File
@@ -1,85 +0,0 @@
<?php
namespace App\Http;
use App\Http\Middleware\Authenticate;
use App\Http\Middleware\CheckForMaintenanceMode;
use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustProxies;
use App\Http\Middleware\ValidateToken;
use App\Http\Middleware\VerifyCsrfToken;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\LogRequestPathMiddleware::class,
],
'api' => [
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\LogRequestPathMiddleware::class,
],
'apipub' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\LogRequestPathMiddleware::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'valid.token' => ValidateToken::class,
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class, //cief maintenance
];
}
@@ -2,7 +2,6 @@
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
+7 -2
View File
@@ -2,7 +2,7 @@
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
@@ -19,5 +19,10 @@ class TrustProxies extends Middleware
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_PREFIX;
}
+2 -16
View File
@@ -7,23 +7,9 @@ use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use Closure;
use Exception;
use Tymon\JWTAuth\JWT;
class ValidateToken
{
/** @var JWT */
private $manager;
/**
* ValidateToken constructor.
* @param JWT $manager
*/
public function __construct(JWT $manager)
{
$this->manager = $manager;
}
/**
* Checks if jwt token is valid.
*
@@ -35,9 +21,9 @@ class ValidateToken
{
try {
if(!$this->manager->check()){ throw new AccessUnauthorisedException(); }
if(!auth('api')->check()){ throw new AccessUnauthorisedException(); }
} catch (Exception $exception) {
} catch (Exception) {
return (new ApiResponseObject('Authentication', 'To keep your account secure we need to re-validate your account', HttpStatus::ACCESS_UNAUTHORISED))->handler();
+1 -1
View File
@@ -3,7 +3,7 @@
namespace App\Logging;
use Aws\CloudWatchLogs\CloudWatchLogsClient;
use Maxbanton\Cwh\Handler\CloudWatch;
use PhpNexus\Cwh\Handler\CloudWatch;
use Monolog\Formatter\JsonFormatter;
use Monolog\Logger;
+10 -1
View File
@@ -6,12 +6,21 @@ namespace App\Models;
use App\Classes\General\Interfaces\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class AbstractModel extends Model implements Notifiable
{
use LogsActivity;
protected static $logFillable = true;
/**
* Get the options for logging activity.
*/
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logFillable();
}
/**
* @return MorphTo
+9 -1
View File
@@ -20,10 +20,18 @@ class AccountStatement extends Model
'mapped_rows',
];
protected $casts = [
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'date_from' => 'date',
'date_to' => 'date',
];
}
public function account()
{
+19 -9
View File
@@ -9,14 +9,14 @@ use Illuminate\Database\Eloquent\Builder;
* Class Address
* @package App\Models
*
* @property \App\Models\Country country_id
* @property \App\Models\Company company_id
* @property \App\Models\State state_id
* @property \App\Models\District district_id
* @property string postcode
* @property string street_one
* @property string street_two
* @property integer billing_type
* @property int $country_id
* @property int $company_id
* @property int $state_id
* @property int $district_id
* @property string $postcode
* @property string $street_one
* @property string $street_two
* @property int $billing_type
*/
class Address extends AbstractModel
{
@@ -24,7 +24,17 @@ class Address extends AbstractModel
protected $table = 'addresses';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
+11 -3
View File
@@ -11,7 +11,6 @@ class Affiliate extends AbstractModel
use SoftDeletes;
protected $table = 'affiliates';
protected $dates = ['deleted_at'];
protected $fillable = [
'code',
@@ -24,12 +23,21 @@ class Affiliate extends AbstractModel
'orders_count'
];
protected $casts = [
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'is_active' => 'boolean',
'clicks_count' => 'integer',
'registrations_count' => 'integer',
'orders_count' => 'integer'
'orders_count' => 'integer',
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
-4
View File
@@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Announcement
* @package App\Models
*
*/
class Announcement extends AbstractModel
{
@@ -16,9 +15,6 @@ class Announcement extends AbstractModel
protected $table = 'announcements';
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
**/
public function segments(): BelongsToMany
{
return $this->BelongsToMany(Segment::class);
+9 -10
View File
@@ -14,22 +14,21 @@ use App\Classes\General\Interfaces\KeyValueInterface;
* Class Bank
* @package App\Models
*
* @property \App\Models\Country country_id
* @property \App\Models\Company company_id
* @property string bank_name
* @property string holder_name
* @property string account_no
* @property int type
* @property int default
* @property int status
* @property int $country_id
* @property int $company_id
* @property string $bank_name
* @property string $holder_name
* @property string $account_no
* @property int $type
* @property int $default
* @property int $status
*/
class Bank extends AbstractModel implements KeyValueInterface
{
use SoftDeletes;
/**
*
* @var array
* @var array<int, string>
*/
protected $fillable = [
'company_id',
+11 -1
View File
@@ -19,7 +19,17 @@ class BillGroup extends Model implements Documentable, Transactionable
protected $table = 'bill_groups';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return MorphMany
+18 -8
View File
@@ -19,13 +19,13 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships;
* Class Booking
* @package App\Models
*
* @property \App\Models\Company company_id
* @property \App\Models\Bank transferable_bank_id
* @property string marking
* @property string reference
* @property float fix_amount
* @property int convertible_currency_id
* @property int conversion_currency_id
* @property int $company_id
* @property int $transferable_bank_id
* @property string $marking
* @property string $reference
* @property float $fix_amount
* @property int $convertible_currency_id
* @property int $conversion_currency_id
*/
class Booking extends AbstractModel implements Documentable, Transactionable, Voucherifiable, KeyValueInterface
{
@@ -35,7 +35,17 @@ class Booking extends AbstractModel implements Documentable, Transactionable, Vo
protected $table = 'bookings';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
+19 -9
View File
@@ -20,13 +20,13 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships;
* Class Company
* @package App\Models
*
* @property \App\Models\Country country_id
* @property \App\Models\State state_id
* @property \App\Models\District district_id
* @property string postcode
* @property string street_one
* @property string street_two
* @property integer billing_type
* @property int $country_id
* @property int $state_id
* @property int $district_id
* @property string $postcode
* @property string $street_one
* @property string $street_two
* @property int $billing_type
*/
class Company extends AbstractModel implements Documentable
{
@@ -35,8 +35,18 @@ class Company extends AbstractModel implements Documentable
protected $table = 'companies';
protected $dates = ['deleted_at', 'created_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
'created_at' => 'datetime',
];
}
/**
* @return HasMany
+19 -12
View File
@@ -10,12 +10,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class Contact
* @package App\Models
*
* @property \App\Models\Country country_id
* @property \App\Models\Company company_id
* @property string reference
* @property string phone
* @property string email
* @property string wechat_id
* @property int $country_id
* @property int $company_id
* @property string $reference
* @property string $phone
* @property string $email
* @property string $wechat_id
*/
class Contact extends AbstractModel
{
@@ -23,20 +23,27 @@ class Contact extends AbstractModel
protected $table = 'contacts';
protected $dates = ['deleted_at'];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne
**/
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function company(): HasOne
{
return $this->hasOne(Company::class);
}
/**
* @return belongsTo
* @return BelongsTo
**/
public function country(): belongsTo
public function country(): BelongsTo
{
return $this->belongsTo(Country::class);
}
+14 -4
View File
@@ -9,9 +9,9 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class Country
* @package App\Models
*
* @property string name
* @property string short_code
* @property string phone_code
* @property string $name
* @property string $short_code
* @property string $phone_code
*/
class Country extends AbstractModel
{
@@ -19,7 +19,17 @@ class Country extends AbstractModel
protected $table = 'countries';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
protected $fillable = ['name', 'short_code', 'phone_code'];
+18 -8
View File
@@ -6,16 +6,16 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\hasMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Class Currency
* @package App\Models
*
* @property \App\Models\Country country_id
* @property string name
* @property string short_code
* @property string symbol
* @property int $country_id
* @property string $name
* @property string $short_code
* @property string $symbol
*/
class Currency extends AbstractModel
@@ -24,7 +24,17 @@ class Currency extends AbstractModel
protected $table = 'currencies';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
@@ -35,9 +45,9 @@ class Currency extends AbstractModel
}
/**
* @return hasMany
* @return HasMany
*/
public function rates(): hasMany
public function rates(): HasMany
{
return $this->hasMany(CurrencyRate::class, 'currency_id');
}
+11 -1
View File
@@ -12,5 +12,15 @@ class CurrencyRate extends AbstractModel
protected $fillable = ['currency_id', 'selling', 'payment_method_type'];
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
}
+15 -5
View File
@@ -10,10 +10,10 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class District
* @package App\Models
*
* @property \App\Models\Country country_id
* @property \App\Models\State state_id
* @property string name
* @property string postcode
* @property int $country_id
* @property int $state_id
* @property string $name
* @property string $postcode
*/
class District extends AbstractModel
{
@@ -21,7 +21,17 @@ class District extends AbstractModel
protected $table = 'districts';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
+24 -15
View File
@@ -7,22 +7,21 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\hasMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Class Document
* @package App\Models
* @version August 4, 2020, 4:36 am
*
* @property int owner_id
* @property int owner_type
* @property int document_type
* @property string reference
* @property int status
* @property \App\Models\User approver
* @property timestamp issued_date
* @property timestamp expired_date
* @property timestamp approved_date
* @property int $owner_id
* @property int $owner_type
* @property int $document_type
* @property string $reference
* @property int $status
* @property int $approver
* @property string $issued_date
* @property string $expired_date
* @property string $approved_date
*/
class Document extends AbstractModel
{
@@ -30,7 +29,17 @@ class Document extends AbstractModel
protected $table = 'documents';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
@@ -41,9 +50,9 @@ class Document extends AbstractModel
}
/**
* @return hasMany
* @return HasMany
*/
public function files(): hasMany
public function files(): HasMany
{
return $this->hasMany(File::class, 'document_id');
}
@@ -51,7 +60,7 @@ class Document extends AbstractModel
/**
* @return HasOne
*/
public function approver(): hasOne
public function approver(): HasOne
{
return $this->hasOne(User::class, 'id', 'approver');
}
+3 -6
View File
@@ -6,11 +6,11 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
/**
* Class CompanyEmployee
* Class Employee
* @package App\Models
*
* @property \App\Models\Company company_id
* @property \App\Models\User user_id
* @property int $company_id
* @property int $user_id
*/
class Employee extends AbstractModel
{
@@ -24,9 +24,6 @@ class Employee extends AbstractModel
return $this->HasMany(Company::class, 'company_id', 'id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne
**/
public function user(): HasOne
{
return $this->hasOne(User::class, 'user_id', 'id');
+13 -8
View File
@@ -8,11 +8,10 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class File
* @package App\Models
* @version August 4, 2020, 4:36 am
*
* @property \App\Models\Document document_id
* @property text file
* @property int file_type_id
* @property int $document_id
* @property object $file
* @property int $file_type_id
*/
class File extends AbstractModel
{
@@ -22,10 +21,16 @@ class File extends AbstractModel
protected $fillable = ['file'];
protected $dates = ['deleted_at'];
public function getFileAttribute($value)
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return $value ? json_decode($value) : [];
return [
'file' => 'object',
'deleted_at' => 'datetime',
];
}
}
+12 -2
View File
@@ -8,8 +8,6 @@ class KeyValuePair extends AbstractModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'key_value_pairs';
protected $fillable = [
@@ -19,6 +17,18 @@ class KeyValuePair extends AbstractModel
'value',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function owner(): MorphTo
{
return $this->morphTo();
+12 -1
View File
@@ -8,7 +8,18 @@ class Milestone extends AbstractModel
use SoftDeletes;
protected $table = 'milestones';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function progress()
{
+12 -1
View File
@@ -9,7 +9,18 @@ class MilestoneProgress extends AbstractModel
use SoftDeletes;
protected $table = 'milestone_progress';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function milestone()
{
+10 -2
View File
@@ -15,9 +15,17 @@ class ModelAttribute extends Model
"value"
];
protected $casts = [
"value" => "array"
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
"value" => "array",
];
}
public function owner(): morphTo
{
+12 -1
View File
@@ -10,7 +10,18 @@ class Reward extends AbstractModel
use SoftDeletes;
protected $table = 'rewards';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function milestones()
{
+19 -11
View File
@@ -11,13 +11,13 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* Class SeasonalSegment
* @package App\Models
*
* @property \App\Models\Company company_id
* @property \App\Models\Bank transferable_bank_id
* @property string marking
* @property string reference
* @property float fix_amount
* @property int convertible_currency_id
* @property int conversion_currency_id
* @property int $company_id
* @property int $transferable_bank_id
* @property string $marking
* @property string $reference
* @property float $fix_amount
* @property int $convertible_currency_id
* @property int $conversion_currency_id
*/
class SeasonalSegment extends Model
{
@@ -27,11 +27,19 @@ class SeasonalSegment extends Model
protected $table = 'seasonal_segment';
protected $dates = [
'starting_on',
'ending_on',
'deleted_at',
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'starting_on' => 'datetime',
'ending_on' => 'datetime',
'deleted_at' => 'datetime',
];
}
/**
* @return BelongsTo
+13 -3
View File
@@ -9,8 +9,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class Segment
* @package App\Models
*
* @property string name
* @property string reference
* @property string $name
* @property string $reference
*/
class Segment extends AbstractModel
{
@@ -18,7 +18,17 @@ class Segment extends AbstractModel
protected $table = 'segments';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return HasMany
+12 -10
View File
@@ -10,8 +10,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class SegmentConstant
* @package App\Models
*
* @property \App\Models\Segment segment_id
* @property string detail
* @property int $segment_id
* @property object $detail
*/
class SegmentConstant extends AbstractModel
{
@@ -19,15 +19,17 @@ class SegmentConstant extends AbstractModel
protected $table = 'segment_constants';
protected $dates = ['deleted_at'];
// protected $casts = [
// 'detail' => 'array',
// ];
public function getDetailAttribute($value)
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return $value ? json_decode($value) : [];
return [
'detail' => 'object',
'deleted_at' => 'datetime',
];
}
/**
+14 -14
View File
@@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @package App\Models
* @version February 16, 2021, 9:04 pm
*
* @property string name
* @property string $name
*/
class ServiceType extends AbstractModel
{
@@ -25,44 +25,44 @@ class ServiceType extends AbstractModel
protected $dates = ['deleted_at'];
public $fillable = [
'name'
];
/**
* The attributes that should be casted to native types.
* Get the attributes that should be cast.
*
* @var array
* @return array<string, string>
*/
protected $casts = [
'name' => 'string'
protected function casts(): array
{
return [
'name' => 'string',
'deleted_at' => 'datetime',
];
}
/**
* Validation rules
*
* @var array
* @var array<string, string>
*/
public static $rules = [
'name' => 'required'
];
/**
* @return hasMany
* @return HasMany
*/
public function rates(): hasMany
public function rates(): HasMany
{
return $this->hasMany(CurrencyRate::class, 'service_id');
}
/**
* @return hasMany
* @return HasMany
*/
public function constants(): hasMany
public function constants(): HasMany
{
return $this->hasMany(SegmentConstant::class, 'detail->id')
->whereIn('reference', [SegmentConstants::SERVICE_TYPE, SegmentConstants::CUSTOM_SERVICE_TYPE]);
+13 -3
View File
@@ -9,8 +9,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* Class State
* @package App\Models
*
* @property \App\Models\Country country_id
* @property string name
* @property int $country_id
* @property string $name
*/
class State extends AbstractModel
{
@@ -18,7 +18,17 @@ class State extends AbstractModel
protected $table = 'states';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return HasOne
+9 -1
View File
@@ -30,9 +30,17 @@ class StatementTransaction extends Model
'end_balance',
];
protected $casts = [
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'posting_date' => 'datetime',
];
}
public function account()
{
+12 -4
View File
@@ -29,12 +29,20 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
use SoftDeletes;
use LogData;
protected $casts = [
'type' => 'int'
];
protected $table = 'transactions';
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'type' => 'int',
];
}
public function owner(): morphTo
{
return $this->morphTo();
+9 -1
View File
@@ -9,9 +9,17 @@ class TransactionMappingLog extends Model
{
protected $fillable = ['imported_by','data','imported_date','type'];
protected $casts = [
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'data' => 'array',
];
}
public static function boot() {
parent::boot();
+1 -1
View File
@@ -105,7 +105,7 @@ class User extends AbstractModel implements
return $this->HasMany(UserReward::class, 'user_id', 'id');
}
public function hasAttribute(string $key, $value = null): bool
public function hasCustomAttribute(string $key, $value = null): bool
{
$query = $this->attributesKVP()->where('key', $key);
+11 -3
View File
@@ -15,10 +15,18 @@ class UserAffiliate extends AbstractModel
'registered_at'
];
protected $dates = [
'clicked_at',
'registered_at'
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'clicked_at' => 'datetime',
'registered_at' => 'datetime',
];
}
/**
* @return BelongsTo
+12 -1
View File
@@ -9,7 +9,18 @@ class UserReward extends AbstractModel
use SoftDeletes;
protected $table = 'user_rewards';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
public function reward()
{
+12 -1
View File
@@ -10,7 +10,18 @@ class VoucherEntityMapping extends AbstractModel
use SoftDeletes;
protected $table = 'voucher_entity_mappings';
protected $dates = ['deleted_at'];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'deleted_at' => 'datetime',
];
}
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
+8
View File
@@ -5,6 +5,9 @@ namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
class AppServiceProvider extends ServiceProvider
{
@@ -29,5 +32,10 @@ class AppServiceProvider extends ServiceProvider
if (!file_exists(storage_path('framework/sessions'))) {
mkdir(storage_path('framework/sessions'), 0777, true);
}
//From Shipping Portal
// RateLimiter::for('api', function (Request $request) {
// return Limit::perMinute(300)->by($request->user()?->id ?: $request->ip());
// });
}
}
-2
View File
@@ -23,8 +23,6 @@ class AuthServiceProvider extends ServiceProvider
*/
public function boot()
{
$this->registerPolicies();
//
}
}
-97
View File
@@ -1,97 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to your controller routes.
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
*/
protected $namespace = 'App\Http\Controllers';
/**
* The path to the "home" route for your application.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
//
parent::boot();
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapApiPubRoutes();
//
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
/**
* Define the "apipub" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiPubRoutes()
{
Route::prefix('public/api')
->middleware('apipub')
->namespace($this->namespace)
->group(base_path('routes/apipub.php'));
}
}
+138 -46
View File
@@ -1,55 +1,147 @@
<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
use App\Http\Middleware\ValidateToken;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Facades\Route;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__ . '/../routes/web.php',
api: __DIR__ . '/../routes/api.php',
commands: __DIR__ . '/../routes/console.php',
health: '/up',
then: function () {
// Load public API routes (not loaded in api.php)
Route::middleware('apipub')
->prefix('public/api')
->group(base_path('routes/apipub.php'));
},
)
->withMiddleware(function (Middleware $middleware) {
// '*' trusts all proxies, required for correct IP/HTTPS detection behind AWS ALB/Vapor
$middleware->trustProxies(at: '*');
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$middleware->web(append: [
\App\Http\Middleware\LogRequestPathMiddleware::class,
]);
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$middleware->api(append: [
\App\Http\Middleware\LogRequestPathMiddleware::class,
]);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$middleware->api(prepend: [
'throttle:300,1',
]);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
$middleware->validateCsrfTokens(except: [
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
]);
return $app;
$middleware->alias([
'valid.token' => ValidateToken::class,
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
]);
$middleware->appendToGroup('apipub', [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\LogRequestPathMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
// Custom exception rendering
// $exceptions->render(function (MaintenanceModeException $e, $request) {
// return response()->view('pages.errors.maintenance');
// });
$exceptions->render(function (AuthenticationException $e, $request) {
return (new ApiResponseObject(
'Authentication',
'To keep your account secure, we need to re-validate it.',
HttpStatus::ACCESS_UNAUTHORISED
))->handler();
});
// Don't flash these inputs
$exceptions->dontFlash([
'password',
'password_confirmation',
]);
})
->withCommands([
__DIR__ . '/../app/Console/Commands',
__DIR__ . '/../app/Console/Commands/V2',
])
->withSchedule(function ($schedule) {
// Commands Version 2: Laravel Vapor/AWS
$isEnabled = env('COMMANDS_V2_ENABLED', false);
if ($isEnabled) {
$schedule->command('housekeeping-s3-files-command')
->dailyAt('01:00')
->withoutOverlapping();
$schedule->command('password-reset-token-expriration-check-command')
->everySixHours()
->withoutOverlapping();
$schedule->command('new-user-registration-expire-check-command')
->everySixHours()
->withoutOverlapping();
if (env('APP_ENV') === 'production') {
$schedule->command('email-do-to-vt-command')
->dailyAt('10:00')
->withoutOverlapping();
$schedule->command('seasonal-segmant-company-remove-command')
->dailyAt('01:00')
->withoutOverlapping();
$schedule->command('delete-bulk-download-files-command')
->hourly()
->withoutOverlapping();
$schedule->command('booking-expired-command')
->dailyAt('02:00')
->withoutOverlapping();
// Push company module to Lark
$schedule->command('lark:push-company-module')
->hourly()
->withoutOverlapping();
// Push booking module to Lark
$schedule->command('lark:push-booking-module')
->hourly()
->withoutOverlapping();
}
}
// Commands Version 1: Before Laravel Vapor/AWS
else {
$schedule->command('mail:EmailDoToVTCommand')
->dailyAt('10:00')
->withoutOverlapping();
$schedule->command('seasonalSegmantCompany:remove')
->dailyAt('01:00')
->appendOutputTo(storage_path() . '/logs/soft-delete-seasonal-segmant-company.log')
->withoutOverlapping();
$schedule->command('delete:bulk-download-files')
->hourly()
->appendOutputTo(storage_path() . '/logs/delete-bulk-download-files.log')
->withoutOverlapping();
$schedule->command('booking:expired')
->dailyAt('02:00')
->appendOutputTo(storage_path() . '/logs/expire-booking.log')
->withoutOverlapping();
}
})
->create();
+22 -25
View File
@@ -8,53 +8,50 @@
],
"license": "MIT",
"require": {
"php": "^7.2.5",
"php": "^8.3",
"ext-bcmath": "*",
"ext-fileinfo": "*",
"ext-json": "*",
"ext-zip": "*",
"barryvdh/laravel-dompdf": "^0.9.0",
"barryvdh/laravel-dompdf": "^3.1",
"carlos-meneses/laravel-mpdf": "^2.1",
"doctrine/dbal": "^2.12.1",
"fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^1.0",
"guzzlehttp/guzzle": "^7.0.1",
"intervention/image": "^2.5",
"doctrine/dbal": "^3.0|^4.0",
"guzzlehttp/guzzle": "^7.4",
"intervention/image": "^2.7|^3.0",
"kwn/number-to-words": "^2.11",
"laravel/framework": "^8.0",
"laravel/sanctum": "^2.15",
"laravel/tinker": "^2.0",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.9",
"laravel/vapor-cli": "^1.55",
"laravel/vapor-core": "^2.33",
"league/flysystem-aws-s3-v3": "^3.0",
"maatwebsite/excel": "^3.1",
"maxbanton/cwh": "^2.0",
"phpnexus/cwh": "^3.0",
"mpdf/mpdf": "^8.1",
"pusher/pusher-php-server": "^7.2",
"rinvex/countries": "^6.1",
"rinvex/countries": "^9.0",
"rspective/voucherify": " v2.0.*",
"smalot/pdfparser": "^2.2",
"spatie/laravel-activitylog": "^3.14",
"spatie/laravel-permission": "^3.17",
"spatie/laravel-activitylog": "^4.10",
"spatie/laravel-permission": "^7.0",
"staudenmeir/eloquent-has-many-deep": "^1.7",
"timehunter/laravel-google-recaptcha-v3": "~2.5",
"tymon/jwt-auth": "^1.0",
"symfony/http-client": "^7.4",
"symfony/mailgun-mailer": "^7.4",
"tymon/jwt-auth": "^2.0",
"webklex/laravel-pdfmerger": "^1.3"
},
"require-dev": {
"facade/ignition": "^2.3.6",
"fzaninotto/faker": "^1.9.1",
"laravel/dusk": "^6.23",
"mockery/mockery": "^1.3.1",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.0"
"fakerphp/faker": "^1.20",
"laravel/dusk": "^8.0",
"mockery/mockery": "^1.5",
"nunomaduro/collision": "^8.5",
"phpunit/phpunit": "^11.5",
"spatie/laravel-ignition": "^2.5"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"audit": {
"block-insecure": false
}
"sort-packages": true
},
"extra": {
"laravel": {
+1 -2
View File
@@ -173,7 +173,6 @@ return [
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
// Third Parties
Spatie\Permission\PermissionServiceProvider::class,
@@ -233,7 +232,7 @@ return [
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'PDF' => Barryvdh\DomPDF\Facade::class,
'PDF' => Barryvdh\DomPDF\Facade\Pdf::class,
'MPDF' => Mccarlosen\LaravelMpdf\Facades\LaravelMpdf::class,
'GoogleReCaptchaV3'=> TimeHunter\LaravelGoogleReCaptchaV3\Facades\GoogleReCaptchaV3::class,
'PDFMerger' => Webklex\PDFMerger\Facades\PDFMergerFacade::class
+1 -1
View File
@@ -15,7 +15,7 @@ return [
|
*/
'paths' => ['api/*'],
'paths' => ['api/*', 'public/api/*'],
'allowed_methods' => ['*'],
+2 -2
View File
@@ -13,7 +13,7 @@ return [
|
*/
'default' => env('FILESYSTEM_DRIVER', 'local'),
'default' => env('FILESYSTEM_DISK', env('FILESYSTEM_DRIVER', 'local')),
/*
|--------------------------------------------------------------------------
@@ -45,7 +45,7 @@ return [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'root' => storage_path('app/private'),
],
'public' => [
+13
View File
@@ -49,4 +49,17 @@ return [
'time' => 2,
],
/*
|--------------------------------------------------------------------------
| Password Rehashing on Login
|--------------------------------------------------------------------------
|
| When enabled, passwords will be automatically rehashed during
| authentication if the hashing algorithm's work factor has changed.
| This ensures passwords stay secure as hardware improves.
|
*/
'rehash_on_login' => true,
];
@@ -20,7 +20,7 @@ class CreateBookingsTable extends Migration
$table->string('marking')->unique();
$table->foreignId('service_id')->unsigned();
$table->foreignId('bank_id')->unsigned();
$table->float('fix_amount', 20, 5);
$table->decimal('fix_amount', 20, 5);
$table->foreignId('fix_currency_id')->unsigned();
$table->foreignId('convertible_currency_id')->unsigned();
$table->foreignId('conversion_currency_id')->unsigned();
@@ -24,7 +24,7 @@ class CreateStatementTransactionsTable extends Migration
$table->string('transaction_description_4')->nullable();
$table->string('transaction_description_5')->nullable();
$table->string('transaction_ref')->nullable();
$table->float('amount', 15, 2)->unsigned(false);
$table->decimal('amount', 15, 2)->unsigned(false);
$table->string('teller_id')->nullable();
$table->string('branch_channel');
$table->string('transaction_code');
@@ -13,12 +13,14 @@ class AddInvoiceStatusToBookingLogsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->boolean('invoice_status')
->default(false)
->after('status');
});
}
}
/**
* Reverse the migrations.
@@ -27,8 +29,10 @@ class AddInvoiceStatusToBookingLogsTable extends Migration
*/
public function down()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->dropColumn('invoice_status');
});
}
}
}
@@ -13,12 +13,14 @@ class AddIsInvoiceGeneratedToBookingLogsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->boolean('is_invoice_generated')
->default(false)
->after('status');
});
}
}
/**
* Reverse the migrations.
@@ -27,8 +29,10 @@ class AddIsInvoiceGeneratedToBookingLogsTable extends Migration
*/
public function down()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->dropColumn('is_invoice_generated');
});
}
}
}
@@ -13,10 +13,12 @@ class RemoveIsInvoiceGeneratedFromBookingLogsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->dropColumn('is_invoice_generated');
});
}
}
/**
* Reverse the migrations.
@@ -25,6 +27,7 @@ class RemoveIsInvoiceGeneratedFromBookingLogsTable extends Migration
*/
public function down()
{
if (Schema::hasTable('booking_logs')) {
Schema::table('booking_logs', function (Blueprint $table) {
$table->boolean('is_invoice_generated')
->default(false)
@@ -32,3 +35,4 @@ class RemoveIsInvoiceGeneratedFromBookingLogsTable extends Migration
});
}
}
}
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('activity_log', function (Blueprint $table) {
$table->uuid('batch_uuid')->nullable()->after('properties');
$table->string('event')->nullable()->after('subject_type');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('activity_log', function (Blueprint $table) {
$table->dropColumn('batch_uuid');
$table->dropColumn('event');
});
}
};
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
* Update all roles (id 1 & 2) and all permissions to use 'api' guard_name
* instead of 'web', to align with Spatie Laravel Permission v7 strict
* guard matching behaviour for SPA/API-based requests.
*/
public function up(): void
{
DB::table('roles')->where('id', 1)->update(['guard_name' => 'api']);
DB::table('roles')->where('id', 2)->update(['guard_name' => 'api']);
DB::table('permissions')->where('id', '>', 0)->update(['guard_name' => 'api']);
// Clear Spatie permission cache so changes take effect immediately
app()['cache']->forget('spatie.permission.cache');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('roles')->where('id', 1)->update(['guard_name' => 'web']);
DB::table('roles')->where('id', 2)->update(['guard_name' => 'web']);
DB::table('permissions')->where('id', '>', 0)->update(['guard_name' => 'web']);
// Clear Spatie permission cache so rollback takes effect immediately
app()['cache']->forget('spatie.permission.cache');
}
};
@@ -20,61 +20,61 @@ class AdminUserPermissionsTableSeeder extends Seeder
// admin permissions
$permissions = [
['name' => 'view document', 'guard_name' => 'web'],
['name' => 'add document', 'guard_name' => 'web'],
['name' => 'edit document', 'guard_name' => 'web'],
['name' => 'delete document', 'guard_name' => 'web'],
['name' => 'view document', 'guard_name' => 'api'],
['name' => 'add document', 'guard_name' => 'api'],
['name' => 'edit document', 'guard_name' => 'api'],
['name' => 'delete document', 'guard_name' => 'api'],
['name' => 'view standard_segment', 'guard_name' => 'web'],
['name' => 'add standard_segment', 'guard_name' => 'web'],
['name' => 'edit standard_segment', 'guard_name' => 'web'],
['name' => 'delete standard_segment', 'guard_name' => 'web'],
['name' => 'view standard_segment', 'guard_name' => 'api'],
['name' => 'add standard_segment', 'guard_name' => 'api'],
['name' => 'edit standard_segment', 'guard_name' => 'api'],
['name' => 'delete standard_segment', 'guard_name' => 'api'],
['name' => 'view standard_segment_constant', 'guard_name' => 'web'],
['name' => 'add standard_segment_constant', 'guard_name' => 'web'],
['name' => 'edit standard_segment_constant', 'guard_name' => 'web'],
['name' => 'delete standard_segment_constant', 'guard_name' => 'web'],
['name' => 'view standard_segment_constant', 'guard_name' => 'api'],
['name' => 'add standard_segment_constant', 'guard_name' => 'api'],
['name' => 'edit standard_segment_constant', 'guard_name' => 'api'],
['name' => 'delete standard_segment_constant', 'guard_name' => 'api'],
['name' => 'view segment', 'guard_name' => 'web'],
['name' => 'add segment', 'guard_name' => 'web'],
['name' => 'edit segment', 'guard_name' => 'web'],
['name' => 'delete segment', 'guard_name' => 'web'],
['name' => 'view segment', 'guard_name' => 'api'],
['name' => 'add segment', 'guard_name' => 'api'],
['name' => 'edit segment', 'guard_name' => 'api'],
['name' => 'delete segment', 'guard_name' => 'api'],
['name' => 'view segment_constant', 'guard_name' => 'web'],
['name' => 'add segment_constant', 'guard_name' => 'web'],
['name' => 'edit segment_constant', 'guard_name' => 'web'],
['name' => 'delete segment_constant', 'guard_name' => 'web'],
['name' => 'view segment_constant', 'guard_name' => 'api'],
['name' => 'add segment_constant', 'guard_name' => 'api'],
['name' => 'edit segment_constant', 'guard_name' => 'api'],
['name' => 'delete segment_constant', 'guard_name' => 'api'],
['name' => 'view company_bank', 'guard_name' => 'web'],
['name' => 'add company_bank', 'guard_name' => 'web'],
['name' => 'edit company_bank', 'guard_name' => 'web'],
['name' => 'delete company_bank', 'guard_name' => 'web'],
['name' => 'view company_bank', 'guard_name' => 'api'],
['name' => 'add company_bank', 'guard_name' => 'api'],
['name' => 'edit company_bank', 'guard_name' => 'api'],
['name' => 'delete company_bank', 'guard_name' => 'api'],
['name' => 'view currency', 'guard_name' => 'web'],
['name' => 'add currency', 'guard_name' => 'web'],
['name' => 'edit currency', 'guard_name' => 'web'],
['name' => 'delete currency', 'guard_name' => 'web'],
['name' => 'view currency', 'guard_name' => 'api'],
['name' => 'add currency', 'guard_name' => 'api'],
['name' => 'edit currency', 'guard_name' => 'api'],
['name' => 'delete currency', 'guard_name' => 'api'],
['name' => 'view currency_rate', 'guard_name' => 'web'],
['name' => 'add currency_rate', 'guard_name' => 'web'],
['name' => 'edit currency_rate', 'guard_name' => 'web'],
['name' => 'delete currency_rate', 'guard_name' => 'web'],
['name' => 'view currency_rate', 'guard_name' => 'api'],
['name' => 'add currency_rate', 'guard_name' => 'api'],
['name' => 'edit currency_rate', 'guard_name' => 'api'],
['name' => 'delete currency_rate', 'guard_name' => 'api'],
['name' => 'view booking', 'guard_name' => 'web'],
['name' => 'add booking', 'guard_name' => 'web'],
['name' => 'edit booking', 'guard_name' => 'web'],
['name' => 'delete booking', 'guard_name' => 'web'],
['name' => 'view booking', 'guard_name' => 'api'],
['name' => 'add booking', 'guard_name' => 'api'],
['name' => 'edit booking', 'guard_name' => 'api'],
['name' => 'delete booking', 'guard_name' => 'api'],
['name' => 'add milestone', 'guard_name' => 'web'],
['name' => 'add reward', 'guard_name' => 'web'],
['name' => 'edit milestone', 'guard_name' => 'web'],
['name' => 'delete milestone', 'guard_name' => 'web'],
['name' => 'delete reward', 'guard_name' => 'web'],
['name' => 'add milestone', 'guard_name' => 'api'],
['name' => 'add reward', 'guard_name' => 'api'],
['name' => 'edit milestone', 'guard_name' => 'api'],
['name' => 'delete milestone', 'guard_name' => 'api'],
['name' => 'delete reward', 'guard_name' => 'api'],
['name' => 'add voucher', 'guard_name' => 'web'],
['name' => 'list voucher campaigns', 'guard_name' => 'web'],
['name' => 'add voucher', 'guard_name' => 'api'],
['name' => 'list voucher campaigns', 'guard_name' => 'api'],
['name' => 'update bank_metadata', 'guard_name' => 'web'],
['name' => 'update bank_metadata', 'guard_name' => 'api'],
];
foreach ($permissions as $permission){
@@ -87,7 +87,7 @@ class AdminUserPermissionsTableSeeder extends Seeder
['name' => 'Shadow Admin'],
[
'name' => 'Shadow Admin',
'guard_name' => 'web',
'guard_name' => 'api',
'type' => 1,
]
);
@@ -108,7 +108,7 @@ class AdminUserPermissionsTableSeeder extends Seeder
['name' => 'Ultimate Admin'],
[
'name' => 'Ultimate Admin',
'guard_name' => 'web',
'guard_name' => 'api',
'type' => 1,
]
);
@@ -125,7 +125,7 @@ class AdminUserPermissionsTableSeeder extends Seeder
['name' => 'Admin'],
[
'name' => 'Admin',
'guard_name' => 'web',
'guard_name' => 'api',
'type' => 1,
]
);
+1 -1
View File
@@ -1,3 +1,3 @@
FROM laravelphp/vapor:php74
FROM laravelphp/vapor:php83
COPY . /var/task
+35 -17
View File
@@ -1,12 +1,10 @@
FROM php:7.4-fpm
FROM php:8.3-fpm
WORKDIR /var/www/html
RUN pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug
RUN docker-php-ext-install pdo pdo_mysql
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
@@ -15,25 +13,45 @@ RUN apt-get update && apt-get install -y \
cron \
supervisor \
nano \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& rm -rf /var/lib/apt/lists/*
# Install Xdebug (compatible with PHP 8.3)
RUN pecl install xdebug && docker-php-ext-enable xdebug
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install zip \
&& docker-php-ext-install bcmath
COPY --from=composer:1.9.3 /usr/bin/composer /usr/bin/composer
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
#NODEJS & NPM
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get -y install nodejs
#NODEJS & NPM (OLD Before upgrade)
# RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
# RUN apt-get -y install nodejs
RUN chown -R www-data:www-data /var/www
RUN chmod 755 /var/www
#NODEJS & NPM (Node 14 for x86_64 (amd64))
# RUN curl -fsSL https://nodejs.org/dist/v14.21.3/node-v14.21.3-linux-x64.tar.xz -o node.tar.xz \
# && tar -xJf node.tar.xz -C /usr/local --strip-components=1 \
# && rm node.tar.xz
# Configure xdebug
RUN echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.remote_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.remote_port=9002" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
# NODEJS & NPM (Node 14 for ARM64)
RUN curl -fsSL https://nodejs.org/dist/v14.21.3/node-v14.21.3-linux-arm64.tar.xz -o node.tar.xz \
&& tar -xJf node.tar.xz -C /usr/local --strip-components=1 \
&& rm node.tar.xz
# Set permissions
RUN chown -R www-data:www-data /var/www \
&& chmod 755 /var/www
# Configure Xdebug
RUN echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.client_port=9002" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.idekey=VSCODE" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
# Moved to docker-setup folder
+7 -7
View File
@@ -1,13 +1,13 @@
version: '3'
networks:
exchange-staging:
exchange-development:
services:
#################################################################
nginx:
image: nginx:stable-alpine
container_name: exchange-ngnix
container_name: exchange-2-ngnix
ports:
- "8082:80"
volumes:
@@ -17,11 +17,11 @@ services:
- php
- mysql
networks:
- exchange-staging
- exchange-development
#################################################################
mysql:
image: mysql:5.7.29
container_name: exchange-mysql
container_name: exchange-2-mysql
restart: unless-stopped
tty: true
ports:
@@ -36,20 +36,20 @@ services:
volumes:
- mysql-data:/var/lib/mysql
networks:
- exchange-staging
- exchange-development
#################################################################
php:
build:
context: .
dockerfile: Dockerfile
container_name: exchange-php
container_name: exchange-2-php
volumes:
- ../:/var/www/html
- ./php/default.conf:/usr/local/etc/php-fpm.d/zz-docker.conf
ports:
- "9002:9000"
networks:
- exchange-staging
- exchange-development
#################################################################
volumes:
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">./app</directory>
</include>
</source>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/> -->
<!--
<server name="DB_CONNECTION" value="mysql"/>
<server name="DB_HOST" value="172.18.0.3"/>
<server name="DB_PORT" value="3306"/>
<server name="DB_DATABASE" value="ci_test_exchange"/>
<server name="DB_USERNAME" value="ci"/>
<server name="DB_PASSWORD" value="ci"/>
-->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
+6 -6
View File
@@ -12,17 +12,17 @@
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<source>
<include>
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
</include>
</source>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
+1 -1
View File
@@ -1,3 +1,3 @@
FROM laravelphp/vapor:php74
FROM laravelphp/vapor:php83
COPY . /var/task
@@ -69,7 +69,7 @@
</div>
</div>
</div>
<advertisement-component class="m-b-15 m-t-15" v-if="!isLoading"></advertisement-component>
<advertisement-component class="m-b-15 m-t-15"></advertisement-component>
<!-- C2C consent -->
<div class="row m-l-0 m-r-0 m-b-15 animate__animated animate__tada animate__repeat-2 animate__delay-3s" v-if="!data.segments.some(item => item.id === 29)">
<div class="col bg-white padding-15">
@@ -41,10 +41,12 @@
},
},
created() {
this.parameters = {};
this.parameters.type = [0,1].includes(this.data.type) ? this.data.type: 0;
this.parameters.email = this.data.contact ? this.data.contact.email : "";
this.parameters.phone = this.data.contact ? this.data.contact.phone : "";
this.initParameters();
},
watch: {
'data': function() {
this.initParameters();
}
},
data(){
return {
@@ -59,8 +61,14 @@
}
},
methods: {
initParameters() {
this.parameters = {};
this.parameters.type = [0,1].includes(this.data.type) ? this.data.type: 0;
this.parameters.email = this.data.contact ? this.data.contact.email : "";
this.parameters.phone = this.data.contact ? this.data.contact.phone : "";
},
submitForm(){
this.submit(route('api.company.profile.update', this.data.id), 'put', this.section, true, true);
this.submit(route('api.company.profile.update', this.data.id), 'put', this.section + 'EditCompanyType', true, true);
},
successHandler(){
window.location.reload();
@@ -14,7 +14,7 @@
<div class="col">
<div class="d-flex align-items-center h-100">
<span class="btn btn-md fs-11 bg-primary text-white fs-12 m-r-5" :class="[{'bg-primary-darker': showingPreciseAmount}]" @click="showingPreciseAmount=!showingPreciseAmount">{{ showingPreciseAmount ? 'Showing Precise Wallet Transaction' : 'Show Precise Wallet Transaction'}}</span>
<a v-if="company" @click="download(company, showingPreciseAmount)" target="_blank" class="btn btn-md btn-primary fs-11"><i class="fa fa-download m-r-5"></i>{{ showingPreciseAmount ? 'Download Precise Transaction' : 'Download Transaction'}}</a>
<a v-if="company" @click="download(company, showingPreciseAmount)" target="_blank" class="btn btn-md btn-primary fs-12"><i class="fa fa-download m-r-5"></i>{{ showingPreciseAmount ? 'Download Precise Transaction' : 'Download Transaction'}}</a>
</div>
</div>
<div class="col-2">
+1 -1
View File
@@ -26,7 +26,7 @@ export default {
return !unprotectedPaths.includes(currentPath);
},
isWithTokenRoute(){
return window.location.href.includes(this.route('account.password.reset'));
return window.location.href.includes(this.route('account.password.reset')) || window.location.href.includes('/account/email/verification');
}
}
@@ -2,7 +2,7 @@
@section('content')
<h4 style="font-size: 1em;">Hello, {{$user->name}}</h4>
<p style="font-size: 0.9em">verify your email to finish your account registration on <a href="{{route('login')}}" class="bold">{{route('login')}}</a></p>
<p style="font-size: 0.9em">Please verify your email to finish your account registration on <a href="{{route('login')}}" class="bold">{{route('login')}}</a></p>
<p style="margin-top: 30px; font-size: 0.8em">Please confirm that <b>{{$user->email}}</b> is your email address by clicking on the button below or use this link <a href="{{route('account.email.verification', $attempt->token)}}">{{route('account.email.verification', $attempt->token)}}</a> within 48 hours</p>
<div style="margin-top: 20px;">
<a href="{{route('account.email.verification', $attempt->token)}}"><button class="btn all-caps bg-primary no-border text-white pointer" style="font-size: 0.8em" >Verify</button></a>
+8
View File
@@ -19,6 +19,12 @@
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>
<script>
setInterval(function() {
window.location.href = "/";
}, 60000); // 60000 ms = 1 minute, 300000 ms = 5 minutes
</script>
</head>
<body>
<div class="content">
@@ -26,6 +32,8 @@
<img src="{{ asset('images/maintenance.png') }}" alt="Maintenance" style="max-width: 300px; margin-bottom: 20px;">
<p>{{ config('maintenance.message') }}</p>
<p>&mdash; CIEF EXCHANGE</p>
<a href="/" class="btn">Go Back Home</a>
</div>
</body>
</html>
+33 -17
View File
@@ -1,48 +1,64 @@
<?php
use App\Http\Controllers\Accounts\CreateSystemUserController;
use App\Http\Controllers\Accounts\UserAuthenticationLogoutController;
use App\Http\Controllers\Accounts\RefreshAuthenticationTokenController;
use App\Http\Controllers\Accounts\UserAuthenticationController;
use App\Http\Controllers\Accounts\CheckEmailController;
use App\Http\Controllers\Accounts\GeneratePasswordResetController;
use App\Http\Controllers\Accounts\ResetPasswordController;
use App\Http\Controllers\Accounts\CreateCustomerController;
use App\Http\Controllers\Accounts\UserEmailVerificationController;
use App\Http\Controllers\Accounts\ResendEmailVerificationController;
use App\Http\Controllers\Accounts\FetchUserByEmailController;
use App\Http\Controllers\Accounts\FetchUserController;
use App\Http\Controllers\Accounts\ListUsersController;
use App\Http\Controllers\Accounts\UpdateUserController;
use App\Http\Controllers\Accounts\CreateAdminUserController;
use App\Http\Controllers\Accounts\DeleteUserController;
use App\Http\Controllers\Accounts\UpdateUserRoleController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'account', 'namespace' => 'Accounts', 'as' => 'account.'], function () {
Route::group(['prefix' => 'account', 'as' => 'account.'], function () {
Route::group(['prefix' => 'authentication', 'as' => 'authentication.'], function () {
Route::group(['middleware' => 'valid.token'], function () {
Route::get('/logout', 'UserAuthenticationLogoutController@logout')->name('logout');
Route::get('/refresh', 'RefreshAuthenticationTokenController@refresh')->name('refresh');
Route::get('/logout', [UserAuthenticationLogoutController::class, 'logout'])->name('logout');
Route::get('/refresh', [RefreshAuthenticationTokenController::class, 'refresh'])->name('refresh');
});
Route::group(['prefix' => 'login', 'as' => 'authenticate.'], function () {
Route::post('/attempt', 'UserAuthenticationController@authenticate')->name('attempt');
Route::post('/check_email', 'CheckEmailController@check')->name('email.check');
Route::post('/attempt', [UserAuthenticationController::class, 'authenticate'])->name('attempt');
Route::post('/check_email', [CheckEmailController::class, 'check'])->name('email.check');
});
Route::group(['prefix' => 'password', 'as' => 'password.'], function () {
Route::post('/forget', 'GeneratePasswordResetController@generate')->name('forget');
Route::post('/reset', 'ResetPasswordController@reset')->name('reset');
Route::post('/forget', [GeneratePasswordResetController::class, 'generate'])->name('forget');
Route::post('/reset', [ResetPasswordController::class, 'reset'])->name('reset');
});
});
Route::group(['prefix' => 'registration', 'as' => 'registration.'], function () {
Route::post('/registration', 'CreateCustomerController@create')->name('register');
Route::post('/registration', [CreateCustomerController::class, 'create'])->name('register');
});
Route::group(['prefix' => 'email', 'as' => 'email.'], function () {
Route::post('/verify', 'UserEmailVerificationController@verify')->name('verify');
Route::post('/verification/resend', 'ResendEmailVerificationController@resend')->name('verification.resend');
Route::post('/verify', [UserEmailVerificationController::class, 'verify'])->name('verify');
Route::post('/verification/resend', [ResendEmailVerificationController::class, 'resend'])->name('verification.resend');
});
Route::group(['prefix' => 'user', 'as' => 'user.', 'middleware' => 'valid.token'], function () {
Route::get('email/{email}', 'FetchUserByEmailController@fetch')->name('company');
Route::post('/show', 'FetchUserController@fetch')->name('show');
Route::get('/list', 'ListUsersController@list')->name('list');
Route::put('/update/{id}', 'UpdateUserController@update')->name('update');
Route::get('email/{email}', [FetchUserByEmailController::class, 'fetch'])->name('company');
Route::post('/show', [FetchUserController::class, 'fetch'])->name('show');
Route::get('/list', [ListUsersController::class, 'list'])->name('list');
Route::put('/update/{id}', [UpdateUserController::class, 'update'])->name('update');
Route::post('/admin/create', 'CreateAdminUserController@create')->name('admin.create');
Route::delete('/delete/{id}', 'DeleteUserController@delete')->name('delete');
Route::put('/update/{id}/role', 'UpdateUserRoleController@update')->name('update.role');
Route::post('/admin/create', [CreateAdminUserController::class, 'create'])->name('admin.create');
Route::delete('/delete/{id}', [DeleteUserController::class, 'delete'])->name('delete');
Route::put('/update/{id}/role', [UpdateUserRoleController::class, 'update'])->name('update.role');
Route::post('/system/create', [CreateSystemUserController::class, 'create'])->name('system.create');
});
+14 -9
View File
@@ -1,22 +1,27 @@
<?php
use App\Http\Controllers\Accounting\ApproveDuplicateBankStatementDetailsStatusController;
use App\Http\Controllers\Accounting\BankStatementController;
use App\Http\Controllers\Accounting\GroupApproveStatementTransactionController;
use App\Http\Controllers\Accounting\HistoryImportedTransactionMappedController;
use App\Http\Controllers\Accounting\UpdateStatementTransactionStatusController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'accounting', 'as' => 'accounting.', 'namespace' => 'Accounting'], function () {
Route::post('/import', 'BankStatementController@import')->name('statement.import');
Route::get('/bank_account', 'BankStatementController@transactions')->name('bank.transaction');
Route::group(['prefix' => 'accounting', 'as' => 'accounting.'], function () {
Route::post('/import', [BankStatementController::class, 'import'])->name('statement.import');
Route::get('/bank_account', [BankStatementController::class, 'transactions'])->name('bank.transaction');
Route::group(['prefix' => 'statements/{id}', 'as' => 'statement.'], function () {
Route::get('/details', 'BankStatementController@fetch')->name('details');
Route::put('/details/update', 'BankStatementController@update')->name('details.update');
Route::get('/details', [BankStatementController::class, 'fetch'])->name('details');
Route::put('/details/update', [BankStatementController::class, 'update'])->name('details.update');
});
Route::post('bankStatement/{id}/details/{status}', 'ApproveDuplicateBankStatementDetailsStatusController@update')->where('status', 'approve|reject|pending_verification')->name('bankStatement.details.status.update');
Route::post('bankStatement/{id}/details/{status}', [ApproveDuplicateBankStatementDetailsStatusController::class, 'update'])->where('status', 'approve|reject|pending_verification')->name('bankStatement.details.status.update');
Route::group(['prefix' => 'statement_transaction', 'as' => 'statement_transaction.'], function () {
Route::post('/owner/group-approve', 'GroupApproveStatementTransactionController@approve')->name('owner.groupApprove');
Route::post('/{id}/owner/{status}', 'UpdateStatementTransactionStatusController@update')->where('status', 'approve|reject')->name('owner.status.update');
Route::post('/owner/group-approve', [GroupApproveStatementTransactionController::class, 'approve'])->name('owner.groupApprove');
Route::post('/{id}/owner/{status}', [UpdateStatementTransactionStatusController::class, 'update'])->where('status', 'approve|reject')->name('owner.status.update');
});
Route::get('history/imported', 'HistoryImportedTransactionMappedController@getImported')->name('history.imported');
Route::get('history/imported', [HistoryImportedTransactionMappedController::class, 'getImported'])->name('history.imported');
});
+12 -6
View File
@@ -1,14 +1,20 @@
<?php
use App\Http\Controllers\Affiliate\GetAffiliateSettingsController;
use App\Http\Controllers\Affiliate\UpdateAffiliateSettingsController;
use App\Http\Controllers\Affiliate\ListAffiliatesController;
use App\Http\Controllers\Affiliate\CreateAffiliateController;
use App\Http\Controllers\Affiliate\UpdateAffiliateController;
use App\Http\Controllers\Affiliate\DeleteAffiliateController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'affiliate', 'as' => 'affiliate.'], function () {
Route::get('/settings', 'Affiliate\GetAffiliateSettingsController@get')->name('settings.get');
Route::post('/settings', 'Affiliate\UpdateAffiliateSettingsController@update')->name('settings.update');
Route::get('/settings', [GetAffiliateSettingsController::class, 'get'])->name('settings.get');
Route::post('/settings', [UpdateAffiliateSettingsController::class, 'update'])->name('settings.update');
Route::get('/list', 'Affiliate\ListAffiliatesController@list')->name('list');
Route::post('/create', 'Affiliate\CreateAffiliateController@create')->name('create');
Route::put('/update/{id}', 'Affiliate\UpdateAffiliateController@update')->name('update');
Route::delete('/delete/{id}', 'Affiliate\DeleteAffiliateController@delete')->name('delete');
Route::get('/list', [ListAffiliatesController::class, 'list'])->name('list');
Route::post('/create', [CreateAffiliateController::class, 'create'])->name('create');
Route::put('/update/{id}', [UpdateAffiliateController::class, 'update'])->name('update');
Route::delete('/delete/{id}', [DeleteAffiliateController::class, 'delete'])->name('delete');
});
+13 -7
View File
@@ -1,15 +1,21 @@
<?php
use App\Http\Controllers\Announcements\AssignAnnouncementToSegmentController;
use App\Http\Controllers\Announcements\CreateAnnouncementController;
use App\Http\Controllers\Announcements\DeleteAnnouncementController;
use App\Http\Controllers\Announcements\ListAnnouncementsController;
use App\Http\Controllers\Announcements\RemoveSegmentFromAnnouncementController;
use App\Http\Controllers\Announcements\UpdateAnnouncementController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'announcement', 'as' => 'announcement.', 'namespace' => 'Announcements'], function () {
Route::get('/list', 'ListAnnouncementsController@list')->name('list');
Route::post('/create', 'CreateAnnouncementController@create')->name('create');
Route::put('/update/{id}', 'UpdateAnnouncementController@update')->name('update');
Route::delete('/delete/{id}', 'DeleteAnnouncementController@delete')->name('delete');
Route::group(['prefix' => 'announcement', 'as' => 'announcement.'], function () {
Route::get('/list', [ListAnnouncementsController::class, 'list'])->name('list');
Route::post('/create', [CreateAnnouncementController::class, 'create'])->name('create');
Route::put('/update/{id}', [UpdateAnnouncementController::class, 'update'])->name('update');
Route::delete('/delete/{id}', [DeleteAnnouncementController::class, 'delete'])->name('delete');
Route::group(['prefix' => '{id}/segment', 'as' => 'segment.'], function () {
Route::post('/assign', 'AssignAnnouncementToSegmentController@assign')->name('assign');
Route::delete('/detach/{segment_id}', 'RemoveSegmentFromAnnouncementController@detach')->name('detach');
Route::post('/assign', [AssignAnnouncementToSegmentController::class, 'assign'])->name('assign');
Route::delete('/detach/{segment_id}', [RemoveSegmentFromAnnouncementController::class, 'detach'])->name('detach');
});
});
+20 -11
View File
@@ -1,5 +1,14 @@
<?php
use App\Http\Controllers\Services\CountriesListController;
use App\Http\Controllers\Billplz\CallbackBillplzController;
use App\Http\Controllers\Documents\RenderDocumentController;
use App\Http\Controllers\Imports\ImportUpdateDebtorController;
use App\Http\Controllers\Imports\ImportHoneyTrapController;
use App\Http\Controllers\Imports\ImportStatementInvoiceController;
use App\Http\Controllers\Imports\ImportStatementReceiptsController;
use App\Http\Controllers\Companies\BulkDownloadCustomerInvoicesController;
use App\Http\Controllers\Companies\BulkDownloadSupplierWhiteFormsController;
use Illuminate\Support\Facades\Route;
/*
@@ -13,28 +22,28 @@ use Illuminate\Support\Facades\Route;
|
*/
Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function () {
Route::group(['prefix' => 'v1', 'as' => 'api.'], function () {
require __DIR__ . '/account.php';
// Route::get('/rate/calculate', 'RateCalculateCurrencyController@convert')->name('calculate');
// Route::get('/rate/calculate', [RateCalculateCurrencyController::class, 'convert'])->name('calculate');
Route::group(['prefix' => 'service', 'as' => 'service.'], function () {
Route::get('countries/list', 'Services\CountriesListController@index')->name('list.countries');
Route::get('countries/list', [CountriesListController::class, 'index'])->name('list.countries');
});
Route::post('online_payment/callback', 'Billplz\CallbackBillplzController@callback')->name('online_payment.callback');
Route::post('online_payment/callback', [CallbackBillplzController::class, 'callback'])->name('online_payment.callback');
Route::group(['middleware' => 'valid.token'], function () {
Route::group(['middleware' => 'admin'], function () { //cief maintenance
Route::get('/storage/{fileName}/fetch', 'Documents\RenderDocumentController@fileStorageServe')->where(['fileName' => '.*'])->name('storage.document.file');
Route::post('/import/update-debtor/f614e339d7058904a831aad742e24d55', 'Imports\ImportUpdateDebtorController@import')->name('debtor.import');
Route::post('/import/upload-honey-trap', 'Imports\ImportHoneyTrapController@import')->name('honey_trap.upload');
Route::post('/import/upload-import-invoices', 'Imports\ImportStatementInvoiceController@import')->name('import_invoices.upload');
Route::post('/import/upload-import-receipt', 'Imports\ImportStatementReceiptsController@import')->name('import_receipts.upload');
Route::post('/customers/invoices', 'Companies\BulkDownloadCustomerInvoicesController@download')->name('customers.invoices');
Route::post('/supplier/white-form/bulk-download', 'Companies\BulkDownloadSupplierWhiteFormsController@download')->name('suppliers.white_forms');
Route::get('/storage/{fileName}/fetch', [RenderDocumentController::class, 'fileStorageServe'])->where(['fileName' => '.*'])->name('storage.document.file');
Route::post('/import/update-debtor/f614e339d7058904a831aad742e24d55', [ImportUpdateDebtorController::class, 'import'])->name('debtor.import');
Route::post('/import/upload-honey-trap', [ImportHoneyTrapController::class, 'import'])->name('honey_trap.upload');
Route::post('/import/upload-import-invoices', [ImportStatementInvoiceController::class, 'import'])->name('import_invoices.upload');
Route::post('/import/upload-import-receipt', [ImportStatementReceiptsController::class, 'import'])->name('import_receipts.upload');
Route::post('/customers/invoices', [BulkDownloadCustomerInvoicesController::class, 'download'])->name('customers.invoices');
Route::post('/supplier/white-form/bulk-download', [BulkDownloadSupplierWhiteFormsController::class, 'download'])->name('suppliers.white_forms');
require __DIR__ . '/company.php';
+3 -2
View File
@@ -2,11 +2,12 @@
use App\Http\Controllers\Bookings\ListBookingsSalesInvoiceController;
use App\Http\Controllers\Bookings\UpdateBookingSalesInvoiceController;
use App\Http\Controllers\Transactions\ListMappableTransactionsController;
use Illuminate\Support\Facades\Route;
Route::group(['middleware' => 'apipub', 'prefix' => 'v1', 'as' => 'apipub.'], function () {
Route::group(['prefix' => 'v1', 'as' => 'apipub.'], function () {
Route::group(['middleware' => 'token.check'], function () {
Route::get('transactions/mappable/query', 'Transactions\ListMappableTransactionsController@list')->name('transaction.mappable.list');
Route::get('transactions/mappable/query', [ListMappableTransactionsController::class, 'list'])->name('transaction.mappable.list');
Route::group(['prefix' => 'booking', 'as' => 'booking.'], function () {
Route::get('/sales-invoice/list', [ListBookingsSalesInvoiceController::class, 'list'])->name('booking.sales-invoice.list');
+15 -8
View File
@@ -1,15 +1,22 @@
<?php
use App\Http\Controllers\Banks\CreateBankController;
use App\Http\Controllers\Banks\DeleteBankController;
use App\Http\Controllers\Banks\ListBanksController;
use App\Http\Controllers\Banks\SetBankToDefaultController;
use App\Http\Controllers\Banks\UpdateBankController;
use App\Http\Controllers\Banks\UpdateBankMetadataController;
use App\Http\Controllers\Banks\UpdateBankStatusController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'bank', 'as' => 'bank.', 'namespace' => 'Banks'], function () {
Route::get('/list', 'ListBanksController@list')->name('list');
Route::post('/create', 'CreateBankController@create')->name('create');
Route::put('/update/{id}', 'UpdateBankController@update')->name('update');
Route::put('/{id}/default', 'SetBankToDefaultController@update')->name('default');
Route::delete('/delete/{id}', 'DeleteBankController@delete')->name('delete');
Route::group(['prefix' => 'bank', 'as' => 'bank.'], function () {
Route::get('/list', [ListBanksController::class, 'list'])->name('list');
Route::post('/create', [CreateBankController::class, 'create'])->name('create');
Route::put('/update/{id}', [UpdateBankController::class, 'update'])->name('update');
Route::put('/{id}/default', [SetBankToDefaultController::class, 'update'])->name('default');
Route::delete('/delete/{id}', [DeleteBankController::class, 'delete'])->name('delete');
Route::put('/update/{id}/status', 'UpdateBankStatusController@update')->name('status.update');
Route::put('/update/{id}/status', [UpdateBankStatusController::class, 'update'])->name('status.update');
Route::post('/metadata/update/{id}', 'UpdateBankMetadataController@delete')->name('update.metadata');
Route::post('/metadata/update/{id}', [UpdateBankMetadataController::class, 'delete'])->name('update.metadata');
});
+3 -2
View File
@@ -1,9 +1,10 @@
<?php
use App\Http\Controllers\Billplz\CreateBillplzBillController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'billplz', 'as' => 'billplz.', 'namespace' => 'Billplz'], function () {
Route::group(['prefix' => 'billplz', 'as' => 'billplz.'], function () {
Route::group(['prefix' => 'bill', 'as' => 'bill.'], function () {
Route::post('/create', 'CreateBillplzBillController@create')->name('create');
Route::post('/create', [CreateBillplzBillController::class, 'create'])->name('create');
});
});
+55 -31
View File
@@ -1,53 +1,77 @@
<?php
use App\Http\Controllers\Bookings\RegenerateBookingPaymentRVController;
use App\Http\Controllers\Bookings\RegenerateBookingEInvoiceController;
use App\Http\Controllers\Bookings\UpdateBookingAmountController;
use App\Http\Controllers\Bookings\CreateBookingLockController;
use App\Http\Controllers\Bookings\DeleteBookingLockController;
use App\Http\Controllers\Bookings\ApprovePaymentVerificationController;
use App\Http\Controllers\Bookings\ApprovePurchaseOrderController;
use App\Http\Controllers\Bookings\CancelBookingController;
use App\Http\Controllers\Bookings\CreateBankingInvoiceTransactionController;
use App\Http\Controllers\Bookings\CreateBookingController;
use App\Http\Controllers\Bookings\CreateBookingLockController;
use App\Http\Controllers\Bookings\CreateBookingPaymentController;
use App\Http\Controllers\Bookings\CreateBookingRefundController;
use App\Http\Controllers\Bookings\CreateBookingRefundCreditNoteController;
use App\Http\Controllers\Bookings\CreatePaymentVerificationController;
use App\Http\Controllers\Bookings\CreateProformaInvoiceTransaction;
use App\Http\Controllers\Bookings\DeleteBookingController;
use App\Http\Controllers\Bookings\DeleteBookingLockController;
use App\Http\Controllers\Bookings\DeletePurchaseOrderPdfController;
use App\Http\Controllers\Bookings\ExpireBookingPaymentController;
use App\Http\Controllers\Bookings\FetchBookingController;
use App\Http\Controllers\Bookings\FetchBookingPaymentQuotationController;
use App\Http\Controllers\Bookings\ListBookingsController;
use App\Http\Controllers\Bookings\ListBookingsJobController;
use App\Http\Controllers\Bookings\MergeBookingController;
use App\Http\Controllers\Bookings\RegenerateBookingEInvoiceController;
use App\Http\Controllers\Bookings\RegenerateBookingPaymentRVController;
use App\Http\Controllers\Bookings\RegenerateInvoiceBookingController;
use App\Http\Controllers\Bookings\RestoreBookingController;
use App\Http\Controllers\Bookings\UpdateBookingAmountController;
use App\Http\Controllers\Bookings\UpdateBookingController;
use App\Http\Controllers\Bookings\UpdateBookingOrderReferenceController;
use App\Http\Controllers\Bookings\UpdateBookingOwnerController;
use App\Http\Controllers\Bookings\UpdateBookingRecipientController;
use App\Http\Controllers\Bookings\UploadPurchaseOrderController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Bookings'], function () {
Route::get('/show/{marking}', 'FetchBookingController@fetch')->name('show');
Route::get('/list', 'ListBookingsController@list')->name('list');
Route::get('/list/job', 'ListBookingsJobController@list')->name('list.job');
Route::post('/create', 'CreateBookingController@create')->name('create');
Route::group(['prefix' => 'booking', 'as' => 'booking.'], function () {
Route::get('/show/{marking}', [FetchBookingController::class, 'fetch'])->name('show');
Route::get('/list', [ListBookingsController::class, 'list'])->name('list');
Route::get('/list/job', [ListBookingsJobController::class, 'list'])->name('list.job');
Route::post('/create', [CreateBookingController::class, 'create'])->name('create');
Route::post('/create/lock', [CreateBookingLockController::class, 'create'])->name('create.lock');
Route::delete('/delete/lock/{id}', [DeleteBookingLockController::class, 'delete'])->name('delete.lock');
Route::put('/update/{id}', 'UpdateBookingController@update')->name('update');
Route::put('/recipient/update/{id}', 'UpdateBookingRecipientController@update')->name('update.recipient');
Route::put('/cancel/{id}', 'CancelBookingController@cancel')->name('cancel');
Route::put('/restore/{id}', 'RestoreBookingController@restore')->name('restore');
Route::delete('/delete/{id}', 'DeleteBookingController@delete')->name('delete');
Route::post('/regenerate/invoice/{id}', 'RegenerateInvoiceBookingController@regenerate')->name('regenerate.invoice');
Route::put('/update/{id}', [UpdateBookingController::class, 'update'])->name('update');
Route::put('/recipient/update/{id}', [UpdateBookingRecipientController::class, 'update'])->name('update.recipient');
Route::put('/cancel/{id}', [CancelBookingController::class, 'cancel'])->name('cancel');
Route::put('/restore/{id}', [RestoreBookingController::class, 'restore'])->name('restore');
Route::delete('/delete/{id}', [DeleteBookingController::class, 'delete'])->name('delete');
Route::post('/regenerate/invoice/{id}', [RegenerateInvoiceBookingController::class, 'regenerate'])->name('regenerate.invoice');
Route::put('/owner/update/{id}', 'UpdateBookingOwnerController@update')->name('owner.update');
Route::put('/owner/update/{id}', [UpdateBookingOwnerController::class, 'update'])->name('owner.update');
Route::group(['prefix' => '{id}/payment', 'as' => 'payment.'], function () {
Route::post('quotation', 'FetchBookingPaymentQuotationController@fetch')->name('quotation');
Route::post('create', 'CreateBookingPaymentController@create')->name('create');
Route::post('{payment_id}/verification/create', 'CreatePaymentVerificationController@create')->name('verification.create');
Route::put('/{payment_id}/approval/{status}', 'ApprovePaymentVerificationController@approve')->where('status', 'approve|reject')->name('approval');
Route::post('delete', 'ExpireBookingPaymentController@expire')->name('expire');
Route::post('quotation', [FetchBookingPaymentQuotationController::class, 'fetch'])->name('quotation');
Route::post('create', [CreateBookingPaymentController::class, 'create'])->name('create');
Route::post('{payment_id}/verification/create', [CreatePaymentVerificationController::class, 'create'])->name('verification.create');
Route::put('/{payment_id}/approval/{status}', [ApprovePaymentVerificationController::class, 'approve'])->where('status', 'approve|reject')->name('approval');
Route::post('delete', [ExpireBookingPaymentController::class, 'expire'])->name('expire');
});
Route::group(['prefix' => '{id}/refund', 'as' => 'refund.'], function () {
Route::post('{payment_id}/create', 'CreateBookingRefundController@create')->name('create');
Route::post('{payment_id}/credit_note/create', 'CreateBookingRefundCreditNoteController@create')->name('credit_note.create');
Route::post('{payment_id}/create', [CreateBookingRefundController::class, 'create'])->name('create');
Route::post('{payment_id}/credit_note/create', [CreateBookingRefundCreditNoteController::class, 'create'])->name('credit_note.create');
});
Route::post('{id}/purchase_order/verification', 'ApprovePurchaseOrderController@approve')->name('po.approval');
Route::post('{id}/purchase_order/pdf', 'UploadPurchaseOrderController@upload')->name('po.pdf');
Route::delete('{id}/purchase_order/pdf', 'DeletePurchaseOrderPdfController@delete')->name('po.pdf.delete');
Route::post('{id}/purchase_order/verification', [ApprovePurchaseOrderController::class, 'approve'])->name('po.approval');
Route::post('{id}/purchase_order/pdf', [UploadPurchaseOrderController::class, 'upload'])->name('po.pdf');
Route::delete('{id}/purchase_order/pdf', [DeletePurchaseOrderPdfController::class, 'delete'])->name('po.pdf.delete');
Route::put('{id}/updateAmount', 'UpdateBookingAmountController@update')->name('booking_amount.update');
Route::put('{id}/updateAmount', [UpdateBookingAmountController::class, 'update'])->name('booking_amount.update');
Route::put('{id}/updateAmountWithPO', [UpdateBookingAmountController::class, 'updateOnHold'])->name('amount.update');
Route::put('{id}/updateOrderReferences', 'UpdateBookingOrderReferenceController@update')->name('booking_order_reference.update');
Route::put('{id}/updateOrderReferences', [UpdateBookingOrderReferenceController::class, 'update'])->name('booking_order_reference.update');
Route::post('/merge', 'MergeBookingController@merge')->name('merge');
Route::post('/merge', [MergeBookingController::class, 'merge'])->name('merge');
Route::post('{id}/proforma/create', 'CreateProformaInvoiceTransaction@create')->name('proforma.create');
Route::post('{id}/proforma/create', [CreateProformaInvoiceTransaction::class, 'create'])->name('proforma.create');
Route::post('{id}/banking/create', [CreateBankingInvoiceTransactionController::class, 'create'])->name('banking.create');
+38 -20
View File
@@ -1,42 +1,60 @@
<?php
use App\Http\Controllers\Companies\AddNewMemberController;
use App\Http\Controllers\Companies\ApproveIdentificationDocumentController;
use App\Http\Controllers\Companies\AssignCompanyToSegmentController;
use App\Http\Controllers\Companies\CreateCompanyController;
use App\Http\Controllers\Companies\CreateIdentificationDocumentController;
use App\Http\Controllers\Companies\DeleteCompanyController;
use App\Http\Controllers\Companies\FetchCompanyBookingQuotationController;
use App\Http\Controllers\Companies\FetchCompanyController;
use App\Http\Controllers\Companies\FetchCompanyEInvoiceInfoController;
use App\Http\Controllers\Companies\ListBusinessTypesController;
use App\Http\Controllers\Companies\ListCompaniesController;
use App\Http\Controllers\Companies\ListCompanyTypesController;
use App\Http\Controllers\Companies\RemoveCompanyFromSegmentController;
use App\Http\Controllers\Companies\UpdateCompanyController;
use App\Http\Controllers\Companies\UpdateCompanyDebtorController;
use App\Http\Controllers\Companies\UpdateCompanyDetailsController;
use App\Http\Controllers\Companies\UpdateCompanyEInvoiceInfoController;
use App\Http\Controllers\Companies\UpdateCompanyNameAndDebtorController;
use App\Http\Controllers\Companies\UpdateCompanyProfileController;
use App\Http\Controllers\Companies\UpdateCompanyStatusController;
use App\Http\Controllers\Companies\UpdateSupplierCurrenciesController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Companies'], function () {
Route::get('/{id}/show', 'FetchCompanyController@fetch')->name('show');
Route::get('/list', 'ListCompaniesController@list')->name('list');
Route::post('/create', 'CreateCompanyController@create')->name('create');
Route::put('/update/{id}', 'UpdateCompanyController@update')->name('update');
Route::put('/update/{id}/profile', 'UpdateCompanyProfileController@update')->name('profile.update');
Route::put('update/{id}/status', 'UpdateCompanyStatusController@update')->name('status.update');
// Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('delete');
Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('destroy');
Route::put('/name-and-debtor/update/{id}', 'UpdateCompanyNameAndDebtorController@update')->name('update.nameAndDebtor');
Route::group(['prefix' => 'company', 'as' => 'company.'], function () {
Route::get('/{id}/show', [FetchCompanyController::class, 'fetch'])->name('show');
Route::get('/list', [ListCompaniesController::class, 'list'])->name('list');
Route::post('/create', [CreateCompanyController::class, 'create'])->name('create');
Route::put('/update/{id}', [UpdateCompanyController::class, 'update'])->name('update');
Route::put('/update/{id}/profile', [UpdateCompanyProfileController::class, 'update'])->name('profile.update');
Route::put('update/{id}/status', [UpdateCompanyStatusController::class, 'update'])->name('status.update');
// Route::delete('/delete/{id}', [DeleteCompanyController::class, 'destroy'])->name('delete');
Route::delete('/delete/{id}', [DeleteCompanyController::class, 'destroy'])->name('destroy');
Route::put('/name-and-debtor/update/{id}', [UpdateCompanyNameAndDebtorController::class, 'update'])->name('update.nameAndDebtor');
Route::get('/business-type/list', 'ListBusinessTypesController@list')->name('business_type.list');
Route::get('/company-type/list', 'ListCompanyTypesController@list')->name('company_type.list');
Route::get('/business-type/list', [ListBusinessTypesController::class, 'list'])->name('business_type.list');
Route::get('/company-type/list', [ListCompanyTypesController::class, 'list'])->name('company_type.list');
Route::put('/update/debtor/{id}', 'UpdateCompanyDebtorController@update')->name('delete');
Route::put('/update/debtor/{id}', [UpdateCompanyDebtorController::class, 'update'])->name('delete');
Route::post('/team/create', 'AddNewMemberController@create')->name('team.create');
Route::post('/team/create', [AddNewMemberController::class, 'create'])->name('team.create');
Route::group(['prefix' => '{id}/segment', 'as' => 'segment.'], function () {
Route::post('/assign', 'AssignCompanyToSegmentController@assign')->name('assign');
Route::delete('/detach/{segment_id}', 'RemoveCompanyFromSegmentController@detach')->name('detach');
Route::post('/assign', [AssignCompanyToSegmentController::class, 'assign'])->name('assign');
Route::delete('/detach/{segment_id}', [RemoveCompanyFromSegmentController::class, 'detach'])->name('detach');
});
Route::group(['prefix' => '{id}/currency', 'as' => 'currency.'], function () {
Route::post('/convert', 'FetchCompanyBookingQuotationController@fetch')->name('convert');
Route::post('/convert', [FetchCompanyBookingQuotationController::class, 'fetch'])->name('convert');
});
Route::put('supplier/{id}/currencies/update', 'UpdateSupplierCurrenciesController@update')->name('supplier.currencies.update');
Route::put('supplier/{id}/currencies/update', [UpdateSupplierCurrenciesController::class, 'update'])->name('supplier.currencies.update');
Route::group(['prefix' => '{id}/identification', 'as' => 'identification.'], function () {
Route::post('/create', 'CreateIdentificationDocumentController@create')->name('create');
Route::put('/{document_id}/approval/{status}', 'ApproveIdentificationDocumentController@approve')->where('status', 'approve|reject')->name('approval');
Route::post('/create', [CreateIdentificationDocumentController::class, 'create'])->name('create');
Route::put('/{document_id}/approval/{status}', [ApproveIdentificationDocumentController::class, 'approve'])->where('status', 'approve|reject')->name('approval');
});
Route::put('/details/update/{id}', [UpdateCompanyDetailsController::class, 'update'])->name('update.details');

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