Passed
Push — main ( 51ae85...215362 )
by Iain
04:38
created

RefundManager::issueProrateRefundForSubscription()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 17
c 0
b 0
f 0
nc 6
nop 4
dl 0
loc 27
rs 9.7
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright Iain Cambridge 2020-2023.
7
 *
8
 * Use of this software is governed by the Business Source License included in the LICENSE file and at https://getparthenon.com/docs/next/license.
9
 *
10
 * Change Date: TBD ( 3 years after 2.2.0 release )
11
 *
12
 * On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
13
 */
14
15
namespace Parthenon\Billing\Refund;
16
17
use Obol\Model\Refund\IssueRefund;
18
use Obol\Provider\ProviderInterface;
19
use Parthenon\Billing\Entity\BillingAdminInterface;
20
use Parthenon\Billing\Entity\Refund;
21
use Parthenon\Billing\Entity\Subscription;
22
use Parthenon\Billing\Repository\PaymentRepositoryInterface;
23
use Parthenon\Billing\Repository\RefundRepositoryInterface;
24
25
class RefundManager implements RefundManagerInterface
26
{
27
    public function __construct(
28
        private ProviderInterface $provider,
29
        private PaymentRepositoryInterface $paymentRepository,
30
        private RefundRepositoryInterface $refundRepository,
31
    ) {
32
    }
33
34
    public function issueFullRefundForSubscription(Subscription $subscription, BillingAdminInterface $billingAdmin): void
35
    {
36
        $payment = $this->paymentRepository->getLastPaymentForSubscription($subscription);
37
38
        $issueRefund = new IssueRefund();
39
        $issueRefund->setAmount($subscription->getMoneyAmount());
40
        $issueRefund->setPaymentExternalReference($payment->getPaymentReference());
41
42
        $refund = $this->provider->refunds()->issueRefund($issueRefund);
43
44
        $this->createEntityRecord($refund, $billingAdmin, $payment, $subscription);
45
    }
46
47
    public function issueProrateRefundForSubscription(Subscription $subscription, BillingAdminInterface $billingAdmin, \DateTimeInterface $start, \DateTimeInterface $end): void
48
    {
49
        if ('month' === $subscription->getPaymentSchedule()) {
50
            $days = date('t');
51
        } elseif ('year' === $subscription->getPaymentSchedule()) {
52
            $days = 365;
53
        } else {
54
            $days = 7;
55
        }
56
57
        $interval = $start->diff($end);
58
        if (!is_int($interval->days)) {
59
            return;
60
        }
61
62
        $payment = $this->paymentRepository->getLastPaymentForSubscription($subscription);
63
64
        $perDay = $subscription->getMoneyAmount()->dividedBy($days);
65
        $totalAmount = $perDay->multipliedBy(abs($interval->days))->multipliedBy($subscription->getSeats());
66
67
        $issueRefund = new IssueRefund();
68
        $issueRefund->setAmount($totalAmount);
69
        $issueRefund->setPaymentExternalReference($payment->getPaymentReference());
70
71
        $refund = $this->provider->refunds()->issueRefund($issueRefund);
72
73
        $this->createEntityRecord($refund, $billingAdmin, $payment, $subscription);
74
    }
75
76
    public function createEntityRecord(\Obol\Model\Refund $refund, BillingAdminInterface $billingAdmin, \Parthenon\Billing\Entity\Payment $payment, Subscription $subscription): void
77
    {
78
        $refundEn = new Refund();
79
        $refundEn->setAmount($refund->getAmount());
80
        $refundEn->setCurrency($refund->getCurrency());
81
        $refundEn->setExternalReference($refund->getId());
82
        $refundEn->setStatus('refunded');
83
        $refundEn->setBillingAdmin($billingAdmin);
84
        $refundEn->setPayment($payment);
85
        $refundEn->setCustomer($subscription->getCustomer());
86
        $refundEn->setCreatedAt(new \DateTime());
87
88
        $this->refundRepository->save($refundEn);
89
    }
90
}
91