Passed
Push — main ( 44657d...ffb381 )
by Iain
04:31
created

SubscriptionManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 10
dl 0
loc 12
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Subscription;
16
17
use Obol\Provider\ProviderInterface;
18
use Parthenon\Billing\Dto\StartSubscriptionDto;
19
use Parthenon\Billing\Entity\CustomerInterface;
20
use Parthenon\Billing\Entity\PaymentDetails;
21
use Parthenon\Billing\Entity\Subscription;
22
use Parthenon\Billing\Obol\BillingDetailsFactoryInterface;
23
use Parthenon\Billing\Obol\PaymentFactoryInterface;
24
use Parthenon\Billing\Obol\SubscriptionFactoryInterface;
25
use Parthenon\Billing\Plan\Plan;
26
use Parthenon\Billing\Plan\PlanManagerInterface;
27
use Parthenon\Billing\Plan\PlanPrice;
28
use Parthenon\Billing\Repository\PaymentDetailsRepositoryInterface;
29
use Parthenon\Billing\Repository\PaymentRepositoryInterface;
30
use Parthenon\Billing\Repository\PriceRepositoryInterface;
31
use Parthenon\Billing\Repository\SubscriptionPlanRepositoryInterface;
32
use Parthenon\Billing\Repository\SubscriptionRepositoryInterface;
33
use Parthenon\Common\Exception\GeneralException;
34
35
class SubscriptionManager implements SubscriptionManagerInterface
36
{
37
    public function __construct(
38
        private PaymentDetailsRepositoryInterface $paymentDetailsRepository,
39
        private ProviderInterface $provider,
40
        private BillingDetailsFactoryInterface $billingDetailsFactory,
41
        private PaymentFactoryInterface $paymentFactory,
42
        private SubscriptionFactoryInterface $subscriptionFactory,
43
        private PaymentRepositoryInterface $paymentRepository,
44
        private PlanManagerInterface $planManager,
45
        private SubscriptionPlanRepositoryInterface $subscriptionPlanRepository,
46
        private PriceRepositoryInterface $priceRepository,
47
        private SubscriptionRepositoryInterface $subscriptionRepository,
48
    ) {
49
    }
50
51
    public function startSubscription(CustomerInterface $customer, Plan $plan, PlanPrice $planPrice, PaymentDetails $paymentDetails, int $seatNumbers): Subscription
52
    {
53
        $billingDetails = $this->billingDetailsFactory->createFromCustomerAndPaymentDetails($customer, $paymentDetails);
54
        $obolSubscription = $this->subscriptionFactory->createSubscription($billingDetails, $planPrice, $seatNumbers);
55
56
        if ($this->subscriptionRepository->hasActiveMainSubscription($customer)) {
57
            $main = false;
58
            $subscription = $this->subscriptionRepository->getActiveMainSubscription($customer);
59
60
            if ($subscription->getCurrency() != $planPrice->getCurrency()) {
61
                throw new GeneralException("Can't add a child subscription for a different currency");
62
            }
63
64
            $obolSubscription->setParentReference($subscription->getExternalReference());
65
        } else {
66
            $main = true;
67
        }
68
69
        $subscriptionCreationResponse = $this->provider->payments()->startSubscription($obolSubscription);
70
        if ($subscriptionCreationResponse->hasCustomerCreation()) {
71
            $customer->setPaymentProviderDetailsUrl($subscriptionCreationResponse->getCustomerCreation()->getDetailsUrl());
72
            $customer->setExternalCustomerReference($subscriptionCreationResponse->getCustomerCreation()->getReference());
73
        }
74
        $payment = $this->paymentFactory->fromSubscriptionCreation($subscriptionCreationResponse);
75
        $this->paymentRepository->save($payment);
76
77
        $subscription = new Subscription();
78
        $subscription->setPlanName($plan->getName());
79
        $subscription->setPaymentSchedule($planPrice->getSchedule());
80
        $subscription->setActive(true);
81
        $subscription->setMoneyAmount($planPrice->getPriceAsMoney());
82
        $subscription->setStatus(\Parthenon\Billing\Entity\EmbeddedSubscription::STATUS_ACTIVE);
83
        $subscription->setExternalReference($subscriptionCreationResponse->getSubscriptionId());
84
        $subscription->setSeats($seatNumbers);
85
        $subscription->setCreatedAt(new \DateTime());
86
        $subscription->setUpdatedAt(new \DateTime());
87
        $subscription->setCustomer($customer);
88
        $subscription->setMainSubscription($main);
89
90
        if ($plan->hasEntityId()) {
91
            $subscriptionPlan = $this->subscriptionPlanRepository->findById($plan->getEntityId());
92
            $subscription->setSubscriptionPlan($subscriptionPlan);
93
        }
94
95
        if ($planPrice->hasEntityId()) {
96
            $price = $this->priceRepository->findById($planPrice->getEntityId());
97
            $subscription->setPrice($price);
98
        }
99
100
        $this->subscriptionRepository->save($subscription);
101
102
        return $subscription;
103
    }
104
105
    public function startSubscriptionWithDto(CustomerInterface $customer, StartSubscriptionDto $startSubscriptionDto): Subscription
106
    {
107
        if (!$startSubscriptionDto->getPaymentDetailsId()) {
108
            $paymentDetails = $this->paymentDetailsRepository->getDefaultPaymentDetailsForCustomer($customer);
109
        } else {
110
            $paymentDetails = $this->paymentDetailsRepository->findById($startSubscriptionDto->getPaymentDetailsId());
111
        }
112
113
        $plan = $this->planManager->getPlanByName($startSubscriptionDto->getPlanName());
114
        $planPrice = $plan->getPriceForPaymentSchedule($startSubscriptionDto->getSchedule(), $startSubscriptionDto->getCurrency());
115
116
        return $this->startSubscription($customer, $plan, $planPrice, $paymentDetails, $startSubscriptionDto->getSeatNumbers());
117
    }
118
}
119