Skip to content

Commit

Permalink
add usps girth calculator, improve asendia validation, add few tests,…
Browse files Browse the repository at this point in the history
… add dimensions model
  • Loading branch information
moriony committed Nov 11, 2015
1 parent 6c7fa71 commit 5f6dbd0
Show file tree
Hide file tree
Showing 18 changed files with 725 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/Calculator/AbstractCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,5 @@ protected function createResult()
* @param PackageInterface $package
* @return int|float|string
*/
abstract protected function visit(CalculationResultInterface $result, PackageInterface $package);
abstract public function visit(CalculationResultInterface $result, PackageInterface $package);
}
260 changes: 226 additions & 34 deletions src/Calculator/Asendia/Tariff.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
namespace EsteIt\ShippingCalculator\Calculator\Asendia;

use EsteIt\ShippingCalculator\Exception\InvalidConfigurationException;
use EsteIt\ShippingCalculator\Exception\InvalidDimensionsException;
use EsteIt\ShippingCalculator\Exception\InvalidRecipientAddressException;
use EsteIt\ShippingCalculator\Exception\InvalidSenderAddressException;
use EsteIt\ShippingCalculator\Exception\InvalidArgumentException;
use EsteIt\ShippingCalculator\Exception\InvalidWeightException;
use EsteIt\ShippingCalculator\Model\AddressInterface;
use EsteIt\ShippingCalculator\Model\DimensionsInterface;
use EsteIt\ShippingCalculator\Model\PackageInterface;
use Moriony\Trivial\Converter\LengthConverter;
use Moriony\Trivial\Converter\UnitConverterInterface;
use Moriony\Trivial\Converter\WeightConverter;
use Moriony\Trivial\Math\MathInterface;
Expand Down Expand Up @@ -44,6 +50,14 @@ class Tariff
* @var UnitConverterInterface
*/
protected $weightConverter;
/**
* @var UnitConverterInterface
*/
protected $lengthConverter;
/**
* @var UspsGirthCalculator
*/
protected $girthCalculator;
/**
* @var string
*/
Expand All @@ -52,6 +66,18 @@ class Tariff
* @var string
*/
protected $currency;
/**
* @var string
*/
protected $dimensionsUnit;
/**
* @var string
*/
protected $sideLengthLimit;
/**
* @var string
*/
protected $girthLimit;

/**
* Tariff constructor.
Expand All @@ -60,9 +86,98 @@ public function __construct()
{
$this->senderCountries = ['USA'];
$this->recipientCountries = [];
$this->priceGroups = [];
$this->currency = 'USD';
}

/**
* @param PackageInterface $package
* @return mixed
*/
public function calculate(PackageInterface $package)
{
$this->validateSenderAddress($package->getSenderAddress());
$this->validateRecipientAddress($package->getRecipientAddress());
$this->validateDimensions($package->getDimensions());
$this->validateWeight($package);

$priceGroup = $this->getPriceGroup($package);

$weight = $package->getWeight();
$weight = $this->getWeightConverter()->convert($weight->getValue(), $weight->getUnit(), $this->getMassUnit());

$math = $this->getMath();
$cost = $priceGroup->getPrice($weight);
$wholeWeight = $math->roundDown($weight);
$fuelCost = $math->mul($wholeWeight, $this->getFuelSubcharge());
$total = $math->sum($cost, $fuelCost);
$total = $math->roundUp($total, 2);
$result = number_format($total, 2, '.', '');

return $result;
}

/**
* @param AddressInterface $address
*/
public function validateSenderAddress(AddressInterface $address)
{
$isValidSenderCountry = in_array($address->getCountryCode(), $this->senderCountries);
if (!$isValidSenderCountry) {
throw new InvalidSenderAddressException('Can not send a package from this country.');
}
}

/**
* @param AddressInterface $address
*/
public function validateRecipientAddress(AddressInterface $address)
{
try {
$recipientCountry = $this->getRecipientCountry($address->getCountryCode());
} catch (InvalidArgumentException $e) {
throw new InvalidRecipientAddressException('Can not send a package to this country.');
}

if (!array_key_exists($recipientCountry->getPriceGroup(), $this->priceGroups)) {
throw new InvalidRecipientAddressException('Can not send a package to this country.');
}
}

/**
* @param DimensionsInterface $dimensions
*/
public function validateDimensions(DimensionsInterface $dimensions)
{
$math = $this->getMath();
$converter = $this->getLengthConverter();
$girthCalculator = $this->getGirthCalculator();

$dimensions = $girthCalculator->normalizeDimensions($dimensions);
$sideLengthLimit = $converter->convert($this->getSideLengthLimit(), $this->getDimensionsUnit(), $dimensions->getUnit());
if ($math->greaterThan($dimensions->getLength(), $sideLengthLimit)) {
throw new InvalidDimensionsException('Side length limit is exceeded.');
}

$girth = $girthCalculator->calculate($dimensions);
$girthLimit = $converter->convert($this->getGirthLimit(), $this->getDimensionsUnit(), $dimensions->getUnit());
if ($math->greaterThan($girth, $girthLimit)) {
throw new InvalidDimensionsException('Girth limit is exceeded.');
}
}

