Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
- PHP_VERSION: php74-fpm
MAGENTO_VERSION: 2.4.4
- PHP_VERSION: php84-fpm
MAGENTO_VERSION: 2.4.8
MAGENTO_VERSION: 2.4.8-p2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v5

- name: Start Docker
run: docker run --detach --name magento-project-community-edition michielgerritsen/magento-project-community-edition:${{ matrix.PHP_VERSION }}-magento${{ matrix.MAGENTO_VERSION }}
Expand All @@ -24,7 +24,9 @@ jobs:
run: docker cp $(pwd)/. magento-project-community-edition:/data/extensions/mollie-magento2-subscriptions/

- name: Install Mollie and Mollie Subscription extensions
run: docker exec magento-project-community-edition ./install-composer-package mollie/magento2 mollie/magento2-subscriptions:@dev
run: |
docker exec magento-project-community-edition composer config preferred-install.mollie/magento2 source
docker exec magento-project-community-edition ./install-composer-package mollie/magento2 mollie/magento2-subscriptions:@dev

- name: Enable modules
run: docker exec magento-project-community-edition bash -c "php bin/magento module:enable Mollie_Payment Mollie_Subscriptions && php bin/magento setup:upgrade"
Expand Down
14 changes: 14 additions & 0 deletions Api/Data/SubscriptionToProductInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface SubscriptionToProductInterface extends ExtensibleDataInterface
const CUSTOMER_ID = 'customer_id';
const SUBSCRIPTION_ID = 'subscription_id';
const PRODUCT_ID = 'product_id';
const OPTION_ID = 'option_id';
const STORE_ID = 'store_id';
const HAS_PRICE_UPDATE = 'has_price_update';
const NEXT_PAYMENT_DATE = 'next_payment_date';
Expand Down Expand Up @@ -72,6 +73,19 @@ public function getProductId(): int;
*/
public function setProductId(int $productId);

/**
* Get option_id
* @return string|null
*/
public function getOptionId(): ?string;

/**
* Set option_id
* @param string $optionId
* @return \Mollie\Subscriptions\Api\Data\SubscriptionToProductInterface
*/
public function setOptionId(string $optionId);

/**
* Get store_id
* @return int|null
Expand Down
39 changes: 39 additions & 0 deletions Block/Adminhtml/UpdatePrice/BackButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/*
* Copyright Magmodules.eu. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Mollie\Subscriptions\Block\Adminhtml\UpdatePrice;

use Magento\Backend\Block\Widget\Context;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class BackButton implements ButtonProviderInterface
{
/**
* @var Context
*/
private $context;

public function __construct(Context $context)
{
$this->context = $context;
}

public function getButtonData(): array
{
return [
'label' => __('Back'),
'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
'class' => 'back',
'sort_order' => 10
];
}

private function getBackUrl(): string
{
return $this->context->getUrlBuilder()->getUrl('*/*/index');
}
}
26 changes: 26 additions & 0 deletions Block/Adminhtml/UpdatePrice/SaveButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/*
* Copyright Magmodules.eu. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Mollie\Subscriptions\Block\Adminhtml\UpdatePrice;

use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;

class SaveButton implements ButtonProviderInterface
{
public function getButtonData(): array
{
return [
'label' => __('Update Price'),
'class' => 'save primary',
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'save']],
'form-role' => 'save',
],
'sort_order' => 90,
];
}
}
29 changes: 29 additions & 0 deletions Block/Frontend/Product/View/SubscriptionOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Boolean;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\Registry;
use Magento\Framework\View\Element\Template;
use Mollie\Subscriptions\Config;
Expand All @@ -32,19 +33,25 @@ class SubscriptionOptions extends Template
* @var ParseSubscriptionOptions
*/
private $parseSubscriptionOptions;
/**
* @var PriceCurrencyInterface
*/
private $priceCurrency;

