AppointmentFactory.php
2 weeks ago
CustomerBookingExtraFactory.php
6 months ago
CustomerBookingFactory.php
2 weeks ago
AppointmentFactory.php
406 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\Domain\Factory\Booking\Appointment; |
| 9 | |
| 10 | use AmeliaBooking\Domain\Collection\Collection; |
| 11 | use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; |
| 12 | use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; |
| 13 | use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; |
| 14 | use AmeliaBooking\Domain\Factory\Location\LocationFactory; |
| 15 | use AmeliaBooking\Domain\Factory\User\UserFactory; |
| 16 | use AmeliaBooking\Domain\Factory\Zoom\ZoomFactory; |
| 17 | use AmeliaBooking\Domain\Services\DateTime\DateTimeService; |
| 18 | use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; |
| 19 | use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; |
| 20 | use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; |
| 21 | use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; |
| 22 | use AmeliaBooking\Domain\ValueObjects\String\Description; |
| 23 | use AmeliaBooking\Domain\ValueObjects\String\Label; |
| 24 | use AmeliaBooking\Domain\ValueObjects\String\Token; |
| 25 | |
| 26 | /** |
| 27 | * Class AppointmentFactory |
| 28 | * |
| 29 | * @package AmeliaBooking\Domain\Factory\Booking\Appointment |
| 30 | */ |
| 31 | class AppointmentFactory |
| 32 | { |
| 33 | /** |
| 34 | * @param $data |
| 35 | * |
| 36 | * @return Appointment |
| 37 | * @throws InvalidArgumentException |
| 38 | */ |
| 39 | public static function create($data) |
| 40 | { |
| 41 | $appointment = new Appointment( |
| 42 | new DateTimeValue(DateTimeService::getCustomDateTimeObject($data['bookingStart'])), |
| 43 | new DateTimeValue(DateTimeService::getCustomDateTimeObject($data['bookingEnd'])), |
| 44 | $data['notifyParticipants'], |
| 45 | new Id($data['serviceId']), |
| 46 | new Id($data['providerId']) |
| 47 | ); |
| 48 | |
| 49 | if (isset($data['createPaymentLinks'])) { |
| 50 | $appointment->setCreatePaymentLinks($data['createPaymentLinks']); |
| 51 | } |
| 52 | |
| 53 | if (!empty($data['id'])) { |
| 54 | $appointment->setId(new Id($data['id'])); |
| 55 | } |
| 56 | |
| 57 | if (!empty($data['parentId'])) { |
| 58 | $appointment->setParentId(new Id($data['parentId'])); |
| 59 | } |
| 60 | |
| 61 | if (!empty($data['locationId'])) { |
| 62 | $appointment->setLocationId(new Id($data['locationId'])); |
| 63 | } |
| 64 | |
| 65 | if (!empty($data['location'])) { |
| 66 | $appointment->setLocation(LocationFactory::create($data['location'])); |
| 67 | } |
| 68 | |
| 69 | if (isset($data['internalNotes'])) { |
| 70 | $appointment->setInternalNotes(new Description($data['internalNotes'])); |
| 71 | } |
| 72 | |
| 73 | if (isset($data['status'])) { |
| 74 | $appointment->setStatus(new BookingStatus($data['status'])); |
| 75 | } |
| 76 | |
| 77 | if (isset($data['provider'])) { |
| 78 | $appointment->setProvider(UserFactory::create($data['provider'])); |
| 79 | } |
| 80 | |
| 81 | if (!empty($data['assignedEmployeeId'])) { |
| 82 | $appointment->setAssignedEmployeeId(new Id($data['assignedEmployeeId'])); |
| 83 | } |
| 84 | |
| 85 | if (isset($data['service'])) { |
| 86 | $appointment->setService(ServiceFactory::create($data['service'])); |
| 87 | } |
| 88 | |
| 89 | if (!empty($data['googleCalendarEventId'])) { |
| 90 | $appointment->setGoogleCalendarEventId(new Token($data['googleCalendarEventId'])); |
| 91 | } |
| 92 | |
| 93 | if (!empty($data['googleMeetUrl'])) { |
| 94 | $appointment->setGoogleMeetUrl($data['googleMeetUrl']); |
| 95 | } |
| 96 | |
| 97 | if (!empty($data['outlookCalendarEventId'])) { |
| 98 | $appointment->setOutlookCalendarEventId(new Label($data['outlookCalendarEventId'])); |
| 99 | } |
| 100 | |
| 101 | if (!empty($data['microsoftTeamsUrl'])) { |
| 102 | $appointment->setMicrosoftTeamsUrl($data['microsoftTeamsUrl']); |
| 103 | } |
| 104 | |
| 105 | if (!empty($data['appleCalendarEventId'])) { |
| 106 | $appointment->setAppleCalendarEventId(new Label($data['appleCalendarEventId'])); |
| 107 | } |
| 108 | |
| 109 | if (!empty($data['zoomMeeting']['id'])) { |
| 110 | $zoomMeeting = ZoomFactory::create( |
| 111 | $data['zoomMeeting'] |
| 112 | ); |
| 113 | |
| 114 | $appointment->setZoomMeeting($zoomMeeting); |
| 115 | } |
| 116 | |
| 117 | if (isset($data['lessonSpace']) && !empty($data['lessonSpace'])) { |
| 118 | $appointment->setLessonSpace($data['lessonSpace']); |
| 119 | } |
| 120 | |
| 121 | if (isset($data['isRescheduled'])) { |
| 122 | $appointment->setRescheduled(new BooleanValueObject($data['isRescheduled'])); |
| 123 | } |
| 124 | |
| 125 | if (array_key_exists('isChangedStatus', $data)) { |
| 126 | $appointment->setChangedStatus(new BooleanValueObject($data['isChangedStatus'])); |
| 127 | } |
| 128 | |
| 129 | if (!empty($data['initialAppointmentDateTime']['bookingStart'])) { |
| 130 | $appointment->setInitialBookingStart( |
| 131 | new DateTimeValue( |
| 132 | DateTimeService::getCustomDateTimeObject($data['initialAppointmentDateTime']['bookingStart']) |
| 133 | ) |
| 134 | ); |
| 135 | } |
| 136 | |
| 137 | if (!empty($data['initialAppointmentDateTime']['bookingEnd'])) { |
| 138 | $appointment->setInitialBookingEnd( |
| 139 | new DateTimeValue( |
| 140 | DateTimeService::getCustomDateTimeObject($data['initialAppointmentDateTime']['bookingEnd']) |
| 141 | ) |
| 142 | ); |
| 143 | } |
| 144 | |
| 145 | $bookings = new Collection(); |
| 146 | |
| 147 | if (isset($data['bookings'])) { |
| 148 | foreach ((array)$data['bookings'] as $key => $value) { |
| 149 | $bookings->addItem( |
| 150 | CustomerBookingFactory::create($value), |
| 151 | $key |
| 152 | ); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | $appointment->setBookings($bookings); |
| 157 | |
| 158 | return $appointment; |
| 159 | } |
| 160 | |
| 161 | /** |
| 162 | * @param array $rows |
| 163 | * |
| 164 | * @return Collection |
| 165 | * @throws InvalidArgumentException |
| 166 | */ |
| 167 | public static function createCollection($rows) |
| 168 | { |
| 169 | $appointments = []; |
| 170 | |
| 171 | foreach ($rows as $row) { |
| 172 | $appointmentId = $row['appointment_id']; |
| 173 | $bookingId = isset($row['booking_id']) ? $row['booking_id'] : null; |
| 174 | $bookingExtraId = isset($row['bookingExtra_id']) ? $row['bookingExtra_id'] : null; |
| 175 | $paymentId = isset($row['payment_id']) ? $row['payment_id'] : null; |
| 176 | $couponId = isset($row['coupon_id']) ? $row['coupon_id'] : null; |
| 177 | $customerId = isset($row['customer_id']) ? $row['customer_id'] : null; |
| 178 | $providerId = isset($row['provider_id']) ? $row['provider_id'] : null; |
| 179 | $locationId = isset($row['location_id']) ? $row['location_id'] : null; |
| 180 | $serviceId = isset($row['service_id']) ? $row['service_id'] : null; |
| 181 | |
| 182 | if (!array_key_exists($appointmentId, $appointments)) { |
| 183 | $zoomMeetingJson = !empty($row['appointment_zoom_meeting']) ? |
| 184 | json_decode($row['appointment_zoom_meeting'], true) : null; |
| 185 | |
| 186 | $appointments[$appointmentId] = [ |
| 187 | 'id' => $appointmentId, |
| 188 | 'parentId' => isset($row['appointment_parentId']) ? |
| 189 | $row['appointment_parentId'] : null, |
| 190 | 'bookingStart' => DateTimeService::getCustomDateTimeFromUtc( |
| 191 | $row['appointment_bookingStart'] |
| 192 | ), |
| 193 | 'bookingEnd' => DateTimeService::getCustomDateTimeFromUtc( |
| 194 | $row['appointment_bookingEnd'] |
| 195 | ), |
| 196 | 'notifyParticipants' => isset($row['appointment_notifyParticipants']) ? |
| 197 | $row['appointment_notifyParticipants'] : null, |
| 198 | 'createPaymentLinks' => isset($row['appointment_createPaymentLinks']) ? |
| 199 | $row['appointment_createPaymentLinks'] : null, |
| 200 | 'serviceId' => $row['appointment_serviceId'], |
| 201 | 'providerId' => $row['appointment_providerId'], |
| 202 | 'locationId' => isset($row['appointment_locationId']) ? |
| 203 | $row['appointment_locationId'] : null, |
| 204 | 'internalNotes' => isset($row['appointment_internalNotes']) ? |
| 205 | $row['appointment_internalNotes'] : null, |
| 206 | 'status' => $row['appointment_status'], |
| 207 | 'googleCalendarEventId' => isset($row['appointment_google_calendar_event_id']) ? |
| 208 | $row['appointment_google_calendar_event_id'] : null, |
| 209 | 'googleMeetUrl' => isset($row['appointment_google_meet_url']) ? |
| 210 | $row['appointment_google_meet_url'] : null, |
| 211 | 'outlookCalendarEventId' => isset($row['appointment_outlook_calendar_event_id']) ? |
| 212 | $row['appointment_outlook_calendar_event_id'] : null, |
| 213 | 'microsoftTeamsUrl' => isset($row['appointment_microsoft_teams_url']) ? |
| 214 | $row['appointment_microsoft_teams_url'] : null, |
| 215 | 'appleCalendarEventId' => isset($row['appointment_apple_calendar_event_id']) ? |
| 216 | $row['appointment_apple_calendar_event_id'] : null, |
| 217 | 'zoomMeeting' => [ |
| 218 | 'id' => $zoomMeetingJson ? $zoomMeetingJson['id'] : null, |
| 219 | 'startUrl' => $zoomMeetingJson ? $zoomMeetingJson['startUrl'] : null, |
| 220 | 'joinUrl' => $zoomMeetingJson ? $zoomMeetingJson['joinUrl'] : null, |
| 221 | ], |
| 222 | 'lessonSpace' => !empty($row['appointment_lesson_space']) ? $row['appointment_lesson_space'] : null, |
| 223 | ]; |
| 224 | } |
| 225 | |
| 226 | if ($bookingId && !isset($appointments[$appointmentId]['bookings'][$bookingId])) { |
| 227 | $appointments[$appointmentId]['bookings'][$bookingId] = [ |
| 228 | 'id' => $bookingId, |
| 229 | 'appointmentId' => $appointmentId, |
| 230 | 'customerId' => $row['booking_customerId'], |
| 231 | 'status' => $row['booking_status'], |
| 232 | 'couponId' => $couponId, |
| 233 | 'price' => $row['booking_price'], |
| 234 | 'persons' => $row['booking_persons'], |
| 235 | 'customFields' => isset($row['booking_customFields']) ? $row['booking_customFields'] : null, |
| 236 | 'info' => isset($row['booking_info']) ? $row['booking_info'] : null, |
| 237 | 'utcOffset' => isset($row['booking_utcOffset']) ? $row['booking_utcOffset'] : null, |
| 238 | 'aggregatedPrice' => isset($row['booking_aggregatedPrice']) ? |
| 239 | $row['booking_aggregatedPrice'] : null, |
| 240 | 'packageCustomerService' => !empty($row['booking_packageCustomerServiceId']) ? [ |
| 241 | 'id' => $row['booking_packageCustomerServiceId'], |
| 242 | 'serviceId' => !empty($row['package_customer_service_serviceId']) ? |
| 243 | $row['package_customer_service_serviceId'] : null, |
| 244 | 'bookingsCount' => !empty($row['package_customer_service_bookingsCount']) ? |
| 245 | $row['package_customer_service_bookingsCount'] : null, |
| 246 | 'packageCustomer' => [ |
| 247 | 'id' => !empty($row['package_customer_id']) ? |
| 248 | $row['package_customer_id'] : null, |
| 249 | 'packageId' => !empty($row['package_customer_packageId']) ? |
| 250 | $row['package_customer_packageId'] : null, |
| 251 | 'price' => !empty($row['package_customer_price']) ? |
| 252 | $row['package_customer_price'] : null, |
| 253 | 'couponId' => !empty($row['package_customer_couponId']) ? |
| 254 | $row['package_customer_couponId'] : null, |
| 255 | 'tax' => !empty($row['package_customer_tax']) ? |
| 256 | $row['package_customer_tax'] : null, |
| 257 | ] |
| 258 | ] : null, |
| 259 | 'duration' => isset($row['booking_duration']) ? $row['booking_duration'] : null, |
| 260 | 'created' => !empty($row['booking_created']) ? DateTimeService::getCustomDateTimeFromUtc($row['booking_created']) : null, |
| 261 | 'tax' => isset($row['booking_tax']) ? $row['booking_tax'] : null, |
| 262 | 'ivyEntryId' => isset($row['booking_ivyEntryId']) ? $row['booking_ivyEntryId'] : null, |
| 263 | ]; |
| 264 | } |
| 265 | |
| 266 | if ($bookingId && $bookingExtraId) { |
| 267 | $appointments[$appointmentId]['bookings'][$bookingId]['extras'][$bookingExtraId] = |
| 268 | [ |
| 269 | 'id' => $bookingExtraId, |
| 270 | 'customerBookingId' => $bookingId, |
| 271 | 'extraId' => $row['bookingExtra_extraId'], |
| 272 | 'quantity' => $row['bookingExtra_quantity'], |
| 273 | 'price' => $row['bookingExtra_price'], |
| 274 | 'aggregatedPrice' => $row['bookingExtra_aggregatedPrice'], |
| 275 | 'tax' => isset($row['bookingExtra_tax']) ? $row['bookingExtra_tax'] : null, |
| 276 | ]; |
| 277 | } |
| 278 | |
| 279 | if ($bookingId && $paymentId) { |
| 280 | $appointments[$appointmentId]['bookings'][$bookingId]['payments'][$paymentId] = |
| 281 | [ |
| 282 | 'id' => $paymentId, |
| 283 | 'customerBookingId' => $bookingId, |
| 284 | 'packageCustomerId' => !empty($row['payment_packageCustomerId']) ? $row['payment_packageCustomerId'] : null, |
| 285 | 'status' => $row['payment_status'], |
| 286 | 'dateTime' => DateTimeService::getCustomDateTimeFromUtc($row['payment_dateTime']), |
| 287 | 'gateway' => $row['payment_gateway'], |
| 288 | 'gatewayTitle' => $row['payment_gatewayTitle'], |
| 289 | 'transactionId' => !empty($row['payment_transactionId']) ? $row['payment_transactionId'] : null, |
| 290 | 'parentId' => !empty($row['payment_parentId']) ? $row['payment_parentId'] : null, |
| 291 | 'amount' => $row['payment_amount'], |
| 292 | 'data' => $row['payment_data'], |
| 293 | 'invoiceNumber' => !empty($row['payment_invoiceNumber']) ? $row['payment_invoiceNumber'] : null, |
| 294 | 'wcOrderId' => !empty($row['payment_wcOrderId']) ? $row['payment_wcOrderId'] : null, |
| 295 | 'wcOrderItemId' => !empty($row['payment_wcOrderItemId']) ? |
| 296 | $row['payment_wcOrderItemId'] : null, |
| 297 | 'created' => !empty($row['payment_created']) ? $row['payment_created'] : null, |
| 298 | ]; |
| 299 | } |
| 300 | |
| 301 | if ($bookingId && $couponId) { |
| 302 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['id'] = $couponId; |
| 303 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['code'] = $row['coupon_code']; |
| 304 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['discount'] = $row['coupon_discount']; |
| 305 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['deduction'] = $row['coupon_deduction']; |
| 306 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['limit'] = $row['coupon_limit']; |
| 307 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['customerLimit'] = $row['coupon_customerLimit']; |
| 308 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['status'] = $row['coupon_status']; |
| 309 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['expirationDate'] = $row['coupon_expirationDate']; |
| 310 | $appointments[$appointmentId]['bookings'][$bookingId]['coupon']['startDate'] = $row['coupon_startDate']; |
| 311 | } |
| 312 | |
| 313 | if ($bookingId && $customerId) { |
| 314 | $appointments[$appointmentId]['bookings'][$bookingId]['customer'] = |
| 315 | [ |
| 316 | 'id' => $customerId, |
| 317 | 'firstName' => $row['customer_firstName'], |
| 318 | 'lastName' => $row['customer_lastName'], |
| 319 | 'email' => $row['customer_email'], |
| 320 | 'note' => $row['customer_note'], |
| 321 | 'phone' => $row['customer_phone'], |
| 322 | 'countryPhoneIso' => !empty($row['customer_countryPhoneIso']) ? $row['customer_countryPhoneIso'] : null, |
| 323 | 'gender' => $row['customer_gender'], |
| 324 | 'status' => $row['customer_status'], |
| 325 | 'birthday' => !empty($row['customer_birthday']) ? $row['customer_birthday'] : null, |
| 326 | 'type' => 'customer', |
| 327 | ]; |
| 328 | } |
| 329 | |
| 330 | if ($bookingId && $locationId) { |
| 331 | $appointments[$appointmentId]['location'] = |
| 332 | [ |
| 333 | 'id' => $locationId, |
| 334 | 'name' => !empty($row['location_name']) ? $row['location_name'] : '', |
| 335 | 'address' => !empty($row['location_address']) ? $row['location_address'] : '', |
| 336 | 'description' => !empty($row['location_description']) ? $row['location_description'] : null, |
| 337 | 'status' => !empty($row['location_status']) ? $row['location_status'] : null, |
| 338 | 'phone' => !empty($row['location_phone']) ? $row['location_phone'] : null, |
| 339 | 'latitude' => !empty($row['location_latitude']) ? $row['location_latitude'] : null, |
| 340 | 'longitude' => !empty($row['location_longitude']) ? $row['location_longitude'] : null, |
| 341 | 'pictureFullPath' => !empty($row['location_pictureFullPath']) ? $row['location_pictureFullPath'] : null, |
| 342 | 'pictureThumbPath' => !empty($row['location_pictureThumbPath']) ? $row['location_pictureThumbPath'] : null, |
| 343 | 'pin' => !empty($row['location_pin']) ? $row['location_pin'] : null, |
| 344 | 'translations' => !empty($row['location_translations']) ? $row['location_translations'] : null |
| 345 | ]; |
| 346 | } |
| 347 | |
| 348 | if ($bookingId && $providerId) { |
| 349 | $appointments[$appointmentId]['provider'] = |
| 350 | [ |
| 351 | 'id' => $providerId, |
| 352 | 'firstName' => $row['provider_firstName'], |
| 353 | 'lastName' => $row['provider_lastName'], |
| 354 | 'email' => $row['provider_email'], |
| 355 | 'note' => !empty($row['provider_note']) ? $row['provider_note'] : null, |
| 356 | 'description' => !empty($row['provider_description']) ? $row['provider_description'] : null, |
| 357 | 'phone' => !empty($row['provider_phone']) ? $row['provider_phone'] : null, |
| 358 | 'countryPhoneIso' => !empty($row['provider_countryPhoneIso']) ? $row['provider_countryPhoneIso'] : null, |
| 359 | 'gender' => !empty($row['provider_gender']) ? $row['provider_gender'] : null, |
| 360 | 'timeZone' => !empty($row['provider_timeZone']) ? $row['provider_timeZone'] : null, |
| 361 | 'type' => 'provider', |
| 362 | 'badgeId' => !empty($row['provider_badgeId']) ? $row['provider_badgeId'] : null, |
| 363 | 'pictureFullPath' => !empty($row['provider_pictureFullPath']) ? $row['provider_pictureFullPath'] : null, |
| 364 | 'pictureThumbPath' => !empty($row['provider_pictureThumbPath']) ? $row['provider_pictureThumbPath'] : null, |
| 365 | 'zoomUserId' => !empty($row['provider_zoomUserId']) ? $row['provider_zoomUserId'] : null, |
| 366 | ]; |
| 367 | } |
| 368 | |
| 369 | if ($serviceId) { |
| 370 | $appointments[$appointmentId]['service']['id'] = $row['service_id']; |
| 371 | $appointments[$appointmentId]['service']['name'] = isset($row['service_name']) ? $row['service_name'] : null; |
| 372 | $appointments[$appointmentId]['service']['description'] = isset($row['service_description']) ? $row['service_description'] : null; |
| 373 | $appointments[$appointmentId]['service']['pictureFullPath'] = isset($row['service_pictureFullPath']) ? $row['service_pictureFullPath'] : null; |
| 374 | $appointments[$appointmentId]['service']['pictureThumbPath'] = isset($row['service_pictureThumbPath']) ? |
| 375 | $row['service_pictureThumbPath'] : null; |
| 376 | $appointments[$appointmentId]['service']['color'] = isset($row['service_color']) ? $row['service_color'] : null; |
| 377 | $appointments[$appointmentId]['service']['price'] = isset($row['service_price']) ? $row['service_price'] : null; |
| 378 | $appointments[$appointmentId]['service']['status'] = isset($row['service_status']) ? $row['service_status'] : null; |
| 379 | $appointments[$appointmentId]['service']['categoryId'] = isset($row['service_categoryId']) ? $row['service_categoryId'] : null; |
| 380 | $appointments[$appointmentId]['service']['minCapacity'] = isset($row['service_minCapacity']) ? $row['service_minCapacity'] : null; |
| 381 | $appointments[$appointmentId]['service']['maxCapacity'] = isset($row['service_maxCapacity']) ? $row['service_maxCapacity'] : null; |
| 382 | $appointments[$appointmentId]['service']['duration'] = isset($row['service_duration']) ? $row['service_duration'] : null; |
| 383 | $appointments[$appointmentId]['service']['timeBefore'] = isset($row['service_timeBefore']) |
| 384 | ? $row['service_timeBefore'] : null; |
| 385 | $appointments[$appointmentId]['service']['timeAfter'] = isset($row['service_timeAfter']) |
| 386 | ? $row['service_timeAfter'] : null; |
| 387 | $appointments[$appointmentId]['service']['aggregatedPrice'] = isset($row['service_aggregatedPrice']) |
| 388 | ? $row['service_aggregatedPrice'] : null; |
| 389 | $appointments[$appointmentId]['service']['settings'] = isset($row['service_settings']) |
| 390 | ? $row['service_settings'] : null; |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | $collection = new Collection(); |
| 395 | |
| 396 | foreach ($appointments as $key => $value) { |
| 397 | $collection->addItem( |
| 398 | self::create($value), |
| 399 | $key |
| 400 | ); |
| 401 | } |
| 402 | |
| 403 | return $collection; |
| 404 | } |
| 405 | } |
| 406 |