PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Commands / Stats / GetStatsCommandHandler.php
ameliabooking / src / Application / Commands / Stats Last commit date
GetStatsCommand.php 6 months ago GetStatsCommandHandler.php 6 months ago
GetStatsCommandHandler.php
448 lines
1 <?php
2
3 /**
4 * @copyright © Melograno Ventures. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace AmeliaBooking\Application\Commands\Stats;
9
10 use AmeliaBooking\Application\Commands\CommandHandler;
11 use AmeliaBooking\Application\Commands\CommandResult;
12 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
13 use AmeliaBooking\Application\Services\Bookable\AbstractPackageApplicationService;
14 use AmeliaBooking\Application\Services\Booking\EventApplicationService;
15 use AmeliaBooking\Application\Services\Stats\StatsService;
16 use AmeliaBooking\Application\Services\User\ProviderApplicationService;
17 use AmeliaBooking\Domain\Collection\Collection;
18 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
19 use AmeliaBooking\Domain\Entity\Bookable\Service\Package;
20 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
21 use AmeliaBooking\Domain\Entity\Booking\Event\Event;
22 use AmeliaBooking\Domain\Entity\Entities;
23 use AmeliaBooking\Domain\Entity\User\Provider;
24 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
25 use AmeliaBooking\Domain\Services\Settings\SettingsService;
26 use AmeliaBooking\Domain\Services\User\ProviderService;
27 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
28 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
29 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
30 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
31 use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository;
32 use Exception;
33 use Interop\Container\Exception\ContainerException;
34 use Slim\Exception\ContainerValueNotFoundException;
35
36 /**
37 * Class GetStatsCommandHandler
38 *
39 * @package AmeliaBooking\Application\Commands\Stats
40 */
41 class GetStatsCommandHandler extends CommandHandler
42 {
43 /**
44 * @param GetStatsCommand $command
45 *
46 * @return CommandResult
47 * @throws ContainerValueNotFoundException
48 * @throws AccessDeniedException
49 * @throws InvalidArgumentException
50 * @throws QueryExecutionException
51 * @throws Exception
52 * @throws ContainerException
53 */
54 public function handle(GetStatsCommand $command)
55 {
56 if (!$command->getPermissionService()->currentUserCanRead(Entities::DASHBOARD)) {
57 throw new AccessDeniedException('You are not allowed to read coupons.');
58 }
59
60 $result = new CommandResult();
61
62 /** @var ServiceRepository $serviceRepository */
63 $serviceRepository = $this->container->get('domain.bookable.service.repository');
64 /** @var ProviderRepository $providerRepository */
65 $providerRepository = $this->container->get('domain.users.providers.repository');
66
67 /** @var StatsService $statsAS */
68 $statsAS = $this->container->get('application.stats.service');
69 /** @var SettingsService $settingsDS */
70 $settingsDS = $this->container->get('domain.settings.service');
71 /** @var AbstractPackageApplicationService $packageAS */
72 $packageAS = $this->container->get('application.bookable.package');
73 /** @var ProviderApplicationService $providerAS */
74 $providerAS = $this->container->get('application.user.provider.service');
75 /** @var EventApplicationService $eventAS */
76 $eventAS = $this->container->get('application.booking.event.service');
77 /** @var ProviderService $providerDS */
78 $providerDS = $this->container->get('domain.user.provider.service');
79
80 $params = $command->getField('params');
81
82 $startDate = $params['dates'][0] . ' 00:00:00';
83
84 $endDate = $params['dates'][1] . ' 23:59:59';
85
86 $previousPeriodStart = DateTimeService::getCustomDateTimeObject($startDate);
87
88 $previousPeriodEnd = DateTimeService::getCustomDateTimeObject($endDate);
89
90 $numberOfDays = $previousPeriodEnd->diff($previousPeriodStart)->days + 1;
91
92 $entities = [
93 'providers' => [],
94 'services' => [],
95 'packages' => [],
96 'events' => [],
97 ];
98
99 $pastDates = [
100 $previousPeriodStart->modify("-{$numberOfDays} day")->format('Y-m-d H:i:s'),
101 $previousPeriodEnd->modify("-{$numberOfDays} day")->format('Y-m-d H:i:s'),
102 ];
103
104 $past = isset($params['past']) ? (int)$params['past'] : true;
105
106 $stats = !empty($params) ? $params['stats'] : [];
107
108 $selectedEventsPeriodStatistics = [];
109
110 $previousEventsPeriodStatistics = [];
111
112 $eventsNewCustomers = 0;
113
114 $eventsReturningCustomers = 0;
115
116 $eventsPastCustomers = 0;
117
118 if (!$stats || in_array('events', $stats)) {
119 /** @var Collection $events */
120 $events = $eventAS->getEventsByCriteria(
121 [
122 'id' => !empty($params['events']) ? $params['events'] : [],
123 'dates' => [$startDate, $endDate],
124 'providers' => !empty($params['providers']) ? $params['providers'] : [],
125 'tag' => !empty($params['tag']) ? $params['tag'] : [],
126 'status' => BookingStatus::APPROVED,
127 ],
128 [
129 'fetchEventsPeriods' => true,
130 'fetchEventsTickets' => true,
131 'fetchBookings' => true,
132 'fetchBookingsTickets' => true,
133 'fetchBookingsPayments' => true,
134 'fetchApprovedBookings' => true,
135 ],
136 0
137 );
138
139 $selectedEventsPeriodStatistics = $statsAS->getEventsRangeStatisticsData(
140 $events,
141 $startDate,
142 $endDate
143 );
144
145 $eventsCustomersIds = [];
146
147 foreach ($selectedEventsPeriodStatistics as $statsData) {
148 foreach (!empty($statsData['customers']) ? $statsData['customers'] : [] as $id => $count) {
149 $eventsCustomersIds = array_unique(
150 array_merge($eventsCustomersIds, [$id])
151 );
152 }
153 }
154
155 /** @var Event $event */
156 foreach ($events->getItems() as $event) {
157 $entities['events'][$event->getId()->getValue()] = [
158 'name' => $event->getName()->getValue(),
159 'photo' => $event->getPicture()
160 ? $event->getPicture()->getThumbPath()
161 : null,
162 ];
163 }
164
165 if ($past) {
166 /** @var Collection $previousEvents */
167 $previousEvents = $eventAS->getEventsByCriteria(
168 [
169 'id' => !empty($params['events']) ? $params['events'] : [],
170 'dates' => $pastDates,
171 'providers' => !empty($params['providers']) ? $params['providers'] : [],
172 'tag' => !empty($params['tag']) ? $params['tag'] : [],
173 'status' => BookingStatus::APPROVED,
174 ],
175 [
176 'fetchEventsPeriods' => true,
177 'fetchEventsTickets' => true,
178 'fetchBookings' => true,
179 'fetchBookingsTickets' => true,
180 'fetchBookingsPayments' => true,
181 'fetchApprovedBookings' => true,
182 ],
183 0
184 );
185
186 $previousEventsPeriodStatistics = $statsAS->getEventsRangeStatisticsData(
187 $previousEvents,
188 $pastDates[0],
189 $pastDates[1]
190 );
191
192 $eventsPastCustomersIds = [];
193
194 foreach ($previousEventsPeriodStatistics as $statsData) {
195 foreach (!empty($statsData['customers']) ? $statsData['customers'] : [] as $id => $count) {
196 $eventsPastCustomersIds = array_unique(
197 array_merge($eventsPastCustomersIds, [$id])
198 );
199 }
200 }
201
202 $eventsPastCustomers = count($eventsPastCustomersIds);
203
204 $eventsReturningCustomers = count(array_intersect($eventsCustomersIds, $eventsPastCustomersIds));
205
206 $eventsNewCustomers = count($eventsCustomersIds) - $eventsReturningCustomers;
207 }
208 }
209
210 $selectedAppointmentsPeriodStatistics = [];
211
212 $previousAppointmentsPeriodStatistics = [];
213
214 $appointmentsNewCustomers = 0;
215
216 $appointmentsReturningCustomers = 0;
217
218 $appointmentsPastCustomers = 0;
219
220 if (!$stats || in_array('appointments', $stats)) {
221 $appointmentStatsParams = [
222 'dates' => [$startDate, $endDate],
223 'status' => BookingStatus::APPROVED,
224 'providers' => !empty($params['providers']) ? $params['providers'] : [],
225 'services' => !empty($params['services']) ? $params['services'] : [],
226 'locations' => !empty($params['locations']) ? $params['locations'] : [],
227 ];
228
229 /** @var Collection $services */
230 $services = $serviceRepository->getAllArrayIndexedById();
231
232 /** @var Collection $packages */
233 $packages = $packageAS->getPackages();
234
235 /** @var Collection $selectedProviders */
236 $selectedProviders = $providerRepository->getWithSchedule(
237 [
238 'dates' => $appointmentStatsParams['dates'],
239 'providers' => $appointmentStatsParams['providers'],
240 ],
241 false
242 );
243
244 $providerDS->filterProvidersAndScheduleByCriteria($selectedProviders, $params);
245
246 // Statistic
247 $selectedAppointmentsPeriodStatistics = $statsAS->getAppointmentsRangeStatisticsData(
248 $appointmentStatsParams,
249 $services,
250 $selectedProviders
251 );
252
253 $servicesIds = [];
254
255 $appointmentsCustomersIds = [];
256
257 foreach ($selectedAppointmentsPeriodStatistics as $statsData) {
258 foreach (!empty($statsData['providers']) ? $statsData['providers'] : [] as $id => $entityData) {
259 if (empty($entities['providers'][$id])) {
260 /** @var Provider $provider */
261 $provider = $selectedProviders->getItem($id);
262
263 $entities['providers'][$id] = [
264 'name' => $provider->getFullName(),
265 'photo' => $provider->getPicture()
266 ? $provider->getPicture()->getThumbPath()
267 : null,
268 'badge' => $provider->getBadgeId()
269 ? $providerAS->getBadge($provider->getBadgeId()->getValue())
270 : null,
271 ];
272 }
273
274 foreach ($entityData['intervals'] as $interval) {
275 $servicesIds = array_unique(
276 array_merge($servicesIds, $interval['services'])
277 );
278 }
279 }
280
281 foreach (!empty($statsData['services']) ? $statsData['services'] : [] as $id => $entityData) {
282 $servicesIds = array_unique(
283 array_merge($servicesIds, [$id])
284 );
285 }
286
287 foreach (!empty($statsData['packages']) ? $statsData['packages'] : [] as $id => $entityData) {
288 if (empty($entities['packages'][$id])) {
289 /** @var Package $package */
290 $package = $packages->getItem($id);
291
292 $entities['packages'][$id] = [
293 'name' => $package->getName()->getValue(),
294 'photo' => $package->getPicture()
295 ? $package->getPicture()->getThumbPath()
296 : null,
297 ];
298 }
299 }
300
301 foreach (!empty($statsData['customers']) ? $statsData['customers'] : [] as $id => $count) {
302 $appointmentsCustomersIds = array_unique(
303 array_merge($appointmentsCustomersIds, [$id])
304 );
305 }
306 }
307
308 /** @var Package $package */
309 foreach ($packages->getItems() as $package) {
310 if (empty($entities['packages'][$package->getId()->getValue()])) {
311 $entities['packages'][$package->getId()->getValue()] = [
312 'name' => $package->getName()->getValue(),
313 'photo' => $package->getPicture()
314 ? $package->getPicture()->getThumbPath()
315 : null,
316 ];
317 }
318 }
319
320 foreach ($servicesIds as $id) {
321 if (empty($entities['services'][$id])) {
322 /** @var Service $service */
323 $service = $services->getItem($id);
324
325 $entities['services'][$id] = [
326 'name' => $service->getName()->getValue(),
327 'photo' => $service->getPicture()
328 ? $service->getPicture()->getThumbPath()
329 : null,
330 ];
331 }
332 }
333
334 if ($past) {
335 /** @var Collection $pastProviders */
336 $pastProviders = $providerRepository->getWithSchedule(
337 [
338 'dates' => $pastDates,
339 'providers' => $appointmentStatsParams['providers'],
340 ],
341 false
342 );
343
344 $providerDS->filterProvidersAndScheduleByCriteria($pastProviders, $params);
345
346 $previousAppointmentsPeriodStatistics = $statsAS->getAppointmentsRangeStatisticsData(
347 array_merge(
348 $appointmentStatsParams,
349 [
350 'dates' => $pastDates,
351 ]
352 ),
353 $services,
354 $pastProviders
355 );
356
357 $appointmentsPastCustomersIds = [];
358
359 foreach ($previousAppointmentsPeriodStatistics as $statsData) {
360 foreach (!empty($statsData['customers']) ? $statsData['customers'] : [] as $id => $count) {
361 $appointmentsPastCustomersIds = array_unique(
362 array_merge($appointmentsPastCustomersIds, [$id])
363 );
364 }
365 }
366
367 $appointmentsPastCustomers = count($appointmentsPastCustomersIds);
368
369 $appointmentsReturningCustomers = count(array_intersect($appointmentsCustomersIds, $appointmentsPastCustomersIds));
370
371 $appointmentsNewCustomers = count($appointmentsCustomersIds) - $appointmentsReturningCustomers;
372 }
373 }
374
375 $selectedPeriodStatistics = [];
376 $previousPeriodStatistics = [];
377
378 foreach ($selectedAppointmentsPeriodStatistics as $key => $value) {
379 $selectedPeriodStatistics[$key] = $value;
380 }
381
382 foreach ($previousAppointmentsPeriodStatistics as $key => $value) {
383 $previousPeriodStatistics[$key] = $value;
384 }
385
386 foreach ($selectedEventsPeriodStatistics as $key => $value) {
387 $selectedPeriodStatistics[$key] = array_merge(
388 !empty($selectedPeriodStatistics[$key]) ? $selectedPeriodStatistics[$key] : [],
389 $value ?: []
390 );
391 }
392
393 foreach ($previousEventsPeriodStatistics as $key => $value) {
394 $previousPeriodStatistics[$key] = array_merge(
395 !empty($previousPeriodStatistics[$key]) ? $previousPeriodStatistics[$key] : [],
396 $value ?: []
397 );
398 }
399
400 $customersNoShowCount = [];
401
402 $customersNoShowCountIds = [];
403
404 $noShowTagEnabled = $settingsDS->getSetting('roles', 'enableNoShowTag');
405
406 if ($noShowTagEnabled && $customersNoShowCountIds) {
407 /** @var CustomerBookingRepository $bookingRepository */
408 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
409
410 $customersNoShowCount = $bookingRepository->countByNoShowStatus($customersNoShowCountIds);
411 }
412
413
414 $selectedPeriodStatistics = apply_filters('amelia_get_stats_filter', $selectedPeriodStatistics);
415
416 do_action('amelia_get_stats', $selectedPeriodStatistics);
417
418 $result->setResult(CommandResult::RESULT_SUCCESS);
419 $result->setMessage('Successfully retrieved stats.');
420 $result->setData(
421 [
422 'selectedPeriodStats' => $selectedPeriodStatistics,
423 'previousPeriodStats' => $previousPeriodStatistics,
424 'employeesStats' => !$stats || in_array('employees', $stats)
425 ? $statsAS->getEmployeesStats(['dates' => [$startDate, $endDate]])
426 : [],
427 'servicesStats' => !$stats || in_array('services', $stats)
428 ? $statsAS->getServicesStats(['dates' => [$startDate, $endDate]])
429 : [],
430 'locationsStats' => !$stats || in_array('locations', $stats)
431 ? $statsAS->getLocationsStats(['dates' => [$startDate, $endDate]])
432 : [],
433 'customersStats' => !$stats || in_array('customers', $stats)
434 ? [
435 'newCustomersCount' => $appointmentsNewCustomers + $eventsNewCustomers,
436 'returningCustomersCount' => $appointmentsReturningCustomers + $eventsReturningCustomers,
437 'totalPastPeriodCustomers' => $appointmentsPastCustomers + $eventsPastCustomers,
438 ]
439 : [],
440 'customersNoShowCount' => $customersNoShowCount ? array_values($customersNoShowCount) : [],
441 'entities' => $entities,
442 ]
443 );
444
445 return $result;
446 }
447 }
448