Allow setting percent for fare overrides against base fare #125

This commit is contained in:
Nabeel Shahzad 2018-02-23 15:12:09 -06:00
parent dd144cc9bc
commit d5aef6fb87
7 changed files with 276 additions and 75 deletions

View File

@ -36,9 +36,9 @@ class CreateSubfleetTables extends Migration
Schema::create('subfleet_fare', function (Blueprint $table) { Schema::create('subfleet_fare', function (Blueprint $table) {
$table->unsignedInteger('subfleet_id'); $table->unsignedInteger('subfleet_id');
$table->unsignedInteger('fare_id'); $table->unsignedInteger('fare_id');
$table->unsignedDecimal('price')->nullable(); $table->string('price')->nullable();
$table->unsignedDecimal('cost')->nullable(); $table->string('cost')->nullable();
$table->unsignedInteger('capacity')->nullable(); $table->string('capacity')->nullable();
$table->timestamps(); $table->timestamps();
$table->primary(['subfleet_id', 'fare_id']); $table->primary(['subfleet_id', 'fare_id']);

View File

@ -5,9 +5,44 @@ namespace App\Services;
use App\Models\Fare; use App\Models\Fare;
use App\Models\Flight; use App\Models\Flight;
use App\Models\Subfleet; use App\Models\Subfleet;
use App\Support\Math;
class FareService extends BaseService class FareService extends BaseService
{ {
/**
* Get fares
* @param $fare
* @return mixed
*/
protected function getFares($fare)
{
if (filled($fare->pivot->price)) {
if (substr_count($fare->pivot->price, '%', -1)) {
$fare->price = Math::addPercent($fare->price, $fare->pivot->price);
} else {
$fare->price = $fare->pivot->price;
}
}
if (filled($fare->pivot->cost)) {
if (substr_count($fare->pivot->cost, '%', -1)) {
$fare->cost = Math::addPercent($fare->cost, $fare->pivot->cost);
} else {
$fare->cost = $fare->pivot->cost;
}
}
if (filled($fare->pivot->capacity)) {
if (substr_count($fare->pivot->capacity, '%', -1)) {
$fare->capacity = Math::addPercent($fare->capacity, $fare->pivot->capacity);
} else {
$fare->capacity = $fare->pivot->capacity;
}
}
return $fare;
}
/** /**
* Attach a fare to an flight * Attach a fare to an flight
* *
@ -40,19 +75,7 @@ class FareService extends BaseService
public function getForFlight(Flight $flight) public function getForFlight(Flight $flight)
{ {
$fares = $flight->fares->map(function ($fare) { $fares = $flight->fares->map(function ($fare) {
if (null !== $fare->pivot->price) { return $this->getFares($fare);
$fare->price = $fare->pivot->price;
}
if (null !== $fare->pivot->cost) {
$fare->cost = $fare->pivot->cost;
}
if (null !== $fare->pivot->capacity) {
$fare->capacity = $fare->pivot->capacity;
}
return $fare;
}); });
return $fares; return $fares;
@ -102,19 +125,7 @@ class FareService extends BaseService
public function getForSubfleet(Subfleet $subfleet) public function getForSubfleet(Subfleet $subfleet)
{ {
$fares = $subfleet->fares->map(function($fare) { $fares = $subfleet->fares->map(function($fare) {
if(!is_null($fare->pivot->price)) { return $this->getFares($fare);
$fare->price = $fare->pivot->price;
}
if(!is_null($fare->pivot->cost)) {
$fare->cost = $fare->pivot->cost;
}
if(!is_null($fare->pivot->capacity)) {
$fare->capacity = $fare->pivot->capacity;
}
return $fare;
}); });
return $fares; return $fares;

32
app/Support/Math.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace App\Support;
/**
* Helper math
* @package App\Support
*/
class Math
{
/**
* Add/subtract a percentage to a number
* @param $number
* @param $percent
* @return float
*/
public static function addPercent($number, $percent): float
{
if(!is_numeric($number)) {
$number = (float) $number;
}
if(!is_numeric($percent)) {
$percent = (float) $percent;
}
return $number + ($number * ($percent/100));
}
}

View File

@ -35,7 +35,8 @@
"joshbrw/laravel-module-installer": "0.1.x", "joshbrw/laravel-module-installer": "0.1.x",
"irazasyed/laravel-gamp": "1.3.x", "irazasyed/laravel-gamp": "1.3.x",
"vierbergenlars/php-semver": "3.0.x", "vierbergenlars/php-semver": "3.0.x",
"php-units-of-measure/php-units-of-measure": "2.1.x" "php-units-of-measure/php-units-of-measure": "2.1.x",
"markrogoyski/math-php": "^0.38.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~7.0", "phpunit/phpunit": "~7.0",

105
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "e7d8d8ba45af9c9112ed11327aca1c5f", "content-hash": "873311d78a79fd569567c865d174e4ab",
"packages": [ "packages": [
{ {
"name": "arrilot/laravel-widgets", "name": "arrilot/laravel-widgets",
@ -1740,7 +1740,7 @@
"geometry", "geometry",
"geotools" "geotools"
], ],
"time": "2018-02-10T13:29:13+00:00" "time": "2018-02-10 13:29:13"
}, },
{ {
"name": "league/iso3166", "name": "league/iso3166",
@ -1796,6 +1796,71 @@
], ],
"time": "2018-01-02T06:45:36+00:00" "time": "2018-01-02T06:45:36+00:00"
}, },
{
"name": "markrogoyski/math-php",
"version": "v0.38.0",
"source": {
"type": "git",
"url": "https://github.com/markrogoyski/math-php.git",
"reference": "0a5b2d4084c35cebbdd0ce8c51716bb65b2c4790"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/markrogoyski/math-php/zipball/0a5b2d4084c35cebbdd0ce8c51716bb65b2c4790",
"reference": "0a5b2d4084c35cebbdd0ce8c51716bb65b2c4790",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "5.*",
"satooshi/php-coveralls": "dev-master",
"squizlabs/php_codesniffer": "2.*"
},
"type": "library",
"autoload": {
"psr-4": {
"MathPHP\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Rogoyski",
"email": "mark@rogoyski.com",
"homepage": "https://github.com/markrogoyski",
"role": "Developer"
},
{
"name": "Kevin Nowaczyk",
"role": "Contributor"
},
{
"name": "Jakob Sandberg",
"role": "Contributor"
}
],
"description": "Math Library for PHP. Features descriptive statistics and regressions; Continuous and discrete probability distributions; Linear algebra with matrices and vectors, Numerical analysis; special mathematical functions; Algebra",
"homepage": "https://github.com/markrogoyski/math-php/",
"keywords": [
"algebra",
"combinatorics",
"distributions",
"linear algebra",
"math",
"mathematics",
"matrix",
"numerical analysis",
"probability",
"regressions",
"statistics"
],
"time": "2017-12-11T05:05:12+00:00"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "1.23.0", "version": "1.23.0",
@ -2110,7 +2175,7 @@
"lib/random.php" "lib/random.php"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -2225,7 +2290,7 @@
"Http\\Client\\": "src/" "Http\\Client\\": "src/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -2276,7 +2341,7 @@
"Http\\Promise\\": "src/" "Http\\Promise\\": "src/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -2649,7 +2714,7 @@
"Prettus\\Validator\\": "src/Prettus/Validator/" "Prettus\\Validator\\": "src/Prettus/Validator/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"authors": [ "authors": [
{ {
"name": "Anderson Andrade", "name": "Anderson Andrade",
@ -2738,7 +2803,7 @@
"Psr\\Container\\": "src/" "Psr\\Container\\": "src/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -2884,7 +2949,7 @@
"Psr\\SimpleCache\\": "src/" "Psr\\SimpleCache\\": "src/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -3293,7 +3358,7 @@
"lib/swift_required.php" "lib/swift_required.php"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -5241,7 +5306,7 @@
"Faker\\": "src/Faker/" "Faker\\": "src/Faker/"
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -5593,7 +5658,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -5640,7 +5705,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -5697,7 +5762,7 @@
] ]
} }
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@ -6460,7 +6525,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6512,7 +6577,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6580,7 +6645,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6630,7 +6695,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6675,7 +6740,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6720,7 +6785,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],
@ -6909,7 +6974,7 @@
"src/" "src/"
] ]
}, },
"notification-url": "http://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"BSD-3-Clause" "BSD-3-Clause"
], ],

