Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAYONE-92] payment method specific status mapping #115

Merged
merged 13 commits into from
Aug 30, 2021
100 changes: 17 additions & 83 deletions src/Components/TransactionStatus/TransactionStatusService.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PayonePayment\Components\ConfigReader\ConfigReaderInterface;
use PayonePayment\Components\Currency\CurrencyPrecisionInterface;
use PayonePayment\Configuration\ConfigurationPrefixes;
use PayonePayment\Installer\CustomFieldInstaller;
use PayonePayment\Struct\PaymentTransaction;
use Psr\Log\LoggerInterface;
Expand Down Expand Up @@ -84,8 +85,10 @@ public function transitionByConfigMapping(SalesChannelContext $salesChannelConte
return;
}

$configuration = $this->configReader->read($salesChannelContext->getSalesChannel()->getId());
$currency = $paymentTransaction->getOrder()->getCurrency();
$configuration = $this->configReader->read($salesChannelContext->getSalesChannel()->getId());
$currency = $paymentTransaction->getOrder()->getCurrency();
$orderTransaction = $paymentTransaction->getOrderTransaction();
$paymentMethod = $orderTransaction->getPaymentMethod();

if (null === $currency) {
return;
Expand All @@ -101,27 +104,24 @@ public function transitionByConfigMapping(SalesChannelContext $salesChannelConte

$transitionName = $configuration->getString($configurationKey);

if (empty($transitionName)) {
if ($this->isTransactionOpen($transactionData)) {
$transitionName = StateMachineTransitionActions::ACTION_REOPEN;
} elseif ($this->isTransactionPartialPaid($transactionData, $currency)) {
$transitionName = StateMachineTransitionActions::ACTION_PAID_PARTIALLY;
} elseif ($this->isTransactionPaid($transactionData, $currency)) {
$transitionName = StateMachineTransitionActions::ACTION_PAID;
} elseif ($this->isTransactionPartialRefund($transactionData, $currency)) {
$transitionName = StateMachineTransitionActions::ACTION_REFUND_PARTIALLY;
} elseif ($this->isTransactionRefund($transactionData, $currency)) {
$transitionName = StateMachineTransitionActions::ACTION_REFUND;
} elseif ($this->isTransactionCancelled($transactionData)) {
$transitionName = StateMachineTransitionActions::ACTION_CANCEL;
}
if (null !== $paymentMethod) {
$configurationPrefix = ConfigurationPrefixes::CONFIGURATION_PREFIXES[$paymentMethod->getHandlerIdentifier()];
/** @var string $transitionName */
$transitionName = $configuration->getByPrefix($configurationKey, $configurationPrefix, $configuration->getString($configurationKey));
}

if (empty($transitionName)) {
$this->logger->info('No status transition configured',
[
'configurationKey' => $configurationKey,
'paymentMethod' => (null !== $paymentMethod) ? $paymentMethod->getHandlerIdentifier() : 'unknown',
]
);

return;
}

$this->executeTransition($salesChannelContext->getContext(), $paymentTransaction->getOrderTransaction()->getId(), strtolower($transitionName), $transactionData);
$this->executeTransition($salesChannelContext->getContext(), $orderTransaction->getId(), strtolower($transitionName), $transactionData);
}

public function transitionByName(Context $context, string $transactionId, string $transitionName, array $parameter = []): void
Expand Down Expand Up @@ -161,44 +161,6 @@ private function executeTransition(Context $context, string $transactionId, stri
}
}

private function isTransactionOpen(array $transactionData): bool
{
return strtolower($transactionData['txaction']) === self::ACTION_APPOINTED;
}

private function isTransactionPaid(array $transactionData, CurrencyEntity $currency): bool
{
if (in_array(strtolower($transactionData['txaction']), [self::ACTION_PAID, self::ACTION_COMPLETED], true)) {
return true;
}

if (!in_array(strtolower($transactionData['txaction']), [self::ACTION_DEBIT, self::ACTION_CAPTURE, self::ACTION_INVOICE], true)) {
return false;
}

if (array_key_exists('transactiontype', $transactionData) && $transactionData['transactiontype'] === self::TRANSACTION_TYPE_GT) {
return false;
}

$precision = $this->currencyPrecision->getTotalRoundingPrecision($currency);

if (array_key_exists('price', $transactionData) && array_key_exists('receivable', $transactionData) &&
(int) round(((float) $transactionData['receivable'] * (10 ** $precision))) === (int) round(((float) $transactionData['price'] * (10 ** $precision)))) {
return true;
}

if (array_key_exists('price', $transactionData) && array_key_exists('invoice_grossamount', $transactionData) &&
(int) round(((float) $transactionData['invoice_grossamount'] * (10 ** $precision))) === (int) round(((float) $transactionData['price'] * (10 ** $precision)))) {
return true;
}

if ((int) round(((float) $transactionData['receivable'] * (10 ** $precision))) === 0) {
return true;
}

return false;
}

private function isTransactionPartialPaid(array $transactionData, CurrencyEntity $currency): bool
{
if (!in_array(strtolower($transactionData['txaction']), [self::ACTION_DEBIT, self::ACTION_CAPTURE, self::ACTION_INVOICE], true)) {
Expand Down Expand Up @@ -228,29 +190,6 @@ private function isTransactionPartialPaid(array $transactionData, CurrencyEntity
return true;
}

private function isTransactionRefund(array $transactionData, CurrencyEntity $currency): bool
{
$precision = $this->currencyPrecision->getTotalRoundingPrecision($currency);

if (strtolower($transactionData['txaction']) !== self::ACTION_DEBIT) {
return false;
}

if (!array_key_exists('receivable', $transactionData)) {
return false;
}

if (array_key_exists('transactiontype', $transactionData) && $transactionData['transactiontype'] !== self::TRANSACTION_TYPE_GT) {
return false;
}

if ((int) round(((float) $transactionData['receivable'] * (10 ** $precision))) !== 0) {
return false;
}

return true;
}

private function isTransactionPartialRefund(array $transactionData, CurrencyEntity $currency): bool
{
$precision = $this->currencyPrecision->getTotalRoundingPrecision($currency);
Expand All @@ -274,11 +213,6 @@ private function isTransactionPartialRefund(array $transactionData, CurrencyEnti
return true;
}

private function isTransactionCancelled(array $transactionData): bool
{
return in_array(strtolower($transactionData['txaction']), [self::ACTION_CANCELATION, self::ACTION_FAILED], true);
}

private function isAsyncCancelled(PaymentTransaction $paymentTransaction, array $transactionData): bool
{
$customFields = $paymentTransaction->getCustomFields();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Component.register('payone-settings', {
showValidationErrors: false,
isSupportModalOpen: false,
stateMachineTransitionActions: [],
displayStatusMapping: {},
collapsibleState: {
'status_mapping': true,
'payment_credit_card': true,
Expand Down Expand Up @@ -106,6 +107,10 @@ Component.register('payone-settings', {
];
},

isVisiblePaymentMethodCard(card) {
return card.name.startsWith('payment') && !this.isCollapsed(card);
},

isCollapsible(card) {
return card.name in this.collapsibleState;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,33 @@
/>

<sw-form-field-renderer
v-else
v-else-if="!element.name.includes('PaymentStatus')"
v-bind="getElementBind(getBind(element, config))"
v-model="config[element.name]"
/>
</div>
</template>

<template #afterElements="{card, config}">
<sw-switch-field v-if="isVisiblePaymentMethodCard(card)"
v-model="displayStatusMapping[card.name]"
:label="$tc('payone-payment.settingsForm.labelShowSpecificStatusMapping')"
:helpText="$tc('payone-payment.settingsForm.helpTextShowSpecificStatusMapping')"></sw-switch-field>

<div v-if="config">
<template v-for="element in card.elements">
<sw-form-field-renderer
v-if="element.name.includes('PaymentStatus') && displayStatusMapping[card.name]"
:config="{
componentName: 'sw-single-select',
label: getInlineSnippet(getElementBind(getBind(element, config)).config.label),
helpText: getInlineSnippet(getElementBind(getBind(element, config)).config.helpText),
options: stateMachineTransitionActions,
}"
v-model="config[element.name]" />
</template>
</div>
</template>
</sw-system-config>
</sw-card-view>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"test": "API-Zugangsdaten testen",
"titleSuccess": "Erfolg",
"titleError": "Fehler",
"labelShowSpecificStatusMapping": "Statusmappingkonfiguration einblenden",
"helpTextShowSpecificStatusMapping": "Sie können für jede Zahlungsart ein spezifisches Statusmapping konfigurieren. Existiert eine solche Konfiguration nicht, wird auf die allgemeine Konfiguration zurückgegriffen.",
"messageTestSuccess": "Die API-Zugangsdaten wurden erfolgreich validiert.",
"messageTestNoTestedPayments": "Bei der Prüfung wurden keine Zahlarten getestet, weil keine der PAYONE Zahlarten aktiviert ist. Bitte aktivieren Sie mindestens eine PAYONE Zahlart unter Einstellungen --> Shop --> Zahlungsarten.",
"messageTestError": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"test": "Test API Credentials",
"titleSuccess": "Success",
"titleError": "Error",
"labelShowSpecificStatusMapping": "Display state mapping configuration",
"helpTextShowSpecificStatusMapping": "If not configured the general status mapping config will be applied.",
"messageTestSuccess": "The API credentials were verified successfully.",
"messageTestNoTestedPayments": "No payment methods were tested during the check because none of the PAYONE payment methods are activated. Please activate at least one PAYONE payment method under Settings --> Shop --> Payment.",
"messageTestError": {
Expand Down
Loading