* Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting
This commit is contained in:
95
app/Console/Commands/CreateConfigs.php
Normal file
95
app/Console/Commands/CreateConfigs.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App;
|
||||
use App\Contracts\Command;
|
||||
use App\Services\Installer\SeederService;
|
||||
use DatabaseSeeder;
|
||||
use Modules\Installer\Services\ConfigService;
|
||||
|
||||
/**
|
||||
* Create the config files
|
||||
*/
|
||||
class CreateConfigs extends Command
|
||||
{
|
||||
protected $signature = 'phpvms:config {db_host} {db_name} {db_user} {db_pass}';
|
||||
protected $description = 'Create the config files';
|
||||
|
||||
private $databaseSeeder;
|
||||
private $seederSvc;
|
||||
|
||||
public function __construct(DatabaseSeeder $databaseSeeder, SeederService $seederSvc)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->databaseSeeder = $databaseSeeder;
|
||||
$this->seederSvc = $seederSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run dev related commands
|
||||
*
|
||||
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->writeConfigs();
|
||||
|
||||
// Reload the configuration
|
||||
App::boot();
|
||||
|
||||
$this->info('Recreating database');
|
||||
$this->call('database:create', [
|
||||
'--reset' => true,
|
||||
]);
|
||||
|
||||
$this->info('Running migrations');
|
||||
$this->call('migrate:fresh', [
|
||||
'--seed' => true,
|
||||
]);
|
||||
|
||||
$this->seederSvc->syncAllSeeds();
|
||||
|
||||
$this->info('Done!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite the configuration files
|
||||
*
|
||||
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
|
||||
*/
|
||||
protected function writeConfigs()
|
||||
{
|
||||
/** @var ConfigService $cfgSvc */
|
||||
$cfgSvc = app(ConfigService::class);
|
||||
|
||||
$this->info('Removing the old config files');
|
||||
|
||||
// Remove the old files
|
||||
$config_file = base_path('config.php');
|
||||
if (file_exists($config_file)) {
|
||||
unlink($config_file);
|
||||
}
|
||||
|
||||
$env_file = base_path('env.php');
|
||||
if (file_exists($env_file)) {
|
||||
unlink($env_file);
|
||||
}
|
||||
|
||||
//{name} {db_host} {db_name} {db_user} {db_pass}
|
||||
|
||||
$this->info('Regenerating the config files');
|
||||
$cfgSvc->createConfigFiles([
|
||||
'APP_ENV' => 'dev',
|
||||
'SITE_NAME' => $this->argument('name'),
|
||||
'DB_CONN' => 'mysql',
|
||||
'DB_HOST' => $this->argument('db_host'),
|
||||
'DB_NAME' => $this->argument('db_name'),
|
||||
'DB_USER' => $this->argument('db_user'),
|
||||
'DB_PASS' => $this->argument('db_pass'),
|
||||
]);
|
||||
|
||||
$this->info('Config files generated!');
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Console\Services\Database;
|
||||
use App\Contracts\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Tivie\OS\Detector;
|
||||
|
||||
class CreateDatabase extends Command
|
||||
{
|
||||
protected $signature = 'database:create {--reset} {--conn=?}';
|
||||
protected $signature = 'database:create {--reset} {--migrate} {--conn=?}';
|
||||
protected $description = 'Create a database';
|
||||
protected $os;
|
||||
|
||||
@@ -36,8 +37,7 @@ class CreateDatabase extends Command
|
||||
$user = config($dbkey.'username');
|
||||
$pass = config($dbkey.'password');
|
||||
|
||||
$dbSvc = new \App\Console\Services\Database();
|
||||
|
||||
$dbSvc = new Database();
|
||||
$dsn = $dbSvc->createDsn($host, $port);
|
||||
Log::info('Connection string: '.$dsn);
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Contracts\Command;
|
||||
|
||||
class ImportFromClassic extends Command
|
||||
{
|
||||
protected $signature = 'phpvms:importer {db_host} {db_name} {db_user} {db_pass?} {table_prefix=phpvms_}';
|
||||
protected $description = 'Import from an older version of phpVMS';
|
||||
|
||||
/**
|
||||
* Run dev related commands
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$db_creds = [
|
||||
'host' => $this->argument('db_host'),
|
||||
'name' => $this->argument('db_name'),
|
||||
'user' => $this->argument('db_user'),
|
||||
'pass' => $this->argument('db_pass'),
|
||||
'table_prefix' => $this->argument('table_prefix'),
|
||||
];
|
||||
|
||||
$importerSvc = new \App\Console\Services\Importer($db_creds);
|
||||
$importerSvc->run();
|
||||
}
|
||||
}
|
||||
@@ -1,704 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Services;
|
||||
|
||||
use App\Facades\Utils;
|
||||
use App\Models\Aircraft;
|
||||
use App\Models\Airline;
|
||||
use App\Models\Airport;
|
||||
use App\Models\Enums\FlightType;
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Enums\UserState;
|
||||
use App\Models\Flight;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\Rank;
|
||||
use App\Models\Subfleet;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
/**
|
||||
* Class Importer
|
||||
* TODO: Batch import
|
||||
*/
|
||||
class Importer
|
||||
{
|
||||
/**
|
||||
* Hold references
|
||||
*/
|
||||
private $mappedEntities = [];
|
||||
|
||||
/**
|
||||
* Hold the PDO connection to the old database
|
||||
*
|
||||
* @var
|
||||
*/
|
||||
private $conn;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $creds;
|
||||
|
||||
/**
|
||||
* Hold the instance of the console logger
|
||||
*
|
||||
* @var
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* CONSTANTS
|
||||
*/
|
||||
public const BATCH_READ_ROWS = 300;
|
||||
public const SUBFLEET_NAME = 'Imported Aircraft';
|
||||
|
||||
/**
|
||||
* Importer constructor.
|
||||
*
|
||||
* @param $db_creds
|
||||
*/
|
||||
public function __construct($db_creds)
|
||||
{
|
||||
// Setup the logger
|
||||
$this->log = new ConsoleOutput();
|
||||
|
||||
// The db credentials
|
||||
$this->creds = array_merge([
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 3306,
|
||||
'name' => '',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'table_prefix' => '',
|
||||
], $db_creds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->reconnect();
|
||||
|
||||
// Import all the different parts
|
||||
$this->importRanks();
|
||||
$this->importAirlines();
|
||||
$this->importAircraft();
|
||||
$this->importAirports();
|
||||
|
||||
$this->importUsers();
|
||||
$this->importFlights();
|
||||
$this->importPireps();
|
||||
|
||||
// Finish up
|
||||
$this->findLastPireps();
|
||||
$this->recalculateRanks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnect to the old phpVMS DB using PDO
|
||||
*/
|
||||
protected function reconnect()
|
||||
{
|
||||
$dsn = 'mysql:'.implode(';', [
|
||||
'host='.$this->creds['host'],
|
||||
'port='.$this->creds['port'],
|
||||
'dbname='.$this->creds['name'],
|
||||
]);
|
||||
|
||||
$this->info('Connection string: '.$dsn);
|
||||
|
||||
try {
|
||||
$this->conn = new PDO($dsn, $this->creds['user'], $this->creds['pass']);
|
||||
$this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
|
||||
} catch (\PDOException $e) {
|
||||
$this->error($e);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
*/
|
||||
protected function comment($message)
|
||||
{
|
||||
$this->log->writeln('<comment>'.$message.'</comment>');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
*/
|
||||
protected function error($message)
|
||||
{
|
||||
$this->log->writeln('<error>'.$message.'</error>');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $message
|
||||
*/
|
||||
protected function info($message)
|
||||
{
|
||||
if (\is_array($message)) {
|
||||
/* @noinspection ForgottenDebugOutputInspection */
|
||||
print_r($message);
|
||||
} else {
|
||||
$this->log->writeln('<info>'.$message.'</info>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table name with the prefix
|
||||
*
|
||||
* @param $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function tableName($table)
|
||||
{
|
||||
if ($this->creds['table_prefix'] !== false) {
|
||||
return $this->creds['table_prefix'].$table;
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function saveModel($model)
|
||||
{
|
||||
try {
|
||||
$model->save();
|
||||
|
||||
return true;
|
||||
} catch (QueryException $e) {
|
||||
if ($e->getCode() !== '23000') {
|
||||
$this->error($e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new mapping between an old ID and the new one
|
||||
*
|
||||
* @param $entity
|
||||
* @param $old_id
|
||||
* @param $new_id
|
||||
*/
|
||||
protected function addMapping($entity, $old_id, $new_id)
|
||||
{
|
||||
if (!array_key_exists($entity, $this->mappedEntities)) {
|
||||
$this->mappedEntities[$entity] = [];
|
||||
}
|
||||
|
||||
$this->mappedEntities[$entity][$old_id] = $new_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ID for a mapping
|
||||
*
|
||||
* @param $entity
|
||||
* @param $old_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function getMapping($entity, $old_id)
|
||||
{
|
||||
if (!array_key_exists($entity, $this->mappedEntities)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$entity = $this->mappedEntities[$entity];
|
||||
if (array_key_exists($old_id, $entity)) {
|
||||
return $entity[$old_id];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $date
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
protected function parseDate($date)
|
||||
{
|
||||
$carbon = Carbon::parse($date);
|
||||
|
||||
return $carbon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a decimal duration and convert it to minutes
|
||||
*
|
||||
* @param $duration
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
protected function convertDuration($duration)
|
||||
{
|
||||
if (strpos($duration, '.') !== false) {
|
||||
$delim = '.';
|
||||
} elseif (strpos($duration, ':')) {
|
||||
$delim = ':';
|
||||
} else {
|
||||
// no delimiter, assume it's just a straight hour
|
||||
return (int) $duration * 60;
|
||||
}
|
||||
|
||||
$hm = explode($delim, $duration);
|
||||
$hours = (int) $hm[0] * 60;
|
||||
$mins = (int) $hm[1];
|
||||
|
||||
return $hours + $mins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getTotalRows($table)
|
||||
{
|
||||
$table = $this->tableName($table);
|
||||
|
||||
$sql = 'SELECT COUNT(*) FROM '.$table;
|
||||
$rows = $this->conn->query($sql)->fetchColumn();
|
||||
|
||||
$this->info('Found '.$rows.' rows in '.$table);
|
||||
|
||||
return (int) $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the rows in a table, but read them in a batched manner
|
||||
*
|
||||
* @param string $table The name of the table
|
||||
* @param null $read_rows Number of rows to read
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function readRows($table, $read_rows = null)
|
||||
{
|
||||
// Set the table prefix if it has been entered
|
||||
$this->tableName($table);
|
||||
|
||||
$offset = 0;
|
||||
if ($read_rows === null) {
|
||||
$read_rows = self::BATCH_READ_ROWS;
|
||||
}
|
||||
|
||||
$total_rows = $this->getTotalRows($table);
|
||||
|
||||
while ($offset < $total_rows) {
|
||||
$rows_to_read = $offset + $read_rows;
|
||||
if ($rows_to_read > $total_rows) {
|
||||
$rows_to_read = $total_rows;
|
||||
}
|
||||
|
||||
$this->info('Reading '.$offset.' to '.$rows_to_read.' of '.$total_rows);
|
||||
|
||||
$sql = 'SELECT * FROM '.$this->tableName($table)
|
||||
.' LIMIT '.self::BATCH_READ_ROWS.' OFFSET '.$offset;
|
||||
|
||||
try {
|
||||
foreach ($this->conn->query($sql) as $row) {
|
||||
yield $row;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// Without incrementing the offset, it should re-run the same query
|
||||
$this->error($e);
|
||||
|
||||
if (strpos($e->getMessage(), 'server has gone away') !== false) {
|
||||
$this->reconnect();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$offset += self::BATCH_READ_ROWS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subfleet
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getSubfleet()
|
||||
{
|
||||
$airline = Airline::first();
|
||||
$subfleet = Subfleet::firstOrCreate(
|
||||
['airline_id' => $airline->id, 'name' => self::SUBFLEET_NAME],
|
||||
['type' => 'PHPVMS']
|
||||
);
|
||||
|
||||
return $subfleet;
|
||||
}
|
||||
|
||||
/**
|
||||
* All the individual importers, done on a per-table basis
|
||||
* Some tables get saved locally for tables that use FK refs
|
||||
*/
|
||||
|
||||
/**
|
||||
* Import all of the ranks
|
||||
*/
|
||||
protected function importRanks()
|
||||
{
|
||||
$this->comment('--- RANK IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('ranks') as $row) {
|
||||
$rank = Rank::firstOrCreate(
|
||||
['name' => $row->rank],
|
||||
['image_url' => $row->rankimage, 'hours' => $row->minhours]
|
||||
);
|
||||
|
||||
$this->addMapping('ranks', $row->rankid, $rank->id);
|
||||
$this->addMapping('ranks', $row->rank, $rank->id);
|
||||
|
||||
if ($rank->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' ranks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all of the airlines. Save them all in the private var $airlines
|
||||
* They're used to lookup from other reference tables
|
||||
*/
|
||||
protected function importAirlines()
|
||||
{
|
||||
$this->comment('--- AIRLINE IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('airlines') as $row) {
|
||||
$airline = Airline::firstOrCreate(
|
||||
['icao' => $row->code],
|
||||
['iata' => $row->code, 'name' => $row->name, 'active' => $row->enabled]
|
||||
);
|
||||
|
||||
$this->addMapping('airlines', $row->id, $airline->id);
|
||||
$this->addMapping('airlines', $row->code, $airline->id);
|
||||
|
||||
if ($airline->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' airlines');
|
||||
}
|
||||
|
||||
/**
|
||||
* Imported the aircraft
|
||||
*/
|
||||
protected function importAircraft()
|
||||
{
|
||||
$this->comment('--- AIRCRAFT IMPORT ---');
|
||||
|
||||
$subfleet = $this->getSubfleet();
|
||||
|
||||
$this->info('Subfleet ID is '.$subfleet->id);
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('aircraft') as $row) {
|
||||
$aircraft = Aircraft::firstOrCreate(
|
||||
['name' => $row->fullname, 'registration' => $row->registration],
|
||||
['icao' => $row->icao,
|
||||
'subfleet_id' => $subfleet->id,
|
||||
'active' => $row->enabled,
|
||||
]
|
||||
);
|
||||
|
||||
$this->addMapping('aircraft', $row->id, $aircraft->id);
|
||||
|
||||
if ($aircraft->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' aircraft');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all of the airports
|
||||
*/
|
||||
protected function importAirports()
|
||||
{
|
||||
$this->comment('--- AIRPORT IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('airports') as $row) {
|
||||
$attrs = [
|
||||
'id' => trim($row->icao),
|
||||
'icao' => trim($row->icao),
|
||||
'name' => $row->name,
|
||||
'country' => $row->country,
|
||||
'lat' => $row->lat,
|
||||
'lon' => $row->lng,
|
||||
'hub' => $row->hub,
|
||||
];
|
||||
|
||||
$airport = Airport::updateOrCreate(
|
||||
['id' => $attrs['id']],
|
||||
$attrs
|
||||
);
|
||||
|
||||
if ($airport->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' airports');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the flights and schedules
|
||||
*/
|
||||
protected function importFlights()
|
||||
{
|
||||
$this->comment('--- FLIGHT SCHEDULE IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('schedules') as $row) {
|
||||
$airline_id = $this->getMapping('airlines', $row->code);
|
||||
|
||||
$flight_num = trim($row->flightnum);
|
||||
|
||||
$attrs = [
|
||||
'dpt_airport_id' => $row->depicao,
|
||||
'arr_airport_id' => $row->arricao,
|
||||
'route' => $row->route ?: '',
|
||||
'distance' => round($row->distance ?: 0, 2),
|
||||
'level' => $row->flightlevel ?: 0,
|
||||
'dpt_time' => $row->deptime ?: '',
|
||||
'arr_time' => $row->arrtime ?: '',
|
||||
'flight_time' => $this->convertDuration($row->flighttime) ?: '',
|
||||
'notes' => $row->notes ?: '',
|
||||
'active' => $row->enabled ?: true,
|
||||
];
|
||||
|
||||
try {
|
||||
$flight = Flight::updateOrCreate(
|
||||
['airline_id' => $airline_id, 'flight_number' => $flight_num],
|
||||
$attrs
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
//$this->error($e);
|
||||
}
|
||||
|
||||
$this->addMapping('flights', $row->id, $flight->id);
|
||||
|
||||
// TODO: deserialize route_details into ACARS table
|
||||
|
||||
if ($flight->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' flights');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import all of the PIREPs
|
||||
*/
|
||||
protected function importPireps()
|
||||
{
|
||||
$this->comment('--- PIREP IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('pireps') as $row) {
|
||||
$pirep_id = $row->pirepid;
|
||||
$user_id = $this->getMapping('users', $row->pilotid);
|
||||
$airline_id = $this->getMapping('airlines', $row->code);
|
||||
$aircraft_id = $this->getMapping('aircraft', $row->aircraft);
|
||||
|
||||
$attrs = [
|
||||
//'id' => $pirep_id,
|
||||
'user_id' => $user_id,
|
||||
'airline_id' => $airline_id,
|
||||
'aircraft_id' => $aircraft_id,
|
||||
'flight_number' => $row->flightnum ?: '',
|
||||
'dpt_airport_id' => $row->depicao,
|
||||
'arr_airport_id' => $row->arricao,
|
||||
'block_fuel' => $row->fuelused,
|
||||
'route' => $row->route ?: '',
|
||||
'source_name' => $row->source,
|
||||
'created_at' => $this->parseDate($row->submitdate),
|
||||
'updated_at' => $this->parseDate($row->modifieddate),
|
||||
];
|
||||
|
||||
// Set the distance
|
||||
$distance = round($row->distance ?: 0, 2);
|
||||
$attrs['distance'] = $distance;
|
||||
$attrs['planned_distance'] = $distance;
|
||||
|
||||
// Set the flight time properly
|
||||
$duration = $this->convertDuration($row->flighttime_stamp);
|
||||
$attrs['flight_time'] = $duration;
|
||||
$attrs['planned_flight_time'] = $duration;
|
||||
|
||||
// Set how it was filed
|
||||
if (strtoupper($row->source) === 'MANUAL') {
|
||||
$attrs['source'] = PirepSource::MANUAL;
|
||||
} else {
|
||||
$attrs['source'] = PirepSource::ACARS;
|
||||
}
|
||||
|
||||
// Set the flight type
|
||||
$row->flighttype = strtoupper($row->flighttype);
|
||||
if ($row->flighttype === 'P') {
|
||||
$attrs['flight_type'] = FlightType::SCHED_PAX;
|
||||
} elseif ($row->flighttype === 'C') {
|
||||
$attrs['flight_type'] = FlightType::SCHED_CARGO;
|
||||
} else {
|
||||
$attrs['flight_type'] = FlightType::CHARTER_PAX_ONLY;
|
||||
}
|
||||
|
||||
// Set the flight level of the PIREP is set
|
||||
if (property_exists($row, 'flightlevel')) {
|
||||
$attrs['level'] = $row->flightlevel;
|
||||
} else {
|
||||
$attrs['level'] = 0;
|
||||
}
|
||||
|
||||
$pirep = Pirep::updateOrCreate(
|
||||
['id' => $pirep_id],
|
||||
$attrs
|
||||
);
|
||||
|
||||
$source = strtoupper($row->source);
|
||||
if ($source === 'SMARTCARS') {
|
||||
// TODO: Parse smartcars log into the acars table
|
||||
} elseif ($source === 'KACARS') {
|
||||
// TODO: Parse kACARS log into acars table
|
||||
} elseif ($source === 'XACARS') {
|
||||
// TODO: Parse XACARS log into acars table
|
||||
}
|
||||
|
||||
// TODO: Add extra fields in as PIREP fields
|
||||
$this->addMapping('pireps', $row->pirepid, $pirep->id);
|
||||
|
||||
if ($pirep->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' pireps');
|
||||
}
|
||||
|
||||
protected function importUsers()
|
||||
{
|
||||
$this->comment('--- USER IMPORT ---');
|
||||
|
||||
$count = 0;
|
||||
foreach ($this->readRows('pilots', 50) as $row) {
|
||||
// TODO: What to do about pilot ids
|
||||
|
||||
$name = $row->firstname.' '.$row->lastname;
|
||||
|
||||
$airline_id = $this->getMapping('airlines', $row->code);
|
||||
$rank_id = $this->getMapping('ranks', $row->rank);
|
||||
$state = $this->getUserState($row->retired);
|
||||
|
||||
$new_password = Str::random(60);
|
||||
|
||||
$attrs = [
|
||||
'name' => $name,
|
||||
'password' => Hash::make($new_password),
|
||||
'api_key' => Utils::generateApiKey(),
|
||||
'airline_id' => $airline_id,
|
||||
'rank_id' => $rank_id,
|
||||
'home_airport_id' => $row->hub,
|
||||
'curr_airport_id' => $row->hub,
|
||||
'flights' => (int) $row->totalflights,
|
||||
'flight_time' => Utils::hoursToMinutes($row->totalhours),
|
||||
'state' => $state,
|
||||
'created_at' => $this->parseDate($row->joindate),
|
||||
];
|
||||
|
||||
$user = User::updateOrCreate(
|
||||
['email' => $row->email],
|
||||
$attrs
|
||||
);
|
||||
|
||||
$this->addMapping('users', $row->pilotid, $user->id);
|
||||
|
||||
if ($user->wasRecentlyCreated) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Imported '.$count.' users');
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through and set the last PIREP ID for the users
|
||||
*/
|
||||
protected function findLastPireps()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate all of the user ranks
|
||||
*/
|
||||
protected function recalculateRanks()
|
||||
{
|
||||
/*$this->comment('--- RECALCULATING RANKS ---');*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's new state from their original state
|
||||
*
|
||||
* @param $state
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getUserState($state)
|
||||
{
|
||||
// TODO: This state might differ between simpilot and classic version
|
||||
|
||||
$state = (int) $state;
|
||||
|
||||
// Declare array of classic states
|
||||
$phpvms_classic_states = [
|
||||
'ACTIVE' => 0,
|
||||
'INACTIVE' => 1,
|
||||
'BANNED' => 2,
|
||||
'ON_LEAVE' => 3,
|
||||
];
|
||||
|
||||
// Decide which state they will be in accordance with v7
|
||||
if ($state === $phpvms_classic_states['ACTIVE']) {
|
||||
return UserState::ACTIVE;
|
||||
}
|
||||
|
||||
if ($state === $phpvms_classic_states['INACTIVE']) {
|
||||
// TODO: Make an inactive state?
|
||||
return UserState::REJECTED;
|
||||
}
|
||||
|
||||
if ($state === $phpvms_classic_states['BANNED']) {
|
||||
return UserState::SUSPENDED;
|
||||
}
|
||||
|
||||
if ($state === $phpvms_classic_states['ON_LEAVE']) {
|
||||
return UserState::ON_LEAVE;
|
||||
}
|
||||
|
||||
$this->error('Unknown status: '.$state);
|
||||
return UserState::ACTIVE;
|
||||
}
|
||||
}
|
||||
11
app/Contracts/Middleware.php
Normal file
11
app/Contracts/Middleware.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Contracts;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
interface Middleware
|
||||
{
|
||||
public function handle(Request $request, Closure $next);
|
||||
}
|
||||
@@ -3,12 +3,13 @@
|
||||
namespace App\Contracts;
|
||||
|
||||
/**
|
||||
* Class Model
|
||||
*
|
||||
* @property mixed $id
|
||||
* @property bool $skip_mutator
|
||||
*
|
||||
* @method static where(array $array)
|
||||
* @method static Model find(int $airline_id)
|
||||
* @method static Model where(array $array)
|
||||
* @method static Model updateOrCreate(array $array, array $attrs)
|
||||
* @method static truncate()
|
||||
*/
|
||||
abstract class Model extends \Illuminate\Database\Eloquent\Model
|
||||
{
|
||||
|
||||
@@ -28,28 +28,6 @@ class UsersAddPilotId extends Migration
|
||||
|
||||
// Migrate the current pilot IDs
|
||||
DB::update('UPDATE `users` SET `pilot_id`=`id`');
|
||||
|
||||
// Drop the old ID column and add a new one
|
||||
/*Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropPrimary('users_id_primary');
|
||||
$table->dropColumn('id');
|
||||
$table->string('id', Model::ID_MAX_LENGTH)->primary();
|
||||
});
|
||||
|
||||
// Update the users to use the `pilot_id` (so we don't need to migrate data from other tables)
|
||||
$users = DB::table('users')->get(['id']);
|
||||
foreach ($users as $user) {
|
||||
$user->id = $user->pilot_id;
|
||||
$user->save();
|
||||
}*/
|
||||
|
||||
// role_user
|
||||
// permission_user
|
||||
// sessions
|
||||
// pireps
|
||||
// bids
|
||||
// news
|
||||
// user_awards
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# All of the different permissions that can be assigned to roles
|
||||
---
|
||||
- name: admin-access
|
||||
display_name: Admin Access
|
||||
display_name: Administrator
|
||||
description: Access the admin panel
|
||||
- name: airlines
|
||||
display_name: Airlines
|
||||
|
||||
@@ -79,7 +79,8 @@ class DashboardController extends Controller
|
||||
$this->checkNewVersion();
|
||||
|
||||
return view('admin.dashboard.index', [
|
||||
'news' => $this->newsRepo->getLatest(),
|
||||
'news' => $this->newsRepo->getLatest(),
|
||||
// 'installer_enabled' => $installerEnabled,
|
||||
'pending_pireps' => $this->pirepRepo->getPendingCount(),
|
||||
'pending_users' => $this->userRepo->getPendingCount(),
|
||||
]);
|
||||
|
||||
@@ -7,29 +7,33 @@ use App\Http\Requests\CreateRoleRequest;
|
||||
use App\Http\Requests\UpdateRoleRequest;
|
||||
use App\Repositories\PermissionsRepository;
|
||||
use App\Repositories\RoleRepository;
|
||||
use Flash;
|
||||
use App\Services\RoleService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Laracasts\Flash\Flash;
|
||||
use Prettus\Repository\Criteria\RequestCriteria;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
* Class AirlinesController
|
||||
*/
|
||||
class RolesController extends Controller
|
||||
{
|
||||
private $permsRepo;
|
||||
private $rolesRepo;
|
||||
private $roleSvc;
|
||||
|
||||
/**
|
||||
* AirlinesController constructor.
|
||||
*
|
||||
* @param PermissionsRepository $permsRepo
|
||||
* @param RoleRepository $rolesRepo
|
||||
* @param $roleSvc
|
||||
*/
|
||||
public function __construct(PermissionsRepository $permsRepo, RoleRepository $rolesRepo)
|
||||
{
|
||||
public function __construct(
|
||||
PermissionsRepository $permsRepo,
|
||||
RoleRepository $rolesRepo,
|
||||
RoleService $roleSvc
|
||||
) {
|
||||
$this->permsRepo = $permsRepo;
|
||||
$this->rolesRepo = $rolesRepo;
|
||||
$this->roleSvc = $roleSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,8 +136,6 @@ class RolesController extends Controller
|
||||
* @param int $id
|
||||
* @param UpdateRoleRequest $request
|
||||
*
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function update($id, UpdateRoleRequest $request)
|
||||
@@ -145,14 +147,8 @@ class RolesController extends Controller
|
||||
return redirect(route('admin.roles.index'));
|
||||
}
|
||||
|
||||
$this->rolesRepo->update($request->all(), $id);
|
||||
|
||||
// Update the permissions, filter out null/invalid values
|
||||
$perms = collect($request->permissions)->filter(static function ($v, $k) {
|
||||
return $v;
|
||||
});
|
||||
|
||||
$role->permissions()->sync($perms);
|
||||
$this->roleSvc->updateRole($role, $request->all());
|
||||
$this->roleSvc->setPermissionsForRole($role, $request->permissions);
|
||||
|
||||
Flash::success('Roles updated successfully.');
|
||||
return redirect(route('admin.roles.index'));
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use App\Models\Enums\UserState;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ApiAuth
|
||||
class ApiAuth implements Middleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
@@ -20,7 +22,7 @@ class ApiAuth
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// Check if Authorization header is in place
|
||||
$api_key = $request->header('x-api-key', null);
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
|
||||
|
||||
class EncryptCookies extends BaseEncrypter
|
||||
class EncryptCookies extends BaseEncrypter implements Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the cookies that should not be encrypted.
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InstalledCheck
|
||||
/**
|
||||
* Check the app.key to see whether we're installed or not
|
||||
*
|
||||
* If the default key is set and we're not in any of the installer routes
|
||||
* show the message that we need to be installed
|
||||
*/
|
||||
class InstalledCheck implements Middleware
|
||||
{
|
||||
/**
|
||||
* Check the app.key to see whether we're installed or not
|
||||
*
|
||||
* If the default key is set and we're not in any of the installer routes
|
||||
* show the message that we need to be installed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (config('app.key') === 'base64:zdgcDqu9PM8uGWCtMxd74ZqdGJIrnw812oRMmwDF6KY='
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class JsonResponse
|
||||
class JsonResponse implements Middleware
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
$response->headers->set('Content-Type', 'application/json');
|
||||
|
||||
@@ -5,19 +5,13 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MeasureExecutionTime
|
||||
class MeasureExecutionTime implements Middleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// Get the response
|
||||
$response = $next($request);
|
||||
|
||||
@@ -2,21 +2,14 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
class RedirectIfAuthenticated implements Middleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
public function handle(Request $request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect('/');
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Closure;
|
||||
use Igaster\LaravelTheme\Facades\Theme;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Read the current theme from the settings (set in admin), and set it
|
||||
*/
|
||||
class SetActiveTheme
|
||||
class SetActiveTheme implements Middleware
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$theme = setting('general.theme');
|
||||
if (!empty($theme)) {
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use App\Services\Installer\InstallerService;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Determine if an update is pending by checking in with the Installer service
|
||||
*/
|
||||
class UpdatePending
|
||||
class UpdatePending implements Middleware
|
||||
{
|
||||
private $installerSvc;
|
||||
|
||||
@@ -17,13 +19,7 @@ class UpdatePending
|
||||
$this->installerSvc = $installerSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->installerSvc->isUpgradePending()) {
|
||||
return redirect('/update/step1');
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Contracts\Middleware;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
|
||||
|
||||
class VerifyCsrfToken extends BaseVerifier
|
||||
class VerifyCsrfToken extends BaseVerifier implements Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
|
||||
@@ -4,6 +4,9 @@ namespace App\Models;
|
||||
|
||||
use Laratrust\Models\LaratrustPermission;
|
||||
|
||||
/**
|
||||
* @method static firstOrCreate(array $array, array $array1)
|
||||
*/
|
||||
class Permission extends LaratrustPermission
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ use Laratrust\Models\LaratrustRole;
|
||||
|
||||
/**
|
||||
* @method static where(string $string, $group)
|
||||
* @method static firstOrCreate(array $array, array $array1)
|
||||
* @method static truncate()
|
||||
*/
|
||||
class Role extends LaratrustRole
|
||||
{
|
||||
|
||||
@@ -34,6 +34,10 @@ use Laratrust\Traits\LaratrustUserTrait;
|
||||
* @property int state
|
||||
* @property bool opt_in
|
||||
* @property string last_pirep_id
|
||||
*
|
||||
* @method static updateOrCreate(array $array, array $attrs)
|
||||
* @method static where()
|
||||
* @method static truncate()
|
||||
* @mixin \Illuminate\Notifications\Notifiable
|
||||
* @mixin \Laratrust\Traits\LaratrustUserTrait
|
||||
*/
|
||||
|
||||
@@ -26,8 +26,8 @@ use App\Models\User;
|
||||
use App\Repositories\SettingRepository;
|
||||
use App\Services\ModuleService;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use View;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
@@ -11,17 +11,16 @@ use App\Models\Pirep;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
use App\Repositories\JournalRepository;
|
||||
use App\Services\FareService;
|
||||
use App\Services\FinanceService;
|
||||
use App\Support\Math;
|
||||
use App\Support\Money;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class FinanceService
|
||||
*/
|
||||
class PirepFinanceService extends Service
|
||||
{
|
||||
private $expenseRepo;
|
||||
private $fareSvc;
|
||||
private $financeSvc;
|
||||
private $journalRepo;
|
||||
|
||||
/**
|
||||
@@ -30,15 +29,18 @@ class PirepFinanceService extends Service
|
||||
* @param ExpenseRepository $expenseRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param JournalRepository $journalRepo
|
||||
* @param FinanceService $financeSvc
|
||||
*/
|
||||
public function __construct(
|
||||
ExpenseRepository $expenseRepo,
|
||||
FareService $fareSvc,
|
||||
FinanceService $financeSvc,
|
||||
JournalRepository $journalRepo
|
||||
) {
|
||||
$this->expenseRepo = $expenseRepo;
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->journalRepo = $journalRepo;
|
||||
$this->financeSvc = $financeSvc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,13 +151,11 @@ class PirepFinanceService extends Service
|
||||
Log::info('Finance: Fuel cost, (fuel='.$fuel_used.', cost='.$ap->fuel_jeta_cost.') D='
|
||||
.$debit->getAmount());
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
null,
|
||||
$debit,
|
||||
$pirep,
|
||||
'Fuel Cost ('.$ap->fuel_jeta_cost.'/'.config('phpvms.internal_units.fuel').')',
|
||||
null,
|
||||
'Fuel',
|
||||
'fuel'
|
||||
);
|
||||
@@ -194,13 +194,11 @@ class PirepFinanceService extends Service
|
||||
$debit = Money::createFromAmount($cost_per_min * $block_time);
|
||||
Log::info('Finance: Subfleet Block Hourly, D='.$debit->getAmount());
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
null,
|
||||
$debit,
|
||||
$pirep,
|
||||
'Subfleet '.$sf->type.': Block Time Cost',
|
||||
null,
|
||||
'Subfleet '.$sf->type,
|
||||
'subfleet'
|
||||
);
|
||||
@@ -265,13 +263,11 @@ class PirepFinanceService extends Service
|
||||
$journal = $pirep->user->journal;
|
||||
}
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$journal,
|
||||
null,
|
||||
$debit,
|
||||
$pirep,
|
||||
$memo,
|
||||
null,
|
||||
$transaction_group,
|
||||
strtolower($klass)
|
||||
);
|
||||
@@ -320,13 +316,11 @@ class PirepFinanceService extends Service
|
||||
|
||||
$debit = Money::createFromAmount($expense->amount);
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
null,
|
||||
$debit,
|
||||
$pirep,
|
||||
'Expense: '.$expense->name,
|
||||
null,
|
||||
$expense->transaction_group ?? 'Expenses',
|
||||
'expense'
|
||||
);
|
||||
@@ -347,13 +341,12 @@ class PirepFinanceService extends Service
|
||||
{
|
||||
$ground_handling_cost = $this->getGroundHandlingCost($pirep);
|
||||
Log::info('Finance: PIREP: '.$pirep->id.'; ground handling: '.$ground_handling_cost);
|
||||
$this->journalRepo->post(
|
||||
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
null,
|
||||
Money::createFromAmount($ground_handling_cost),
|
||||
$pirep,
|
||||
'Ground Handling',
|
||||
null,
|
||||
'Ground Handling',
|
||||
'ground_handling'
|
||||
);
|
||||
@@ -378,24 +371,20 @@ class PirepFinanceService extends Service
|
||||
Log::info('Finance: PIREP: '.$pirep->id
|
||||
.'; pilot pay: '.$pilot_pay_rate.', total: '.$pilot_pay);
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$pirep->airline->journal,
|
||||
null,
|
||||
$pilot_pay,
|
||||
$pirep,
|
||||
$memo,
|
||||
null,
|
||||
'Pilot Pay',
|
||||
'pilot_pay'
|
||||
);
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->creditToJournal(
|
||||
$pirep->user->journal,
|
||||
$pilot_pay,
|
||||
null,
|
||||
$pirep,
|
||||
$memo,
|
||||
null,
|
||||
'Pilot Pay',
|
||||
'pilot_pay'
|
||||
);
|
||||
|
||||
@@ -8,23 +8,22 @@ use App\Models\Enums\ExpenseType;
|
||||
use App\Models\Expense;
|
||||
use App\Models\JournalTransaction;
|
||||
use App\Repositories\JournalRepository;
|
||||
use App\Services\FinanceService;
|
||||
use App\Support\Money;
|
||||
use Log;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Process all of the daily expenses and charge them
|
||||
*/
|
||||
class RecurringFinanceService extends Service
|
||||
{
|
||||
private $financeSvc;
|
||||
private $journalRepo;
|
||||
|
||||
/**
|
||||
* RecurringFinanceService constructor.
|
||||
*
|
||||
* @param JournalRepository $journalRepo
|
||||
*/
|
||||
public function __construct(JournalRepository $journalRepo)
|
||||
public function __construct(JournalRepository $journalRepo, FinanceService $financeSvc)
|
||||
{
|
||||
$this->financeSvc = $financeSvc;
|
||||
$this->journalRepo = $journalRepo;
|
||||
}
|
||||
|
||||
@@ -87,10 +86,8 @@ class RecurringFinanceService extends Service
|
||||
/**
|
||||
* Run all of the daily expense/financials
|
||||
*
|
||||
* @param int $type
|
||||
* @param string $type
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*/
|
||||
public function processExpenses($type = ExpenseType::DAILY): void
|
||||
@@ -101,7 +98,7 @@ class RecurringFinanceService extends Service
|
||||
if ($type === ExpenseType::DAILY) {
|
||||
$tag = 'expenses_daily';
|
||||
} elseif ($type === ExpenseType::MONTHLY) {
|
||||
$tag === 'expenses_monthly';
|
||||
$tag = 'expenses_monthly';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +119,7 @@ class RecurringFinanceService extends Service
|
||||
];
|
||||
|
||||
$found = JournalTransaction::where($w)
|
||||
->whereDate('post_date', '=', \Carbon::now('UTC')->toDateString())
|
||||
->whereDate('post_date', '=', Carbon::now('UTC')->toDateString())
|
||||
->count(['id']);
|
||||
|
||||
if ($found > 0) {
|
||||
@@ -132,13 +129,11 @@ class RecurringFinanceService extends Service
|
||||
|
||||
[$memo, $ta_group] = $this->getMemoAndGroup($expense);
|
||||
|
||||
$this->journalRepo->post(
|
||||
$this->financeSvc->debitFromJournal(
|
||||
$journal,
|
||||
null,
|
||||
Money::createFromAmount($amount),
|
||||
$expense,
|
||||
$memo,
|
||||
null,
|
||||
$ta_group,
|
||||
$tag
|
||||
);
|
||||
|
||||
@@ -4,11 +4,93 @@ namespace App\Services;
|
||||
|
||||
use App\Contracts\Service;
|
||||
use App\Models\Airline;
|
||||
use App\Models\Journal;
|
||||
use App\Models\JournalTransaction;
|
||||
use App\Repositories\JournalRepository;
|
||||
use App\Support\Money;
|
||||
|
||||
class FinanceService extends Service
|
||||
{
|
||||
private $journalRepo;
|
||||
|
||||
public function __construct(JournalRepository $journalRepo)
|
||||
{
|
||||
$this->journalRepo = $journalRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Credit some amount to a given journal
|
||||
* E.g, some amount for expenses or ground handling fees, etc. Example, to pay a user a dollar
|
||||
* for a pirep:
|
||||
*
|
||||
* creditToJournal($user->journal, new Money(1000), $pirep, 'Payment', 'pirep', 'payment');
|
||||
*
|
||||
* @param \App\Models\Journal $journal
|
||||
* @param Money $amount
|
||||
* @param \Illuminate\Database\Eloquent\Model $reference
|
||||
* @param string $memo
|
||||
* @param string $transaction_group
|
||||
* @param string|array $tag
|
||||
*
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function creditToJournal(
|
||||
Journal $journal,
|
||||
Money $amount,
|
||||
$reference,
|
||||
$memo,
|
||||
$transaction_group,
|
||||
$tag
|
||||
) {
|
||||
return $this->journalRepo->post(
|
||||
$journal,
|
||||
$amount,
|
||||
null,
|
||||
$reference,
|
||||
$memo,
|
||||
null,
|
||||
$transaction_group,
|
||||
$tag
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge some expense for a given PIREP to the airline its file against
|
||||
* E.g, some amount for expenses or ground handling fees, etc.
|
||||
*
|
||||
* @param \App\Models\Journal $journal
|
||||
* @param Money $amount
|
||||
* @param \Illuminate\Database\Eloquent\Model $reference
|
||||
* @param string $memo
|
||||
* @param string $transaction_group
|
||||
* @param string|array $tag
|
||||
*
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function debitFromJournal(
|
||||
Journal $journal,
|
||||
Money $amount,
|
||||
$reference,
|
||||
$memo,
|
||||
$transaction_group,
|
||||
$tag
|
||||
) {
|
||||
return $this->journalRepo->post(
|
||||
$journal,
|
||||
null,
|
||||
$amount,
|
||||
$reference,
|
||||
$memo,
|
||||
null,
|
||||
$transaction_group,
|
||||
$tag
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the transactions for an airline between two given dates. Returns an array
|
||||
* with `credits`, `debits` and `transactions` fields, where transactions contains the
|
||||
|
||||
@@ -236,6 +236,15 @@ class SeederService extends Service
|
||||
return true;
|
||||
}
|
||||
|
||||
// See if any of these column values have changed
|
||||
foreach (['name', 'description'] as $column) {
|
||||
$currVal = $row->{$column};
|
||||
$newVal = $setting[$column];
|
||||
if ($currVal !== $newVal) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// See if any of the options have changed
|
||||
if ($row->type === 'select') {
|
||||
if ($row->options !== $setting['options']) {
|
||||
@@ -259,10 +268,20 @@ class SeederService extends Service
|
||||
$yml = Yaml::parse($data);
|
||||
|
||||
foreach ($yml as $perm) {
|
||||
$count = DB::table('permissions')->where('name', $perm['name'])->count('name');
|
||||
if ($count === 0) {
|
||||
$row = DB::table('permissions')
|
||||
->where('name', $perm['name'])
|
||||
->first();
|
||||
|
||||
if (!$row) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// See if any of these column values have changed
|
||||
foreach (['display_name', 'description'] as $column) {
|
||||
if ($row->{$column} !== $perm[$column]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
47
app/Services/RoleService.php
Normal file
47
app/Services/RoleService.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Contracts\Service;
|
||||
use App\Models\Role;
|
||||
use App\Repositories\RoleRepository;
|
||||
|
||||
class RoleService extends Service
|
||||
{
|
||||
private $roleRepo;
|
||||
|
||||
public function __construct(RoleRepository $roleRepo)
|
||||
{
|
||||
$this->roleRepo = $roleRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a role with the given attributes
|
||||
*
|
||||
* @param Role $role
|
||||
* @param array $attrs
|
||||
*
|
||||
* @return Role
|
||||
*/
|
||||
public function updateRole(Role $role, array $attrs)
|
||||
{
|
||||
$role->update($attrs);
|
||||
$role->save();
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Role $role
|
||||
* @param array $permissions
|
||||
*/
|
||||
public function setPermissionsForRole(Role $role, array $permissions)
|
||||
{
|
||||
// Update the permissions, filter out null/invalid values
|
||||
$perms = collect($permissions)->filter(static function ($v, $k) {
|
||||
return $v;
|
||||
});
|
||||
|
||||
$role->permissions()->sync($perms);
|
||||
}
|
||||
}
|
||||
@@ -48,14 +48,14 @@ class UserService extends Service
|
||||
* Register a pilot. Also attaches the initial roles
|
||||
* required, and then triggers the UserRegistered event
|
||||
*
|
||||
* @param User $user User model
|
||||
* @param array $groups Additional groups to assign
|
||||
* @param User $user User model
|
||||
* @param array $roles List of "display_name" of groups to assign
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function createUser(User $user, array $groups = null)
|
||||
public function createUser(User $user, array $roles = null)
|
||||
{
|
||||
// Determine if we want to auto accept
|
||||
if (setting('pilots.auto_accept') === true) {
|
||||
@@ -66,15 +66,10 @@ class UserService extends Service
|
||||
|
||||
$user->save();
|
||||
|
||||
// Attach the user roles
|
||||
// $role = Role::where('name', 'user')->first();
|
||||
// $user->attachRole($role);
|
||||
|
||||
// Attach any additional roles
|
||||
if (!empty($groups) && is_array($groups)) {
|
||||
foreach ($groups as $group) {
|
||||
$role = Role::where('name', $group)->first();
|
||||
$user->attachRole($role);
|
||||
if (!empty($roles) && is_array($roles)) {
|
||||
foreach ($roles as $role) {
|
||||
$this->addUserToRole($user, $role);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +82,32 @@ class UserService extends Service
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a user to a given role
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $roleName
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function addUserToRole(User $user, $roleName): User
|
||||
{
|
||||
$role = Role::where('name', $roleName)->first();
|
||||
$user->attachRole($role);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return the next available pilot ID (usually just the max+1)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNextAvailablePilotId(): int
|
||||
{
|
||||
return (int) User::max('pilot_id') + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the next available pilot ID and set the current user's pilot_id to that +1
|
||||
* Called from UserObserver right now after a record is created
|
||||
@@ -101,8 +122,7 @@ class UserService extends Service
|
||||
return $user;
|
||||
}
|
||||
|
||||
$max = (int) User::max('pilot_id');
|
||||
$user->pilot_id = $max + 1;
|
||||
$user->pilot_id = $this->getNextAvailablePilotId();
|
||||
$user->save();
|
||||
|
||||
Log::info('Set pilot ID for user '.$user->id.' to '.$user->pilot_id);
|
||||
@@ -348,8 +368,8 @@ class UserService extends Service
|
||||
'state' => PirepState::ACCEPTED,
|
||||
];
|
||||
|
||||
$flight_count = Pirep::where($w)->count();
|
||||
$user->flights = $flight_count;
|
||||
$pirep_count = Pirep::where($w)->count();
|
||||
$user->flights = $pirep_count;
|
||||
|
||||
$flight_time = Pirep::where($w)->sum('flight_time');
|
||||
$user->flight_time = $flight_time;
|
||||
@@ -359,7 +379,7 @@ class UserService extends Service
|
||||
// Recalc the rank
|
||||
$this->calculatePilotRank($user);
|
||||
|
||||
Log::info('User '.$user->ident.' updated; flight count='.$flight_count
|
||||
Log::info('User '.$user->ident.' updated; pirep count='.$pirep_count
|
||||
.', rank='.$user->rank->name
|
||||
.', flight_time='.$user->flight_time.' minutes');
|
||||
|
||||
|
||||
27
app/Support/Utils.php
Normal file
27
app/Support/Utils.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
use Nwidart\Modules\Facades\Module;
|
||||
|
||||
/**
|
||||
* Global utilities
|
||||
*/
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* Is the installer enabled?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function installerEnabled()
|
||||
{
|
||||
/** @var \Nwidart\Modules\Module $installer */
|
||||
$installer = Module::find('installer');
|
||||
if (!$installer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $installer->isEnabled();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user