ORVIAN’s Communications module connects two external services: Evolution API (WhatsApp) for automated attendance alerts sent to student guardians, and Chatwoot for a school messaging center accessible to Directors. Both integrations are configured entirely viaDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Elian-D/ORVIAN/llms.txt
Use this file to discover all available pages before exploring further.
.env variables and are registered as HTTP singletons in AppServiceProvider. Neither integration requires inbound webhook handling on ORVIAN’s side.
WhatsApp Attendance Alerts
ORVIAN usesWhatsAppService (App\Services\Communications\WhatsAppService) as its HTTP client to Evolution API. The service acts as a sender only — ORVIAN dispatches messages and does not process incoming WhatsApp replies.
The full alert pipeline works as follows:
- Scheduled trigger — the
orvian:evaluate-attendance-alertsArtisan command runs daily at 16:00 viaroutes/console.phpwithwithoutOverlapping()to prevent concurrent runs. - Evaluation —
AttendanceAlertEvaluator::evaluate(Student $student)is called for each active student. It queriesPlantelAttendanceRecordfor the current calendar month and counts records withstatus = 'absent'andstatus = 'late'. - Threshold check — if either count meets or exceeds the configured threshold, the evaluator checks an anti-spam cache key before dispatching.
- Job dispatch —
SendAttendanceAlertJobis dispatched with the student, alert type, count, and month name. The job has 3 retries and a 60-second backoff between attempts. - Message send — the job calls
WhatsAppService::sendTextMessage(string $phone, string $message). The phone number is stripped of the leading+before sending, as Evolution API expects the E.164 number without the plus sign.
Alert Thresholds
Thresholds are configured in.env and read via config/communications.php:
| Variable | Default | Description |
|---|---|---|
ALERT_ABSENCE_THRESHOLD | 3 | Number of absences in the current month that triggers an alert |
ALERT_TARDINESS_THRESHOLD | 3 | Number of late arrivals in the current month that triggers an alert |
AttendanceAlertEvaluator checks a cache key in the format:
alert_absence_42_21. If this key exists, the job is not dispatched for that student this week. The cache entry is set with a 7-day TTL when a job is dispatched. This guarantees a guardian receives at most one alert of each type per week per student, regardless of how many times the command runs.
Students without a tutor_phone value are silently skipped. Their IDs are accumulated in $skippedStudents and logged as a single consolidated warning entry at the end of the command run.
WhatsApp Message Templates
WhatsAppTemplates (App\Services\Communications\WhatsAppTemplates) provides two static methods that build the message body sent to guardians. Templates use WhatsApp’s native markdown formatting: *bold* for emphasis and _italic_ for secondary information.
Absence alert (WhatsAppTemplates::absenceAlert()):
WhatsAppTemplates::tardinessAlert()):
su representado / su representada) is resolved automatically from the student’s gender field (M or F).
The
tutor_phone field on the Student model must be stored in E.164 format (e.g., +18091234567) for WhatsApp delivery to work correctly. During SIGERD import, phone numbers are automatically normalized to E.164. For manually created or edited students, the form validates E.164 format before saving. Students missing a tutor_phone are skipped by the evaluator and their IDs are reported in the application log.Running Alert Evaluation Manually
You can trigger the evaluation outside the daily schedule using Artisan:Chatwoot Messaging Center
ORVIAN integrates with a self-hosted Chatwoot instance viaChatwootService (App\Services\Communications\ChatwootService), an HTTP singleton registered in AppServiceProvider.
Agent registration at onboarding — When a school completes onboarding (via either CompleteOnboardingAction or CompleteTenantOnboardingAction), the Director’s user account is registered as a Chatwoot agent via ChatwootService::syncUserAsAgent(). This call is wrapped in DB::afterCommit to guarantee it only fires after the outermost database transaction has committed — preventing the race condition where the agent registration is attempted before the user record is fully persisted.
syncUserAsAgent() first checks findAgentByEmail() to avoid duplicate registrations. If the agent already exists, the method returns early. On successful creation, the Chatwoot-assigned agent ID is stored in preferences['chatwoot_agent_id'] on the user record via updateQuietly().
SSO access for Directors — When a Director clicks the Messages tile in their dashboard, ORVIAN redirects them directly to chat.orvian.com.do with two query string parameters:
email— the Director’s email addressidentifier_hash— an HMAC-SHA256 signature computed server-side ashash_hmac('sha256', $email, $hmacToken)
ChatwootService::getPendingConversationsCount() and displayed as a badge on the Messages tile in the school dashboard.
Required Environment Variables
Configure the following variables in your.env file:
| Variable | Description |
|---|---|
CHATWOOT_BASE_URL | Full URL of your Chatwoot instance (e.g., https://chat.orvian.com.do) |
CHATWOOT_API_ACCESS_TOKEN | Superadmin API access token from the Chatwoot account settings |
CHATWOOT_ACCOUNT_ID | Numeric Chatwoot account ID (typically 1 for single-account installs) |
CHATWOOT_HMAC_TOKEN | HMAC token from Chatwoot Identity Verification settings — used to sign the identifier_hash for SSO |
EVOLUTION_API_URL | Base URL of your Evolution API instance (e.g., https://evolution.orvian.com.do) |
EVOLUTION_API_KEY | API key for authenticating requests to Evolution API |
EVOLUTION_INSTANCE_NAME | Name of the WhatsApp instance registered in Evolution API |
config/communications.php — update the config cache after changing .env values in production: