Skip to content

Commit

Permalink
Capture card and Automatic Capture during Document Creation for Invoi…
Browse files Browse the repository at this point in the history
…ce B2C and B2B (#72)
  • Loading branch information
hasanzade-hasan authored Jun 19, 2023
1 parent 2362ecc commit d3c8633
Show file tree
Hide file tree
Showing 14 changed files with 516 additions and 6 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "better-payment/bp-plugin-shopware6-api2",
"description": "Better Payment plugin to implement payment methods using API2",
"version": "1.0.0",
"version": "1.1.0",
"type": "shopware-platform-plugin",
"license": "proprietary",
"authors": [
Expand Down
111 changes: 111 additions & 0 deletions src/EventSubscriber/OrderInvoiceDocumentCreatedEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php declare(strict_types=1);

namespace BetterPayment\EventSubscriber;


use BetterPayment\PaymentMethod\Invoice;
use BetterPayment\PaymentMethod\InvoiceB2B;
use BetterPayment\Util\BetterPaymentClient;
use BetterPayment\Util\ConfigReader;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Class OrderInvoiceDocumentCreatedEventSubscriber
*
* This event subscriber listens to the 'document.written' event and performs actions when an invoice document is created.
*/
class OrderInvoiceDocumentCreatedEventSubscriber implements EventSubscriberInterface
{
private BetterPaymentClient $betterPaymentClient;
private EntityRepositoryInterface $orderRepository;
private ConfigReader $configReader;

/**
* OrderInvoiceDocumentCreatedEventSubscriber constructor.
*
* @param BetterPaymentClient $betterPaymentClient
* @param EntityRepositoryInterface $orderRepository
* @param ConfigReader $configReader
*/
public function __construct(BetterPaymentClient $betterPaymentClient, EntityRepositoryInterface $orderRepository, ConfigReader $configReader)
{
$this->betterPaymentClient = $betterPaymentClient;
$this->orderRepository = $orderRepository;
$this->configReader = $configReader;
}

/**
* Returns the subscribed events and their corresponding methods.
*
* @return array The array of subscribed events and their methods.
*/
public static function getSubscribedEvents(): array
{
return [
'document.written' => 'onInvoiceDocumentCreated',
];
}

/**
* Performs following actions when an invoice document is created:
* 1. confirms whether this is really invoice type document to go on
* 2. fetches order from DB, and its corresponding successful(last) order transaction
* 3. checks whether this order transaction is capturable
* 4. sends capture request using BetterPaymentClient
*
* @param EntityWrittenEvent $event
*/
public function onInvoiceDocumentCreated(EntityWrittenEvent $event): void
{
$payloads = $event->getPayloads();
foreach ($payloads as $payload) {
if (isset($payload['config']['name']) && $payload['config']['name'] == 'invoice') {
$orderId = $payload['orderId'];
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('transactions.paymentMethod');

/** @var OrderEntity $order */
$order = $this->orderRepository->search(
$criteria,
Context::createDefaultContext()
)->first();

$orderTransaction = $order->getTransactions()->last();

if ($this->isCapturable($orderTransaction)) {
$invoiceId = $payload['config']['documentNumber'];
$invoiceDate = $payload['config']['documentDate'];

$captureParameters = [
'transaction_id' => $orderTransaction->getCustomFields()['better_payment_transaction_id'],
'invoice_id' => $invoiceId,
'amount' => $order->getAmountTotal(),
'execution_date' => $invoiceDate,
'comment' => 'Captured using Shopware 6 plugin',
];

$this->betterPaymentClient->capture($captureParameters);
}
}
}
}

/**
* Checks if an order transaction is capturable based on the payment method and corresponding configuration flag.
*
* @param OrderTransactionEntity $orderTransaction
* @return bool Whether the order transaction is capturable or not.
*/
public function isCapturable(OrderTransactionEntity $orderTransaction): bool
{
$paymentMethodShortname = $orderTransaction->getPaymentMethod()->getCustomFields()['shortname'];
return ($paymentMethodShortname == Invoice::SHORTNAME && $this->configReader->getBool(ConfigReader::INVOICE_AUTOMATICALLY_CAPTURE_ON_ORDER_INVOICE_DOCUMENT_SENT))
|| ($paymentMethodShortname == InvoiceB2B::SHORTNAME && $this->configReader->getBool(ConfigReader::INVOICE_B2B_AUTOMATICALLY_CAPTURE_ON_ORDER_INVOICE_DOCUMENT_SENT));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{% block sw_order_detail_base_line_items_card %}
{% parent %}
<sw-card
v-if="captureCardIsVisible"
:title="$tc('betterpayment.capture.cardTitle')">
<template #grid>
<sw-card-section divider="bottom" :slim="true">
<sw-container>
<sw-label variant="info" style="height: auto">
<div style="white-space: normal;">
<span v-if="paymentMethod == 'kar'">
{{ $tc('betterpayment.capture.labels.paymentMethodsInfo.invoice') }}
</span>
<span v-else-if="paymentMethod == 'kar_b2b'">
{{ $tc('betterpayment.capture.labels.paymentMethodsInfo.invoiceB2B') }}
</span>
</div>
</sw-label>
</sw-container>
<sw-container v-if="!isCapturableState">
<sw-label variant="warning">
{{ $tc('betterpayment.capture.labels.notCapturableState') }}
</sw-label>
</sw-container>
<sw-container columns="1fr 1fr" gap="0px 14px">
<sw-container rows="1fr 1fr 1fr 1fr" gap="10px 0px">
<sw-number-field
required numberType="float" :digits="2" :allowEmpty="false" size="small"
:disabled="!canCreateCapture"
:label="$tc('betterpayment.capture.labels.amount')"
v-model="capture.amount">
</sw-number-field>
<sw-text-field
required size="small"
:disabled="!canCreateCapture"
:label="$tc('betterpayment.capture.labels.invoiceId')"
v-model="capture.invoice_id">
</sw-text-field>
<sw-datepicker
required size="small" :label="$tc('betterpayment.capture.labels.date')"
:disabled="!canCreateCapture"
v-model="capture.execution_date">
</sw-datepicker>
<sw-text-field
:copyable="true" :copyableTooltip="true" disabled size="small"
v-model="betterPaymentTransactionId"
:label="$tc('betterpayment.capture.labels.transactionId')">
</sw-text-field>
</sw-container>
<sw-textarea-field
type="textarea" size="small"
:disabled="!canCreateCapture"
:label="$tc('betterpayment.capture.labels.comment')"
v-model="capture.comment">
</sw-textarea-field>
</sw-container>
<sw-button-process
style="float: right;"
:processSuccess="processSuccess"
:disabled="buttonDisabled || !canCreateCapture"
@click="createCapture"
variant="ghost"
size="small"
@process-finish="createCaptureFinished">
{{ $tc('betterpayment.capture.actions.createNew') }}
</sw-button-process>
</sw-card-section>
<sw-data-grid
:isLoading="isLoading"
:showSelection="false" :showActions="false"
:dataSource="captures" v-if="captures.length !== 0"
:columns="[
{ property: 'amount', label: $tc('betterpayment.capture.labels.amount') },
{ property: 'message', label: $tc('betterpayment.capture.labels.comment') },
{# TODO: parse it according to shop setting for datetime #}
{ property: 'created_at', label: $tc('betterpayment.capture.labels.date') }
]">
</sw-data-grid>
</template>
</sw-card>
{% endblock %}
Loading

0 comments on commit d3c8633

Please sign in to comment.