arch-8.x-1.x-dev/modules/price/src/Price/Price.php
modules/price/src/Price/Price.php
<?php
namespace Drupal\arch_price\Price;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\currency\Entity\CurrencyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Default price implementation.
*
* @package Drupal\arch_price\Price
*/
class Price implements PriceInterface {
use StringTranslationTrait;
use DependencySerializationTrait;
/**
* Price values.
*
* @var array
*/
protected $values;
/**
* Currency entity storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $currencyStorage;
/**
* Price type storage.
*
* @var \Drupal\arch_price\Entity\Storage\PriceTypeStorageInterface
*/
protected $priceTypeStorage;
/**
* Exchange provider.
*
* @var \Drupal\currency\PluginBasedExchangeRateProvider
*/
protected $exchangeProvider;
/**
* Price factory.
*
* @var \Drupal\arch_price\Price\PriceFactoryInterface
*/
protected $priceFactory;
/**
* VAT Category storage.
*
* @var \Drupal\arch_price\Entity\Storage\VatCategoryStorageInterface
*/
protected $vatCategoryStorage;
/**
* Module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Price constructor.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* Service container.
* @param array|null $values
* Price values.
*/
public function __construct(
ContainerInterface $container,
?array $values = NULL,
) {
$this->currencyStorage = $container->get('entity_type.manager')->getStorage('currency');
$this->vatCategoryStorage = $container->get('entity_type.manager')->getStorage('vat_category');
$this->priceTypeStorage = $container->get('entity_type.manager')->getStorage('price_type');
$this->exchangeProvider = $container->get('currency.exchange_rate_provider');
$this->priceFactory = $container->get('price_factory');
$this->moduleHandler = $container->get('module_handler');
if (!empty($values)) {
$this->setValues($values);
}
}
/**
* {@inheritdoc}
*/
public static function create(
ContainerInterface $container,
array $values,
) {
return new static(
$container,
$values
);
}
/**
* {@inheritdoc}
*/
public function getValues() {
return [
'base' => $this->getCalculationBase(),
'price_type' => $this->values['price_type'] ?? NULL,
'currency' => $this->getCurrencyId(),
'net' => $this->getNetPrice(),
'gross' => $this->getGrossPrice(),
'vat_category' => $this->getVatCategoryId(),
'vat_rate' => $this->getVatRate(),
'vat_value' => $this->getVatValue(),
'date_from' => $this->values['date_from'] ?? NULL,
'date_to' => $this->values['date_to'] ?? NULL,
'reason_of_diff' => $this->values['reason_of_diff'] ?? NULL,
];
}
/**
* {@inheritdoc}
*/
public function setValues(array $values) {
if (!isset($values['currency'])) {
throw new \InvalidArgumentException('Value "currency" is missing. Currency is required!');
}
if (!isset($values['base'])) {
throw new \InvalidArgumentException('Value "base" is missing. Calculation base is required!');
}
$values += [
'base' => NULL,
'price_type' => NULL,
'currency' => NULL,
'net' => NULL,
'gross' => NULL,
'vat_category' => NULL,
'vat_rate' => NULL,
'vat_value' => NULL,
'date_from' => NULL,
'date_to' => NULL,
'reason_of_diff' => NULL,
];
$this->values = $values;
$currency = $this->currencyStorage->load($values['currency']);
if (!$currency) {
$currency = $this->currencyStorage->load('XXX');
}
$this->values['currency'] = $currency->id();
if (
empty($values['vat_rate'])
&& !empty($values['vat_category'])
&& ($vat_category = $this->vatCategoryStorage->load($values['vat_category']))
) {
/** @var \Drupal\arch_price\Entity\VatCategoryInterface $vat_category */
$this->values['vat_category'] = $vat_category->id();
$this->values['vat_rate'] = $vat_category->getRate();
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getNetPrice() {
if ($this->getCalculationBase() === 'net') {
return round((float) $this->values['net'], 2);
}
$gross = round((float) $this->values['gross'], 2);
$rate = $this->getVatRate();
return round($gross / (1 + $rate), 2);
}
/**
* {@inheritdoc}
*/
public function getGrossPrice() {
if ($this->getCalculationBase() === 'gross') {
return round((float) $this->values['gross'], 2);
}
$net = round((float) $this->values['net'], 2);
$rate = $this->getVatRate();
return round($net * (1 + $rate), 2);
}
/**
* {@inheritdoc}
*/
public function getVatValue() {
return round($this->getGrossPrice() - $this->getNetPrice(), 2);
}
/**
* {@inheritdoc}
*/
public function getVatRate() {
return $this->values['vat_rate'];
}
/**
* {@inheritdoc}
*/
public function getVatRatePercentage() {
return round($this->getVatRate() * 100, 2);
}
/**
* {@inheritdoc}
*/
public function getCurrencyId() {
return $this->values['currency'];
}
/**
* {@inheritdoc}
*/
public function getCurrency() {
if (!empty($this->values['currency'])) {
return $this->currencyStorage->load($this->values['currency']);
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function getPriceType() {
try {
return $this->priceTypeStorage->load($this->values['price_type']);
}
catch (\Exception $e) {
// @todo handle error.
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function getPriceTypeId() {
return $this->values['price_type'];
}
/**
* {@inheritdoc}
*/
public function getCalculationBase() {
return $this->values['base'];
}
/**
* {@inheritdoc}
*/
public function getVatCategoryId() {
return $this->values['vat_category'];
}
/**
* {@inheritdoc}
*/
public function getExchangedPriceValues($currency) {
if (empty($currency)) {
throw new \InvalidArgumentException('Missing currency!');
}
if (is_string($currency)) {
$currency = $this->currencyStorage->load($currency);
}
if (!($currency instanceof CurrencyInterface)) {
throw new \InvalidArgumentException('Invalid currency!');
}
/** @var \Drupal\currency\Entity\CurrencyInterface $currency */
/** @var \Drupal\currency\ExchangeRateInterface $rate */
$rate = $this->exchangeProvider->load($this->values['currency'], $currency->id());
$rate_value = 0;
if (!empty($rate)) {
$rate_value = $rate->getRate();
}
$values = $this->getValues();
$net = $values['net'] * $rate_value;
$gross = $values['gross'] * $rate_value;
$values['currency'] = $currency->id();
$values['net'] = round($net, 2);
$values['gross'] = round($gross, 2);
$values['vat_value'] = round($gross - $net, 2);
$this->moduleHandler->alter('arch_price_get_exchanged_price_values', $values, $currency);
return $values;
}
/**
* {@inheritdoc}
*/
public function getExchangedPrice($currency) {
$values = $this->getExchangedPriceValues($currency);
if (empty($values)) {
return $values;
}
return $this->priceFactory->getInstance($values);
}
/**
* {@inheritdoc}
*/
public function setReasonOfDifference($reason) {
$this->values['reason_of_diff'] = (string) $reason;
return $this;
}
/**
* {@inheritdoc}
*/
public function getReasonOfDifference() {
return $this->values['reason_of_diff'];
}
}
