275 lines
5.5 KiB
PHP
275 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use Akaunting\Money\Currency;
|
|
use Akaunting\Money\Money as MoneyBase;
|
|
|
|
/**
|
|
* Compositional wrapper to MoneyPHP with some helpers
|
|
*/
|
|
class Money
|
|
{
|
|
public $money;
|
|
public $subunit_amount;
|
|
public static $iso_currencies;
|
|
public static $subunit_multiplier;
|
|
|
|
/**
|
|
* @param mixed $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return MoneyBase
|
|
*/
|
|
public static function create($amount)
|
|
{
|
|
return new MoneyBase($amount, static::currency());
|
|
}
|
|
|
|
/**
|
|
* Create from a dollar amount
|
|
*
|
|
* @param mixed $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return Money
|
|
*/
|
|
public static function createFromAmount($amount)
|
|
{
|
|
return new self(
|
|
static::convertToSubunit($amount)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Convert a whole unit into it's subunit, e,g: dollar to cents
|
|
*
|
|
* @param mixed $amount
|
|
*
|
|
* @return float|int
|
|
*/
|
|
public static function convertToSubunit($amount)
|
|
{
|
|
$currency = config('phpvms.currency');
|
|
return (int) $amount * config('money.'.$currency.'.subunit');
|
|
}
|
|
|
|
/**
|
|
* Create a new currency object using the currency setting
|
|
* Fall back to USD if it's not valid
|
|
*
|
|
* @throws \OutOfBoundsException
|
|
*
|
|
* @return Currency
|
|
*/
|
|
public static function currency()
|
|
{
|
|
try {
|
|
return new Currency(config('phpvms.currency', 'USD'));
|
|
} catch (\OutOfBoundsException $e) {
|
|
return new Currency('USD');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Money constructor.
|
|
*
|
|
* @param mixed $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*/
|
|
public function __construct($amount)
|
|
{
|
|
$this->money = static::create($amount);
|
|
}
|
|
|
|
/**
|
|
* Return the amount of currency in smallest denomination
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getAmount()
|
|
{
|
|
return $this->money->getAmount();
|
|
}
|
|
|
|
/**
|
|
* Alias of getAmount()
|
|
*/
|
|
public function toAmount()
|
|
{
|
|
return $this->getAmount();
|
|
}
|
|
|
|
/**
|
|
* Returns the value in whole amounts, e.g: 100.00
|
|
* instead of returning in the smallest denomination
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getValue()
|
|
{
|
|
return $this->money->getValue();
|
|
}
|
|
|
|
/**
|
|
* Alias of getValue()
|
|
*/
|
|
public function toValue()
|
|
{
|
|
return $this->getValue();
|
|
}
|
|
|
|
/**
|
|
* @return MoneyBase
|
|
*/
|
|
public function getInstance()
|
|
{
|
|
return $this->money;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getPrecision()
|
|
{
|
|
return $this->money->getCurrency()->getPrecision();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function __toString()
|
|
{
|
|
return $this->money->format();
|
|
}
|
|
|
|
/**
|
|
* Add an amount
|
|
*
|
|
* @param mixed $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return Money
|
|
*/
|
|
public function add($amount)
|
|
{
|
|
if (!($amount instanceof self)) {
|
|
$amount = static::createFromAmount($amount);
|
|
}
|
|
|
|
$this->money = $this->money->add($amount->money);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $percent
|
|
*
|
|
* @throws \OutOfBoundsException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function addPercent($percent)
|
|
{
|
|
if (!is_numeric($percent)) {
|
|
$percent = (float) $percent;
|
|
}
|
|
|
|
$amount = $this->money->multiply($percent / 100);
|
|
$this->money = $this->money->add($amount);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Subtract an amount
|
|
*
|
|
* @param $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return Money
|
|
*/
|
|
public function subtract($amount)
|
|
{
|
|
if (!($amount instanceof self)) {
|
|
$amount = static::createFromAmount($amount);
|
|
}
|
|
|
|
$this->money = $this->money->subtract($amount->money);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Multiply by an amount
|
|
*
|
|
* @param $amount
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \OutOfBoundsException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return Money
|
|
*/
|
|
public function multiply($amount)
|
|
{
|
|
if (!($amount instanceof self)) {
|
|
$amount = static::createFromAmount($amount);
|
|
}
|
|
|
|
$this->money = $this->money->multiply($amount->money);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Divide by an amount
|
|
*
|
|
* @param $amount
|
|
*
|
|
* @throws \OutOfBoundsException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return Money
|
|
*/
|
|
public function divide($amount)
|
|
{
|
|
$this->money = $this->money->divide($amount, PHP_ROUND_HALF_EVEN);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param $money
|
|
*
|
|
* @throws \UnexpectedValueException
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function equals($money)
|
|
{
|
|
if ($money instanceof self) {
|
|
return $this->money->equals($money->money);
|
|
}
|
|
|
|
if ($money instanceof MoneyBase) {
|
|
return $this->money->equals($money);
|
|
}
|
|
|
|
$money = static::convertToSubunit($money);
|
|
|
|
return $this->money->equals(static::create($money));
|
|
}
|
|
}
|