Deploy Ladill Frontdesk / deploy (push) Successful in 58s
Monthly auto-renew charges due organizations from the Ladill wallet and downgrades after grace when payment fails. Co-authored-by: Cursor <cursoragent@cursor.com>
321 lines
12 KiB
PHP
321 lines
12 KiB
PHP
<?php
|
|
|
|
return [
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Inbound service API keys (sibling Ladill apps calling Frontdesk)
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
'service_api_keys' => array_filter([
|
|
'pos' => env('FRONTDESK_API_KEY_POS'),
|
|
'crm' => env('FRONTDESK_API_KEY_CRM'),
|
|
'care' => env('FRONTDESK_API_KEY_CARE'),
|
|
'lab' => env('FRONTDESK_API_KEY_LAB'),
|
|
]),
|
|
|
|
'visitor_types' => [
|
|
'visitor' => 'Visitor',
|
|
'contractor' => 'Contractor',
|
|
'vendor' => 'Vendor',
|
|
'interview_candidate' => 'Interview Candidate',
|
|
'delivery' => 'Delivery Personnel',
|
|
],
|
|
|
|
'visit_purposes' => [
|
|
'meeting' => 'Business meeting',
|
|
'interview' => 'Job interview',
|
|
'delivery' => 'Delivery or pickup',
|
|
'maintenance' => 'Maintenance or repairs',
|
|
'sales' => 'Sales or vendor visit',
|
|
'training' => 'Training or workshop',
|
|
'personal' => 'Personal visit',
|
|
'other' => 'Other',
|
|
],
|
|
|
|
'visit_statuses' => [
|
|
'scheduled' => 'Scheduled',
|
|
'expected' => 'Expected',
|
|
'waiting' => 'Waiting',
|
|
'checked_in' => 'Checked In',
|
|
'checked_out' => 'Checked Out',
|
|
'cancelled' => 'Cancelled',
|
|
'overdue' => 'Overdue',
|
|
],
|
|
|
|
'watchlist_statuses' => [
|
|
'allowed' => 'Allowed',
|
|
'requires_approval' => 'Requires Approval',
|
|
'blacklisted' => 'Blacklisted',
|
|
],
|
|
|
|
'audit_actions' => [
|
|
'visit.checked_in' => 'Visit checked in',
|
|
'visit.checked_out' => 'Visit checked out',
|
|
'visit.awaiting_approval' => 'Visit awaiting approval',
|
|
'visit.scheduled' => 'Visit scheduled',
|
|
'visit.waiting' => 'Visitor waiting',
|
|
'visit.cancelled' => 'Visit cancelled',
|
|
'visit.deleted' => 'Visit archived',
|
|
'visit.restored' => 'Visit restored',
|
|
'visitor.deleted' => 'Visitor archived',
|
|
'visitor.restored' => 'Visitor restored',
|
|
'watchlist.blocked_attempt' => 'Blocked check-in attempt',
|
|
'watchlist.flagged_checkin' => 'Flagged visitor check-in',
|
|
'watchlist.entry_created' => 'Watchlist entry added',
|
|
'watchlist.entry_removed' => 'Watchlist entry removed',
|
|
'badge.expired' => 'Badge expired',
|
|
'employee.signed_in' => 'Employee signed in',
|
|
'employee.signed_out' => 'Employee signed out',
|
|
'employee.stepped_out' => 'Employee stepped out',
|
|
'employee.stepped_in' => 'Employee returned',
|
|
],
|
|
|
|
'roles' => [
|
|
'super_admin' => 'Super Administrator',
|
|
'org_admin' => 'Organization Administrator',
|
|
'branch_admin' => 'Branch Administrator',
|
|
'receptionist' => 'Receptionist',
|
|
'security_officer' => 'Security Officer',
|
|
'host' => 'Host',
|
|
'auditor' => 'Auditor',
|
|
],
|
|
|
|
'device_types' => [
|
|
'reception_computer' => 'Reception Computer',
|
|
'kiosk' => 'Visitor Kiosk',
|
|
'tablet' => 'Tablet',
|
|
'badge_printer' => 'Badge Printer',
|
|
'qr_scanner' => 'QR Scanner',
|
|
'camera' => 'Camera',
|
|
'signature_pad' => 'Signature Pad',
|
|
],
|
|
|
|
/*
|
|
| Device types that receive a server-generated token for unattended API/kiosk access.
|
|
*/
|
|
'device_token_types' => ['kiosk', 'badge_printer', 'qr_scanner'],
|
|
|
|
/*
|
|
| Contextual copy for the register / edit device forms (keyed by device type).
|
|
*/
|
|
'device_registration_hints' => [
|
|
'reception_computer' => 'Tracked for your team only. Staff sign in on this machine — no device token or automatic connection is created.',
|
|
'kiosk' => 'A device token is created after registration. Open the kiosk URL on your tablet to run self-service check-in without staff login.',
|
|
'tablet' => 'Tracked for inventory. Use Visitor Kiosk if this tablet should run unattended check-in.',
|
|
'badge_printer' => 'A device token is created for unattended printing. The printer connects when your print agent sends requests with that token.',
|
|
'qr_scanner' => 'A device token is created for unattended scanning. The scanner connects when it calls Frontdesk with that token.',
|
|
'camera' => 'Tracked for inventory at this reception desk or branch — no device token is issued.',
|
|
'signature_pad' => 'Tracked for inventory at this reception desk or branch — no device token is issued.',
|
|
],
|
|
|
|
'notification_channels' => [
|
|
'email' => 'Email (platform SMTP)',
|
|
'sms' => 'SMS',
|
|
],
|
|
|
|
'billing' => [
|
|
'email_cost_ghs' => (float) env('FRONTDESK_EMAIL_COST_GHS', 0.0135),
|
|
'sms_cost_per_segment_ghs' => (float) env('FRONTDESK_SMS_COST_PER_SEGMENT_GHS', 0.05),
|
|
'sms_segment_length' => (int) env('FRONTDESK_SMS_SEGMENT_LENGTH', 160),
|
|
],
|
|
|
|
'pro' => [
|
|
'grace_days' => (int) env('FRONTDESK_PRO_GRACE_DAYS', 3),
|
|
'period_days' => (int) env('FRONTDESK_PRO_PERIOD_DAYS', 30),
|
|
],
|
|
|
|
'plans' => [
|
|
'free' => [
|
|
'label' => 'Free',
|
|
'price_minor' => 0,
|
|
'max_branches' => 1,
|
|
'max_kiosk_devices' => 1,
|
|
'free_emails_per_month' => (int) env('FRONTDESK_FREE_EMAILS_PER_MONTH', 100),
|
|
'features' => [
|
|
'check_in',
|
|
'hosts',
|
|
'badges',
|
|
'watchlist',
|
|
],
|
|
],
|
|
'pro' => [
|
|
'label' => 'Pro',
|
|
'price_minor' => (int) env('FRONTDESK_PRO_PRICE_MINOR', 7900),
|
|
'max_branches' => null,
|
|
'max_kiosk_devices' => null,
|
|
'free_emails_per_month' => env('FRONTDESK_PRO_FREE_EMAILS_PER_MONTH') !== null
|
|
? (int) env('FRONTDESK_PRO_FREE_EMAILS_PER_MONTH')
|
|
: null,
|
|
'features' => [
|
|
'check_in',
|
|
'hosts',
|
|
'badges',
|
|
'watchlist',
|
|
'integrations',
|
|
'webhooks',
|
|
'scheduled_reports',
|
|
'custom_badge_templates',
|
|
],
|
|
],
|
|
],
|
|
|
|
'notification_events' => [
|
|
'visitor_arrived' => 'Visitor arrived (checked in)',
|
|
'visitor_checked_out' => 'Visitor checked out',
|
|
'visitor_expected' => 'Visitor expected today',
|
|
'visitor_waiting' => 'Visitor waiting in reception',
|
|
'visit_cancelled' => 'Visit cancelled',
|
|
'approval_needed' => 'Approval required',
|
|
'watchlist_alert' => 'Watchlist / security alerts',
|
|
'badge_expired' => 'Expired badge while checked in',
|
|
'employee_overdue_return' => 'Employee overdue to return from step-out',
|
|
],
|
|
|
|
'default_notification_events' => [
|
|
'visitor_arrived' => true,
|
|
'visitor_checked_out' => true,
|
|
'visitor_expected' => true,
|
|
'visitor_waiting' => true,
|
|
'visit_cancelled' => true,
|
|
'approval_needed' => true,
|
|
'watchlist_alert' => true,
|
|
'badge_expired' => true,
|
|
'employee_overdue_return' => true,
|
|
],
|
|
|
|
'kiosk' => [
|
|
'inactivity_reset_seconds' => (int) env('FRONTDESK_KIOSK_RESET_SECONDS', 120),
|
|
'default_visit_duration_minutes' => 60,
|
|
],
|
|
|
|
'employee_presence_statuses' => [
|
|
'off_site' => 'Off site',
|
|
'on_site' => 'On site',
|
|
'stepped_out' => 'Stepped out',
|
|
],
|
|
|
|
'employee_step_out_reasons' => [
|
|
'lunch' => 'Lunch',
|
|
'client_visit' => 'Client / external meeting',
|
|
'errand' => 'Bank / errands',
|
|
'personal' => 'Personal',
|
|
'other' => 'Other',
|
|
],
|
|
|
|
'employee_presence_events' => [
|
|
'sign_in' => 'Sign in',
|
|
'sign_out' => 'Sign out',
|
|
'step_out' => 'Step out',
|
|
'step_in' => 'Return',
|
|
],
|
|
|
|
'badge' => [
|
|
'default_expiry_hours' => 8,
|
|
'qr_url_path' => '/q',
|
|
'employee_qr_url_path' => '/eq',
|
|
],
|
|
|
|
'default_badge_template' => [
|
|
'show_photo' => true,
|
|
'show_qr' => true,
|
|
'show_host' => true,
|
|
'show_company' => true,
|
|
'show_type' => true,
|
|
'primary_color' => '#0d9488',
|
|
'footer_text' => '',
|
|
],
|
|
|
|
'webhook_events' => [
|
|
'visit.checked_in',
|
|
'visit.checked_out',
|
|
'visit.awaiting_approval',
|
|
'employee.signed_in',
|
|
'employee.signed_out',
|
|
'employee.stepped_out',
|
|
'employee.stepped_in',
|
|
],
|
|
|
|
'integrations' => [
|
|
'care' => 'Ladill Care',
|
|
'lab' => 'Ladill Lab',
|
|
'pos' => 'Ladill POS',
|
|
'crm' => 'Ladill CRM',
|
|
'queue' => 'Ladill Queue',
|
|
],
|
|
|
|
'queue' => [
|
|
'api_url' => env('QUEUE_API_URL', 'https://queue.ladill.com/api/v1'),
|
|
'api_key' => env('QUEUE_API_KEY_FRONTDESK'),
|
|
],
|
|
|
|
'printers' => [
|
|
'default_driver' => env('FRONTDESK_PRINTER_DRIVER', 'pdf'),
|
|
'drivers' => ['pdf', 'zebra', 'brother', 'dymo'],
|
|
],
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Visitor type workflows (Phase 4)
|
|
|--------------------------------------------------------------------------
|
|
| Config-driven fields, badge expiry overrides, and approval requirements.
|
|
*/
|
|
'visitor_type_config' => [
|
|
'visitor' => [
|
|
'requires_approval' => false,
|
|
'badge_expiry_hours' => null,
|
|
'details_key' => null,
|
|
'fields' => [],
|
|
],
|
|
'contractor' => [
|
|
'requires_approval' => false,
|
|
'badge_expiry_hours' => 12,
|
|
'details_key' => 'contractor_details',
|
|
'fields' => [
|
|
['name' => 'contract_company', 'label' => 'Contract company', 'type' => 'text', 'required' => true],
|
|
['name' => 'supervisor', 'label' => 'Site supervisor', 'type' => 'text', 'required' => true],
|
|
['name' => 'contract_start', 'label' => 'Contract start', 'type' => 'date', 'required' => false],
|
|
['name' => 'contract_end', 'label' => 'Contract end', 'type' => 'date', 'required' => false],
|
|
['name' => 'safety_induction_completed', 'label' => 'Safety induction completed', 'type' => 'checkbox', 'required' => true],
|
|
['name' => 'insurance_reference', 'label' => 'Insurance reference', 'type' => 'text', 'required' => false],
|
|
['name' => 'permit_number', 'label' => 'Permit number', 'type' => 'text', 'required' => false],
|
|
['name' => 'equipment_carried', 'label' => 'Equipment carried', 'type' => 'textarea', 'required' => false],
|
|
],
|
|
],
|
|
'delivery' => [
|
|
'requires_approval' => false,
|
|
'badge_expiry_hours' => 2,
|
|
'details_key' => 'delivery_details',
|
|
'fields' => [
|
|
['name' => 'courier_company', 'label' => 'Courier company', 'type' => 'text', 'required' => true],
|
|
['name' => 'recipient', 'label' => 'Recipient', 'type' => 'text', 'required' => true],
|
|
['name' => 'tracking_number', 'label' => 'Tracking number', 'type' => 'text', 'required' => false],
|
|
['name' => 'package_description', 'label' => 'Package description', 'type' => 'text', 'required' => false],
|
|
['name' => 'delivery_photo', 'label' => 'Delivery photo', 'type' => 'photo', 'required' => false],
|
|
['name' => 'delivery_signature', 'label' => 'Signature', 'type' => 'signature', 'required' => false],
|
|
],
|
|
],
|
|
'vendor' => [
|
|
'requires_approval' => true,
|
|
'badge_expiry_hours' => null,
|
|
'details_key' => 'contractor_details',
|
|
'fields' => [
|
|
['name' => 'vendor_company', 'label' => 'Vendor company', 'type' => 'text', 'required' => true],
|
|
['name' => 'service_type', 'label' => 'Service / product', 'type' => 'text', 'required' => true],
|
|
['name' => 'purchase_order', 'label' => 'PO number', 'type' => 'text', 'required' => false],
|
|
],
|
|
],
|
|
'interview_candidate' => [
|
|
'requires_approval' => true,
|
|
'badge_expiry_hours' => null,
|
|
'details_key' => 'contractor_details',
|
|
'fields' => [
|
|
['name' => 'position_applied', 'label' => 'Position applied for', 'type' => 'text', 'required' => true],
|
|
['name' => 'interviewer', 'label' => 'Interviewer', 'type' => 'text', 'required' => false],
|
|
['name' => 'scheduled_interview_at', 'label' => 'Interview time', 'type' => 'datetime-local', 'required' => false],
|
|
],
|
|
],
|
|
],
|
|
|
|
];
|