Completed
Push — master ( f95222...60b5cc )
by Michał
444:52 queued 431:46
created

StateResolver::countOrderShipmentsInState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 1
eloc 6
nc 1
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Component\Core\OrderProcessing;
13
14
use SM\Factory\FactoryInterface;
15
use SM\StateMachine\StateMachineInterface;
16
use Sylius\Component\Core\Model\OrderInterface;
17
use Sylius\Component\Core\Model\OrderShippingStates;
18
use Sylius\Component\Core\Model\PaymentInterface;
19
use Sylius\Component\Core\Model\ShipmentInterface;
20
use Sylius\Component\Core\OrderPaymentStates;
21
use Sylius\Component\Core\OrderPaymentTransitions;
22
use Sylius\Component\Core\OrderShippingTransitions;
23
24
/**
25
 * @author Paweł Jędrzejewski <[email protected]>
26
 * @author Arkadiusz Krakowiak <[email protected]>
27
 * @author Grzegorz Sadowski <[email protected]>
28
 */
29
class StateResolver implements StateResolverInterface
30
{
31
    /**
32
     * @var FactoryInterface
33
     */
34
    private $stateMachineFactory;
35
36
    /**
37
     * @param FactoryInterface $stateMachineFactory
38
     */
39
    public function __construct(FactoryInterface $stateMachineFactory)
40
    {
41
        $this->stateMachineFactory = $stateMachineFactory;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function resolvePaymentState(OrderInterface $order)
48
    {
49
        $stateMachine = $this->stateMachineFactory->get($order, OrderPaymentTransitions::GRAPH);
50
51
        if (OrderPaymentStates::STATE_PAID === $order->getPaymentState()) {
52
            return;
53
        }
54
55
        if ($order->hasPayments()) {
56
            $completedPaymentTotal = 0;
57
            $payments = $order->getPayments()->filter(function (PaymentInterface $payment) {
58
                return PaymentInterface::STATE_COMPLETED === $payment->getState();
59
            });
60
61
            foreach ($payments as $payment) {
62
                $completedPaymentTotal += $payment->getAmount();
63
            }
64
65
            if (0 < $payments->count() && $completedPaymentTotal >= $order->getTotal()) {
66
                $this->applyTransition($stateMachine, OrderPaymentTransitions::TRANSITION_PAY);
67
68
                return;
69
            }
70
71
            if ($completedPaymentTotal < $order->getTotal() && 0 < $completedPaymentTotal) {
72
                $this->applyTransition($stateMachine, OrderPaymentTransitions::TRANSITION_PARTIALLY_PAY);
73
74
                return;
75
            }
76
        }
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function resolveShippingState(OrderInterface $order)
83
    {
84
        if (OrderShippingStates::STATE_SHIPPED === $order->getShippingState()) {
85
            return;
86
        }
87
        /** @var StateMachine $stateMachine */
88
        $stateMachine = $this->stateMachineFactory->get($order, OrderShippingTransitions::GRAPH);
89
90
        if ($this->allShipmentsInStateButOrderStateNotUpdated($order, ShipmentInterface::STATE_SHIPPED, OrderShippingStates::STATE_SHIPPED)) {
91
            $stateMachine->apply(OrderShippingTransitions::TRANSITION_SHIP);
92
        }
93
94
        if ($this->isPartiallyShippedButOrderStateNotUpdated($order)) {
95
            $stateMachine->apply(OrderShippingTransitions::TRANSITION_PARTIALLY_SHIP);
96
        }
97
    }
98
99
    /**
100
     * @param OrderInterface $order
101
     * @param string $shipmentState
102
     *
103
     * @return int
104
     */
105
    private function countOrderShipmentsInState(OrderInterface $order, $shipmentState)
106
    {
107
        $shipments = $order->getShipments();
108
109
        return $shipments
110
            ->filter(function (ShipmentInterface $shipment) use ($shipmentState) {
111
                return $shipment->getState() === $shipmentState;
112
            })
113
            ->count()
114
        ;
115
    }
116
117
    /**
118
     * @param OrderInterface $order
119
     * @param string $shipmentState
120
     * @param string $orderShippingState
121
     *
122
     * @return bool
123
     */
124
    private function allShipmentsInStateButOrderStateNotUpdated(OrderInterface $order, $shipmentState, $orderShippingState)
125
    {
126
        $shipmentInStateAmount = $this->countOrderShipmentsInState($order, $shipmentState);
127
        $shipmentAmount = $order->getShipments()->count();
128
129
        return $shipmentAmount === $shipmentInStateAmount && $orderShippingState !== $order->getShippingState();
130
    }
131
132
    /**
133
     * @param OrderInterface $order
134
     *
135
     * @return bool
136
     */
137
    private function isPartiallyShippedButOrderStateNotUpdated(OrderInterface $order)
138
    {
139
        $shipmentInShippedStateAmount = $this->countOrderShipmentsInState($order, ShipmentInterface::STATE_SHIPPED);
140
        $shipmentAmount = $order->getShipments()->count();
141
142
        return
143
            1 <= $shipmentInShippedStateAmount &&
144
            $shipmentInShippedStateAmount < $shipmentAmount &&
145
            OrderShippingStates::STATE_PARTIALLY_SHIPPED !== $order->getShippingState()
146
        ;
147
    }
148
149
    /**
150
     * @param StateMachineInterface $stateMachine
151
     * @param string $transition
152
     */
153
    private function applyTransition(StateMachineInterface $stateMachine, $transition)
154
    {
155
        if ($stateMachine->can($transition)) {
156
            $stateMachine->apply($transition);
157
        }
158
    }
159
}
160