Test Setup Failed
Pull Request — master (#487)
by Andrew
08:10
created

TicketService::setTicketAmount()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 4
1
<?php
2
3
namespace Application\Bundle\DefaultBundle\Service;
4
5
use Application\Bundle\DefaultBundle\Entity\TicketCost;
6
use Application\Bundle\UserBundle\Entity\User;
7
use Doctrine\ORM\EntityManager;
8
use Stfalcon\Bundle\EventBundle\Entity\Event;
9
use Stfalcon\Bundle\EventBundle\Entity\Payment;
10
use Stfalcon\Bundle\EventBundle\Entity\Ticket;
11
use Stfalcon\Bundle\EventBundle\Entity\PromoCode;
12
use Symfony\Component\HttpFoundation\RequestStack;
13
use Symfony\Component\Routing\RouterInterface;
14
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
15
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16
use Symfony\Component\Translation\TranslatorInterface;
17
18
/**
19
 * Сервис для работы с билетами.
20
 */
21
class TicketService
22
{
23
    const CAN_BUY_TICKET = 'can buy ticket';
24
    const CAN_DOWNLOAD_TICKET = 'can download ticket';
25
    const TICKETS_SOLD_OUT = 'all tickets sold out';
26
    const CAN_WANNA_VISIT = 'can wanna visit';
27
    const WAIT_FOR_PAYMENT_RECEIVE = 'wit for payment receive';
28
    const PAID_FOR_ANOTHER = 'paid for another';
29
    const PAID_IS_RETURNED = 'paid is return';
30
    const EVENT_DONE = 'event done';
31
    const EVENT_DEFAULT_STATE = 'event default state';
32
33
    /** @var EntityManager */
34
    protected $em;
35
36
    /** @var array */
37
    protected $paymentsConfig;
38
39
    /** @var TranslatorInterface */
40
    protected $translator;
41
42
    /** @var RouterInterface */
43
    protected $router;
44
45
    /** @var TicketCostService */
46
    protected $ticketCostService;
47
48
    /** @var TokenStorageInterface */
49
    protected $tokenStorage;
50
51
    /**
52
     * TicketService constructor.
53
     *
54
     * @param EntityManager         $em
55
     * @param array                 $paymentsConfig
56
     * @param TranslatorInterface   $translator
57
     * @param RouterInterface       $router
58
     * @param TicketCostService     $ticketCostService
59
     * @param TokenStorageInterface $tokenStorage
60
     */
61
    public function __construct($em, $paymentsConfig, $translator, $router, $ticketCostService, TokenStorageInterface $tokenStorage)
62
    {
63
        $this->em = $em;
64
        $this->paymentsConfig = $paymentsConfig;
65
        $this->translator = $translator;
66
        $this->router = $router;
67
        $this->ticketCostService = $ticketCostService;
68
        $this->tokenStorage = $tokenStorage;
69
    }
70
71
    /**
72
     * Check discount for ticket.
73
     *
74
     * @param Ticket $ticket
75
     *
76
     * @return bool
77
     */
78
    public function isMustBeDiscount($ticket)
79
    {
80
        $event = $ticket->getEvent();
81
        $user = $ticket->getUser();
82
83
        if (!$event->getUseDiscounts()) {
84
            return false;
85
        }
86
87
        $paidPayments = $this->em->getRepository('StfalconEventBundle:Payment')
88
            ->findPaidPaymentsForUser($user);
89
90
        return \count($paidPayments) > 0;
91
    }
92
93
    /**
94
     * Set Ticket Amount with recalculate discount.
95
     *
96
     * @param Ticket     $ticket
97
     * @param float      $amount
98
     * @param bool       $isMustBeDiscount
99
     * @param TicketCost $currentTicketCost
100
     */
101
    public function setTicketAmount($ticket, $amount, $isMustBeDiscount, $currentTicketCost)
102
    {
103
        $ticket->setAmountWithoutDiscount($amount);
104
        $ticket->setAmount($amount);
105
        $ticket->setTicketCost($currentTicketCost);
106
        /** -1 flag means you need to discount in the configuration */
107
        $discount = $isMustBeDiscount ? -1 : 0;
108
        $this->setTicketBestDiscount($ticket, $ticket->getPromoCode(), $discount);
109
    }
110
111
    /**
112
     * Set the best (from promo code or standard discount) discount for ticket.
113
     *
114
     * @param Ticket    $ticket
115
     * @param PromoCode $promoCode
116
     * @param float     $discount
117
     *
118
     * @return Ticket
119
     */
120
    public function setTicketBestDiscount($ticket, $promoCode, $discount = -1)
121
    {
122
        if (-1 === $discount) {
123
            $discount = (float) $this->paymentsConfig['discount'];
124
        }
125
        if ($promoCode instanceof PromoCode && $promoCode->getDiscountAmount() / 100 > $discount) {
126
            $this->setTicketPromoCode($ticket, $promoCode);
127
        } else {
128
            $ticket->setPromoCode(null);
129
            $this->setTicketDiscount($ticket, $discount);
130
        }
131
132
        return $ticket;
133
    }
134
135
    /**
136
     * Set Ticket promo-code.
137
     *
138
     * @param Ticket    $ticket
139
     * @param PromoCode $promoCode
140
     *
141
     * @return Ticket
142
     */
143
    public function setTicketPromoCode($ticket, $promoCode)
144
    {
145
        $ticket->setPromoCode($promoCode);
146
        $this->setTicketDiscount($ticket, $promoCode->getDiscountAmount() / 100);
147
        $promoCode->incTmpUsedCount();
148
149
        return $ticket;
150
    }
151
152
    /**
153
     * Set ticket discount.
154
     *
155
     * @param Ticket $ticket
156
     * @param float  $discount
157
     *
158
     * @return Ticket
159
     */
160
    public function setTicketDiscount($ticket, $discount)
161
    {
162
        $amountWithDiscount = $ticket->getAmountWithoutDiscount() - ($ticket->getAmountWithoutDiscount() * $discount);
163
        $ticket
164
            ->setAmount($amountWithDiscount)
165
            ->setHasDiscount((float) $ticket->getAmount() !== (float) $ticket->getAmountWithoutDiscount());
166
        $this->em->flush();
167
168
        return $ticket;
169
    }
170
171
    /**
172
     * Create ticket for User and Event.
173
     *
174
     * @param Event $event
175
     * @param User  $user
176
     *
177
     * @return Ticket
178
     */
179
    public function createTicket($event, $user)
180
    {
181
        $ticket = (new Ticket())
182
            ->setEvent($event)
183
            ->setUser($user)
184
            ->setAmountWithoutDiscount($event->getCost())
185
            ->setAmount($event->getCost());
186
        $this->em->persist($ticket);
187
        $this->em->flush();
188
189
        return $ticket;
190
    }
191
192
    /**
193
     * @param Event      $event
194
     * @param string     $position
195
     * @param TicketCost $ticketCost
196
     *
197
     * @return array
198
     */
199
    public function getTicketHtmlData($event, $position, $ticketCost)
200
    {
201
        $eventState = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $eventState is dead and can be removed.
Loading history...
202
        $ticket = null;
203
        /** @var Payment $payment */
204
        $payment = null;
205
206
        $token = $this->tokenStorage->getToken();
207
208
        $user = $token instanceof TokenInterface && $token->getUser() instanceof User ? $token->getUser() : null;
209
        if ($user instanceof User) {
210
            $payment = $this->em
211
                ->getRepository('StfalconEventBundle:Payment')
212
                ->findPaymentByUserAndEvent($user, $event);
213
214
            $ticket = $this->em->getRepository('StfalconEventBundle:Ticket')
215
                ->findOneBy(['event' => $event->getId(), 'user' => $user->getId()]);
216
        }
217
218
        $eventState = null;
219
        $ticketState = null;
220
        $isDiv = null;
221
        $data = null;
222
        $class = '';
223
        $ticketClass = '';
224
        $href = null;
225
        $isMob = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $isMob is dead and can be removed.
Loading history...
226
        $caption = '';
227
        $ticketCaption = '';
228
229
        if ($event->isActiveAndFuture()) {
230
            if ($ticket && $ticket->isPaid()) {
231
                $ticketState = self::CAN_DOWNLOAD_TICKET;
232
            }
233
            if ($ticket && !$event->getReceivePayments()) {
234
                $eventState = self::WAIT_FOR_PAYMENT_RECEIVE;
235
            } elseif ($payment && $payment->isPaid()) {
236
                $eventState = self::PAID_FOR_ANOTHER;
237
//            } elseif ($event->getTicketsCost()->count() > 0 && !$this->ticketCostService->isEventHaveTickets($event)) {
238
//                $eventState = self::TICKETS_SOLD_OUT;
239
            } elseif (!$event->getReceivePayments()) {
240
                $eventState = self::CAN_WANNA_VISIT;
241
            } elseif (!$event->isHaveFreeTickets()) {
242
                $eventState = self::TICKETS_SOLD_OUT;
243
            } elseif (!$payment || ($payment && $payment->isPending())) {
244
                $eventState = self::CAN_BUY_TICKET;
245
            } elseif ($payment && $payment->isReturned()) {
246
                $eventState = self::PAID_IS_RETURNED;
247
            }
248
        } else {
249
            $eventState = self::EVENT_DONE;
250
        }
251
252
        $states =
253
            [
254
                'row' => [
255
                        self::CAN_DOWNLOAD_TICKET => '',
256
                        self::EVENT_DONE => 'event-row__status',
257
                        self::EVENT_DEFAULT_STATE => 'event-row__btn btn btn--primary btn--sm',
258
                    ],
259
                'card' => [
260
                        self::CAN_DOWNLOAD_TICKET => 'event-card__download',
261
                        self::EVENT_DONE => 'event-card__status',
262
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--sm event-card__btn',
263
                    ],
264
                'event_header' => [
265
                        self::CAN_DOWNLOAD_TICKET => 'event-card__download',
266
                        self::EVENT_DONE => 'event-header__status',
267
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg event-header__btn',
268
                    ],
269
                'event_fix_header' => [
270
                        self::CAN_DOWNLOAD_TICKET => '',
271
                        self::EVENT_DONE => 'fix-event-header__status',
272
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg fix-event-header__btn',
273
                    ],
274
                'event_fix_header_mob' => [
275
                        self::CAN_DOWNLOAD_TICKET => '',
276
                        self::EVENT_DONE => 'fix-event-header__status fix-event-header__status--mob',
277
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg fix-event-header__btn fix-event-header__btn--mob',
278
                    ],
279
                'event_action_mob' => [
280
                        self::CAN_DOWNLOAD_TICKET => 'event-action-mob__download',
281
                        self::EVENT_DONE => 'event-action-mob__status',
282
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg event-action-mob__btn',
283
                    ],
284
                'price_block_mob' => [
285
                        self::CAN_DOWNLOAD_TICKET => '',
286
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg cost__buy cost__buy--mob',
287
                    ],
288
                'price_block' => [
289
                        self::CAN_DOWNLOAD_TICKET => '',
290
                        self::EVENT_DEFAULT_STATE => 'btn btn--primary btn--lg cost__buy',
291
                    ],
292
            ];
293
294
        if (in_array(
295
            $eventState,
296
            [
297
                self::EVENT_DONE,
298
                self::PAID_IS_RETURNED,
299
                self::PAID_FOR_ANOTHER,
300
                self::TICKETS_SOLD_OUT,
301
            ]
302
        )) {
303
            $class = isset($states[$position][self::EVENT_DONE]) ? $states[$position][self::EVENT_DONE]
304
                : $states[$position][self::EVENT_DEFAULT_STATE];
305
        } else {
306
            $class = isset($states[$position][$eventState]) ? $states[$position][$eventState]
307
                : $states[$position][self::EVENT_DEFAULT_STATE];
308
        }
309
310
        $isMob = in_array($position, ['event_fix_header_mob', 'price_block_mob']);
311
312
        if ($event->isActiveAndFuture()) {
313
            $data = $event->getSlug();
314
315
            if (self::CAN_DOWNLOAD_TICKET === $ticketState) {
316
                $ticketCaption = $isMob ? $this->translator->trans('ticket.status.download')
317
                    : $this->translator->trans('ticket.status.download');
318
                $ticketClass = isset($states[$position][$ticketState]) ? $states[$position][$ticketState]
319
                    : $states[$position][self::EVENT_DEFAULT_STATE];
320
                if (!empty($ticketClass)) {
321
                    $href = $this->router->generate('event_ticket_download', ['eventSlug' => $event->getSlug()]);
322
                }
323
            }
324
325
            if (self::WAIT_FOR_PAYMENT_RECEIVE === $eventState) {
326
                $caption = $this->translator->trans('ticket.status.event.add');
327
                $isDiv = true;
328
            } elseif (self::PAID_FOR_ANOTHER === $eventState) {
329
                if ($isMob) {
330
                    $caption = $this->translator->trans('ticket.status.paid_mob');
331
                } else {
332
                    $caption = $this->translator->trans('ticket.status.paid');
333
                }
334
            } elseif (self::TICKETS_SOLD_OUT === $eventState) {
335
                $isDiv = true;
336
                if ($isMob) {
337
                    $caption = $this->translator->trans('ticket.status.sold_mob');
338
                } else {
339
                    $caption = $this->translator->trans('ticket.status.sold');
340
                }
341
            } elseif (self::CAN_WANNA_VISIT === $eventState && (!$user || !$user->isEventInWants($event))) {
342
                $class .= ' set-modal-header add-wants-visit-event';
343
                $caption = $this->translator->trans('ticket.status.take_apart');
344
            } elseif (self::CAN_WANNA_VISIT === $eventState && $user->isEventInWants($event)) {
0 ignored issues
show
Bug introduced by
The method isEventInWants() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

344
            } elseif (self::CAN_WANNA_VISIT === $eventState && $user->/** @scrutinizer ignore-call */ isEventInWants($event)) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
345
                $class .= ' set-modal-header sub-wants-visit-event';
346
                $caption = $this->translator->trans('ticket.status.not_take_apart');
347
            } elseif (self::CAN_BUY_TICKET === $eventState) {
348
                if ($isMob) {
349
                    $caption = $this->translator->trans('ticket.mob_status.pay');
350
                } elseif ('price_block' === $position) {
351
                    $amount = $ticketCost ? $ticketCost->getAmount() : $event->getBiggestTicketCost()->getAmount();
0 ignored issues
show
introduced by
$ticketCost is of type Application\Bundle\DefaultBundle\Entity\TicketCost, thus it always evaluated to true.
Loading history...
352
                    $altAmount = '≈$'.number_format($ticketCost->getAltAmount(), 0, ',', ' ');
353
                    $caption = $this->translator->trans('ticket.status.pay_for').' '.$this->translator
354
                            ->trans(
355
                                'payment.price',
356
                                [
357
                                    '%summ%' => number_format($amount, 0, ',', ' '),
358
                                ]
359
                            );
360
                    if ($ticketCost && $ticketCost->getAltAmount()) {
361
                        $caption .= '<span class="cost__dollars">'.$altAmount.'</span>';
362
                    }
363
                } else {
364
                    $caption = $this->translator->trans('ticket.status.pay');
365
                }
366
                if (!in_array($position, ['event_header', 'event_fix_header', 'event_fix_header_mob'])) {
367
                    $class .= ' get-payment';
368
                }
369
            } elseif (self::PAID_IS_RETURNED === $eventState) {
370
                if ($isMob) {
371
                    $caption = $this->translator->trans('ticket.status.payment_returned_mob');
372
                } else {
373
                    $caption = $this->translator->trans('ticket.status.payment_returned');
374
                }
375
            }
376
        } else {
377
            $isDiv = true;
378
            if ($isMob) {
379
                $caption = $this->translator->trans('ticket.status.event_done_mob');
380
            } else {
381
                $caption = $this->translator->trans('ticket.status.event_done');
382
            }
383
        }
384
385
        $result =
386
            [
387
                'class' => $class,
388
                'caption' => $caption,
389
                'ticket_caption' => $ticketCaption,
390
                'ticket_class' => $ticketClass,
391
                'href' => $href,
392
                'isDiv' => $isDiv,
393
                'data' => $data,
394
                'id' => $position.'-'.$data,
395
            ];
396
397
        return $result;
398
    }
399
}
400