diff --git a/config/services.yaml b/config/services.yaml index 7c696fba..e2948103 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -56,6 +56,10 @@ services: arguments: $base_currency: '%default_currency%' + App\Services\PricedetailHelper: + arguments: + $base_currency: '%default_currency%' + App\Services\MoneyFormatter: arguments: $base_currency: '%default_currency%' diff --git a/src/Controller/PartController.php b/src/Controller/PartController.php index 33eb706c..fa83c105 100644 --- a/src/Controller/PartController.php +++ b/src/Controller/PartController.php @@ -35,6 +35,7 @@ use App\Entity\Parts\Part; use App\Form\AttachmentFormType; use App\Form\Part\PartBaseType; use App\Services\AttachmentHelper; +use App\Services\PricedetailHelper; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\FormInterface; @@ -51,14 +52,15 @@ class PartController extends AbstractController * @param AttachmentHelper $attachmentHelper * @return \Symfony\Component\HttpFoundation\Response */ - public function show(Part $part, AttachmentHelper $attachmentHelper) + public function show(Part $part, AttachmentHelper $attachmentHelper, PricedetailHelper $pricedetailHelper) { $this->denyAccessUnlessGranted('read', $part); return $this->render('Parts/info/show_part_info.html.twig', [ 'part' => $part, - 'attachment_helper' => $attachmentHelper + 'attachment_helper' => $attachmentHelper, + 'pricedetail_helper' => $pricedetailHelper ] ); } @@ -102,7 +104,7 @@ class PartController extends AbstractController [ 'part' => $part, 'form' => $form->createView(), - 'attachment_helper' => $attachmentHelper + 'attachment_helper' => $attachmentHelper, ]); } diff --git a/src/Entity/PriceInformations/Currency.php b/src/Entity/PriceInformations/Currency.php index 5b848410..6953d248 100644 --- a/src/Entity/PriceInformations/Currency.php +++ b/src/Entity/PriceInformations/Currency.php @@ -34,6 +34,7 @@ namespace App\Entity\PriceInformations; use App\Entity\Base\StructuralDBElement; use Doctrine\ORM\Mapping as ORM; +use s9e\TextFormatter\Configurator\TemplateNormalizations\AbstractChooseOptimization; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; @@ -47,6 +48,8 @@ use Symfony\Component\Validator\Constraints as Assert; class Currency extends StructuralDBElement { + public const PRICE_SCALE = 5; + /** * @var string The 3 letter ISO code of the currency. * @ORM\Column(type="string") @@ -55,7 +58,7 @@ class Currency extends StructuralDBElement protected $iso_code; /** - * @var float|null The exchange rate between this currency and the base currency + * @var string|null The exchange rate between this currency and the base currency * (how many base units the current currency is worth) * @ORM\Column(type="decimal", precision=11, scale=5, nullable=true) * @Assert\Positive() @@ -94,34 +97,34 @@ class Currency extends StructuralDBElement /** * Returns the inverse exchange rate (how many of the current currency the base unit is worth) - * @return float|null + * @return string|null */ - public function getInverseExchangeRate(): ?float + public function getInverseExchangeRate(): ?string { $tmp = $this->getExchangeRate(); - if ($tmp === null) { + if ($tmp === null || (float) $tmp === 0) { return null; } - return 1 / $tmp; + return bcdiv(1, $tmp, static::PRICE_SCALE); } /** * Returns The exchange rate between this currency and the base currency * (how many base units the current currency is worth) - * @return float|null + * @return string|null */ - public function getExchangeRate(): ?float + public function getExchangeRate(): ?string { return $this->exchange_rate; } /** - * @param float|null $exchange_rate + * @param string|null $exchange_rate * @return Currency */ - public function setExchangeRate(?float $exchange_rate): Currency + public function setExchangeRate(?string $exchange_rate): Currency { $this->exchange_rate = $exchange_rate; return $this; diff --git a/src/Services/PricedetailHelper.php b/src/Services/PricedetailHelper.php new file mode 100644 index 00000000..d0e33bec --- /dev/null +++ b/src/Services/PricedetailHelper.php @@ -0,0 +1,89 @@ +base_currency = $base_currency; + $this->locale = Locale::getDefault(); + } + + /** + * Converts the given value in origin currency to the choosen target currency + * @param $value float|string The value that should be converted + * @param Currency|null $originCurrency The currency the $value is given in. + * Set to null, to use global base currency. + * @param Currency|null $targetCurrency The target currency, to which $value should be converted. + * Set to null, to use global base currency. + * @return string|null The value in $targetCurrency given as bcmath string. + * Returns null, if it was not possible to convert between both values (e.g. when the exchange rates are missing) + */ + public function convertMoneyToCurrency($value, ?Currency $originCurrency = null, ?Currency $targetCurrency = null) : ?string + { + $value = (string) $value; + + //Convert value to base currency + $val_base = $value; + if($originCurrency !== null) { + //Without an exchange rate we can not calculate the exchange rate + if ((float) $originCurrency->getExchangeRate() === 0) { + return null; + } + + $val_base = bcmul($value, $originCurrency->getExchangeRate(), Pricedetail::PRICE_PRECISION); + } + + //Convert value in base currency to target currency + $val_target = $val_base; + if ($targetCurrency !== null) { + //Without an exchange rate we can not calculate the exchange rate + if ($targetCurrency->getExchangeRate() === null) { + return null; + } + + $val_target = bcmul($val_base, $targetCurrency->getInverseExchangeRate(), Pricedetail::PRICE_PRECISION); + } + + return $val_target; + } +} \ No newline at end of file diff --git a/templates/Parts/info/_order_infos.html.twig b/templates/Parts/info/_order_infos.html.twig index f4e0f608..47935f56 100644 --- a/templates/Parts/info/_order_infos.html.twig +++ b/templates/Parts/info/_order_infos.html.twig @@ -41,10 +41,15 @@