Skip to main content

Events

Three custom events in app/Events/:
EventPropertiesFired when
AddressUpdateduser, addressUser updates their address
MobileNumberUpdateduser, mobileNumberUser updates their mobile number
PersonalDetailUpdateduser, personalDetailUser updates personal details (DOB, etc.)
Plus Laravel’s built-in Registered event (fired after user registration).

Event-listener wiring

File: app/Providers/EventServiceProvider.php
Registered
├── SendVerificationEmail          → sends email verification link (6hr expiry)
├── SendNewAccountCreatedEmail     → notifies hello@tutorbloc.com (production only)
└── SendNewTutorAccountCreatedEmail → notifies internal team (production + staging)

AddressUpdated
└── UpdatePaymentAddress           → syncs address to Stripe customer

MobileNumberUpdated
└── UpdatePaymentMobileNumber      → syncs phone to Stripe customer

PersonalDetailUpdated
└── UpdatePaymentPersonalDetail    → syncs DOB to Stripe (tutors only)
SendNewAccountCreatedEmail checks config('env') instead of config('app.env') — this is likely a bug that may cause it to silently fail. Confirm with team.

Email templates

16 Mailable classes in app/Mail/. All use Queueable and SerializesModels.

Lesson lifecycle emails

ClassRecipientSubject patternTrigger
LessonBookedTutor or studentBooking details / reschedule acceptedBooking confirmed or reschedule approved
LessonCancelledOther partyCancellation noticeLesson cancelled
LessonRescheduleOther party”please respond to your reschedule request!”Reschedule proposed (includes Accept/Decline buttons)
LessonSummaryNoteTutor or studentVaries by recipientTutor adds lesson notes

Account & profile emails

ClassRecipientSubject patternTrigger
NewAccountCreatedhello@tutorbloc.com”[NEW ACCOUNT] has just joined!”User registers (production only)
NewTutorAccountCreatedInternal team”[TUTOR] , has just created an account!”Tutor registers
ClaimUsernameTutor”[ACTION] Hey , claim your username!”Manual campaign job
ClaimUsernameReminderTutor”[ACTION] 48 hours left to claim!”Manual reminder job
ShareableLinkTutor”Hey , here’s your unique shareable link!”Username assigned
UserDeletedhello@tutorbloc.com”Account deleted”User deletes account

Review & notification emails

ClassRecipientSubject patternTrigger
ReviewTutorStudent/parent”Hey , please review !”Daily review request job
LearnerReviewInternal team”[TUTOR] , has just submit a review!”Student submits review

Integration emails

ClassRecipientSubject patternTrigger
ReconnectZoomTutor”please reconnect your Zoom account!”Zoom token validation fails

Payment emails

ClassRecipientSubject patternTrigger
SendPendingPayoutStatusInternal team”[INTERNAL] Payout to Payout job success/failure
SendFundFailureInternal team”Send fund failure”Payment transfer fails

Verification emails

ClassRecipientSubject patternTrigger
TutorIDVerificationStatusUpdatedInternal teamVaries by status (PASS/FAIL/REVIEW)Verification account status changes

Email recipients pattern

Most emails follow this pattern:
  • Primary recipient: The relevant user (tutor, student, or parent)
  • BCC: Internal team addresses (MAIL_TO_INTERNAL_TEAM_ADDRESSES env var)
  • Some emails go directly to hello@tutorbloc.com (hardcoded)

Notifications

Two notification classes in app/Notifications/:
ClassChannelExpiryPurpose
ResetPasswordmail6 minutesPassword reset link
VerifyEmailmail6 hoursEmail verification link (signed URL)

Push notifications

Push notifications are sent via the RemotePushNotifiable trait. The system supports:

Apple Push Notification Service (APNS)

Configured via env vars: APNS_KEY_FILE, APNS_KEY_ID, APNS_TEAM_ID, APNS_BUNDLE_ID Device tokens stored in user_devices table:
  • ios_device_token
  • ios_aps_environment (production/sandbox)
  • is_push_notification_enabled
File: app/Models/v1/UserDevice.php The UserDevice model handles token deduplication — removeDeviceTokenIfExists() prevents the same device token being registered to multiple users.

Firebase Cloud Messaging (FCM)

Env vars exist (FCM_API_ACCESS_KEY, FCM_URL) but no FCM service class was found in the codebase. May be incomplete or handled externally — confirm with team.

Push notification triggers

TriggerNotification content
Lesson reminder (2hr/24hr)Upcoming lesson details
Tutor reviewed”You’ve been reviewed”
Lesson note addedNote content with booking action
Profile completion nudge”Complete your profile” with app link
Review request”Please review your tutor”

Broadcast channels

File: routes/channels.php A private broadcast channel is registered for user-specific events:
Broadcast::channel('user.{id}', function ($user, $id) {
    return (int) $user->id === (int) $id;
});
Broadcasting driver defaults to null (disabled). Can be switched to Pusher or Redis via BROADCAST_DRIVER env var. Pusher credentials are configured in config/broadcasting.php.