| @@ -15,8 +15,9 @@ | ||
| 15 | 15 | use FluentBooking\App\Services\PermissionManager; |
| 16 | 16 | use FluentBooking\App\Services\CalendarService; |
| 17 | 17 | use FluentBooking\App\Services\ExportHelper; |
| 18 | 18 | use FluentBooking\App\Services\Integrations\FluentCRM\CrmContactService; |
| 19 | +use FluentBooking\App\Services\Integrations\FluentCart\CustomerProfileService; | |
| 19 | 20 | use FluentCrm\App\Services\PermissionManager as CrmPermissionManager; |
| 20 | 21 | |
| 21 | 22 | class SchedulesController extends Controller |
| 22 | 23 | { |
| @@ -140,9 +141,9 @@ | ||
| 140 | 141 | |
| 141 | 142 | $query = Booking::with(['calendar_event']); |
| 142 | 143 | |
| 143 | 144 | $hasPermission = PermissionManager::userCanSeeAllBookings(); |
| 144 | - | |
| 145 | + | |
| 145 | 146 | if (!$hasPermission || $author == 'me') { |
| 146 | 147 | $query->where('host_user_id', get_current_user_id()); |
| 147 | 148 | } |
| 148 | 149 | |
| @@ -177,9 +178,9 @@ | ||
| 177 | 178 | |
| 178 | 179 | private function addCountsForFirstPage($author, &$data) |
| 179 | 180 | { |
| 180 | 181 | $bookingQuery = Booking::query() |
| 181 | - ->when($author == 'me', function($query) { | |
| 182 | + ->when(!PermissionManager::userCanSeeAllBookings() || $author == 'me', function($query) { | |
| 182 | 183 | return $query->where('host_user_id', get_current_user_id()); |
| 183 | 184 | }) |
| 184 | 185 | ->when($author && is_numeric($author), function($query) use ($author) { |
| 185 | 186 | return $query->where('calendar_id', $author); |
| @@ -239,10 +240,19 @@ | ||
| 239 | 240 | if (!in_array($value, ['scheduled', 'completed', 'cancelled', 'rejected', 'no_show'])) { |
| 240 | 241 | return $this->sendError(['message' => __('Invalid status', 'fluent-booking')]); |
| 241 | 242 | } |
| 242 | 243 | |
| 244 | + if (in_array($booking->status, ['cancelled', 'rejected'])) { | |
| 245 | + return $this->sendError(['message' => __('A cancelled or rejected booking can not be changed', 'fluent-booking')]); | |
| 246 | + } | |
| 247 | + | |
| 243 | 248 | if ($value == 'scheduled' && $booking->payment_method && $booking->payment_order) { |
| 244 | 249 | $order = $booking->payment_order; |
| 250 | + | |
| 251 | + if (in_array($order->status, ['refunded', 'partially-refunded'])) { | |
| 252 | + return $this->sendError(['message' => __('A refunded payment can not be marked as paid', 'fluent-booking')]); | |
| 253 | + } | |
| 254 | + | |
| 245 | 255 | $order->total_paid = $order->total_amount; |
| 246 | 256 | $order->completed_at = gmdate('Y-m-d H:i:s'); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date |
| 247 | 257 | $order->status = 'paid'; |
| 248 | 258 | $order->save(); |
| @@ -257,18 +267,24 @@ | ||
| 257 | 267 | do_action('fluent_booking/log_booking_activity', $this->getConfirmLog($booking->id)); |
| 258 | 268 | } |
| 259 | 269 | |
| 260 | 270 | if ($value == 'cancelled') { |
| 261 | - $cancelReason = sanitize_text_field($data['cancel_reason']); | |
| 271 | + $cancelReason = sanitize_text_field(Arr::get($data, 'cancel_reason', '')); | |
| 262 | 272 | $booking->cancelMeeting($cancelReason, 'host', get_current_user_id()); |
| 263 | 273 | } |
| 264 | 274 | |
| 265 | 275 | if ($value == 'rejected') { |
| 266 | - $rejectReason = sanitize_text_field($data['reject_reason']); | |
| 276 | + $rejectReason = sanitize_text_field(Arr::get($data, 'reject_reason', '')); | |
| 267 | 277 | $booking->rejectMeeting($rejectReason, get_current_user_id()); |
| 268 | 278 | } |
| 269 | 279 | |
| 270 | 280 | if (in_array($value, ['cancelled', 'rejected'])) { |
| 281 | + // cancelMeeting() and rejectMeeting() refuse some statuses without changing the booking. | |
| 282 | + if ($booking->status != $value) { | |
| 283 | + /* translators: %s: Booking status */ | |
| 284 | + return $this->sendError(['message' => sprintf(__('This booking can not be %s', 'fluent-booking'), $value)]); | |
| 285 | + } | |
| 286 | + | |
| 271 | 287 | if ($booking->payment_method && Arr::get($data, 'refund_payment') == 'yes') { |
| 272 | 288 | do_action('fluent_booking/refund_payment_' . $booking->payment_method, $booking, $booking->calendar_event); |
| 273 | 289 | } |
| 274 | 290 | return [ |
| @@ -436,8 +452,9 @@ | ||
| 436 | 452 | { |
| 437 | 453 | $this->resolveOwnedBookingOrFail($bookingId); |
| 438 | 454 | |
| 439 | 455 | $activities = BookingActivity::where('booking_id', $bookingId) |
| 456 | + ->where('type', '!=', BookingActivity::TYPE_NOTE) | |
| 440 | 457 | ->orderBy('id', 'DESC') |
| 441 | 458 | ->get(); |
| 442 | 459 | |
| 443 | 460 | return [ |
| @@ -449,11 +466,12 @@ | ||
| 449 | 466 | { |
| 450 | 467 | $booking = $this->resolveOwnedBookingOrFail($bookingId); |
| 451 | 468 | |
| 452 | 469 | $activities = BookingActivity::where('booking_id', $booking->id) |
| 470 | + ->where('type', '!=', BookingActivity::TYPE_NOTE) | |
| 453 | 471 | ->orderBy('id', 'DESC') |
| 454 | 472 | ->get(); |
| 455 | - | |
| 473 | + | |
| 456 | 474 | $activities->each(function ($activity) { |
| 457 | 475 | $activity->description = wp_unslash($activity->description); |
| 458 | 476 | }); |
| 459 | 477 | |
| @@ -459,9 +477,10 @@ | ||
| 459 | 477 | |
| 460 | 478 | $sidebarContents = []; |
| 461 | 479 | $mainBodyContents = []; |
| 462 | 480 | |
| 463 | - $crmProfile = CrmContactService::getProfileData($booking->email); | |
| 481 | + $canReadCrm = CrmContactService::isActive() && CrmPermissionManager::currentUserCan('fcrm_read_contacts'); | |
| 482 | + $crmProfile = $canReadCrm ? CrmContactService::getProfileData($booking->email) : null; | |
| 464 | 483 | if ($crmProfile) { |
| 465 | 484 | $sidebarContents[] = [ |
| 466 | 485 | 'id' => 'fluent_crm_profule', |
| 467 | 486 | 'title' => __('CRM Profile', 'fluent-booking'), |
| @@ -469,8 +488,20 @@ | ||
| 469 | 488 | 'profile' => $crmProfile, |
| 470 | 489 | ]; |
| 471 | 490 | } |
| 472 | 491 | |
| 492 | + $cartProfile = CustomerProfileService::canView() | |
| 493 | + ? CustomerProfileService::getProfileData($booking->email) | |
| 494 | + : null; | |
| 495 | + if ($cartProfile) { | |
| 496 | + $sidebarContents[] = [ | |
| 497 | + 'id' => 'fluent_cart_profile', | |
| 498 | + 'title' => __('Cart Profile', 'fluent-booking'), | |
| 499 | + 'type' => 'cart_profile', | |
| 500 | + 'profile' => $cartProfile, | |
| 501 | + ]; | |
| 502 | + } | |
| 503 | + | |
| 473 | 504 | $order = null; |
| 474 | 505 | if ($booking->payment_status && $booking->payment_order) { |
| 475 | 506 | $order = $booking->payment_order; |
| 476 | 507 | $relations = ['items', 'transaction']; |
| @@ -505,8 +536,14 @@ | ||
| 505 | 536 | 'message' => __('FluentCRM is not active.', 'fluent-booking') |
| 506 | 537 | ]); |
| 507 | 538 | } |
| 508 | 539 | |
| 540 | + if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) { | |
| 541 | + return $this->sendError([ | |
| 542 | + 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking') | |
| 543 | + ], 403); | |
| 544 | + } | |
| 545 | + | |
| 509 | 546 | $state = CrmContactService::getContactState($booking->email); |
| 510 | 547 | |
| 511 | 548 | if (!$state) { |
| 512 | 549 | return $this->sendError([ |
| @@ -593,8 +630,14 @@ | ||
| 593 | 630 | 'message' => __('FluentCRM is not active.', 'fluent-booking') |
| 594 | 631 | ]); |
| 595 | 632 | } |
| 596 | 633 | |
| 634 | + if (!CrmPermissionManager::currentUserCan('fcrm_read_contacts')) { | |
| 635 | + return $this->sendError([ | |
| 636 | + 'message' => __('You do not have permission to read CRM contacts.', 'fluent-booking') | |
| 637 | + ], 403); | |
| 638 | + } | |
| 639 | + | |
| 597 | 640 | $type = $request->get('type') === 'lists' ? 'lists' : 'tags'; |
| 598 | 641 | $search = sanitize_text_field($request->get('search', '')); |
| 599 | 642 | |
| 600 | 643 | return [ |
| @@ -619,8 +662,14 @@ | ||
| 619 | 662 | if (!CrmContactService::isActive()) { |
| 620 | 663 | return $this->sendError([ |
| 621 | 664 | 'message' => __('FluentCRM is not active.', 'fluent-booking') |
| 622 | 665 | ]); |
| 666 | + } | |
| 667 | + | |
| 668 | + if (!CrmPermissionManager::currentUserCan('fcrm_manage_contacts')) { | |
| 669 | + return $this->sendError([ | |
| 670 | + 'message' => __('You do not have permission to manage CRM contacts.', 'fluent-booking') | |
| 671 | + ], 403); | |
| 623 | 672 | } |
| 624 | 673 | |
| 625 | 674 | $requestKey = $type === 'tags' ? 'tag_ids' : 'list_ids'; |
| 626 | 675 | $desired = (array) $request->get($requestKey, []); |