public function __construct(
Template\Context $context,
Registry $registry,
Config $config,
ParseSubscriptionOptions $parseSubscriptionOptions,
PriceCurrencyInterface $priceCurrency,
array $data = []
) {
parent::__construct($context, $data);

$this->registry = $registry;
$this->config = $config;
$this->parseSubscriptionOptions = $parseSubscriptionOptions;
$this->priceCurrency = $priceCurrency;
}

/**
Expand All @@ -71,4 +78,26 @@ public function allowOneTimePurchase(): bool

return (bool)$value;
}

public function showPriceInSubscriptionButton(): bool
{
return $this->config->showPriceInSubscriptionButton();
}

public function getProductPrice(): float
{
/** @var ProductInterface $product */
$product = $this->registry->registry('current_product');

if ($product->getPrice() === null) {
return 0.0;
}

return (float)$product->getPrice();
}

public function formatPrice(float $price, bool $includeContainer = false): string
{
return $this->priceCurrency->format($price, $includeContainer);
}
}
41 changes: 40 additions & 1 deletion Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,19 @@ class Config
const XML_PATH_EMAILS_ADMIN_CANCEL_NOTIFICATION_TEMPLATE = 'mollie_subscriptions/emails/admin_cancel_notification_template';
const XML_PATH_EMAILS_ENABLE_CUSTOMER_CANCEL_NOTIFICATION = 'mollie_subscriptions/emails/enable_customer_cancel_notification';
const XML_PATH_EMAILS_CUSTOMER_CANCEL_NOTIFICATION_TEMPLATE = 'mollie_subscriptions/emails/customer_cancel_notification_template';
const XML_PATH_EMAILS_ENABLE_ADMIN_FAILURE_NOTIFICATION = 'mollie_subscriptions/emails/enable_admin_failure_notification';
const XML_PATH_EMAILS_ADMIN_FAILURE_NOTIFICATION_TEMPLATE = 'mollie_subscriptions/emails/admin_failure_notification_template';
const XML_PATH_DISABLE_NEW_ORDER_CONFIRMATION = 'mollie_subscriptions/emails/disable_new_order_confirmation';
const XML_PATH_ALLOW_ONE_TIME_PURCHASE = 'mollie_subscriptions/general/allow_one_time_purchases';
const XML_PATH_SHOW_PRICE_IN_SUBSCRIPTION_BUTTON = 'mollie_subscriptions/general/show_price_in_subscription_button';
const XML_PATH_UPDATE_SUBSCRIPTION_WHEN_PRICE_CHANGES = 'mollie_subscriptions/general/update_subscription_when_price_changes';
const MODULE_SUPPORT_LINK = 'https://www.magmodules.eu/help/%s';

/**
* @var \Mollie\Payment\Config
*/
private $config;

/**
* @var StoreManagerInterface
*/
Expand All @@ -58,22 +67,32 @@ class Config
* @var ScopeConfigInterface
*/
private $scopeConfig;

/**
* @var ProductMetadataInterface
*/
private $metadata;

public function __construct(
\Mollie\Payment\Config $config,
StoreManagerInterface $storeManager,
ScopeConfigInterface $scopeConfig,
ProductMetadataInterface $metadata
) {
$this->config = $config;
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
$this->metadata = $metadata;
}

public function addToLog(string $type, $data): void
{
if (!$this->getFlag(static::XML_PATH_DEBUG)) {
return;
}

$this->config->addToLog($type, $data);
}

