Currency
Introduction
The Currency component provides the means for currency calculation in the B2B Suite. The following graph shows components depending on this component:
Context
The Currency component provides an additional Context object (Shopware\B2B\Currency\Framework\CurrencyContext
) containing a currency factor. You can retrieve the default Context, which always contains the currently selected currency factor through the Shopware\B2B\Currency\Framework\CurrencyService
.
<?php declare(strict_types=1);
use Shopware\B2B\Currency\Framework\CurrencyContext;
use Shopware\B2B\Currency\Framework\CurrencyService;
class TestController
{
private CurrencyService $currencyService;
public function __construct(
CurrencyService $currencyService
) {
$this->currencyService = $currencyService;
}
public function testAction(): array
{
return [
'currencyContext' => $this->currencyService->createCurrencyContext(),
];
}
This way, you can either store the currency factor with a newly provided amount or retrieve recalculated data from your repository.
Entity
All recalculable entities must implement the interface Shopware\B2B\Currency\Framework\CurrencyAware
, which provides the means to access the currency data.
use Shopware\B2B\Currency\Framework\CurrencyAware;
class MyEntity implements CurrencyAware
{
public float $amount1;
public float $amount2;
private float $factor;
public function getCurrencyFactor(): float
{
return $this->factor;
}
public function setCurrencyFactor(float $factor)
{
$this->factor = $factor;
}
/**
* @return string[]
*/
public function getAmountPropertyNames(): array
{
return [
'amount1',
'amount2',
];
}
}
Repository
The repository has to guarantee that every entity retrieved from storage has valid and, if necessary, recalculated money values. The Currency component provides Shopware\B2B\Currency\Framework\CurrencyCalculator
to help with this promise. So a typical repository looks like this:
<?php declare(strict_types=1);
use Shopware\B2B\Currency\Framework\CurrencyCalculator;
class Repository
{
private CurrencyCalculator $currencyCalculator;
public function __construct(
CurrencyCalculator $currencyCalculator
) {
$this->currencyCalculator = $currencyCalculator;
}
}
Calculating in PHP (preferred)
To recalculate an entity amount, the calculator provides two convenient functions.
recalculateAmount
for a single entity:
public function fetchOneById(int $id, CurrencyContext $currencyContext): CurrencyAware
{
[...] // load entity from Database
$this->currencyCalculator->recalculateAmount($entity, $currencyContext);
return $entity;
}
recalculateAmounts
to recalculate an array of entities:
public function fetchList([...], CurrencyContext $currencyContext): array
{
[...] // load entities from Database
//recalculate with the current amount
$this->>currencyCalculator->recalculateAmounts($entities, $currencyContext);
return $entities;
}
Calculating in SQL
Although calculation in PHP is the preferred way, it may sometimes be necessary to recalculate the amounts in SQL. This is the case if you, for example, use a GROUP BY
statement and try to create a sum. For this case, the Currency component creates a SQL calculation snippet.
So if your original snippet looked like this:
public function fetchAmount(int $budgetId): float
{
return (float) $this-connection->fetchColumn(
'SELECT SUM(amount) AS sum_amount FROM b2b_budget_transaction WHERE budget_id=:budgetId',
['budgetId' => $budgetId]
)
}
But it should actually look like this:
public function fetchAmount(int $budgetId, CurrencyContext $currencyContext): float
{
$transactionSnippet = $this->currencyCalculator
->getSqlCalculationPart('amount', 'currency_factor', $currencyContext);
return (float) $this-connection->fetchColumn(
'SELECT SUM(' . $transactionSnippet . ') AS sum_amount FROM b2b_budget_transaction WHERE budget_id=:budgetId',
['budgetId' => $budgetId]
)
}