Compare commits

..
Author SHA1 Message Date
snyk-bot 84d0c18272 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-SSRI-1246392
2021-04-16 02:24:02 +00:00
Russell West 61739ce266 Pirep delete confirmation (#1143)
* adds 100ll option to airport admin

* Adds mogas field too

* adds basic confirmation when deleting pirep
2021-04-15 08:39:42 -04:00
Nabeel S bffc4f911c Add tests for the cron jobs (#1141) 2021-04-14 08:37:48 -04:00
Nabeel Shahzad d18925f473 Add tests for 0 results METAR 2021-04-14 06:45:35 -04:00
Russell WestandNabeel S f5e83461a3 adds 100ll option to airport admin (#1138)
* adds 100ll option to airport admin

* Adds mogas field too

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-04-13 12:03:03 -04:00
Nabeel S bfddb2c84d Make sure all dates are in UTC (#1139) 2021-04-13 09:25:38 -04:00
B.Fatih KOZ 7e9eb08135 Use where iso whereTime (#1137)
Using whereTime may present a problem for flights conducted during utc midnight and some active/live flights may be deleted with whereTime.

Scenario;

now = today-01:00  utc
setting = 2 hours
date = yesterday-23:00 utc

Any live pireps will/may be deleted with whereTime 'cause their last updated TIME will be maximum 00:59 which is smaller than 23:00.
2021-04-13 09:08:50 -04:00
B.Fatih KOZ 3d55336823 Fix default value for Captcha setting (#1136) 2021-04-12 16:55:38 -04:00
Nabeel Shahzad 68ed2355ad Add GRAVATAR_DEFAULT_AVATAR to config 2021-04-11 18:42:51 -04:00
Nabeel S fdab4ee530 Fix email for news not going out (#1131) 2021-04-11 14:32:58 -04:00
Nabeel Shahzad 648e7a261d Add APP_NAME to env stub 2021-04-11 13:46:52 -04:00
Nabeel Shahzad 9cb0a0cf36 Change the default driver to use mail 2021-04-11 12:36:37 -04:00
B.Fatih KOZ 2c8372d484 Read Captcha Settings From ENV (#1130)
* Read Captcha Settings From ENV

* Update captcha.php
2021-04-11 11:35:14 -04:00
Nabeel Shahzad 498d5bfaf0 Slugify cache prefix and quote it in the env 2021-04-10 21:13:34 -04:00
Nabeel Shahzad 2202c5b479 Change default env to prod for fresh install 2021-04-10 18:00:03 -04:00
Nabeel S ac64a5db75 Migrate all configs into the env.php file #1075 (#1128)
* Migrate all configs into the env.php file #1075

* Style fixes

* Fix config names in CreateConfig

* Fix installer/installer error messages
2021-04-10 17:19:45 -04:00
B.Fatih KOZ 6c3992e781 Fix for Hourly Crons (#1127)
* Fix for Hourly Cron

We should be using whereTime instead of whereDate

https://laravel.com/docs/8.x/queries#additional-where-clauses
`The whereDate method may be used to compare a column's value against a date`

* Fix for RemoveExpiredBids

I used where to do check 'cause people may set 48 hours to remove a bid, thus neither whereDate nor whereTime will give a correct results.

* Fix for DeletePireps

I used where to do check 'cause people may set 48 hours to delete cancelled or rejected pireps, thus neither whereDate nor whereTime will give a correct results.
2021-04-09 19:15:22 -04:00
B.Fatih KOZandNabeel S 344edde0fb Alphanumeric Callsign For Flights (#1124)
* Alphanumeric Callsign For Flights

PR adds ability to define alphanumeric callsigns to flights, display them and use them during SimBrief OFP generation (if pilot ident as callsign option is not enabled)

Translations for en/es/it/pt-br added.

* Change db table name

* Change db column name, fix rules

* Change db column name

* Another db column name change

* Just another one more

* Last one from anumeric_callsign to callsign

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-04-05 18:00:50 -04:00
Maximiliano FallicoandNabeel S 7502c053bf Show Airline logo / icao to subfleets table (#1121)
Will show the subfleet airline logo or icao in the admin flight create page table.

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-04-05 17:05:28 -04:00
Maximiliano FallicoandNabeel S dbfaed0ecc Adds Airline Icao to Subfleet Select in Flight Create (#1123)
* Adds Airline Icao to Subfleet Select in Flight Create

* Fix Style

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-04-05 16:55:50 -04:00
Maximiliano FallicoandNabeel S ff255c999b Add "View Pirep" In pirep cards (#1122)
Will show it in a new blank page in order to view pirep flight map.,

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-04-05 16:43:51 -04:00
Nabeel Shahzad 8c065a44cf Set default theme as "null" value 2021-04-03 10:25:02 -04:00
Nabeel Shahzad 8e9ba3b922 Fix styling that somehow slipped through 2021-04-01 17:33:57 -04:00
Nabeel Shahzad 677d30883f Check if flash messages are strings 2021-04-01 17:31:53 -04:00
Nabeel Shahzad ede71e6927 Fix the PIREP edit permissions 2021-04-01 09:54:01 -04:00
Andrew Roberts 3f84f84309 Fix issue with being unable to save pirep edits (#1116)
Fixes issue being unable to save pirep edits from the admin section due to incorrect variable being used
2021-03-31 11:03:01 -04:00
excilerandAndreas Palm 50e8f2e52b Fetch timezone on airport lookup (#1103)
Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-29 17:10:00 -04:00
Nabeel S 96fff0248d Save airport timezone (#1112)
* Fix airport timezone lookup

* Save timezone to the airport when importing
2021-03-29 15:49:34 -04:00
Nabeel S 9c4aced837 Move the prefile event and add a new error exception (#1111)
* Move the prefile event and add a new error exception

* Remove extra import

* Add empty handler for testing

* Fix styling

* Fix styleci
2021-03-29 14:53:35 -04:00
excilerandAndreas Palm ed146b2c70 replace windows backslashes by slashes before path mapping (#1107)
Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-28 18:15:56 -04:00
1e320835c2 fix map-info-box display (#1104)
* fix map-info-box display

* Check user on PIREP show/edit/update/submit

* add missing use

* refactoring according to comments; use UpdatePirepRequest for authorization and make user available to view

Co-authored-by: Andreas Palm <ap@ewsp.de>
Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2021-03-28 09:57:16 -04:00
excilerandAndreas Palm d4c301a36c Remove remove_bid_after_accept setting (#1100)
* Remove "Remove bid on accept" setting and remove bids after PIREP was filed

fixes #1039

* Add migration to remove setting from database

* fix migration naming and remove obsolete code

Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-27 08:33:21 -04:00
B.Fatih KOZ c2b0b69eb2 Change LatestPireps Widget Sort Order (#1099)
* Change LatestPireps Widget Sort Order

Latest pireps should be ordered by `submitted_at` instead of `created_at` . 

Pirep may be created even a day before others (with the pause/resume ability we have in acars) but it gets submitted once when the flight is ended, thus I think it should be our reference to sort them in proper order.

* Trying to Pass UnitTest
2021-03-25 09:51:16 -04:00
Nabeel Shahzad 43c33adcfe Unit rounding 2021-03-25 08:59:45 -04:00
excilerandAndreas Palm be6332936f When importing flights, set subfleet name only if subfleet has been created (#1095)
* when importing flights, set subfleet name only if subfleet has been created, do not update existing subfleets

* add tests for flights import regarding subfleets

Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-23 08:50:19 -04:00
B.Fatih KOZ 8f38fc2dec Urgent Fix For SimBriefControlled (#1094)
Added missing Enums
2021-03-22 11:40:21 -04:00
B.Fatih KOZ 65015cbce2 Move SimBrief aircraft selection to Controller (#1093)
* Move SimBrief aircraft selection to Controller

Instead of passing subfleets to blade (and doing two foreach loops and ifs to populate the dropdown), we are building a proper aircraft list here.

Did not removed $subfleets from data being passed to blade on purpose, it may be removed later on.

* Style Fix

* Update aircraft selection blade to use $aircrafts

* Order generated Aircrafts collection

First ICAO then Registration

* Add privatized name setting for simbrief

To prevent possible privacy issues according to latest regulations.

* Add privatized name to SimBrief form

It is controlled with a setting, if not enabled we will not pass any names to SimBrief via API (this will result users SimBrief membership name being used at the OFP as before)
2021-03-22 10:55:33 -04:00
B.Fatih KOZ 3cc5ca2c32 DownloadController Improvements (#1091)
* DownloadController Improvements

Added multiple airline support to both Aircraft and Subfleet downloads, if the user has more than one active airline downloads will display the airline name before the object name. Also sorted the returned results to have a better look at the blade.

* Trying to pass broken UnitTest

Please do fix the UnitTest, this pr has nothing to do with units but still being tested with it and failing.
2021-03-21 09:33:04 -04:00
Maximiliano Fallico 30e88ac6bc Aircraft at departure airport restrictions (#1090)
* Update simbrief_aircraft.blade.php

If resrict airplane at location settings is enabled, Show only  aircraft at the departure location of the flight. Kingly made by @FatihKoz at my ocd request.

* Update simbrief_aircraft.blade.php
2021-03-20 20:03:24 -04:00
Nabeel Shahzad 61ee4254fc Style fix 2021-03-20 17:41:07 -04:00
Nabeel Shahzad f9f0ee826d Fill the flight subfleets even if there's a simbrief 2021-03-20 17:28:54 -04:00
Nabeel Shahzad 4394487392 Add missing aircraft_id to sample data 2021-03-19 18:47:02 -04:00
Nabeel S 1287766a46 Fix aircraft retrieval for Simbrief (#1089)
* Fix full aircraft retrieval for simbriefs

* F off StyleCI
2021-03-19 18:25:19 -04:00
Nabeel Shahzad 11824c9f8b Flight search error 2021-03-19 16:59:39 -04:00
B.Fatih KOZ bbd02bf5c7 Fix For GH Costs (#1088)
* Fix For GH Costs.

PR aims to fix the problem where Airport GH cost is not defined but recored to db as 0.00 or 0 (default value for airports table)
In such cases settings/default apt gh cost will be used.

* Updated logic for JetA1 cost check

* Remove default costs being used during import
2021-03-19 16:42:36 -04:00
excilerandAndreas Palm 9bb192b97f Add disable activity check option on certain roles #1078 (#1087)
* Add boolean field "disable activity checks" to role, check for this field inside PilotLeave-Check, add tests

* fix checkbox on form

* CS fixes

* CS fixes again :-)

Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-19 13:09:29 -04:00
excilerandAndreas Palm 2cede04b1e Optimize view paths for module views in theme folder (#1081)
* override \Igaster\LaravelTheme\themeViewFinder as a workaround until PR#133 in igaster/laravel-theme is merged

* fixup code style

* further code style fix

Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-19 09:22:03 -04:00
B.Fatih KOZ 7072428218 Fix Finance Memo (Ground Handling) (#1083)
PR fixes issue #1082
2021-03-18 20:04:13 -04:00
1d83b85d8b Fix for Fuel and Ground Handling Costs (#1050)
* Fix for Fuel and Ground Handling Costs

PR aims to fix issue #1048  and implements the feature request #1049 

If no fuel cost is defined for departure airport, settings / airport fuel price will be used.
If no ground handling cost is defined for airports, settings / airport ground handling cost will be used.

Ground handling prices of both departure and arrival airport will be used for calculations.

* Resolve conflict with latest dev

PR will still fail checks due to double ground handling fares and will work on it to have two records at transactions for dep/arr

* Remove Double GH Costs / Fix The Bug Only

Removed double GH costs for now, pr aims only fixing the current issue (general settings not being read for fuel and ground handling costs)

* Add departure and arrival airports to ground handling

* Style fix

* Fix tests

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
Co-authored-by: Nabeel Shahzad <nabeel@nabeel.sh>
2021-03-18 11:32:40 -04:00
Nabeel S 63eef59060 Fix null visibility in METAR (#1079)
* Fix null visibility in METAR

* Report the text in units from the METAR
2021-03-17 17:40:45 -04:00
B.Fatih KOZ 0152ff6045 Update pireps/show.blade (#1080)
Added score and landing rate to right sidebar, sorted the pirep logs in asc order to make it easy to read.
2021-03-17 16:43:36 -04:00
B.Fatih KOZ e45bd66388 Fix Metar Decoding / Wind check for Wind Chill (#1072)
* Fix Metar Decoding / Wind check for Wind Chill

PR aims to fix the bug #1071 by checking both the wind speed and it's value for starting Wind Chill calculation.
2021-03-15 10:41:05 -04:00
101 changed files with 4318 additions and 1858 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ APP_LOCALE="en"
PHPVMS_INSTALLED="true" PHPVMS_INSTALLED="true"
APP_LOG="daily" APP_LOG="daily"
APP_LOG_LEVEL="debug" LOG_LEVEL="debug"
APP_LOG_MAX_FILES="3" APP_LOG_MAX_FILES="3"
DB_CONNECTION="mysql" DB_CONNECTION="mysql"
+1
View File
@@ -74,4 +74,5 @@ error_log
.sass-cache .sass-cache
.DS_Store .DS_Store
/config.php /config.php
/config.bak.php
/VERSION /VERSION
+2
View File
@@ -28,6 +28,8 @@ RedirectMatch 403 ^/composer.phar
RedirectMatch 403 ^/env.php.*?$ RedirectMatch 403 ^/env.php.*?$
RedirectMatch 403 ^/env.php RedirectMatch 403 ^/env.php
RedirectMatch 403 ^/env.php$ RedirectMatch 403 ^/env.php$
RedirectMatch 403 ^/config.php$
RedirectMatch 403 ^/config.bak.php$
RedirectMatch 403 ^/Makefile RedirectMatch 403 ^/Makefile
RedirectMatch 403 ^/package.json RedirectMatch 403 ^/package.json
RedirectMatch 403 ^/package-lock.json RedirectMatch 403 ^/package-lock.json
+2 -1
View File
@@ -2,7 +2,7 @@ FROM php:7.4-fpm-alpine
WORKDIR /var/www/ WORKDIR /var/www/
RUN apk add gmp-dev RUN apk add gmp-dev icu-dev
RUN curl --silent --show-error https://getcomposer.org/installer | php RUN curl --silent --show-error https://getcomposer.org/installer | php
# Copy any config files in # Copy any config files in
@@ -12,6 +12,7 @@ RUN ln -sf /dev/stderr /var/log/fpm-error.log
RUN docker-php-ext-install \ RUN docker-php-ext-install \
calendar \ calendar \
intl \
pdo_mysql \ pdo_mysql \
gmp \ gmp \
opcache && \ opcache && \
+8 -8
View File
@@ -4,9 +4,9 @@ namespace App\Console\Commands;
use App; use App;
use App\Contracts\Command; use App\Contracts\Command;
use App\Services\Installer\ConfigService;
use App\Services\Installer\SeederService; use App\Services\Installer\SeederService;
use DatabaseSeeder; use DatabaseSeeder;
use Modules\Installer\Services\ConfigService;
/** /**
* Create the config files * Create the config files
@@ -81,13 +81,13 @@ class CreateConfigs extends Command
$this->info('Regenerating the config files'); $this->info('Regenerating the config files');
$cfgSvc->createConfigFiles([ $cfgSvc->createConfigFiles([
'APP_ENV' => 'dev', 'APP_ENV' => 'dev',
'SITE_NAME' => $this->argument('name'), 'SITE_NAME' => $this->argument('name'),
'DB_CONN' => 'mysql', 'DB_CONNECTION' => 'mysql',
'DB_HOST' => $this->argument('db_host'), 'DB_HOST' => $this->argument('db_host'),
'DB_NAME' => $this->argument('db_name'), 'DB_DATABASE' => $this->argument('db_name'),
'DB_USER' => $this->argument('db_user'), 'DB_USERNAME' => $this->argument('db_user'),
'DB_PASS' => $this->argument('db_pass'), 'DB_PASSWORD' => $this->argument('db_pass'),
]); ]);
$this->info('Config files generated!'); $this->info('Config files generated!');
+3 -3
View File
@@ -79,9 +79,9 @@ class DevInstall extends Command
$this->info('Regenerating the config files'); $this->info('Regenerating the config files');
$cfgSvc->createConfigFiles([ $cfgSvc->createConfigFiles([
'APP_ENV' => 'dev', 'APP_ENV' => 'dev',
'SITE_NAME' => 'phpvms test', 'SITE_NAME' => 'phpvms test',
'DB_CONN' => 'sqlite', 'DB_CONNECTION' => 'sqlite',
]); ]);
$this->info('Config files generated!'); $this->info('Config files generated!');
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Console\Commands;
use App\Contracts\Command;
use App\Services\Installer\ConfigService;
/**
* Command to rewrite the config files
*/
class RewriteConfigs extends Command
{
protected $signature = 'phpvms:rewrite-configs';
protected $description = 'Rewrite the config files';
/**
* Run dev related commands
*/
public function handle()
{
/** @var ConfigService $configSvc */
$configSvc = app(ConfigService::class);
$configSvc->rewriteConfigFiles();
}
}
+3 -3
View File
@@ -17,7 +17,7 @@ use Illuminate\Support\Facades\Log;
class DeletePireps extends Listener class DeletePireps extends Listener
{ {
/** /**
* Remove expired bids * Delete old rejected PIREPs
* *
* @param CronHourly $event * @param CronHourly $event
* *
@@ -37,8 +37,8 @@ class DeletePireps extends Listener
*/ */
protected function deletePireps(int $expire_time_hours, int $state) protected function deletePireps(int $expire_time_hours, int $state)
{ {
$dt = Carbon::now()->subHours($expire_time_hours); $dt = Carbon::now('UTC')->subHours($expire_time_hours);
$pireps = Pirep::whereDate('created_at', '<', $dt)->where(['state' => $state])->get(); $pireps = Pirep::where('created_at', '<', $dt)->where(['state' => $state])->get();
/** @var PirepService $pirepSvc */ /** @var PirepService $pirepSvc */
$pirepSvc = app(PirepService::class); $pirepSvc = app(PirepService::class);
+2 -2
View File
@@ -25,7 +25,7 @@ class RemoveExpiredBids extends Listener
return; return;
} }
$date = Carbon::now()->subHours(setting('bids.expire_time')); $date = Carbon::now('UTC')->subHours(setting('bids.expire_time'));
Bid::whereDate('created_at', '<', $date)->delete(); Bid::where('created_at', '<', $date)->delete();
} }
} }
+2 -2
View File
@@ -26,8 +26,8 @@ class RemoveExpiredLiveFlights extends Listener
return; return;
} }
$date = Carbon::now()->subHours(setting('acars.live_time')); $date = Carbon::now('UTC')->subHours(setting('acars.live_time'));
Pirep::whereDate('updated_at', '<', $date) Pirep::where('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS) ->where('state', PirepState::IN_PROGRESS)
->delete(); ->delete();
} }
@@ -1,17 +1,20 @@
<?php <?php
use App\Models\Journal;
use Carbon\Carbon;
use Faker\Generator as Faker; use Faker\Generator as Faker;
use Ramsey\Uuid\Uuid;
$factory->define(App\Models\JournalTransactions::class, function (Faker $faker) { $factory->define(App\Models\JournalTransaction::class, function (Faker $faker) {
return [ return [
'transaction_group' => \Ramsey\Uuid\Uuid::uuid4()->toString(), 'transaction_group' => Uuid::uuid4()->toString(),
'journal_id' => function () { 'journal_id' => function () {
return factory(\App\Models\Journal::class)->create()->id; return factory(Journal::class)->create()->id;
}, },
'credit' => $faker->numberBetween(100, 10000), 'credit' => $faker->numberBetween(100, 10000),
'debit' => $faker->numberBetween(100, 10000), 'debit' => $faker->numberBetween(100, 10000),
'currency' => 'USD', 'currency' => 'USD',
'memo' => $faker->sentence(6), 'memo' => $faker->sentence(6),
'post_date' => \Carbon\Carbon::now(), 'post_date' => Carbon::now('UTC'),
]; ];
}); });
+13
View File
@@ -0,0 +1,13 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\Role::class, function (Faker $faker) {
return [
'id' => null,
'name' => $faker->name,
'display_name' => $faker->name,
'read_only' => false,
'disable_activity_checks' => $faker->boolean(),
];
});
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDisableactivitychecksToRoles extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('roles', function (Blueprint $table) {
$table->boolean('disable_activity_checks')
->default(false)
->after('read_only');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('roles', function (Blueprint $table) {
$table->dropColumn('disable_activity_checks');
});
}
}
@@ -0,0 +1,19 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class RemoveSettingRemoveBidOnAccept extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::table('settings')
->where(['key' => 'pireps.remove_bid_on_accept'])
->delete();
}
}
@@ -0,0 +1,30 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Add a `anumeric_callsign` column for Alphanumeric Callsign to be assigned for a flight
* Exp DLH78BF, THY8EA, OGE1978
* According to FAA and EASA, callsigns must be maximum 7 chars in which first 3 chars is
* airline ICAO code remaining rest can be used freely according to airline's choices
*/
class FlightsAddAlphanumericCallsign extends Migration
{
public function up()
{
Schema::table('flights', function (Blueprint $table) {
$table->string('callsign', 4)
->nullable()
->after('flight_number');
});
}
public function down()
{
Schema::table('flights', function (Blueprint $table) {
$table->dropColumn('callsign');
});
}
}
@@ -0,0 +1,21 @@
<?php
use App\Contracts\Migration;
use App\Services\Installer\ConfigService;
/**
* Migrate the configuration files
*/
class MigrateConfigs extends Migration
{
public function up()
{
/** @var ConfigService $configSvc */
$configSvc = app(ConfigService::class);
$configSvc->rewriteConfigFiles();
}
public function down()
{
}
}
File diff suppressed because one or more lines are too long
+7 -7
View File
@@ -235,6 +235,13 @@
options: '' options: ''
type: boolean type: boolean
description: 'Use pilot ident as Simbrief ATC Callsign' description: 'Use pilot ident as Simbrief ATC Callsign'
- key: simbrief.name_private
name: 'Use Privatized Name at OFPs'
group: simbrief
value: false
options: ''
type: boolean
description: 'Use privatized user name as SimBrief OFP captain name'
- key: pireps.duplicate_check_time - key: pireps.duplicate_check_time
name: 'PIREP duplicate time check' name: 'PIREP duplicate time check'
group: pireps group: pireps
@@ -256,13 +263,6 @@
options: '' options: ''
type: boolean type: boolean
description: 'Only allow aircraft that are at the departure airport' description: 'Only allow aircraft that are at the departure airport'
- key: pireps.remove_bid_on_accept
name: 'Remove bid on accept'
group: pireps
value: false
options: ''
type: boolean
description: 'When a PIREP is accepted, remove the bid, if it exists'
- key: pireps.advanced_fuel - key: pireps.advanced_fuel
name: 'Advanced Fuel Calculations' name: 'Advanced Fuel Calculations'
group: pireps group: pireps
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace App\Exceptions;
/**
* Prefile Error
*
* If listening to the prefile event message, use `throw new PrefileError("message message");`
* to abort the prefile process and send the message up to ACARS
*/
class PrefileError extends AbstractHttpException
{
private $error;
public function __construct(string $error)
{
$this->error = $error;
parent::__construct(400, $error);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'prefile-error';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [];
}
}
@@ -115,7 +115,7 @@ class FlightController extends Controller
$avail_fleets = $all_aircraft->except($flight->subfleets->modelKeys()); $avail_fleets = $all_aircraft->except($flight->subfleets->modelKeys());
foreach ($avail_fleets as $ac) { foreach ($avail_fleets as $ac) {
$retval[$ac->id] = $ac->type.' - '.$ac->name; $retval[$ac->id] = '['.$ac->airline->icao.']&nbsp;'.$ac->type.' - '.$ac->name;
} }
return $retval; return $retval;
@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Events\PirepPrefiled;
use App\Events\PirepUpdated; use App\Events\PirepUpdated;
use App\Exceptions\AircraftPermissionDenied; use App\Exceptions\AircraftPermissionDenied;
use App\Exceptions\PirepCancelled; use App\Exceptions\PirepCancelled;
@@ -219,8 +218,6 @@ class PirepController extends Controller
$this->updateFields($pirep, $request); $this->updateFields($pirep, $request);
$this->updateFares($pirep, $request); $this->updateFares($pirep, $request);
event(new PirepPrefiled($pirep));
return $this->get($pirep->id); return $this->get($pirep->id);
} }
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Frontend; namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Models\Airline;
use App\Models\File; use App\Models\File;
use Auth; use Auth;
use Flash; use Flash;
@@ -18,6 +19,7 @@ class DownloadController extends Controller
*/ */
public function index() public function index()
{ {
$airlines = Airline::where('active', 1)->count();
$files = File::orderBy('ref_model', 'asc')->get(); $files = File::orderBy('ref_model', 'asc')->get();
/** /**
@@ -42,10 +44,14 @@ class DownloadController extends Controller
$category = explode('\\', $class); $category = explode('\\', $class);
$category = end($category); $category = end($category);
if ($category == 'Aircraft') { if ($category == 'Aircraft' && $airlines > 1) {
$group_name = $category.' > '.$obj->subfleet->airline->name.' '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Aircraft') {
$group_name = $category.' > '.$obj->icao.' '.$obj->registration; $group_name = $category.' > '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Airport') { } elseif ($category == 'Airport') {
$group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')'; $group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')';
} elseif ($category == 'Subfleet' && $airlines > 1) {
$group_name = $category.' > '.$obj->airline->name.' '.$obj->name;
} else { } else {
$group_name = $category.' > '.$obj->name; $group_name = $category.' > '.$obj->name;
} }
@@ -53,13 +59,15 @@ class DownloadController extends Controller
$regrouped_files[$group_name] = $files; $regrouped_files[$group_name] = $files;
} }
ksort($regrouped_files, SORT_STRING);
return view('downloads.index', [ return view('downloads.index', [
'grouped_files' => $regrouped_files, 'grouped_files' => $regrouped_files,
]); ]);
} }
/** /**
* Show the application dashboard. * Show the application dashboard
* *
* @param string $id * @param string $id
* *
@@ -211,6 +211,7 @@ class PirepController extends Controller
return view('pireps.show', [ return view('pireps.show', [
'pirep' => $pirep, 'pirep' => $pirep,
'map_features' => $map_features, 'map_features' => $map_features,
'user' => Auth::user(),
]); ]);
} }
@@ -428,12 +429,18 @@ class PirepController extends Controller
*/ */
public function edit($id) public function edit($id)
{ {
/** @var Pirep $pirep */
$pirep = $this->pirepRepo->findWithoutFail($id); $pirep = $this->pirepRepo->findWithoutFail($id);
if (empty($pirep)) { if (empty($pirep)) {
Flash::error('Pirep not found'); Flash::error('Pirep not found');
return redirect(route('frontend.pireps.index')); return redirect(route('frontend.pireps.index'));
} }
if ($pirep->user_id !== Auth::id()) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
// Eager load the subfleet and fares under it // Eager load the subfleet and fares under it
if ($pirep->aircraft) { if ($pirep->aircraft) {
$pirep->aircraft->load('subfleet.fares'); $pirep->aircraft->load('subfleet.fares');
@@ -486,12 +493,21 @@ class PirepController extends Controller
*/ */
public function update($id, UpdatePirepRequest $request) public function update($id, UpdatePirepRequest $request)
{ {
/** @var User $user */
$user = Auth::user();
/** @var Pirep $pirep */
$pirep = $this->pirepRepo->findWithoutFail($id); $pirep = $this->pirepRepo->findWithoutFail($id);
if (empty($pirep)) { if (empty($pirep)) {
Flash::error('Pirep not found'); Flash::error('Pirep not found');
return redirect(route('admin.pireps.index')); return redirect(route('admin.pireps.index'));
} }
if ($user->id !== $pirep->user_id) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
$orig_route = $pirep->route; $orig_route = $pirep->route;
$attrs = $request->all(); $attrs = $request->all();
$attrs['submit'] = strtolower($attrs['submit']); $attrs['submit'] = strtolower($attrs['submit']);
@@ -544,6 +560,11 @@ class PirepController extends Controller
return redirect(route('admin.pireps.index')); return redirect(route('admin.pireps.index'));
} }
if ($pirep->user_id !== Auth::id()) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
$this->pirepSvc->submit($pirep); $this->pirepSvc->submit($pirep);
return redirect(route('frontend.pireps.show', [$pirep->id])); return redirect(route('frontend.pireps.show', [$pirep->id]));
} }
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Frontend;
use App\Exceptions\AssetNotFound; use App\Exceptions\AssetNotFound;
use App\Models\Aircraft; use App\Models\Aircraft;
use App\Models\Enums\AircraftState;
use App\Models\Enums\AircraftStatus;
use App\Models\Enums\FareType; use App\Models\Enums\FareType;
use App\Models\Enums\FlightType; use App\Models\Enums\FlightType;
use App\Models\Fare; use App\Models\Fare;
@@ -77,8 +79,30 @@ class SimBriefController
$subfleets = $this->userSvc->getAllowableSubfleets($user); $subfleets = $this->userSvc->getAllowableSubfleets($user);
} }
// Build an array of subfleet id's from the subfleets collection
$sf_ids = $subfleets->map(function ($subfleets) {
return collect($subfleets->toArray())
->only(['id'])
->all();
});
// Now we can build a proper aircrafts collection
// Contents will be either members of flight->subfleets
// or members of user's allowable subfleets
$aircrafts = Aircraft::whereIn('subfleet_id', $sf_ids)
->where('state', AircraftState::PARKED)
->where('status', AircraftStatus::ACTIVE)
->orderby('icao')
->orderby('registration')
->get();
if (setting('pireps.only_aircraft_at_dpt_airport')) {
$aircrafts = $aircrafts->where('airport_id', $flight->dpt_airport_id);
}
return view('flights.simbrief_aircraft', [ return view('flights.simbrief_aircraft', [
'flight' => $flight, 'flight' => $flight,
'aircrafts' => $aircrafts,
'subfleets' => $subfleets, 'subfleets' => $subfleets,
]); ]);
} }
@@ -203,21 +203,21 @@ class InstallerController extends Controller
Log::error('Testing db before writing configs failed'); Log::error('Testing db before writing configs failed');
Log::error($e->getMessage()); Log::error($e->getMessage());
Flash::error($e->getMessage()); flash()->error($e->getMessage());
return redirect(route('installer.step2'))->withInput(); return redirect(route('installer.step2'))->withInput();
} }
// Now write out the env file // Now write out the env file
$attrs = [ $attrs = [
'SITE_NAME' => $request->post('site_name'), 'SITE_NAME' => $request->post('site_name'),
'SITE_URL' => $request->post('site_url'), 'SITE_URL' => $request->post('site_url'),
'DB_CONN' => $request->post('db_conn'), 'DB_CONNECTION' => $request->post('db_conn'),
'DB_HOST' => $request->post('db_host'), 'DB_HOST' => $request->post('db_host'),
'DB_PORT' => $request->post('db_port'), 'DB_PORT' => $request->post('db_port'),
'DB_NAME' => $request->post('db_name'), 'DB_DATABASE' => $request->post('db_name'),
'DB_USER' => $request->post('db_user'), 'DB_USERNAME' => $request->post('db_user'),
'DB_PASS' => $request->post('db_pass'), 'DB_PASSWORD' => $request->post('db_pass'),
'DB_PREFIX' => $request->post('db_prefix'), 'DB_PREFIX' => $request->post('db_prefix'),
]; ];
/* /*
@@ -231,7 +231,7 @@ class InstallerController extends Controller
Log::error('Config files failed to write'); Log::error('Config files failed to write');
Log::error($e->getMessage()); Log::error($e->getMessage());
Flash::error($e->getMessage()); flash()->error($e->getMessage());
return redirect(route('installer.step2'))->withInput(); return redirect(route('installer.step2'))->withInput();
} }
@@ -257,7 +257,7 @@ class InstallerController extends Controller
Log::error('Error on db setup: '.$e->getMessage()); Log::error('Error on db setup: '.$e->getMessage());
//dd($e); //dd($e);
$this->envSvc->removeConfigFiles(); $this->envSvc->removeConfigFiles();
Flash::error($e->getMessage()); flash()->error($e->getMessage());
return redirect(route('installer.step2'))->withInput(); return redirect(route('installer.step2'))->withInput();
} }
+1 -1
View File
@@ -52,7 +52,7 @@ class SetActiveTheme implements Middleware
} }
try { try {
$theme = setting('general.theme'); $theme = setting('general.theme', 'default');
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error($e->getMessage()); Log::error($e->getMessage());
$theme = 'default'; $theme = 'default';
+1 -1
View File
@@ -9,7 +9,7 @@ class Bid extends Resource
public function toArray($request) public function toArray($request)
{ {
$res = parent::toArray($request); $res = parent::toArray($request);
$res['flight'] = new Flight($this->flight); $res['flight'] = new BidFlight($this->flight);
return $res; return $res;
} }
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Resources;
use App\Http\Resources\SimBrief as SimbriefResource;
/**
* @mixin \App\Models\Flight
*/
class BidFlight extends Flight
{
/**
* @param \Illuminate\Http\Request $request
*
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
*
* @return array
*/
public function toArray($request)
{
$res = parent::toArray($request);
if ($this->whenLoaded('simbrief')) {
unset($res['subfleets']);
$res['simbrief'] = new SimbriefResource($this->simbrief);
} else {
unset($res['simbrief']);
$res['subfleets'] = Subfleet::collection($this->whenLoaded('subfleets'));
}
$res['fields'] = $this->setFields();
return $res;
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace App\Http\Resources;
class BidSubfleet extends Subfleet
{
protected $aircraft;
protected $fares;
public function __construct($resource, $aircraft, $fares)
{
parent::__construct($resource);
$this->aircraft = $aircraft;
$this->fares = $fares;
}
public function toArray($request)
{
$res = [];
$res['airline_id'] = $this->airline_id;
$res['hub_id'] = $this->hub_id;
$res['type'] = $this->type;
$res['simbrief_type'] = $this->simbrief_type;
$res['name'] = $this->name;
$res['fuel_type'] = $this->fuel_type;
$res['cost_block_hour'] = $this->cost_block_hour;
$res['cost_delay_minute'] = $this->cost_delay_minute;
$res['ground_handling_multiplier'] = $this->ground_handling_multiplier;
$res['cargo_capacity'] = $this->cargo_capacity;
$res['fuel_capacity'] = $this->fuel_capacity;
$res['gross_weight'] = $this->gross_weight;
$res['fares'] = Fare::collection($this->fares);
// There should only be one aircraft tied to a bid subfleet, wrap in a collection
$res['aircraft'] = Aircraft::collection([$this->aircraft]);
return $res;
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ class Flight extends Resource
/** /**
* Set the fields on the flight object * Set the fields on the flight object
*/ */
private function setFields() protected function setFields()
{ {
/** @var \Illuminate\Support\Collection $field_values */ /** @var \Illuminate\Support\Collection $field_values */
$return_values = new stdClass(); $return_values = new stdClass();
+7 -5
View File
@@ -12,25 +12,27 @@ class SimBrief extends Resource
public function toArray($request) public function toArray($request)
{ {
$data = [ $data = [
'id' => $this->id, 'id' => $this->id,
'url' => url(route('api.flights.briefing', ['id' => $this->id])), 'aircraft_id' => $this->aircraft_id,
'url' => url(route('api.flights.briefing', ['id' => $this->id])),
]; ];
$fares = [];
try { try {
if (!empty($this->fare_data)) { if (!empty($this->fare_data)) {
$fares = [];
$fare_data = json_decode($this->fare_data, true); $fare_data = json_decode($this->fare_data, true);
foreach ($fare_data as $fare) { foreach ($fare_data as $fare) {
$fares[] = new \App\Models\Fare($fare); $fares[] = new \App\Models\Fare($fare);
} }
$this->aircraft->subfleet->fares = collect($fares); $fares = collect($fares);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
// Invalid fare data // Invalid fare data
} }
$data['subfleet'] = new Subfleet($this->aircraft->subfleet); $data['subfleet'] = new BidSubfleet($this->aircraft->subfleet, $this->aircraft, $fares);
return $data; return $data;
} }
+5 -21
View File
@@ -3,8 +3,7 @@
namespace App\Listeners; namespace App\Listeners;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\PirepAccepted; use App\Events\PirepFiled;
use App\Events\PirepRejected;
use App\Services\BidService; use App\Services\BidService;
/** /**
@@ -13,8 +12,7 @@ use App\Services\BidService;
class BidEventHandler extends Listener class BidEventHandler extends Listener
{ {
public static $callbacks = [ public static $callbacks = [
PirepAccepted::class => 'onPirepAccept', PirepFiled::class => 'onPirepFiled',
PirepRejected::class => 'onPirepReject',
]; ];
private $bidSvc; private $bidSvc;
@@ -25,29 +23,15 @@ class BidEventHandler extends Listener
} }
/** /**
* When a PIREP is accepted, remove any bids * When a PIREP is filed, remove any bids
* *
* @param PirepAccepted $event * @param PirepFiled $event
* *
* @throws \UnexpectedValueException * @throws \UnexpectedValueException
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* @throws \Exception * @throws \Exception
*/ */
public function onPirepAccept(PirepAccepted $event): void public function onPirepFiled(PirepFiled $event): void
{
$this->bidSvc->removeBidForPirep($event->pirep);
}
/**
* When a PIREP is accepted, remove any bids
*
* @param PirepRejected $event
*
* @throws \UnexpectedValueException
* @throws \InvalidArgumentException
* @throws \Exception
*/
public function onPirepReject(PirepRejected $event): void
{ {
$this->bidSvc->removeBidForPirep($event->pirep); $this->bidSvc->removeBidForPirep($event->pirep);
} }
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\PirepPrefiled;
/**
* Look for and run any of the award classes. Don't modify this.
* See the documentation on creating awards:
*
* @url http://docs.phpvms.net/customizing/awards
*/
class PirepEventsHandler extends Listener
{
/** The events and the callback */
public static $callbacks = [
PirepPrefiled::class => 'onPirepPrefile',
];
/**
* Called when a PIREP is prefiled
*
* @param PirepPrefiled $event
*/
public function onPirepPrefile(PirepPrefiled $event)
{
}
}
+1
View File
@@ -46,6 +46,7 @@ class Airport extends Model
'lon', 'lon',
'hub', 'hub',
'timezone', 'timezone',
'tz',
'ground_handling_cost', 'ground_handling_cost',
'fuel_100ll_cost', 'fuel_100ll_cost',
'fuel_jeta_cost', 'fuel_jeta_cost',
+3
View File
@@ -15,6 +15,7 @@ use Illuminate\Support\Collection;
* @property Airline airline * @property Airline airline
* @property int airline_id * @property int airline_id
* @property mixed flight_number * @property mixed flight_number
* @property mixed callsign
* @property mixed route_code * @property mixed route_code
* @property int route_leg * @property int route_leg
* @property bool has_bid * @property bool has_bid
@@ -60,6 +61,7 @@ class Flight extends Model
'id', 'id',
'airline_id', 'airline_id',
'flight_number', 'flight_number',
'callsign',
'route_code', 'route_code',
'route_leg', 'route_leg',
'dpt_airport_id', 'dpt_airport_id',
@@ -104,6 +106,7 @@ class Flight extends Model
public static $rules = [ public static $rules = [
'airline_id' => 'required|exists:airlines,id', 'airline_id' => 'required|exists:airlines,id',
'flight_number' => 'required', 'flight_number' => 'required',
'callsign' => 'string|max:4|nullable',
'route_code' => 'nullable', 'route_code' => 'nullable',
'route_leg' => 'nullable', 'route_leg' => 'nullable',
'dpt_airport_id' => 'required|exists:airports,id', 'dpt_airport_id' => 'required|exists:airports,id',
+1 -1
View File
@@ -186,7 +186,7 @@ class Journal extends Model
*/ */
public function getCurrentBalance() public function getCurrentBalance()
{ {
return $this->getBalanceOn(Carbon::now()); return $this->getBalanceOn(Carbon::now('UTC'));
} }
/** /**
+9 -1
View File
@@ -5,6 +5,12 @@ namespace App\Models;
use Laratrust\Models\LaratrustRole; use Laratrust\Models\LaratrustRole;
/** /**
* @property int id
* @property string name
* @property string display_name
* @property bool read_only
* @property bool disable_activity_checks
*
* @mixin \Illuminate\Database\Eloquent\Builder * @mixin \Illuminate\Database\Eloquent\Builder
*/ */
class Role extends LaratrustRole class Role extends LaratrustRole
@@ -14,10 +20,12 @@ class Role extends LaratrustRole
'name', 'name',
'display_name', 'display_name',
'read_only', 'read_only',
'disable_activity_checks',
]; ];
protected $casts = [ protected $casts = [
'read_only' => 'boolean', 'read_only' => 'boolean',
'disable_activity_checks' => 'boolean',
]; ];
/** /**
+1 -1
View File
@@ -49,7 +49,7 @@ class SimBrief extends Model
* *
* @return \App\Models\SimBriefXML|null * @return \App\Models\SimBriefXML|null
*/ */
public function getXmlAttribute(): SimBriefXML public function getXmlAttribute(): ?SimBriefXML
{ {
if (empty($this->attributes['ofp_xml'])) { if (empty($this->attributes['ofp_xml'])) {
return null; return null;
+13 -9
View File
@@ -50,10 +50,16 @@ class EventHandler extends Listener
{ {
$admin_users = User::whereRoleIs('admin')->get(); $admin_users = User::whereRoleIs('admin')->get();
try { foreach ($admin_users as $user) {
Notification::send($admin_users, $notification); if (empty($user->email)) {
} catch (Exception $e) { continue;
Log::emergency('Error emailing admins, malformed email='.$e->getMessage()); }
try {
Notification::send([$user], $notification);
} catch (Exception $e) {
Log::emergency('Error emailing admin ('.$user->email.'). Error='.$e->getMessage());
}
} }
} }
@@ -66,7 +72,7 @@ class EventHandler extends Listener
try { try {
$user->notify($notification); $user->notify($notification);
} catch (Exception $e) { } catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage()); Log::emergency('Error emailing user, '.$user->ident.'='.$user->email.', error='.$e->getMessage());
} }
} }
@@ -91,10 +97,8 @@ class EventHandler extends Listener
Log::info('Sending notification to '.$users->count().' users'); Log::info('Sending notification to '.$users->count().' users');
try { foreach ($users as $user) {
Notification::send($users, $notification); $this->notifyUser($user, $notification);
} catch (Exception $e) {
Log::emergency('Error emailing admins, malformed email='.$e->getMessage());
} }
} }
+1 -1
View File
@@ -22,7 +22,7 @@ class NewsAdded extends Notification
$this->news = $news; $this->news = $news;
$this->setMailable( $this->setMailable(
$news->subject, $news->subject,
'notifications.mail.news', 'notifications.mail.news.news',
['news' => $news] ['news' => $news]
); );
} }
+9
View File
@@ -3,6 +3,7 @@
namespace App\Providers; namespace App\Providers;
use App\Services\ModuleService; use App\Services\ModuleService;
use App\Support\ThemeViewFinder;
use App\Support\Utils; use App\Support\Utils;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@@ -23,6 +24,14 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function register(): void public function register(): void
{ {
$this->app->singleton('view.finder', function ($app) {
return new ThemeViewFinder(
$app['files'],
$app['config']['view.paths'],
null
);
});
// Only load the IDE helper if it's included and enabled // Only load the IDE helper if it's included and enabled
if (config('app.debug') === true) { if (config('app.debug') === true) {
/* @noinspection NestedPositiveIfStatementsInspection */ /* @noinspection NestedPositiveIfStatementsInspection */
+2
View File
@@ -9,6 +9,7 @@ use App\Listeners\AwardHandler;
use App\Listeners\BidEventHandler; use App\Listeners\BidEventHandler;
use App\Listeners\ExpenseListener; use App\Listeners\ExpenseListener;
use App\Listeners\FinanceEventHandler; use App\Listeners\FinanceEventHandler;
use App\Listeners\PirepEventsHandler;
use App\Listeners\UserStateListener; use App\Listeners\UserStateListener;
use App\Notifications\EventHandler; use App\Notifications\EventHandler;
use Codedge\Updater\Events\UpdateAvailable; use Codedge\Updater\Events\UpdateAvailable;
@@ -45,5 +46,6 @@ class EventServiceProvider extends ServiceProvider
FinanceEventHandler::class, FinanceEventHandler::class,
EventHandler::class, EventHandler::class,
AwardHandler::class, AwardHandler::class,
PirepEventsHandler::class,
]; ];
} }
+1 -1
View File
@@ -147,7 +147,7 @@ class JournalRepository extends Repository implements CacheableInterface
$journal->refresh(); $journal->refresh();
if (!$date) { if (!$date) {
$date = Carbon::now(); $date = Carbon::now('UTC');
} }
$credit = $this->getCreditBalanceBetween($date, $journal); $credit = $this->getCreditBalanceBetween($date, $journal);
@@ -28,6 +28,7 @@ class VaCentralLookup extends AirportLookup
try { try {
$airport = $this->client->getAirport($icao); $airport = $this->client->getAirport($icao);
$airport->location = $airport->city; $airport->location = $airport->city;
$airport->timezone = $airport->tz;
return $airport; return $airport;
} catch (HttpException $e) { } catch (HttpException $e) {
+2 -2
View File
@@ -2,7 +2,7 @@
namespace App\Services; namespace App\Services;
use App\Contracts\AirportLookup as AirportLookupProvider; use App\Contracts\AirportLookup;
use App\Contracts\Metar as MetarProvider; use App\Contracts\Metar as MetarProvider;
use App\Contracts\Service; use App\Contracts\Service;
use App\Exceptions\AirportNotFound; use App\Exceptions\AirportNotFound;
@@ -23,7 +23,7 @@ class AirportService extends Service
private $metarProvider; private $metarProvider;
public function __construct( public function __construct(
AirportLookupProvider $lookupProvider, AirportLookup $lookupProvider,
AirportRepository $airportRepo, AirportRepository $airportRepo,
MetarProvider $metarProvider MetarProvider $metarProvider
) { ) {
+7 -7
View File
@@ -47,22 +47,26 @@ class BidService extends Service
*/ */
public function findBidsForUser(User $user) public function findBidsForUser(User $user)
{ {
$bids = Bid::with([ $with = [
'flight', 'flight',
'flight.fares', 'flight.fares',
'flight.simbrief' => function ($query) use ($user) { 'flight.simbrief' => function ($query) use ($user) {
$query->where('user_id', $user->id); $query->where('user_id', $user->id);
}, },
'flight.simbrief.aircraft', 'flight.simbrief.aircraft',
'flight.simbrief.aircraft.subfleet',
'flight.subfleets', 'flight.subfleets',
'flight.subfleets.aircraft', 'flight.subfleets.aircraft',
'flight.subfleets.fares', 'flight.subfleets.fares',
]) ];
->where(['user_id' => $user->id])->get();
$bids = Bid::with($with)->where(['user_id' => $user->id])->get();
foreach ($bids as $bid) { foreach ($bids as $bid) {
// if (empty($bid->flight->simbrief)) {
$bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight); $bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight);
$bid->flight = $this->fareSvc->getReconciledFaresForFlight($bid->flight); $bid->flight = $this->fareSvc->getReconciledFaresForFlight($bid->flight);
// }
} }
return $bids; return $bids;
@@ -165,10 +169,6 @@ class BidService extends Service
*/ */
public function removeBidForPirep(Pirep $pirep) public function removeBidForPirep(Pirep $pirep)
{ {
if (!setting('pireps.remove_bid_on_accept')) {
return;
}
$flight = $pirep->flight; $flight = $pirep->flight;
if (!$flight) { if (!$flight) {
return; return;
+38 -16
View File
@@ -152,6 +152,13 @@ class PirepFinanceService extends Service
public function payFuelCosts(Pirep $pirep): void public function payFuelCosts(Pirep $pirep): void
{ {
$ap = $pirep->dpt_airport; $ap = $pirep->dpt_airport;
// Get Airport Fuel Cost or revert back to settings
if (empty($ap->fuel_jeta_cost)) {
$fuel_cost = setting('airports.default_jet_a_fuel_cost');
} else {
$fuel_cost = $ap->fuel_jeta_cost;
}
if (setting('pireps.advanced_fuel', false)) { if (setting('pireps.advanced_fuel', false)) {
$ac = $pirep->aircraft; $ac = $pirep->aircraft;
// Reading second row by skip(1) to reach the previous accepted pirep. Current pirep is at the first row // Reading second row by skip(1) to reach the previous accepted pirep. Current pirep is at the first row
@@ -173,15 +180,15 @@ class PirepFinanceService extends Service
$fuel_amount = $pirep->fuel_used; $fuel_amount = $pirep->fuel_used;
} }
$debit = Money::createFromAmount($fuel_amount * $ap->fuel_jeta_cost); $debit = Money::createFromAmount($fuel_amount * $fuel_cost);
Log::info('Finance: Fuel cost, (fuel='.$fuel_amount.', cost='.$ap->fuel_jeta_cost.') D=' Log::info('Finance: Fuel cost, (fuel='.$fuel_amount.', cost='.$fuel_cost.') D='
.$debit->getAmount()); .$debit->getAmount());
$this->financeSvc->debitFromJournal( $this->financeSvc->debitFromJournal(
$pirep->airline->journal, $pirep->airline->journal,
$debit, $debit,
$pirep, $pirep,
'Fuel Cost ('.$ap->fuel_jeta_cost.'/'.config('phpvms.internal_units.fuel').')', 'Fuel Cost ('.$fuel_cost.'/'.config('phpvms.internal_units.fuel').')',
'Fuel', 'Fuel',
'fuel' 'fuel'
); );
@@ -415,14 +422,26 @@ class PirepFinanceService extends Service
*/ */
public function payGroundHandlingForPirep(Pirep $pirep): void public function payGroundHandlingForPirep(Pirep $pirep): void
{ {
$ground_handling_cost = $this->getGroundHandlingCost($pirep); $ground_handling_cost = $this->getGroundHandlingCost($pirep, $pirep->dpt_airport);
Log::info('Finance: PIREP: '.$pirep->id.'; ground handling: '.$ground_handling_cost); Log::info('Finance: PIREP: '.$pirep->id.'; dpt ground handling: '.$ground_handling_cost);
$this->financeSvc->debitFromJournal( $this->financeSvc->debitFromJournal(
$pirep->airline->journal, $pirep->airline->journal,
Money::createFromAmount($ground_handling_cost), Money::createFromAmount($ground_handling_cost),
$pirep, $pirep,
'Ground Handling (Departure)',
'Ground Handling', 'Ground Handling',
'ground_handling'
);
$ground_handling_cost = $this->getGroundHandlingCost($pirep, $pirep->arr_airport);
Log::info('Finance: PIREP: '.$pirep->id.'; arr ground handling: '.$ground_handling_cost);
$this->financeSvc->debitFromJournal(
$pirep->airline->journal,
Money::createFromAmount($ground_handling_cost),
$pirep,
'Ground Handling (Arrival)',
'Ground Handling', 'Ground Handling',
'ground_handling' 'ground_handling'
); );
@@ -525,23 +544,26 @@ class PirepFinanceService extends Service
* Return the costs for the ground handling, with the multiplier * Return the costs for the ground handling, with the multiplier
* being applied from the subfleet * being applied from the subfleet
* *
* @param Pirep $pirep * @param Pirep $pirep
* @param Airport $airport
* *
* @return float|null * @return float|null
*/ */
public function getGroundHandlingCost(Pirep $pirep) public function getGroundHandlingCost(Pirep $pirep, Airport $airport): ?float
{ {
if (filled($pirep->aircraft->subfleet->ground_handling_multiplier)) { if (empty($airport->ground_handling_cost)) {
// force into percent mode $gh_cost = setting('airports.default_ground_handling_cost');
$multiplier = $pirep->aircraft->subfleet->ground_handling_multiplier.'%'; } else {
$gh_cost = $airport->ground_handling_cost;
return Math::applyAmountOrPercent(
$pirep->arr_airport->ground_handling_cost,
$multiplier
);
} }
return $pirep->arr_airport->ground_handling_cost; if (!filled($pirep->aircraft->subfleet->ground_handling_multiplier)) {
return $gh_cost;
}
// force into percent mode
$multiplier = $pirep->aircraft->subfleet->ground_handling_multiplier.'%';
return Math::applyAmountOrPercent($gh_cost, $multiplier);
} }
/** /**
+3
View File
@@ -135,6 +135,9 @@ class FlightService extends Service
*/ */
public function filterSubfleets(User $user, Flight $flight) public function filterSubfleets(User $user, Flight $flight)
{ {
// Eager load some of the relationships needed
//$flight->load(['flight.subfleets', 'flight.subfleets.aircraft', 'flight.subfleets.fares']);
/** @var \Illuminate\Support\Collection $subfleets */ /** @var \Illuminate\Support\Collection $subfleets */
$subfleets = $flight->subfleets; $subfleets = $flight->subfleets;
+1 -1
View File
@@ -209,7 +209,7 @@ class FlightImporter extends ImportExport
$count = 0; $count = 0;
$subfleets = $this->parseMultiColumnValues($col); $subfleets = $this->parseMultiColumnValues($col);
foreach ($subfleets as $subfleet_type) { foreach ($subfleets as $subfleet_type) {
$subfleet = Subfleet::updateOrCreate( $subfleet = Subfleet::firstOrCreate(
['type' => $subfleet_type], ['type' => $subfleet_type],
['name' => $subfleet_type] ['name' => $subfleet_type]
); );
+4 -4
View File
@@ -31,12 +31,12 @@ class AirportImporter extends BaseImporter
$ground_handling_cost = (float) $row->ground_handling_cost; $ground_handling_cost = (float) $row->ground_handling_cost;
$fuel_jetA_cost = (float) $row->fuel_jeta_cost; $fuel_jetA_cost = (float) $row->fuel_jeta_cost;
if ($ground_handling_cost === null && $ground_handling_cost !== 0) { if (empty($ground_handling_cost)) {
$ground_handling_cost = (float) setting('general.default_ground_handling_cost'); $ground_handling_cost = 0;
} }
if ($fuel_jetA_cost === null && $fuel_jetA_cost !== 0) { if (empty($fuel_jetA_cost)) {
$fuel_jetA_cost = (float) setting('general.default_jetA_fuel_cost'); $fuel_jetA_cost = 0;
} }
$attrs = [ $attrs = [
+98 -28
View File
@@ -15,34 +15,49 @@ use Symfony\Component\HttpFoundation\File\Exception\FileException;
class ConfigService extends Service class ConfigService extends Service
{ {
protected static $defaultValues = [
'APP_ENV' => 'prod',
'APP_KEY' => '',
'APP_DEBUG' => true,
'APP_LOCALE' => 'en',
'DEBUG_TOOLBAR' => false,
'SITE_NAME' => '',
'SITE_URL' => 'http://phpvms.test',
'DB_CONNECTION' => '',
'DB_HOST' => '',
'DB_PORT' => 3306,
'DB_DATABASE' => '',
'DB_USERNAME' => '',
'DB_PASSWORD' => '',
'DB_PREFIX' => '',
'DB_EMULATE_PREPARES' => false,
'CACHE_DRIVER' => 'array',
'CACHE_PREFIX' => '',
'MAIL_DRIVER' => 'mail',
'MAIL_HOST' => '',
'MAIL_PORT' => 587,
'MAIL_ENCRYPTION' => '',
'MAIL_USERNAME' => '',
'MAIL_PASSWORD' => '',
'MAIL_FROM_NAME' => 'phpVMS Admin',
'MAIL_FROM_ADDRESS' => 'no-reply@phpvms.net',
];
/** /**
* Create the .env file * Create the .env file. This is called by an initial install
* *
* @param $attrs * @param $attrs
* *
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException * @throws FileException
* *
* @return bool * @return bool
*/ */
public function createConfigFiles($attrs): bool public function createConfigFiles($attrs): bool
{ {
$opts = [ $opts = array_merge(static::$defaultValues, $attrs);
'APP_ENV' => 'dev', if (empty($opts['APP_KEY'])) {
'APP_KEY' => $this->createAppKey(), $opts['APP_KEY'] = $this->createAppKey();
'SITE_NAME' => '', }
'SITE_URL' => 'http://phpvms.test',
'CACHE_PREFIX' => '',
'DB_CONN' => '',
'DB_HOST' => '',
'DB_PORT' => 3306,
'DB_NAME' => '',
'DB_USER' => '',
'DB_PASS' => '',
'DB_PREFIX' => '',
'DB_EMULATE_PREPARES' => false,
];
$opts = array_merge($opts, $attrs);
$opts = $this->determinePdoOptions($opts); $opts = $this->determinePdoOptions($opts);
$opts = $this->configCacheDriver($opts); $opts = $this->configCacheDriver($opts);
@@ -53,6 +68,61 @@ class ConfigService extends Service
return true; return true;
} }
/**
* Rewrite the config files - this means mapping the values that are currently
* loaded in the config and rewriting them into the env.php file, and then renaming
* the config.php files to config.bak.php
*
* This is called from the migrations which removes the old config.php file
*/
public function rewriteConfigFiles()
{
/*$cfg_file = App::environmentPath().'/config.php';
if (!file_exists($cfg_file)) {
Log::info('Main config.php file is missing, migration already completed');
return;
}*/
$db_opts = config('database.connections.mysql.options');
$emulate_prepares = $db_opts[PDO::ATTR_EMULATE_PREPARES] ? 'true' : 'false';
$opts = array_merge(static::$defaultValues, [
'APP_ENV' => config('app.env'),
'APP_KEY' => config('app.key'),
'APP_DEBUG' => config('app.debug') ? 'true' : 'false',
'APP_LOCALE' => config('app.locale'),
'DEBUG_TOOLBAR' => config('app.debug_toolbar') ? 'true' : 'false',
'SITE_NAME' => config('app.name'),
'SITE_URL' => config('app.url'),
'DB_CONNECTION' => config('database.default'),
'DB_HOST' => config('database.connections.mysql.host'),
'DB_PORT' => config('database.connections.mysql.port'),
'DB_DATABASE' => config('database.connections.mysql.database'),
'DB_USERNAME' => config('database.connections.mysql.username'),
'DB_PASSWORD' => config('database.connections.mysql.password'),
'DB_PREFIX' => config('database.connections.mysql.prefix'),
'DB_EMULATE_PREPARES' => $emulate_prepares,
'CACHE_DRIVER' => config('cache.default'),
'CACHE_PREFIX' => config('cache.prefix'),
'MAIL_DRIVER' => config('mail.default'),
'MAIL_HOST' => config('mail.mailers.smtp.host'),
'MAIL_PORT' => config('mail.mailers.smtp.port'),
'MAIL_ENCRYPTION' => config('mail.mailers.smtp.encryption'),
'MAIL_USERNAME' => config('mail.mailers.smtp.username'),
'MAIL_PASSWORD' => config('mail.mailers.smtp.password'),
'MAIL_FROM_NAME' => config('mail.from.name'),
'MAIL_FROM_ADDRESS' => config('mail.from.address'),
]);
$this->writeConfigFiles($opts);
// Rename the old config file
$cfg_file = App::environmentPath().'/config.php';
if (file_exists($cfg_file)) {
rename($cfg_file, App::environmentPath().'/config.bak.php');
}
}
/** /**
* Update the environment file and update certain keys/values * Update the environment file and update certain keys/values
* *
@@ -97,7 +167,7 @@ class ConfigService extends Service
*/ */
protected function createAppKey(): string protected function createAppKey(): string
{ {
return base64_encode(Encrypter::generateKey(config('app.cipher'))); return 'base64:'.base64_encode(Encrypter::generateKey(config('app.cipher')));
} }
/** /**
@@ -110,14 +180,14 @@ class ConfigService extends Service
*/ */
protected function determinePdoOptions($opts) protected function determinePdoOptions($opts)
{ {
if ($opts['DB_CONN'] !== 'mysql') { if ($opts['DB_CONNECTION'] !== 'mysql') {
return $opts; return $opts;
} }
$dsn = "mysql:host=$opts[DB_HOST];port=$opts[DB_PORT];"; $dsn = "mysql:host=$opts[DB_HOST];port=$opts[DB_PORT];";
Log::info('Connection string: '.$dsn); Log::info('Connection string: '.$dsn);
$conn = new PDO($dsn, $opts['DB_USER'], $opts['DB_PASS']); $conn = new PDO($dsn, $opts['DB_USERNAME'], $opts['DB_PASSWORD']);
$version = strtolower($conn->getAttribute(PDO::ATTR_SERVER_VERSION)); $version = strtolower($conn->getAttribute(PDO::ATTR_SERVER_VERSION));
Log::info('Detected DB Version: '.$version); Log::info('Detected DB Version: '.$version);
@@ -142,7 +212,8 @@ class ConfigService extends Service
protected function configCacheDriver($opts) protected function configCacheDriver($opts)
{ {
// Set the cache prefix // Set the cache prefix
$opts['CACHE_PREFIX'] = uniqid($opts['SITE_NAME'].'_'); $prefix = substr(str_slug($opts['SITE_NAME'], '_'), 0, 8);
$opts['CACHE_PREFIX'] = strtolower(uniqid($prefix.'_'));
// Figure out what cache driver to initially use, depending on // Figure out what cache driver to initially use, depending on
// what is installed. It won't detect redis or anything, though // what is installed. It won't detect redis or anything, though
@@ -171,7 +242,7 @@ class ConfigService extends Service
{ {
// If we're setting up a database, then also setup // If we're setting up a database, then also setup
// the default queue driver to use the database // the default queue driver to use the database
if ($opts['DB_CONN'] === 'mysql' || $opts['DB_CONN'] === 'postgres') { if ($opts['DB_CONNECTION'] === 'mysql' || $opts['DB_CONNECTION'] === 'postgres') {
$opts['QUEUE_DRIVER'] = 'database'; $opts['QUEUE_DRIVER'] = 'database';
} else { } else {
$opts['QUEUE_DRIVER'] = 'sync'; $opts['QUEUE_DRIVER'] = 'sync';
@@ -210,14 +281,13 @@ class ConfigService extends Service
* *
* @param $opts * @param $opts
* *
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException * @throws FileException
*/ */
protected function writeConfigFiles($opts) protected function writeConfigFiles($opts)
{ {
Stub::setBasePath(resource_path('/stubs/installer')); Stub::setBasePath(resource_path('/stubs/installer'));
$env_file = App::environmentFilePath(); $env_file = App::environmentFilePath();
if (file_exists($env_file) && !is_writable($env_file)) { if (file_exists($env_file) && !is_writable($env_file)) {
Log::error('Permissions on existing env.php is not writable'); Log::error('Permissions on existing env.php is not writable');
@@ -239,7 +309,7 @@ class ConfigService extends Service
* Next write out the config file. If there's an error here, * Next write out the config file. If there's an error here,
* then throw an exception but delete the env file first * then throw an exception but delete the env file first
*/ */
try { /*try {
$stub = new Stub('/config.stub', $opts); $stub = new Stub('/config.stub', $opts);
$stub->render(); $stub->render();
$stub->saveTo(App::environmentPath(), 'config.php'); $stub->saveTo(App::environmentPath(), 'config.php');
@@ -247,6 +317,6 @@ class ConfigService extends Service
unlink(App::environmentPath().'/'.App::environmentFile()); unlink(App::environmentPath().'/'.App::environmentFile());
throw new FileException('Couldn\'t write config.php. ('.$e.')'); throw new FileException('Couldn\'t write config.php. ('.$e.')');
} }*/
} }
} }
+2 -2
View File
@@ -90,10 +90,10 @@ class SeederService extends Service
$data = file_get_contents(database_path('/seeds/modules.yml')); $data = file_get_contents(database_path('/seeds/modules.yml'));
$yml = Yaml::parse($data); $yml = Yaml::parse($data);
foreach ($yml as $module) { foreach ($yml as $module) {
$module['updated_at'] = Carbon::now(); $module['updated_at'] = Carbon::now('UTC');
$count = DB::table('modules')->where('name', $module['name'])->count('name'); $count = DB::table('modules')->where('name', $module['name'])->count('name');
if ($count === 0) { if ($count === 0) {
$module['created_at'] = Carbon::now(); $module['created_at'] = Carbon::now('UTC');
DB::table('modules')->insert($module); DB::table('modules')->insert($module);
} else { } else {
DB::table('modules') DB::table('modules')
+4 -1
View File
@@ -6,6 +6,7 @@ use App\Contracts\Service;
use App\Events\PirepAccepted; use App\Events\PirepAccepted;
use App\Events\PirepCancelled; use App\Events\PirepCancelled;
use App\Events\PirepFiled; use App\Events\PirepFiled;
use App\Events\PirepPrefiled;
use App\Events\PirepRejected; use App\Events\PirepRejected;
use App\Events\UserStatsChanged; use App\Events\UserStatsChanged;
use App\Exceptions\AircraftInvalid; use App\Exceptions\AircraftInvalid;
@@ -151,6 +152,8 @@ class PirepService extends Service
} }
} }
event(new PirepPrefiled($pirep));
$pirep->save(); $pirep->save();
return $pirep; return $pirep;
@@ -287,7 +290,7 @@ class PirepService extends Service
public function findDuplicate(Pirep $pirep) public function findDuplicate(Pirep $pirep)
{ {
$minutes = setting('pireps.duplicate_check_time', 10); $minutes = setting('pireps.duplicate_check_time', 10);
$time_limit = Carbon::now()->subMinutes($minutes)->toDateTimeString(); $time_limit = Carbon::now('UTC')->subMinutes($minutes)->toDateTimeString();
$where = [ $where = [
'user_id' => $pirep->user_id, 'user_id' => $pirep->user_id,
+17 -2
View File
@@ -282,9 +282,24 @@ class UserService extends Service
} }
// See if the difference is larger than what the setting calls for // See if the difference is larger than what the setting calls for
if ($date->diffInDays($diff_date) > $leave_days) { if ($date->diffInDays($diff_date) <= $leave_days) {
$return_users[] = $user; continue;
} }
$skip = false;
// If any role for this user has the "disable_activity_check" feature activated, skip this user
foreach ($user->roles()->get() as $role) {
/** @var Role $role */
if ($role->disable_activity_checks) {
$skip = true;
break;
}
}
if ($skip) {
continue;
}
$return_users[] = $user;
} }
return $return_users; return $return_users;
+9 -7
View File
@@ -879,8 +879,8 @@ class Metar implements \ArrayAccess
$this->set_result_value('cavok', true); $this->set_result_value('cavok', true);
$this->method += 4; // can skip the next 4 methods: visibility_min, runway_vr, present_weather, clouds $this->method += 4; // can skip the next 4 methods: visibility_min, runway_vr, present_weather, clouds
} }
} /*elseif ($found[1] === '////') { } elseif ($found[1] === '////') {
}*/ // information not available } // information not available
else { else {
$prefix = ''; $prefix = '';
@@ -994,8 +994,10 @@ class Metar implements \ArrayAccess
} }
$unit = 'meter'; $unit = 'meter';
$report_unit = 'm';
if (isset($found[6]) && $found[6] === 'FT') { if (isset($found[6]) && $found[6] === 'FT') {
$unit = 'feet'; $unit = 'feet';
$report_unit = 'nmi';
} }
$observed = [ $observed = [
@@ -1030,15 +1032,15 @@ class Metar implements \ArrayAccess
if (!empty($observed['runway'])) { if (!empty($observed['runway'])) {
$report = []; $report = [];
if ($observed['variable'] !== null) { if ($observed['variable'] !== null) {
$report[] = $observed['variable']['nmi'].' nmi'; $report[] = $observed['variable'][$report_unit].$report_unit;
} elseif ($observed['interval_min'] !== null && $observed['interval_max'] !== null) { } elseif ($observed['interval_min'] !== null && $observed['interval_max'] !== null) {
if (isset(static::$rvr_prefix_codes[$observed['variable_prefix']])) { if (isset(static::$rvr_prefix_codes[$observed['variable_prefix']])) {
$report[] = 'varying from a min. of '.$observed['interval_min']['nmi'].' nmi until a max. of '. $report[] = 'varying from a min. of '.$observed['interval_min'][$report_unit].$report_unit.' until a max. of '.
static::$rvr_prefix_codes[$observed['variable_prefix']].' that '. static::$rvr_prefix_codes[$observed['variable_prefix']].' that '.
$observed['interval_max']['nmi'].' nmi'; $observed['interval_max'][$report_unit].' '.$report_unit;
} else { } else {
$report[] = 'varying from a min. of '.$observed['interval_min']['nmi'].' nmi until a max. of '. $report[] = 'varying from a min. of '.$observed['interval_min'][$report_unit].$report_unit.' until a max. of '.
$observed['interval_max']['nmi'].' nmi'; $observed['interval_max'][$report_unit].$report_unit;
} }
} }
+89
View File
@@ -0,0 +1,89 @@
<?php
namespace App\Support;
use Igaster\LaravelTheme\Facades\Theme;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
class ThemeViewFinder extends \Igaster\LaravelTheme\themeViewFinder
{
public function __construct(Filesystem $files, array $paths, array $extensions = null)
{
//$this->themeEngine = \App::make('igaster.themes');
parent::__construct($files, $paths, $extensions);
}
/*
* Override findNamespacedView() to add "Theme/vendor/..." paths
*
* @param string $name
* @return string
*/
protected function findNamespacedView($name)
{
// Extract the $view and the $namespace parts
list($namespace, $view) = $this->parseNamespaceSegments($name);
$paths = $this->addThemeNamespacePaths($namespace);
// Find and return the view
return $this->findInPaths($view, $paths);
}
public function addThemeNamespacePaths($namespace)
{
// This rule will remap all paths starting with $key to $value.
// For exapmle paths starting with 'resources/views/vendor' (relative to base_path())
// will be maped to path 'THEMENAME/vendor' (relative to current theme views-path)
$pathsMap = [
// 'resources/views/vendor/mail' => 'mail',
'resources/views/vendor' => 'vendor',
'resources/views/modules' => 'modules',
];
// Does $namespace exists?
if (!isset($this->hints[$namespace])) {
return [];
}
// Get the paths registered to the $namespace
$paths = $this->hints[$namespace];
// Search $paths array and remap paths that start with a key of $pathsMap array.
// replace with the value of $pathsMap array
$themeSubPaths = [];
foreach ($paths as $path) {
$pathRelativeToApp = substr($path, strlen(base_path()) + 1);
$pathRelativeToApp = str_replace('\\', '/', $pathRelativeToApp);
// Ignore paths in composer installed packages (paths inside vendor folder)
if (strpos($pathRelativeToApp, 'vendor') !== 0) {
// Remap paths definded int $pathsMap array
foreach ($pathsMap as $key => $value) {
if (strpos($pathRelativeToApp, $key) === 0) {
$pathRelativeToApp = str_replace($key, $value, $pathRelativeToApp);
break;
}
}
$themeSubPaths[] = $pathRelativeToApp;
}
}
// Prepend current theme's view path to the remaped paths
$newPaths = [];
$searchPaths = array_diff($this->paths, Theme::getLaravelViewPaths());
foreach ($searchPaths as $path1) {
foreach ($themeSubPaths as $path2) {
$newPaths[] = $path1.'/'.$path2;
}
}
// Add new paths in the beggin of the search paths array
foreach (array_reverse($newPaths) as $path) {
if (!in_array($path, $paths, true)) {
$paths = Arr::prepend($paths, $path);
}
}
return $paths;
}
}
+2 -1
View File
@@ -8,6 +8,7 @@ use App\Repositories\PirepRepository;
/** /**
* Show the latest PIREPs in a view * Show the latest PIREPs in a view
* sorted nicely by their submit time
*/ */
class LatestPireps extends Widget class LatestPireps extends Widget
{ {
@@ -28,7 +29,7 @@ class LatestPireps extends Widget
PirepState::CANCELLED, PirepState::CANCELLED,
PirepState::DRAFT, PirepState::DRAFT,
PirepState::IN_PROGRESS, PirepState::IN_PROGRESS,
], 'created_at', 'desc') ], 'submitted_at', 'desc')
->recent($this->config['count']); ->recent($this->config['count']);
return view('widgets.latest_pireps', [ return view('widgets.latest_pireps', [
+1 -1
View File
@@ -15,7 +15,7 @@ return [
'debug' => env('APP_DEBUG', true), 'debug' => env('APP_DEBUG', true),
'url' => env('APP_URL', ''), 'url' => env('APP_URL', ''),
'version' => '7.0.0', 'version' => '7.0.0',
'debug_toolbar' => false, 'debug_toolbar' => env('DEBUG_TOOLBAR', false),
'locale' => env('APP_LOCALE', 'en'), 'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => 'en', 'fallback_locale' => 'en',
+5 -5
View File
@@ -7,17 +7,17 @@
* Don't edit this file directly, add the section to your config.php * Don't edit this file directly, add the section to your config.php
*/ */
return [ return [
'enabled' => false, 'enabled' => env('CAPTCHA_ENABLED', false),
'sitekey' => '', 'sitekey' => env('CAPTCHA_SITEKEY', ''),
'secret' => '', 'secret' => env('CAPTCHA_SECRET', ''),
// Attributes can be found here: // Attributes can be found here:
// https://developers.google.com/recaptcha/docs/display#render_param // https://developers.google.com/recaptcha/docs/display#render_param
'attributes' => [ 'attributes' => [
'data-theme' => 'light', 'data-theme' => env('CAPTCHA_DATATHEME', 'light'),
], ],
'options' => [ 'options' => [
'timeout' => 2.0, 'timeout' => env('CAPTCHA_TIMEOUT', '2.0'),
], ],
]; ];
+1 -1
View File
@@ -5,5 +5,5 @@
return [ return [
'url' => 'https://www.gravatar.com/avatar/', 'url' => 'https://www.gravatar.com/avatar/',
'default' => 'https://en.gravatar.com/userimage/12856995/aa6c0527a723abfd5fb9e246f0ff8af4.png', 'default' => env('GRAVATAR_DEFAULT_AVATAR', 'https://en.gravatar.com/userimage/12856995/aa6c0527a723abfd5fb9e246f0ff8af4.png'),
]; ];
+8 -6
View File
@@ -1,5 +1,7 @@
<?php <?php
use App\Console\Logger;
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -44,18 +46,18 @@ return [
'single' => [ 'single' => [
'driver' => 'single', 'driver' => 'single',
'path' => storage_path('logs/laravel.log'), 'path' => storage_path('logs/laravel.log'),
'level' => 'debug', 'level' => env('LOG_LEVEL', 'debug'),
], ],
'daily' => [ 'daily' => [
'driver' => 'daily', 'driver' => 'daily',
'path' => storage_path('logs/laravel.log'), 'path' => storage_path('logs/laravel.log'),
'level' => 'debug', 'level' => env('LOG_LEVEL', 'debug'),
'days' => 3, 'days' => 3,
], ],
'cron_rotating' => [ 'cron_rotating' => [
'driver' => 'daily', 'driver' => 'daily',
'path' => storage_path('logs/cron.log'), 'path' => storage_path('logs/cron.log'),
'level' => 'debug', 'level' => env('LOG_LEVEL', 'debug'),
'days' => 3, 'days' => 3,
], ],
'slack' => [ 'slack' => [
@@ -67,15 +69,15 @@ return [
], ],
'stdout' => [ 'stdout' => [
'driver' => 'custom', 'driver' => 'custom',
'via' => \App\Console\Logger::class, 'via' => Logger::class,
], ],
'syslog' => [ 'syslog' => [
'driver' => 'syslog', 'driver' => 'syslog',
'level' => 'debug', 'level' => env('LOG_LEVEL', 'debug'),
], ],
'errorlog' => [ 'errorlog' => [
'driver' => 'errorlog', 'driver' => 'errorlog',
'level' => 'debug', 'level' => env('LOG_LEVEL', 'debug'),
], ],
], ],
]; ];
+3 -1
View File
@@ -1,5 +1,7 @@
<?php <?php
use App\Models\User;
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -29,7 +31,7 @@ return [
], ],
'stripe' => [ 'stripe' => [
'model' => App\User::class, 'model' => User::class,
'key' => env('STRIPE_KEY'), 'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'), 'secret' => env('STRIPE_SECRET'),
], ],
+3017 -1552
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -27,7 +27,7 @@
"jquery": "^3.5.1", "jquery": "^3.5.1",
"jquery-pjax": "~2.0", "jquery-pjax": "~2.0",
"js-yaml": "^3.14.0", "js-yaml": "^3.14.0",
"laravel-mix": "^5.0.7", "laravel-mix": "^5.0.8",
"leaflet": "^1.3.4", "leaflet": "^1.3.4",
"leaflet-ajax": "2.1.0", "leaflet-ajax": "2.1.0",
"leaflet-providers": "1.0.*", "leaflet-providers": "1.0.*",
@@ -44,7 +44,7 @@
"popper.js": "^1.15.0", "popper.js": "^1.15.0",
"rivets": "^0.9.6", "rivets": "^0.9.6",
"select2": "^4.0.13", "select2": "^4.0.13",
"ssri": "^5.3.0", "ssri": "^6.0.2",
"tar": ">=4.4.2", "tar": ">=4.4.2",
"webpack": "^4.44.2", "webpack": "^4.44.2",
"webpack-cli": "^3.3.12", "webpack-cli": "^3.3.12",
-1
View File
@@ -6,7 +6,6 @@
} }
.map-info-box { .map-info-box {
display: none;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
padding: 20px; padding: 20px;
+3 -2
View File
@@ -10,6 +10,7 @@ RUN ln -sf /dev/stderr /var/log/fpm-error.log
RUN docker-php-ext-install \ RUN docker-php-ext-install \
bcmath \ bcmath \
calendar \ calendar \
pdo_mysql \
gmp \ gmp \
opcache intl \
opcache \
pdo_mysql
+1
View File
@@ -5,6 +5,7 @@ return [
'flighttime' => 'Flight Time', 'flighttime' => 'Flight Time',
'flighttype' => 'Flight Type', 'flighttype' => 'Flight Type',
'flighthours' => 'Flight Hours', 'flighthours' => 'Flight Hours',
'callsign' => 'Callsign',
'route' => 'Route', 'route' => 'Route',
'mybid' => 'My Bids', 'mybid' => 'My Bids',
'search' => 'Search', 'search' => 'Search',
+1
View File
@@ -5,6 +5,7 @@ return [
'flighttime' => 'Tiempo de vuelo', 'flighttime' => 'Tiempo de vuelo',
'flighttype' => 'Tipo de vuelo', 'flighttype' => 'Tipo de vuelo',
'flighthours' => 'Horas de vuelo', 'flighthours' => 'Horas de vuelo',
'callsign' => 'Indicativo',
'route' => 'Ruta', 'route' => 'Ruta',
'mybid' => 'Mis reservas', 'mybid' => 'Mis reservas',
'search' => 'Buscar', 'search' => 'Buscar',
+1
View File
@@ -5,6 +5,7 @@ return [
'flighttime' => 'Tempo di Volo', 'flighttime' => 'Tempo di Volo',
'flighttype' => 'Tipo di Volo', 'flighttype' => 'Tipo di Volo',
'flighthours' => 'Ore di Volo', 'flighthours' => 'Ore di Volo',
'callsign' => 'Nominativo',
'route' => 'Rotta', 'route' => 'Rotta',
'mybid' => 'Mie Prenotazioni', 'mybid' => 'Mie Prenotazioni',
'addremovebid' => 'Aggiungi/Rimuovi Prenotazione', 'addremovebid' => 'Aggiungi/Rimuovi Prenotazione',
+1
View File
@@ -5,6 +5,7 @@ return [
'flighttime' => 'Tempo do Voo', 'flighttime' => 'Tempo do Voo',
'flighttype' => 'Tipo de Voo', 'flighttype' => 'Tipo de Voo',
'flighthours' => 'Horas de Voo', 'flighthours' => 'Horas de Voo',
'callsign' => 'Indicativo',
'route' => 'Rota', 'route' => 'Rota',
'mybid' => 'Minhas Reservas', 'mybid' => 'Minhas Reservas',
'search' => 'Procurar', 'search' => 'Procurar',
+3 -3
View File
@@ -60,9 +60,9 @@ return [
'mysql' => [ 'mysql' => [
'host' => env('DB_HOST', '$DB_HOST$'), 'host' => env('DB_HOST', '$DB_HOST$'),
'port' => $DB_PORT$, 'port' => $DB_PORT$,
'database' => '$DB_NAME$', 'database' => '$DB_DATABASE$',
'username' => '$DB_USER$', 'username' => '$DB_USERNAME$',
'password' => '$DB_PASS$', 'password' => '$DB_PASSWORD$',
'prefix' => '$DB_PREFIX$', 'prefix' => '$DB_PREFIX$',
'prefix_indexes' => true, 'prefix_indexes' => true,
], ],
+44 -2
View File
@@ -1,8 +1,50 @@
#
# THIS FILE MUST BE KEPT SECRET! IT IS BLOCKED IN THE HTACCESS FILE # THIS FILE MUST BE KEPT SECRET! IT IS BLOCKED IN THE HTACCESS FILE
# HOWEVER, THIS DIRECTORY SHOULDN'T BE EXPOSED TO THE PUBLIC AT ALL # HOWEVER, THIS DIRECTORY SHOULDN'T BE EXPOSED TO THE PUBLIC AT ALL
# SEE THE DOCS FOR PROPER (SECURE) INSTALLATION: # SEE THE DOCS FOR PROPER (SECURE) INSTALLATION:
# https://docs.phpvms.net/installation/uploading # https://docs.phpvms.net/installation/uploading
# #
# This is the place to edit your configuration. To change a config that's
# not present here, you need to either edit the file/config in the config
# folder, or change it to read the value from the environment. Something like:
#
# 'some_key' = env('ENVIRONMENT_VARIABLE_KEY_ADDED_BELOW', 'default value')
#
# Various other settings in the configs also read from some environment variables
# by default. You can override those here
APP_KEY=base64:$APP_KEY$ APP_KEY='$APP_KEY$'
APP_NAME='$SITE_NAME$'
SITE_NAME='$SITE_NAME$'
SITE_URL='$SITE_URL$'
APP_ENV=$APP_ENV$
APP_LOCALE=$APP_LOCALE$
LOG_LEVEL=debug
APP_DEBUG=$APP_DEBUG$
DEBUG_TOOLBAR=$DEBUG_TOOLBAR$
# DATABASE SETTINGS
DB_CONNECTION=$DB_CONNECTION$
DB_HOST='$DB_HOST$'
DB_PORT=$DB_PORT$
DB_DATABASE='$DB_DATABASE$'
DB_USERNAME='$DB_USERNAME$'
DB_PASSWORD='$DB_PASSWORD$'
DB_PREFIX='$DB_PREFIX$'
DB_EMULATE_PREPARES=$DB_EMULATE_PREPARES$
DB_SOCKET=
# CACHE SETTINGS
CACHE_DRIVER=$CACHE_DRIVER$
CACHE_PREFIX='$CACHE_PREFIX$'
# EMAIL SETTINGS
# Look at the available mail configs in config/mail.php
# Also refer to the Laravel docs here: https://laravel.com/docs/8.x/mail
MAIL_DRIVER=$MAIL_DRIVER$
MAIL_FROM_NAME='$MAIL_FROM_NAME$'
MAIL_FROM_ADDRESS='$MAIL_FROM_ADDRESS$'
MAIL_HOST=$MAIL_HOST$
MAIL_PORT=$MAIL_PORT$
MAIL_ENCRYPTION=$MAIL_ENCRYPTION$
MAIL_USERNAME=$MAIL_USERNAME$
MAIL_PASSWORD=$MAIL_PASSWORD$
@@ -60,7 +60,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-sm-6"> <div class="form-group col-sm-3">
{{ Form::label('ground_handling_cost', 'Ground Handling Cost:') }} {{ Form::label('ground_handling_cost', 'Ground Handling Cost:') }}
{{ Form::number('ground_handling_cost', null, ['class' => 'form-control', 'step' => '0.01']) }} {{ Form::number('ground_handling_cost', null, ['class' => 'form-control', 'step' => '0.01']) }}
<p class="text-danger">{{ $errors->first('ground_handling_cost') }}</p> <p class="text-danger">{{ $errors->first('ground_handling_cost') }}</p>
@@ -71,7 +71,7 @@
@endcomponent @endcomponent
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-3">
{{ Form::label('fuel_jeta_cost', 'Jet A Fuel Cost:') }} {{ Form::label('fuel_jeta_cost', 'Jet A Fuel Cost:') }}
{{ Form::number('fuel_jeta_cost', null, ['class' => 'form-control', 'step' => '0.01']) }} {{ Form::number('fuel_jeta_cost', null, ['class' => 'form-control', 'step' => '0.01']) }}
<p class="text-danger">{{ $errors->first('fuel_jeta_cost') }}</p> <p class="text-danger">{{ $errors->first('fuel_jeta_cost') }}</p>
@@ -81,6 +81,26 @@
@endcomponent @endcomponent
</div> </div>
<div class="form-group col-md-3">
{{ Form::label('fuel_100ll_cost', '100LL Fuel Cost:') }}
{{ Form::number('fuel_100ll_cost', null, ['class' => 'form-control', 'step' => '0.01']) }}
<p class="text-danger">{{ $errors->first('fuel_100ll_cost') }}</p>
@component('admin.components.info')
This is the cost per {{ config('phpvms.internal_units.fuel') }}
@endcomponent
</div>
<div class="form-group col-md-3">
{{ Form::label('fuel_mogas_cost', 'MOGAS Fuel Cost:') }}
{{ Form::number('fuel_mogas_cost', null, ['class' => 'form-control', 'step' => '0.01']) }}
<p class="text-danger">{{ $errors->first('fuel_mogas_cost') }}</p>
@component('admin.components.info')
This is the cost per {{ config('phpvms.internal_units.fuel') }}
@endcomponent
</div>
</div> </div>
<div class="row"> <div class="row">
@@ -7,6 +7,8 @@
<th>Hub</th> <th>Hub</th>
<th style="text-align: center;">GH Cost</th> <th style="text-align: center;">GH Cost</th>
<th style="text-align: center;">JetA</th> <th style="text-align: center;">JetA</th>
<th style="text-align: center;">100LL</th>
<th style="text-align: center;">MOGAS</th>
<th></th> <th></th>
</thead> </thead>
<tbody> <tbody>
@@ -27,6 +29,14 @@
<a class="inline" href="#" data-pk="{{ $airport->id }}" <a class="inline" href="#" data-pk="{{ $airport->id }}"
data-name="fuel_jeta_cost">{{ $airport->fuel_jeta_cost }}</a> data-name="fuel_jeta_cost">{{ $airport->fuel_jeta_cost }}</a>
</td> </td>
<td style="text-align: center;">
<a class="inline" href="#" data-pk="{{ $airport->id }}"
data-name="fuel_100ll_cost">{{ $airport->fuel_100ll_cost }}</a>
</td>
<td style="text-align: center;">
<a class="inline" href="#" data-pk="{{ $airport->id }}"
data-name="fuel_mogas_cost">{{ $airport->fuel_mogas_cost }}</a>
</td>
<td style="text-align: right;"> <td style="text-align: right;">
{{ Form::open(['route' => ['admin.airports.destroy', $airport->id], 'method' => 'delete']) }} {{ Form::open(['route' => ['admin.airports.destroy', $airport->id], 'method' => 'delete']) }}
<a href="{{ route('admin.airports.edit', [$airport->id]) }}" class='btn btn-sm btn-success btn-icon'><i <a href="{{ route('admin.airports.edit', [$airport->id]) }}" class='btn btn-sm btn-success btn-icon'><i
+24 -20
View File
@@ -1,26 +1,30 @@
@foreach (session('flash_notification', collect()) as $message) @foreach (session('flash_notification', collect()) as $message)
@if ($message['overlay']) @if (is_string($message))
@include('flash::modal', [ <div class="alert alert-error">{!! $message !!}</div>
'modalClass' => 'flash-modal',
'title' => $message['title'],
'body' => $message['message']
])
@else @else
<div class="alert @if ($message['overlay'])
alert-{{ $message['level'] }} @include('flash::modal', [
{{ $message['important'] ? 'alert-important' : '' }}" 'modalClass' => 'flash-modal',
role="alert"> 'title' => $message['title'],
@if ($message['important']) 'body' => $message['message']
<button type="button" ])
class="close" @else
data-dismiss="alert" <div class="alert
aria-hidden="true" alert-{{ $message['level'] }}
>&times; {{ $message['important'] ? 'alert-important' : '' }}"
</button> role="alert">
@endif @if ($message['important'])
<button type="button"
class="close"
data-dismiss="alert"
aria-hidden="true"
>&times;
</button>
@endif
{!! $message['message'] !!} {!! $message['message'] !!}
</div> </div>
@endif
@endif @endif
@endforeach @endforeach
+11 -4
View File
@@ -29,15 +29,22 @@
</div> </div>
<!-- Route Code Field --> <!-- Callsign Field -->
<div class="form-group col-sm-3"> <div class="form-group input-group-sm col-sm-2">
{{ Form::label('callsign', 'Callsign:') }}
{{ Form::text('callsign', null, ['class'=>'form-control', 'placeholder'=>'optional', 'maxlength' => 4]) }}
<p class="text-danger">{{ $errors->first('callsign') }}</p>
</div>
<!-- Flight Type Field -->
<div class="form-group col-sm-2">
{{ Form::label('level', 'Flight Type:') }}&nbsp;<span class="required">*</span> {{ Form::label('level', 'Flight Type:') }}&nbsp;<span class="required">*</span>
{{ Form::select('flight_type', $flight_types, null, ['class' => 'form-control select2']) }} {{ Form::select('flight_type', $flight_types, null, ['class' => 'form-control select2']) }}
<p class="text-danger">{{ $errors->first('flight_type') }}</p> <p class="text-danger">{{ $errors->first('flight_type') }}</p>
</div> </div>
<!-- Route Leg Field --> <!-- Flight Time Field -->
<div class="form-group col-sm-3"> <div class="form-group col-sm-2">
{{ Form::label('flight_time', 'Flight Time (hours & minutes)') }} {{ Form::label('flight_time', 'Flight Time (hours & minutes)') }}
<div class="input-group input-group-sm mb3"> <div class="input-group input-group-sm mb3">
@@ -13,6 +13,7 @@
<table class="table table-responsive" id="aircrafts-table"> <table class="table table-responsive" id="aircrafts-table">
@if(count($flight->subfleets)) @if(count($flight->subfleets))
<thead> <thead>
<th>Airline</th>
<th>Type</th> <th>Type</th>
<th>Name</th> <th>Name</th>
<th style="text-align: center;">Actions</th> <th style="text-align: center;">Actions</th>
@@ -21,6 +22,12 @@
<tbody> <tbody>
@foreach($flight->subfleets as $sf) @foreach($flight->subfleets as $sf)
<tr> <tr>
<td>@if ($sf->airline->logo)
<img src="{{ $sf->airline->logo }}" style="max-width: 60px; width: 55%; height: auto;">
@else
&nbsp;{{ $sf->airline->icao }}
@endif
</td>
<td>{{ $sf->type }}</td> <td>{{ $sf->type }}</td>
<td>{{ $sf->name }}</td> <td>{{ $sf->name }}</td>
<td style="width: 10%; text-align: center;" class="form-inline"> <td style="width: 10%; text-align: center;" class="form-inline">
+10 -1
View File
@@ -31,7 +31,8 @@
{{ Form::open(['url' => route('admin.pireps.destroy', [$pirep->id]), {{ Form::open(['url' => route('admin.pireps.destroy', [$pirep->id]),
'method' => 'delete', 'method' => 'delete',
'name' => 'delete_'.$pirep->id, 'name' => 'delete_'.$pirep->id,
'id' => $pirep->id.'_delete' 'id' => $pirep->id.'_delete',
'onclick' => "return confirm('Are you sure?')"
]) }} ]) }}
{{ Form::button('Delete', ['type' => 'submit', 'class' => 'btn btn-danger']) }} {{ Form::button('Delete', ['type' => 'submit', 'class' => 'btn btn-danger']) }}
{{ Form::close() }} {{ Form::close() }}
@@ -46,5 +47,13 @@
</form> </form>
</td> </td>
@endif @endif
<td>
<form action="{{ route('frontend.pireps.show', [$pirep->id]) }}" target="_blank">
<button type="submit"
class='btn btn-success'>
<i class="fas fa-eye"></i>&nbsp;&nbsp; View Pirep
</button>
</form>
</td>
</tr> </tr>
</table> </table>
@@ -14,6 +14,23 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-container">
<h6><i class="fas fa-check-square"></i>
Features
</h6>
<div class="form-container-body">
<div class="row">
<div class="form-group col-sm-12">
<div class="checkbox">
{{ Form::hidden('disable_activity_checks', 0) }}
{{ Form::checkbox('disable_activity_checks', 1) }}
{{ Form::label('disable_activity_checks', 'disable activity checks') }}
<p class="text-danger">{{ $errors->first('disable_activity_checks') }}</p>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<!-- Permissions Field --> <!-- Permissions Field -->
@@ -1,26 +1,27 @@
@foreach (collect(session('flash_notification', collect()))->toArray() as $message) @foreach (collect(session('flash_notification', collect()))->toArray() as $message)
@if ($message['overlay']) @if (is_string($message))
@include('flash::modal', [ <div class="alert alert-error">{!! $message !!}</div>
'modalClass' => 'flash-modal',
'title' => $message['title'],
'body' => $message['message']
])
@else @else
<div class="alert @if ($message['overlay'])
alert-{{ $message['level'] }} @include('flash::modal', [
{{ $message['important'] ? 'alert-important' : '' }}" 'modalClass' => 'flash-modal',
role="alert"> 'title' => $message['title'],
@if ($message['important']) 'body' => $message['message']
<button type="button" ])
class="close" @else
data-dismiss="alert" <div class="alert alert-{{ $message['level'] }}
aria-hidden="true" {{ $message['important'] ? 'alert-important' : '' }}"
>&times; role="alert">
</button> @if ($message['important'])
@endif <button type="button"
class="close"
data-dismiss="alert"
aria-hidden="true">&times;</button>
@endif
{!! $message['message'] !!} {!! $message['message'] !!}
</div> </div>
@endif
@endif @endif
@endforeach @endforeach
@@ -43,12 +43,18 @@
</td> </td>
</tr> </tr>
@endif @endif
@if(filled($flight->route))
<tr> <tr>
<td>@lang('flights.route')</td> <td>@lang('flights.route')</td>
<td>{{ $flight->route }}</td> <td>{{ $flight->route }}</td>
</tr> </tr>
@endif
@if(filled($flight->callsign))
<tr>
<td>@lang('flights.callsign')</td>
<td>{{ $flight->airline->icao }} {{ $flight->callsign }}</td>
</tr>
@endif
@if(filled($flight->notes)) @if(filled($flight->notes))
<tr> <tr>
<td>{{ trans_choice('common.note', 2) }}</td> <td>{{ trans_choice('common.note', 2) }}</td>
@@ -12,11 +12,9 @@
<div class="col-md-12"> <div class="col-md-12">
<select id="aircraftselection" class="form-control select2" onchange="checkacselection()"> <select id="aircraftselection" class="form-control select2" onchange="checkacselection()">
<option value="ZZZZZ">Please Select An Aircraft</option> <option value="ZZZZZ">Please Select An Aircraft</option>
@foreach($subfleets as $subfleet) @foreach($aircrafts as $ac)
@foreach($subfleet->aircraft as $ac) <option value="{{ $ac->id }}">[{{ $ac->icao }}] {{ $ac->registration }} @if($ac->registration != $ac->name)'{{ $ac->name }}'@endif</option>
<option value="{{ $ac->id }}">[ {{ $ac->icao }} ] {{ $ac->registration }}</option>
@endforeach @endforeach
@endforeach
</select> </select>
</div> </div>
<div class="col-md-12 text-right"> <div class="col-md-12 text-right">
@@ -143,6 +143,11 @@
<input type="hidden" name="fltnum" value="{{ $flight->flight_number }}"> <input type="hidden" name="fltnum" value="{{ $flight->flight_number }}">
@if(setting('simbrief.callsign', true)) @if(setting('simbrief.callsign', true))
<input type="hidden" name="callsign" value="{{ $user->ident }}"> <input type="hidden" name="callsign" value="{{ $user->ident }}">
@else
<input type="hidden" name="callsign" value="{{ $flight->airline->icao }}{{ $flight->callsign ?? $flight->flight_number }}">
@endif
@if(setting('simbrief.name_private', true))
<input type="hidden" name="cpt" value="{{ $user->name_private }}">
@endif @endif
<input type="hidden" id="steh" name="steh" maxlength="2"> <input type="hidden" id="steh" name="steh" maxlength="2">
<input type="hidden" id="stem" name="stem" maxlength="2"> <input type="hidden" id="stem" name="stem" maxlength="2">
@@ -51,14 +51,20 @@
])}}">{{$flight->arr_airport_id}}</a>) ])}}">{{$flight->arr_airport_id}}</a>)
@if($flight->arr_time), {{ $flight->arr_time }}@endif @if($flight->arr_time), {{ $flight->arr_time }}@endif
<br/> <br/>
@if(filled($flight->callsign))
<span class="title">{{ strtoupper(__('flights.callsign')) }}&nbsp;</span>
{{ $flight->airline->icao }} {{ $flight->callsign }}
<br/>
@endif
@if($flight->distance) @if($flight->distance)
<span class="title">{{ strtoupper(__('common.distance')) }}&nbsp;</span> <span class="title">{{ strtoupper(__('common.distance')) }}&nbsp;</span>
{{ $flight->distance }} {{ setting('units.distance') }} {{ $flight->distance }} {{ setting('units.distance') }}
<br/>
@endif @endif
<br/>
@if($flight->level) @if($flight->level)
<span class="title">{{ strtoupper(__('flights.level')) }}&nbsp;</span> <span class="title">{{ strtoupper(__('flights.level')) }}&nbsp;</span>
{{ $flight->level }} {{ setting('units.altitude') }} {{ $flight->level }} {{ setting('units.altitude') }}
<br/>
@endif @endif
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
@@ -327,7 +327,8 @@ flight reports that have been filed. You've been warned!
'name' => 'submit', 'name' => 'submit',
'value' => 'Delete', 'value' => 'Delete',
'class' => 'btn btn-warning', 'class' => 'btn btn-warning',
'type' => 'submit']) 'type' => 'submit',
'onclick' => "return confirm('Are you sure you want to delete this PIREP?')"])
}} }}
@endif @endif
@@ -15,7 +15,7 @@
class="btn btn-outline-info">View SimBrief</a> class="btn btn-outline-info">View SimBrief</a>
@endif @endif
@if(!$pirep->read_only) @if(!$pirep->read_only && $pirep->user_id === $user->id)
<div class="float-right" style="margin-bottom: 10px;"> <div class="float-right" style="margin-bottom: 10px;">
<form method="get" <form method="get"
action="{{ route('frontend.pireps.edit', $pirep->id) }}" action="{{ route('frontend.pireps.edit', $pirep->id) }}"
@@ -131,28 +131,33 @@
<tr> <tr>
<td>@lang('pireps.filedroute')</td> <td>@lang('pireps.filedroute')</td>
<td> <td>{{ $pirep->route }}</td>
{{ $pirep->route }}
</td>
</tr> </tr>
<tr> <tr>
<td>{{ trans_choice('common.note', 2) }}</td> <td>{{ trans_choice('common.note', 2) }}</td>
<td> <td>{{ $pirep->notes }}</td>
{{ $pirep->notes }}
</td>
</tr> </tr>
@if($pirep->score && $pirep->landing_rate)
<tr>
<td>Score</td>
<td>{{ $pirep->score }}</td>
</tr>
<tr>
<td>Landing Rate</td>
<td>{{ number_format($pirep->landing_rate) }}</td>
</tr>
@endif
<tr> <tr>
<td>@lang('pireps.filedon')</td> <td>@lang('pireps.filedon')</td>
<td> <td>{{ show_datetime($pirep->created_at) }}</td>
{{ show_datetime($pirep->created_at) }}
</td>
</tr> </tr>
</table> </table>
@if(count($pirep->fields) > 0 || count($pirep->fares) > 0) @if(count($pirep->fields) > 0)
<div class="separator"></div> <div class="separator"></div>
@endif @endif
@@ -214,7 +219,7 @@
<div class="col-12"> <div class="col-12">
<table class="table table-hover table-condensed" id="users-table"> <table class="table table-hover table-condensed" id="users-table">
<tbody> <tbody>
@foreach($pirep->acars_logs as $log) @foreach($pirep->acars_logs->sortBy('created_at') as $log)
<tr> <tr>
<td nowrap="true">{{ show_datetime($log->created_at) }}</td> <td nowrap="true">{{ show_datetime($log->created_at) }}</td>
<td>{{ $log->log }}</td> <td>{{ $log->log }}</td>
@@ -29,7 +29,7 @@
A couple of places (like the distance) use both to output the correct bindings. A couple of places (like the distance) use both to output the correct bindings.
--}} --}}
<div id="map-info-box" class="map-info-box" <div id="map-info-box" class="map-info-box"
rv-show="pirep" rv-show="pirep.id"
style="width: {{ $config['width'] }};"> style="width: {{ $config['width'] }};">
<div style="float: left; width: 50%;"> <div style="float: left; width: 50%;">
<h3 style="margin: 0" id="map_flight_id"> <h3 style="margin: 0" id="map_flight_id">
@@ -1,11 +1,7 @@
@component('mail::message') @component('mail::message')
# {{ $news->subject }} # {{ $news->subject }}
$news->body {{ $news->body }}
@component('mail::button', ['url' => route('frontend.pireps.show', [$pirep->id])])
View PIREP
@endcomponent
Thanks,<br> Thanks,<br>
{{ config('app.name') }} {{ config('app.name') }}
@@ -1,19 +1,20 @@
@if (session()->has('flash_notification.message')) @foreach (collect(session('flash_notification', collect()))->toArray() as $message)
@if (session()->has('flash_notification.overlay')) @if (is_string($message))
@include('flash::modal', [ <div class="alert alert-error">{!! $message !!}</div>
'modalClass' => 'flash-modal',
'title' => session('flash_notification.title'),
'body' => session('flash_notification.message')
])
@else @else
<div class="alert <div class="alert alert-{{ $message['level'] }}
alert-{{ session('flash_notification.level') }} {{ $message['important'] ? 'alert-important' : '' }}"
{{ session()->has('flash_notification.important') ? 'alert-important' : '' }}"> role="alert">
@if(session()->has('flash_notification.important')) @if ($message['important'])
<button type="button" class="close" data-dismiss="alert">&times;</button> <button type="button"
class="close"
data-dismiss="alert"
aria-hidden="true">&times;</button>
@endif @endif
{{ session('flash_notification.message') }} {!! $message['message'] !!}
</div> </div>
@endif @endif
@endif @endforeach
{{ session()->forget('flash_notification') }}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Tests;
use App\Models\Airport;
/**
* Test the parsing/support class of the metar
*/
class AirportTest extends TestCase
{
public function testSavingAirportFromApiResponse()
{
// This is the response from the API
$airportResponse = [
'icao' => 'KJFK',
'iata' => 'JFK',
'name' => 'John F Kennedy International Airport',
'city' => 'New York',
'country' => 'United States',
'tz' => 'America/New_York',
'lat' => 40.63980103,
'lon' => -73.77890015,
];
$airport = new Airport($airportResponse);
$this->assertEquals($airportResponse['icao'], $airport->icao);
$this->assertEquals($airportResponse['tz'], $airport->timezone);
}
}
+152
View File
@@ -0,0 +1,152 @@
<?php
namespace Tests;
use App\Cron\Hourly\DeletePireps;
use App\Cron\Hourly\RemoveExpiredLiveFlights;
use App\Events\CronHourly;
use App\Models\Enums\PirepState;
use App\Models\Pirep;
use App\Models\User;
use Carbon\Carbon;
class CronTest extends TestCase
{
/**
* Create a new sample PIREP
*
* @param $subtractTime
*
* @return Pirep
*/
protected static function getPirep($subtractTime): Pirep
{
/** @var User $user */
$user = factory(User::class)->create();
/** @var Pirep $pirep */
return factory(Pirep::class)->create([
'user_id' => $user->id,
'state' => PirepState::IN_PROGRESS,
'updated_at' => Carbon::now('UTC')->subHours($subtractTime),
]);
}
/**
* @throws \Exception
*/
public function testExpiredFlightNotBeingRemoved()
{
$this->updateSetting('acars.live_time', 0);
$pirep = $this->getPirep(2);
/** @var RemoveExpiredLiveFlights $eventListener */
$eventListener = app(RemoveExpiredLiveFlights::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNotNull($found_pirep);
}
/**
* Delete flights that are more than X hours old and still in progress (no updates)
*
* @throws \Exception
*/
public function testExpiredFlightShouldNotBeRemoved()
{
$this->updateSetting('acars.live_time', 3);
$pirep = $this->getPirep(2);
/** @var RemoveExpiredLiveFlights $eventListener */
$eventListener = app(RemoveExpiredLiveFlights::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNotNull($found_pirep);
}
/**
* Delete flights that are more than X hours old and still in progress (no updates)
*
* @throws \Exception
*/
public function testExpiredFlightShouldBeRemoved()
{
$this->updateSetting('acars.live_time', 3);
$pirep = $this->getPirep(4);
/** @var RemoveExpiredLiveFlights $eventListener */
$eventListener = app(RemoveExpiredLiveFlights::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNull($found_pirep);
}
/**
* Delete flights that are more than X hours old and still in progress (no updates)
*
* @throws \Exception
*/
public function testCompletedFlightsShouldNotBeDeleted()
{
$this->updateSetting('acars.live_time', 3);
$pirep = $this->getPirep(4);
// Make sure the state is accepted
$pirep->state = PirepState::ACCEPTED;
$pirep->save();
/** @var RemoveExpiredLiveFlights $eventListener */
$eventListener = app(RemoveExpiredLiveFlights::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNotNull($found_pirep);
}
/**
* Delete flights that are more than X hours old and have been rejected
*
* @throws \Exception
*/
public function testDeleteRejectedPireps()
{
$this->updateSetting('pireps.delete_rejected_hours', 3);
$pirep = $this->getPirep(4);
// Make sure the state is accepted
$pirep->state = PirepState::REJECTED;
$pirep->save();
/** @var DeletePireps $eventListener */
$eventListener = app(DeletePireps::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNotNull($found_pirep);
}
/**
* Delete flights that are more than X hours old and have been cancelled
*
* @throws \Exception
*/
public function testDeleteCancelledPireps()
{
$this->updateSetting('pireps.delete_cancelled_hours', 3);
$pirep = $this->getPirep(4);
// Make sure the state is accepted
$pirep->state = PirepState::CANCELLED;
$pirep->save();
/** @var DeletePireps $eventListener */
$eventListener = app(DeletePireps::class);
$eventListener->handle(new CronHourly());
$found_pirep = Pirep::find($pirep->id);
$this->assertNotNull($found_pirep);
}
}
+6 -6
View File
@@ -900,7 +900,7 @@ class FinanceTest extends TestCase
// $this->assertCount(9, $transactions['transactions']); // $this->assertCount(9, $transactions['transactions']);
$this->assertEquals(3020, $transactions['credits']->getValue()); $this->assertEquals(3020, $transactions['credits']->getValue());
$this->assertEquals(2040, $transactions['debits']->getValue()); $this->assertEquals(2050.0, $transactions['debits']->getValue());
// Check that all the different transaction types are there // Check that all the different transaction types are there
// test by the different groups that exist // test by the different groups that exist
@@ -910,7 +910,7 @@ class FinanceTest extends TestCase
'expense' => 1, 'expense' => 1,
'subfleet' => 2, 'subfleet' => 2,
'fare' => 3, 'fare' => 3,
'ground_handling' => 1, 'ground_handling' => 2,
'pilot_pay' => 2, // debit on the airline, credit to the pilot 'pilot_pay' => 2, // debit on the airline, credit to the pilot
]; ];
@@ -956,7 +956,7 @@ class FinanceTest extends TestCase
// $this->assertCount(9, $transactions['transactions']); // $this->assertCount(9, $transactions['transactions']);
$this->assertEquals(3020, $transactions['credits']->getValue()); $this->assertEquals(3020, $transactions['credits']->getValue());
$this->assertEquals(2040, $transactions['debits']->getValue()); $this->assertEquals(2050.0, $transactions['debits']->getValue());
// Check that all the different transaction types are there // Check that all the different transaction types are there
// test by the different groups that exist // test by the different groups that exist
@@ -966,7 +966,7 @@ class FinanceTest extends TestCase
'expense' => 1, 'expense' => 1,
'subfleet' => 2, 'subfleet' => 2,
'fare' => 3, 'fare' => 3,
'ground_handling' => 1, 'ground_handling' => 2,
'pilot_pay' => 2, // debit on the airline, credit to the pilot 'pilot_pay' => 2, // debit on the airline, credit to the pilot
]; ];
@@ -995,7 +995,7 @@ class FinanceTest extends TestCase
$transactions = $journalRepo->getAllForObject($pirep2); $transactions = $journalRepo->getAllForObject($pirep2);
$this->assertEquals(3020, $transactions['credits']->getValue()); $this->assertEquals(3020, $transactions['credits']->getValue());
$this->assertEquals(2140, $transactions['debits']->getValue()); $this->assertEquals(2150.0, $transactions['debits']->getValue());
// Check that all the different transaction types are there // Check that all the different transaction types are there
// test by the different groups that exist // test by the different groups that exist
@@ -1005,7 +1005,7 @@ class FinanceTest extends TestCase
'expense' => 2, 'expense' => 2,
'subfleet' => 2, 'subfleet' => 2,
'fare' => 3, 'fare' => 3,
'ground_handling' => 1, 'ground_handling' => 2,
'pilot_pay' => 2, // debit on the airline, credit to the pilot 'pilot_pay' => 2, // debit on the airline, credit to the pilot
]; ];
+11 -1
View File
@@ -472,7 +472,7 @@ class ImporterTest extends TestCase
$file_path = base_path('tests/data/flights.csv'); $file_path = base_path('tests/data/flights.csv');
$status = $this->importSvc->importFlights($file_path); $status = $this->importSvc->importFlights($file_path);
$this->assertCount(2, $status['success']); $this->assertCount(3, $status['success']);
$this->assertCount(1, $status['errors']); $this->assertCount(1, $status['errors']);
// See if it imported // See if it imported
@@ -531,6 +531,16 @@ class ImporterTest extends TestCase
// Check the subfleets // Check the subfleets
$subfleets = $flight->subfleets; $subfleets = $flight->subfleets;
$this->assertCount(1, $subfleets); $this->assertCount(1, $subfleets);
$this->assertNotEquals('A32X', $subfleets[0]->name);
$flight = Flight::where([
'airline_id' => $airline->id,
'flight_number' => '999',
])->first();
$subfleets = $flight->subfleets;
$this->assertCount(2, $subfleets);
$this->assertEquals('B737', $subfleets[1]->type);
$this->assertEquals('B737', $subfleets[1]->name);
} }
/** /**
+28
View File
@@ -178,6 +178,23 @@ class MetarTest extends TestCase
$this->assertEquals('38 km', $metar['visibility_report']); $this->assertEquals('38 km', $metar['visibility_report']);
} }
public function testLGKL()
{
$metar = 'LGKL 160320Z AUTO VRB02KT //// -RA ////// 07/04 Q1008 RE//';
$metar = Metar::parse($metar);
$this->assertEquals(2, $metar['wind_speed']['knots']);
$this->assertEquals('Light rain', $metar['present_weather_report']);
}
public function testLBBG()
{
$metar = 'LBBG 041600Z 12003MPS 310V290 1400 R04/1000D R22/P1500U +SN BKN022 OVC050 M04/M07 Q1020 NOSIG 9949//91=';
$metar = Metar::parse($metar);
$this->assertEquals('1000m and decreasing', $metar['runways_visual_range'][0]['report']);
}
public function testHttpCallSuccess() public function testHttpCallSuccess()
{ {
$this->mockXmlResponse('aviationweather/kjfk.xml'); $this->mockXmlResponse('aviationweather/kjfk.xml');
@@ -230,4 +247,15 @@ class MetarTest extends TestCase
$metar = $airportSvc->getMetar('7AK4'); $metar = $airportSvc->getMetar('7AK4');
$this->assertNull($metar); $this->assertNull($metar);
} }
public function testHttpCallNoResults()
{
$this->mockXmlResponse('aviationweather/no_results.xml');
/** @var AirportService $airportSvc */
$airportSvc = app(AirportService::class);
$metar = $airportSvc->getMetar('AYMR');
$this->assertNull($metar);
}
} }
+16 -11
View File
@@ -166,35 +166,41 @@ class PIREPTest extends TestCase
// Check that it has the fuel units // Check that it has the fuel units
$this->assertHasKeys($body['block_fuel'], ['lbs', 'kg']); $this->assertHasKeys($body['block_fuel'], ['lbs', 'kg']);
$this->assertEquals($pirep->block_fuel, $body['block_fuel']['lbs']); $this->assertEquals(round($pirep->block_fuel), round($body['block_fuel']['lbs']));
$this->assertHasKeys($body['fuel_used'], ['lbs', 'kg']); $this->assertHasKeys($body['fuel_used'], ['lbs', 'kg']);
$this->assertEquals($pirep->fuel_used, $body['fuel_used']['lbs']); $this->assertEquals(round($pirep->fuel_used), round($body['fuel_used']['lbs']));
// Check that it has the distance units // Check that it has the distance units
$this->assertHasKeys($body['distance'], ['km', 'nmi', 'mi']); $this->assertHasKeys($body['distance'], ['km', 'nmi', 'mi']);
$this->assertEquals($pirep->distance, $body['distance']['nmi']); $this->assertEquals(round($pirep->distance), round($body['distance']['nmi']));
// Check the planned_distance field // Check the planned_distance field
$this->assertHasKeys($body['planned_distance'], ['km', 'nmi', 'mi']); $this->assertHasKeys($body['planned_distance'], ['km', 'nmi', 'mi']);
$this->assertEquals($pirep->planned_distance, $body['planned_distance']['nmi']); $this->assertEquals(round($pirep->planned_distance), round($body['planned_distance']['nmi']));
//Check conversion on save //Check conversion on save
$val = random_int(1000, 9999999); $val = random_int(1000, 9999999);
$pirep->block_fuel = $val; $pirep->block_fuel = $val;
$pirep->fuel_used = $val; $pirep->fuel_used = $val;
// no conversion with plain numbers // no conversion with plain numbers
$this->assertEquals($pirep->block_fuel, $val); $this->assertEquals($pirep->block_fuel, $val);
$this->assertEquals($pirep->fuel_used, $val); $this->assertEquals($pirep->fuel_used, $val);
// no conversion with lbs // no conversion with lbs
$pirep->block_fuel = new Fuel($val, 'lbs'); $pirep->block_fuel = new Fuel($val, 'lbs');
$this->assertEquals($pirep->block_fuel, $val); $this->assertEquals(round($pirep->block_fuel), round($val));
$pirep->fuel_used = new Fuel($val, 'lbs'); $pirep->fuel_used = new Fuel($val, 'lbs');
$this->assertEquals($pirep->fuel_used, $val); $this->assertEquals(round($pirep->fuel_used), round($val));
// conversion of kg to lbs // conversion of kg to lbs
$pirep->block_fuel = new Fuel($val, 'kg'); $pirep->block_fuel = new Fuel($val, 'kg');
$this->assertEquals($pirep->block_fuel, (new Fuel($val, 'kg'))->toUnit('lbs')); $this->assertEquals(round($pirep->block_fuel), round((new Fuel($val, 'kg'))->toUnit('lbs')));
$pirep->fuel_used = new Fuel($val, 'kg'); $pirep->fuel_used = new Fuel($val, 'kg');
$this->assertEquals($pirep->fuel_used, (new Fuel($val, 'kg'))->toUnit('lbs')); $this->assertEquals(round($pirep->fuel_used), round((new Fuel($val, 'kg'))->toUnit('lbs')));
} }
public function testGetUserPireps() public function testGetUserPireps()
@@ -478,7 +484,7 @@ class PIREPTest extends TestCase
*/ */
$minutes = setting('pireps.duplicate_check_time') + 1; $minutes = setting('pireps.duplicate_check_time') + 1;
$pirep = factory(Pirep::class)->create([ $pirep = factory(Pirep::class)->create([
'created_at' => Carbon::now()->subMinutes($minutes)->toDateTimeString(), 'created_at' => Carbon::now('UTC')->subMinutes($minutes)->toDateTimeString(),
]); ]);
// This should find itself... // This should find itself...
@@ -522,7 +528,6 @@ class PIREPTest extends TestCase
{ {
$bidSvc = app(BidService::class); $bidSvc = app(BidService::class);
$flightSvc = app(FlightService::class); $flightSvc = app(FlightService::class);
$this->settingsRepo->store('pireps.remove_bid_on_accept', true);
$user = factory(User::class)->create([ $user = factory(User::class)->create([
'flight_time' => 0, 'flight_time' => 0,
@@ -543,7 +548,7 @@ class PIREPTest extends TestCase
]); ]);
$pirep = $this->pirepSvc->create($pirep, []); $pirep = $this->pirepSvc->create($pirep, []);
$this->pirepSvc->changeState($pirep, PirepState::ACCEPTED); $this->pirepSvc->submit($pirep);
$user_bid = Bid::where([ $user_bid = Bid::where([
'user_id' => $user->id, 'user_id' => $user->id,
+15 -6
View File
@@ -28,7 +28,7 @@ class SimBriefTest extends TestCase
*/ */
public function createUserData(array $attrs = []): array public function createUserData(array $attrs = []): array
{ {
$subfleet = $this->createSubfleetWithAircraft(1); $subfleet = $this->createSubfleetWithAircraft(2);
$rank = $this->createRank(2, [$subfleet['subfleet']->id]); $rank = $this->createRank(2, [$subfleet['subfleet']->id]);
/** @var User $user */ /** @var User $user */
@@ -141,7 +141,8 @@ class SimBriefTest extends TestCase
{ {
$userinfo = $this->createUserData(); $userinfo = $this->createUserData();
$this->user = $userinfo['user']; $this->user = $userinfo['user'];
$briefing = $this->loadSimBrief($this->user, $userinfo['aircraft']->first(), [ $aircraft = $userinfo['aircraft']->random();
$briefing = $this->loadSimBrief($this->user, $aircraft, [
[ [
'id' => 100, 'id' => 100,
'code' => 'F', 'code' => 'F',
@@ -196,22 +197,30 @@ class SimBriefTest extends TestCase
$userinfo = $this->createUserData(); $userinfo = $this->createUserData();
$this->user = $userinfo['user']; $this->user = $userinfo['user'];
$this->loadSimBrief($this->user, $userinfo['aircraft']->first(), $fares); $aircraft = $userinfo['aircraft']->random();
$this->loadSimBrief($this->user, $aircraft, $fares);
// Find the flight // Add the flight to the bid and then
$uri = '/api/user/bids'; $uri = '/api/user/bids';
$data = ['flight_id' => self::$simbrief_flight_id]; $data = ['flight_id' => self::$simbrief_flight_id];
$body = $this->put($uri, $data); $this->put($uri, $data);
$body = $body->json('data');
// Retrieve it
$body = $this->get($uri);
$body = $body->json('data')[0];
// Make sure Simbrief is there // Make sure Simbrief is there
$this->assertNotNull($body['flight']['simbrief']['id']); $this->assertNotNull($body['flight']['simbrief']['id']);
$this->assertNotNull($body['flight']['simbrief']['id']);
$this->assertNotNull($body['flight']['simbrief']['subfleet']['fares']); $this->assertNotNull($body['flight']['simbrief']['subfleet']['fares']);
$subfleet = $body['flight']['simbrief']['subfleet']; $subfleet = $body['flight']['simbrief']['subfleet'];
$this->assertEquals($fares[0]['id'], $subfleet['fares'][0]['id']); $this->assertEquals($fares[0]['id'], $subfleet['fares'][0]['id']);
$this->assertEquals($fares[0]['count'], $subfleet['fares'][0]['count']); $this->assertEquals($fares[0]['count'], $subfleet['fares'][0]['count']);
$this->assertCount(1, $subfleet['aircraft']);
$this->assertEquals($aircraft->id, $subfleet['aircraft'][0]['id']);
} }
/** /**
+10
View File
@@ -88,6 +88,16 @@ abstract class TestCase extends \Illuminate\Foundation\Testing\TestCase
}); });
} }
/**
* @param $mocks
*/
protected function addMocks($mocks)
{
$handler = HandlerStack::create($mocks);
$client = new Client(['handler' => $handler]);
$this->client->httpClient = $client;
}
/** /**
* @param $user * @param $user
* @param array $headers * @param array $headers
+13
View File
@@ -6,6 +6,7 @@ use App\Models\Aircraft;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\Flight; use App\Models\Flight;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\Role;
use App\Models\Subfleet; use App\Models\Subfleet;
use App\Models\User; use App\Models\User;
use Exception; use Exception;
@@ -154,4 +155,16 @@ trait TestData
'aircraft' => $aircraft, 'aircraft' => $aircraft,
]; ];
} }
/**
* Create a role
*
* @param array $attrs Additional role attributes
*
* @return Role
*/
public function createRole(array $attrs = []): Role
{
return factory(Role::class)->create($attrs);
}
} }
+14
View File
@@ -370,5 +370,19 @@ class UserTest extends TestCase
$users_on_leave = $this->userSvc->findUsersOnLeave(); $users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(0, count($users_on_leave)); $this->assertEquals(0, count($users_on_leave));
// Check disable_activity_checks
$user = $this->createUser([
'status' => UserState::ACTIVE,
'created_at' => Carbon::now('UTC')->subDays(5),
]);
$role = $this->createRole([
'disable_activity_checks' => true,
]);
$user->attachRole($role);
$user->save();
$users_on_leave = $this->userSvc->findUsersOnLeave();
$this->assertEquals(0, count($users_on_leave));
} }
} }
@@ -0,0 +1,9 @@
<response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://www.aviationweather.gov/static/adds/schema/metar1_2.xsd">
<request_index>414399629</request_index>
<data_source name="metars"/>
<request type="retrieve"/>
<errors/>
<warnings/>
<time_taken_ms>5</time_taken_ms>
<data num_results="0"/>
</response>

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