phpvms/app/Support/Money.php

277 lines
5.6 KiB
PHP
Raw Normal View History

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