Refund process management

Edit on GitHub

Refund manages the retour refund process.

Overview

RefundFacade contains the following methods:

  • calculateRefund(array $salesOrderItems, SpySalesOrder $salesOrderEntity): Calculates the refundable amount for the sales order
  • saveRefund(RefundTransfer $refundTransfer) persists the calculated refund amount. RefundFacade::calculateRefund($salesOrderItems, $salesOrderEntity) returns RefundTransfer that contains the calculated refundable amount.

Using the Refund module

Usually, this functionality is integrated into the state machine processes and is called by a command.

A command plugin that calls the refund functionality can be similar to the following example:

<?php

namespace MyNamespace\Zed\MyBundle\Communication\Plugin\Command;

use Orm\Zed\Sales\Persistence\SpySalesOrder;
use Spryker\Zed\Kernel\Communication\AbstractPlugin;
use Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject;
use Spryker\Zed\Oms\Communication\Plugin\Oms\Command\CommandByOrderInterface;

class RefundCommand extends AbstractPlugin implements CommandByOrderInterface
{

    /**
     * @param array $orderItems
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $orderEntity
     * @param \Spryker\Zed\Oms\Business\Util\ReadOnlyArrayObject $data
     *
     * @return array
     */
    public function run(array $orderItems, SpySalesOrder $orderEntity, ReadOnlyArrayObject $data)
    {
        ...

        $result = $this->getFacade()->refundPayment($orderItems, $orderEntity);

        ...

        return [];
    }

}

The needed data to handle the refund is given inside the state machine command, and you only need to pass the data to the Business layer of your payment provider.

In your transaction model, you ask RefundFacade to calculate the refundable amount by calling RefundFacade::calculateRefund($orderItems, $orderEntity), which returns a RefundTransfer.

The RefundTransfer::$amount contains the refundable amount for the given data.

After that, you can tell your payment provider the amount to refund. When the response is successful, you need to save the refund data by calling RefundFacade::saveRefund($refundTransfer).

<?php

namespace MyNamespace\Zed\MyBundle\Business\Model\Transaction;

use Orm\Zed\Sales\Persistence\SpySalesOrder;
use Spryker\Zed\Refund\Business\RefundFacadeInterface;

class RefundTransaction
{

    /**
     * @var \Spryker\Zed\Refund\Business\RefundFacadeInterface
     */
    protected $refundFacade;

    /**
     * @param \Spryker\Zed\Refund\Business\RefundFacadeInterface
     */
    public function __construct(RefundFacadeInterface $refundFacade)
    {
        $this->refundFacade = $refundFacade;
    }

    ...

    /**
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $orderItems
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $orderEntity
     *
     * ...
     */
    public function refundTransaction(array $orderItems, SpySalesOrder $orderEntity)
    {
        ...

        $refundTransfer = $this->refundFacade()->calculateRefund($orderItems, $orderEntity);
        $result = $this->doRefund($refundTransfer);

        if ($result) {
            $this->refundFacade()->saveRefund($refundTransfer);
        }

        ...
    }

    ...

}

Extending the Refund module

The manner of calculating the refundable amount is different from one project to another. One refunds the shipment for every item, while the other one refunds the shipment only when all items are refunded.

The calculation of the refundable amount is achieved through a plugin mechanism.

The default implementation refunds all expenses when the last item is refunded. To change this behavior, create a new plugin that implements RefundCalculatorPluginInterface and replace the default one from the plugin stack with the new one.

This interface contains one method RefundCalculatorPluginInterface::calculateRefund(), that asks for a RefundTransfer object, OrderTransfer, and an array of items that need to be refunded.