Completed
Push — master ( 5bb9e4...33b9a4 )
by Serhii
09:16 queued 09:08
created

GenerateSetHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 4
dl 0
loc 11
rs 9.4285
1
<?php
2
3
namespace AppBundle\Services\Ticket;
4
5
use AppBundle\Entity\PerformanceEvent;
6
use AppBundle\Entity\Seat;
7
use AppBundle\Entity\Ticket;
8
use AppBundle\Entity\VenueSector;
9
use AppBundle\Exception\PriceCategory\PlaceArrangementException;
10
use AppBundle\Exception\Ticket\NotEqualToSeatNumberException;
11
use AppBundle\Repository\PriceCategoryRepository;
12
use AppBundle\Repository\SeatRepository;
13
use AppBundle\Repository\VenueSectorRepository;
14
use AppBundle\Services\PriceCategory\GetSeatsHandler;
15
16
class GenerateSetHandler
17
{
18
    /** @var GetSeatsHandler */
19
    private $priceCategoryGetSeats;
20
21
    /** @var SeatRepository */
22
    private $seatRepository;
23
24
    /** @var VenueSectorRepository */
25
    private $venueSectorRepository;
26
27
    /** @var PriceCategoryRepository */
28
    private $priceCategoryRepository;
29
30
    /**
31
     * @param SeatRepository $seatRepository
32
     * @param VenueSectorRepository $venueSectorRepository
33
     * @param PriceCategoryRepository $priceCategoryRepository
34
     * @param GetSeatsHandler $priceCategoryGetSeats
35
     */
36
    public function __construct(
37
        GetSeatsHandler $priceCategoryGetSeats,
38
        SeatRepository $seatRepository,
39
        VenueSectorRepository $venueSectorRepository,
40
        PriceCategoryRepository $priceCategoryRepository
41
    ) {
42
        $this->priceCategoryGetSeats = $priceCategoryGetSeats;
43
        $this->seatRepository = $seatRepository;
44
        $this->venueSectorRepository = $venueSectorRepository;
45
        $this->priceCategoryRepository = $priceCategoryRepository;
46
    }
47
48
    /**
49
     * @param PerformanceEvent $performanceEvent
50
     *
51
     * @return Ticket[]
52
     */
53
    public function handle(PerformanceEvent $performanceEvent): array
54
    {
55
        return $this->generateSetForPerformanceEvent($performanceEvent);
56
    }
57
58
    /**
59
     * @param PerformanceEvent $performanceEvent
60
     *
61
     * @return Ticket[]
62
     */
63
    protected function generateSetForPerformanceEvent(PerformanceEvent $performanceEvent): array
64
    {
65
        $venueSectors = $this->venueSectorRepository->getByVenue($performanceEvent->getVenue());
66
        $tickets = [];
67
        foreach ($venueSectors as $venueSector) {
68
            $tickets = array_merge(
69
                $tickets,
70
                $this->generateSetForPerformanceEventAndVenueSector($performanceEvent, $venueSector)
71
            );
72
        }
73
        $this->validateTickets($performanceEvent, $tickets);
74
75
        // TODO Logging for generated ticket
76
77
        return $tickets;
78
    }
79
80
    /**
81
     * @param PerformanceEvent $performanceEvent
82
     * @param VenueSector $venueSectors
83
     *
84
     * @return Ticket[]
85
     */
86
    protected function generateSetForPerformanceEventAndVenueSector(
87
        PerformanceEvent $performanceEvent,
88
        VenueSector $venueSectors
89
    ): array {
90
        $tickets = [];
91
92
        $priceCategories = $this->priceCategoryRepository
93
            ->getByPerformanceEventAndVenueSector($performanceEvent, $venueSectors);
94
95
        $seats = [];
96
        foreach ($priceCategories as $priceCategory) {
97
            $priceCategorySeats = $this->priceCategoryGetSeats->handle($priceCategory);
98
            $seats =  array_merge(
99
                $seats,
100
                $priceCategorySeats
101
            );
102
103
            /** @var Seat $seat */
104
            foreach ($priceCategorySeats as $seat) {
105
                // TODO ticket status From ROW for Sale
106
107
                $tickets[] = new Ticket(
108
                    $seat,
109
                    $performanceEvent,
110
                    $priceCategory,
111
                    $priceCategory->getPrice(),
112
                    $performanceEvent->getSeriesDate(),
113
                    $performanceEvent->getSeriesNumber()
114
                );
115
            }
116
        };
117
118
        $this->validateSeatsDuplicates($venueSectors, $seats);
119
        $this->validateSeatsNumberForVenueSector($venueSectors, $seats);
120
121
        return $tickets;
122
    }
123
124
    /**
125
     * @param VenueSector $venueSectors
126
     * @param Seat[] $seats
127
     * @throws PlaceArrangementException
128
     */
129
    protected function validateSeatsNumberForVenueSector(VenueSector $venueSectors, array $seats)
130
    {
131
        $venueSectorSeats = $this->seatRepository->getByVenueSector($venueSectors);
132
        if (count($venueSectorSeats) <> count($seats)) {
133
            throw new PlaceArrangementException(
134
                sprintf(
135
                    'For %s number of seats: %s but should be: %s',
136
                    $venueSectors,
137
                    count($seats),
138
                    count($venueSectorSeats)
139
                )
140
            );
141
        }
142
    }
143
144
    /**
145
     * @param VenueSector $venueSectors
146
     * @param Seat[] $seats
147
     * @throws PlaceArrangementException
148
     */
149
    protected function validateSeatsDuplicates(VenueSector $venueSectors, array $seats)
150
    {
151
        if (count(array_unique($seats)) < count($seats)) {
152
            throw new PlaceArrangementException(
153
                sprintf('For %s PriceCategories arranged incorrectly. Duplicates appears.', $venueSectors)
154
            );
155
        }
156
    }
157
158
    /**
159
     * @param PerformanceEvent $performanceEvent
160
     * @param Ticket[] $ticket
161
     * @throws NotEqualToSeatNumberException
162
     */
163
    protected function validateTickets(PerformanceEvent $performanceEvent, array $ticket)
164
    {
165
        $venueSeats = $this->seatRepository->getByVenue($performanceEvent->getVenue());
166
        if (count($venueSeats) <> count($ticket)) {
167
            throw new NotEqualToSeatNumberException(
168
                sprintf(
169
                    'For %s number of tickets not equal to seats number. Seats: %s. Tickets: %s.',
170
                    $performanceEvent,
171
                    count($venueSeats),
172
                    count($ticket)
173
                )
174
            );
175
        }
176
    }
177
}
178