/**
* Get Configuration data
*
Expand Down Expand Up @@ -269,6 +288,16 @@ public function allowOneTimePurchase($storeId = null, $scope = ScopeInterface::S
return $this->getFlag(static::XML_PATH_ALLOW_ONE_TIME_PURCHASE, $storeId, $scope);
}

public function showPriceInSubscriptionButton(?int $storeId = null, string $scope = ScopeInterface::SCOPE_STORE): bool
{
return $this->getFlag(static::XML_PATH_SHOW_PRICE_IN_SUBSCRIPTION_BUTTON, $storeId, $scope);
}

public function updateSubscriptionWhenPriceChanges(?int $storeId = null, string $scope = ScopeInterface::SCOPE_STORE): bool
{
return $this->getFlag(static::XML_PATH_UPDATE_SUBSCRIPTION_WHEN_PRICE_CHANGES, $storeId, $scope);
}

/**
* @param int $storeId
* @param string $scope
Expand Down Expand Up @@ -379,6 +408,16 @@ public function getAdminCancelNotificationTemplate($storeId = null, $scope = Sco
return $this->getStoreValue(static::XML_PATH_EMAILS_ADMIN_CANCEL_NOTIFICATION_TEMPLATE, $storeId, $scope);
}

public function enableAdminFailureNotificationEmail(?int $storeId = null, string $scope = ScopeInterface::SCOPE_STORE): bool
{
return $this->getFlag(static::XML_PATH_EMAILS_ENABLE_ADMIN_FAILURE_NOTIFICATION, $storeId, $scope);
}

public function getAdminFailureNotificationTemplate(?int $storeId = null, string $scope = ScopeInterface::SCOPE_STORE): ?string
{
return $this->getStoreValue(static::XML_PATH_EMAILS_ADMIN_FAILURE_NOTIFICATION_TEMPLATE, $storeId, $scope);
}

/**
* @param null|int|string $storeId
* @param string $scope
Expand Down
108 changes: 108 additions & 0 deletions Controller/Adminhtml/Subscriptions/SavePrice.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php
/*
* Copyright Magmodules.eu. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Mollie\Subscriptions\Controller\Adminhtml\Subscriptions;

use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Message\ManagerInterface;
use Mollie\Subscriptions\Config;
use Mollie\Subscriptions\Service\Mollie\MollieSubscriptionApi;

class SavePrice implements HttpPostActionInterface
{
/**
* @var ManagerInterface
*/
private $messageManager;
/**
* @var RequestInterface
*/
private $request;
/**
* @var ResultFactory
*/
private $resultFactory;
/**
* @var DataPersistorInterface
*/
private $dataPersistor;
/**
* @var Config
*/
private $config;
/**
* @var MollieSubscriptionApi
*/
private $mollieApi;

public function __construct(
ManagerInterface $messageManager,
RequestInterface $request,
ResultFactory $resultFactory,
DataPersistorInterface $dataPersistor,
Config $config,
MollieSubscriptionApi $mollieApi
) {
$this->messageManager = $messageManager;
$this->request = $request;
$this->resultFactory = $resultFactory;
$this->dataPersistor = $dataPersistor;
$this->config = $config;
$this->mollieApi = $mollieApi;
}

public function execute(): ResultInterface
{
$data = $this->request->getPostValue();
$customerId = $data['customer_id'] ?? null;
$subscriptionId = $data['subscription_id'] ?? null;
$newPrice = $data['new_price'] ?? null;

if (!$customerId || !$subscriptionId) {
throw new LocalizedException(__('Customer ID and subscription ID are required.'));
}

try {
$mollieClient = $this->mollieApi->loadByStore();

$subscription = $mollieClient->subscriptions->getForId($customerId, $subscriptionId);

$mollieClient->subscriptions->update($customerId, $subscriptionId, [
'amount' => [
'value' => number_format((float)$newPrice, 2, '.', ''),
'currency' => $subscription->amount->currency,
]
]);

$this->messageManager->addSuccessMessage(__('Subscription price has been updated successfully.'));
$this->dataPersistor->clear('mollie_subscription_update_price');

return $this->redirect('*/*/index');
} catch (\Exception $exception) {
$this->config->addToLog('Error updating subscription ' . $subscriptionId, $exception);
$this->messageManager->addErrorMessage(__('Error updating subscription price: %1', $exception->getMessage()));
$this->dataPersistor->set('mollie_subscription_update_price', $data);

return $this->redirect('*/*/*', [
'customer_id' => $customerId,
'subscription_id' => $subscriptionId
]);
}
}

private function redirect(string $to, array $arguments = []): ResultInterface
{
$redirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$redirect->setPath($to, $arguments);

return $redirect;
}
}
Loading