SubscriptionPaymentStateResolver   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 5
dl 0
loc 98
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A resolve() 0 9 2
A applyTransition() 0 6 2
C getTargetTransition() 0 40 12
A getPaymentsWithState() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PH\Component\Core\Resolver;
6
7
use PH\Component\Core\Model\SubscriptionInterface;
8
use PH\Component\Core\Model\PaymentInterface;
9
use SM\Factory\FactoryInterface;
10
use SM\StateMachine\StateMachineInterface;
11
use PH\Component\Core\SubscriptionPaymentTransitions;
12
13
final class SubscriptionPaymentStateResolver implements StateResolverInterface
14
{
15
    /**
16
     * @var FactoryInterface
17
     */
18
    private $stateMachineFactory;
19
20
    /**
21
     * @param FactoryInterface $stateMachineFactory
22
     */
23
    public function __construct(FactoryInterface $stateMachineFactory)
24
    {
25
        $this->stateMachineFactory = $stateMachineFactory;
26
    }
27
28
    /**
29
     * {@inheritdoc}
30
     */
31
    public function resolve(SubscriptionInterface $subscription)
32
    {
33
        $stateMachine = $this->stateMachineFactory->get($subscription, SubscriptionPaymentTransitions::GRAPH);
34
        $targetTransition = $this->getTargetTransition($subscription);
35
36
        if (null !== $targetTransition) {
37
            $this->applyTransition($stateMachine, $targetTransition);
38
        }
39
    }
40
41
    /**
42
     * @param StateMachineInterface $stateMachine
43
     * @param string                $transition
44
     */
45
    private function applyTransition(StateMachineInterface $stateMachine, $transition)
46
    {
47
        if ($stateMachine->can($transition)) {
48
            $stateMachine->apply($transition);
49
        }
50
    }
51
52
    /**
53
     * @param SubscriptionInterface $subscription
54
     *
55
     * @return string|null
56
     */
57
    private function getTargetTransition(SubscriptionInterface $subscription)
58
    {
59
        $refundedPaymentTotal = 0;
60
        $refundedPayments = $this->getPaymentsWithState($subscription, PaymentInterface::STATE_REFUNDED);
61
62
        foreach ($refundedPayments as $payment) {
63
            $refundedPaymentTotal += $payment->getAmount();
64
        }
65
66
        if (0 < $refundedPayments->count() && $refundedPaymentTotal >= $subscription->getTotal()) {
67
            return SubscriptionPaymentTransitions::TRANSITION_REFUND;
68
        }
69
70
        if ($refundedPaymentTotal < $subscription->getTotal() && 0 < $refundedPaymentTotal) {
71
            return SubscriptionPaymentTransitions::TRANSITION_PARTIALLY_REFUND;
72
        }
73
74
        $completedPaymentTotal = 0;
75
        $completedPayments = $this->getPaymentsWithState($subscription, PaymentInterface::STATE_COMPLETED);
76
77
        foreach ($completedPayments as $payment) {
78
            $completedPaymentTotal += $payment->getAmount();
79
        }
80
81
        if (0 < $completedPayments->count() && $completedPaymentTotal >= $subscription->getTotal()) {
82
            return SubscriptionPaymentTransitions::TRANSITION_PAY;
83
        }
84
85
        if ($completedPaymentTotal < $subscription->getTotal() && 0 < $completedPaymentTotal) {
86
            return SubscriptionPaymentTransitions::TRANSITION_PARTIALLY_PAY;
87
        }
88
89
        $cancelledPayments = $this->getPaymentsWithState($subscription, PaymentInterface::STATE_CANCELLED);
90
91
        if (0 < $cancelledPayments->count()) {
92
            return SubscriptionPaymentTransitions::TRANSITION_CANCEL;
93
        }
94
95
        return null;
96
    }
97
98
    /**
99
     * @param SubscriptionInterface $subscription
100
     * @param string                $state
101
     *
102
     * @return \Doctrine\Common\Collections\Collection
103
     */
104
    private function getPaymentsWithState(SubscriptionInterface $subscription, string $state)
105
    {
106
        return $subscription->getPayments()->filter(function (PaymentInterface $payment) use ($state) {
107
            return $state === $payment->getState();
108
        });
109
    }
110
}
111