View File

@ -1,25 +1,28 @@
<?php <?php
use App\Services\FareService;
use App\Support\Math;
class FinanceTest extends TestCase class FinanceTest extends TestCase
{ {
protected $ac_svc, protected $ac_svc,
$ICAO = 'B777'; $ICAO = 'B777',
$fareSvc;
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$this->addData('base'); $this->addData('base');
$this->fareSvc = app(FareService::class);
} }
public function testFlightFaresNoOverride() public function testFlightFaresNoOverride()
{ {
$fare_svc = app('App\Services\FareService');
$flight = factory(App\Models\Flight::class)->create(); $flight = factory(App\Models\Flight::class)->create();
$fare = factory(App\Models\Fare::class)->create(); $fare = factory(App\Models\Fare::class)->create();
$fare_svc->setForFlight($flight, $fare); $this->fareSvc->setForFlight($flight, $fare);
$subfleet_fares = $fare_svc->getForFlight($flight); $subfleet_fares = $this->fareSvc->getForFlight($flight);
$this->assertCount(1, $subfleet_fares); $this->assertCount(1, $subfleet_fares);
$this->assertEquals($fare->price, $subfleet_fares->get(0)->price); $this->assertEquals($fare->price, $subfleet_fares->get(0)->price);
@ -28,31 +31,59 @@ class FinanceTest extends TestCase
# #
# set an override now # set an override now
# #
$fare_svc->setForFlight($flight, $fare, [ $this->fareSvc->setForFlight($flight, $fare, [
'price' => 50, 'capacity' => 400 'price' => 50, 'capacity' => 400
]); ]);
# look for them again # look for them again
$subfleet_fares = $fare_svc->getForFlight($flight); $subfleet_fares = $this->fareSvc->getForFlight($flight);
$this->assertCount(1, $subfleet_fares); $this->assertCount(1, $subfleet_fares);
$this->assertEquals(50, $subfleet_fares[0]->price); $this->assertEquals(50, $subfleet_fares[0]->price);
$this->assertEquals(400, $subfleet_fares[0]->capacity); $this->assertEquals(400, $subfleet_fares[0]->capacity);
# delete # delete
$fare_svc->delFareFromFlight($flight, $fare); $this->fareSvc->delFareFromFlight($flight, $fare);
$this->assertCount(0, $fare_svc->getForFlight($flight)); $this->assertCount(0, $this->fareSvc->getForFlight($flight));
}
/**
* Assign percentage values and make sure they're valid
*/
public function testFlightFareOverrideAsPercent()
{
$flight = factory(App\Models\Flight::class)->create();
$fare = factory(App\Models\Fare::class)->create();
$percent_incr = '20%';
$percent_decr = '-20%';
$percent_200 = '200%';
$new_price = Math::addPercent($fare->price, $percent_incr);
$new_cost = Math::addPercent($fare->cost, $percent_decr);
$new_capacity = Math::addPercent($fare->capacity, $percent_200);
$this->fareSvc->setForFlight($flight, $fare, [
'price' => $percent_incr,
'cost' => $percent_decr,
'capacity' => $percent_200,
]);
$ac_fares = $this->fareSvc->getForFlight($flight);
$this->assertCount(1, $ac_fares);
$this->assertEquals($new_price, $ac_fares[0]->price);
$this->assertEquals($new_cost, $ac_fares[0]->cost);
$this->assertEquals($new_capacity, $ac_fares[0]->capacity);
} }
public function testSubfleetFaresNoOverride() public function testSubfleetFaresNoOverride()
{ {
$fare_svc = app('App\Services\FareService');
$subfleet = factory(App\Models\Subfleet::class)->create(); $subfleet = factory(App\Models\Subfleet::class)->create();
$fare = factory(App\Models\Fare::class)->create(); $fare = factory(App\Models\Fare::class)->create();
$fare_svc->setForSubfleet($subfleet, $fare); $this->fareSvc->setForSubfleet($subfleet, $fare);
$subfleet_fares = $fare_svc->getForSubfleet($subfleet); $subfleet_fares = $this->fareSvc->getForSubfleet($subfleet);
$this->assertCount(1, $subfleet_fares); $this->assertCount(1, $subfleet_fares);
$this->assertEquals($fare->price, $subfleet_fares->get(0)->price); $this->assertEquals($fare->price, $subfleet_fares->get(0)->price);
@ -61,34 +92,32 @@ class FinanceTest extends TestCase
# #
# set an override now # set an override now
# #
$fare_svc->setForSubfleet($subfleet, $fare, [ $this->fareSvc->setForSubfleet($subfleet, $fare, [
'price' => 50, 'capacity' => 400 'price' => 50, 'capacity' => 400
]); ]);
# look for them again # look for them again
$subfleet_fares = $fare_svc->getForSubfleet($subfleet); $subfleet_fares = $this->fareSvc->getForSubfleet($subfleet);
$this->assertCount(1, $subfleet_fares); $this->assertCount(1, $subfleet_fares);
$this->assertEquals(50, $subfleet_fares[0]->price); $this->assertEquals(50, $subfleet_fares[0]->price);
$this->assertEquals(400, $subfleet_fares[0]->capacity); $this->assertEquals(400, $subfleet_fares[0]->capacity);
# delete # delete
$fare_svc->delFareFromSubfleet($subfleet, $fare); $this->fareSvc->delFareFromSubfleet($subfleet, $fare);
$this->assertCount(0, $fare_svc->getForSubfleet($subfleet)); $this->assertCount(0, $this->fareSvc->getForSubfleet($subfleet));
} }
public function testSubfleetFaresOverride() public function testSubfleetFaresOverride()
{ {
$fare_svc = app('App\Services\FareService');
$subfleet = factory(App\Models\Subfleet::class)->create(); $subfleet = factory(App\Models\Subfleet::class)->create();
$fare = factory(App\Models\Fare::class)->create(); $fare = factory(App\Models\Fare::class)->create();
$fare_svc->setForSubfleet($subfleet, $fare, [ $this->fareSvc->setForSubfleet($subfleet, $fare, [
'price' => 50, 'capacity' => 400 'price' => 50, 'capacity' => 400
]); ]);
$ac_fares = $fare_svc->getForSubfleet($subfleet); $ac_fares = $this->fareSvc->getForSubfleet($subfleet);
$this->assertCount(1, $ac_fares); $this->assertCount(1, $ac_fares);
$this->assertEquals(50, $ac_fares[0]->price); $this->assertEquals(50, $ac_fares[0]->price);
@ -98,18 +127,48 @@ class FinanceTest extends TestCase
# update the override to a different amount and make sure it updates # update the override to a different amount and make sure it updates
# #
$fare_svc->setForSubfleet($subfleet, $fare, [ $this->fareSvc->setForSubfleet($subfleet, $fare, [
'price' => 150, 'capacity' => 50 'price' => 150, 'capacity' => 50
]); ]);
$ac_fares = $fare_svc->getForSubfleet($subfleet); $ac_fares = $this->fareSvc->getForSubfleet($subfleet);
$this->assertCount(1, $ac_fares); $this->assertCount(1, $ac_fares);
$this->assertEquals(150, $ac_fares[0]->price); $this->assertEquals(150, $ac_fares[0]->price);
$this->assertEquals(50, $ac_fares[0]->capacity); $this->assertEquals(50, $ac_fares[0]->capacity);
# delete # delete
$fare_svc->delFareFromSubfleet($subfleet, $fare); $this->fareSvc->delFareFromSubfleet($subfleet, $fare);
$this->assertCount(0, $fare_svc->getForSubfleet($subfleet)); $this->assertCount(0, $this->fareSvc->getForSubfleet($subfleet));
}
/**
* Assign percentage values and make sure they're valid
*/
public function testSubfleetFareOverrideAsPercent()
{
$subfleet = factory(App\Models\Subfleet::class)->create();
$fare = factory(App\Models\Fare::class)->create();
$percent_incr = '20%';
$percent_decr = '-20%';
$percent_200 = '200%';
$new_price = Math::addPercent($fare->price, $percent_incr);
$new_cost = Math::addPercent($fare->cost, $percent_decr);
$new_capacity = Math::addPercent($fare->capacity, $percent_200);
$this->fareSvc->setForSubfleet($subfleet, $fare, [
'price' => $percent_incr,
'cost' => $percent_decr,
'capacity' => $percent_200,
]);
$ac_fares = $this->fareSvc->getForSubfleet($subfleet);
$this->assertCount(1, $ac_fares);
$this->assertEquals($new_price, $ac_fares[0]->price);
$this->assertEquals($new_cost, $ac_fares[0]->cost);
$this->assertEquals($new_capacity, $ac_fares[0]->capacity);
} }
} }

33
tests/MathTest.php Normal file
View File

@ -0,0 +1,33 @@
<?php
use App\Support\Math;
class MathTest extends TestCase
{
public function setUp() {
}
/**
* Test adding/subtracting a percentage
*/
public function testAddPercent()
{
$tests = [
['expected' => 112, 'fn' => Math::addPercent(100, 12)],
['expected' => 112, 'fn' => Math::addPercent(100, '12')],
['expected' => 112, 'fn' => Math::addPercent(100, '12%')],
['expected' => 112, 'fn' => Math::addPercent(100, '12 %')],
['expected' => 112, 'fn' => Math::addPercent('100 ', '12')],
['expected' => 112.5, 'fn' => Math::addPercent('100', '12.5')],
['expected' => 88, 'fn' => Math::addPercent('100', -12)],
['expected' => 88, 'fn' => Math::addPercent('100', '-12')],
['expected' => 88, 'fn' => Math::addPercent('100', '-12 %')],
['expected' => 88, 'fn' => Math::addPercent('100', '-12%')],
];
foreach($tests as $test) {
$this->assertEquals($test['expected'], $test['fn']);
}
}
}