public function validateWeight(PackageInterface $package)
{
$math = $this->getMath();
$converter = $this->getWeightConverter();
$country = $this->getRecipientCountry($package->getRecipientAddress()->getCountryCode());

$countryWeightLimit = $converter->convert($country->getWeightLimit(), $this->getMassUnit(), $package->getWeight()->getUnit());
if ($math->greaterThan($package->getWeight()->getValue(), $countryWeightLimit)) {
throw new InvalidWeightException('Sender country weight limit is exceeded.');
}
}

/**
* @param PriceGroup $priceGroup
* @return $this
Expand All @@ -89,43 +204,17 @@ public function addPriceGroups(array $priceGroups)

/**
* @param PackageInterface $package
* @return mixed
* @return PriceGroup
*/
public function calculate(PackageInterface $package)
public function getPriceGroup($package)
{
$isValidSenderCountry = in_array($package->getSenderAddress()->getCountryCode(), $this->senderCountries);
if (!$isValidSenderCountry) {
throw new InvalidSenderAddressException();
}

$country = $this->getRecipientCountry($package->getRecipientAddress()->getCountryCode());
$priceGroup = $this->getPriceGroup($country->getPriceGroup());

$weight = $package->getWeight();
$weight = $this->getWeightConverter()->convert($weight->getValue(), $weight->getUnit(), $this->getMassUnit());

$math = $this->getMath();
$cost = $priceGroup->getPrice($weight);
$wholeWeight = $math->roundDown($weight);
$fuelCost = $math->mul($wholeWeight, $this->getFuelSubcharge());
$total = $math->sum($cost, $fuelCost);
$total = $math->roundUp($total, 2);
$result = number_format($total, 2, '.', '');

return $result;
}

/**
* @param string $number
* @return PriceGroup
*/
public function getPriceGroup($number)
{
if (!array_key_exists($number, $this->priceGroups)) {
if (!array_key_exists($country->getPriceGroup(), $this->priceGroups)) {
throw new InvalidConfigurationException('Price group does not exist.');
}

return $this->priceGroups[$number];
return $this->priceGroups[$country->getPriceGroup()];
}

/**
Expand Down Expand Up @@ -205,7 +294,7 @@ public function addRecipientCountries(array $countries)
public function getRecipientCountry($code)
{
if (!array_key_exists($code, $this->recipientCountries)) {
throw new InvalidRecipientAddressException();
throw new InvalidArgumentException();
}

return $this->recipientCountries[$code];
Expand Down Expand Up @@ -247,12 +336,35 @@ public function getWeightConverter()
}

/**
* @param UnitConverterInterface $weightConverter
* @param UnitConverterInterface $converter
* @return $this
*/
public function setWeightConverter(UnitConverterInterface $weightConverter)
public function setWeightConverter(UnitConverterInterface $converter)
{
$this->weightConverter = $weightConverter;
$this->weightConverter = $converter;

return $this;
}

/**
* @return UnitConverterInterface
*/
public function getLengthConverter()
{
if (!$this->lengthConverter) {
$this->lengthConverter = new LengthConverter($this->getMath());
}

return $this->lengthConverter;
}

/**
* @param UnitConverterInterface $converter
* @return $this
*/
public function setLengthConverter(UnitConverterInterface $converter)
{
$this->lengthConverter = $converter;

return $this;
}
Expand Down Expand Up @@ -294,4 +406,84 @@ public function setCurrency($currency)

return $this;
}

/**
* @return string
*/
public function getDimensionsUnit()
{
return $this->dimensionsUnit;
}

/**
* @param string $unit
* @return $this
*/
public function setDimensionsUnit($unit)
{
$this->dimensionsUnit = $unit;

return $this;
}

/**
* @return string
*/
public function getSideLengthLimit()
{
return $this->sideLengthLimit;
}

/**
* @param string $limit
* @return $this
*/
public function setSideLengthLimit($limit)
{
$this->sideLengthLimit = $limit;

return $this;
}

/**
* @return string
*/
public function getGirthLimit()
{
return $this->girthLimit;
}

/**
* @param string $limit
* @return $this
*/
public function setGirthLimit($limit)
{
$this->girthLimit = $limit;

return $this;
}

/**
* @return UspsGirthCalculator
*/
public function getGirthCalculator()
{
if (!$this->girthCalculator) {
$this->girthCalculator = new UspsGirthCalculator($this->getMath());
}

return $this->girthCalculator;
}

/**
* @param UspsGirthCalculator $calculator
* @return $this
*/
public function setGirthCalculator(UspsGirthCalculator $calculator)
{
$this->girthCalculator = $calculator;

return $this;
}
}
Loading

0 comments on commit 5f6dbd0

Please sign in to comment.