Deploy Ladill Frontdesk / deploy (push) Successful in 1m16s
Surface hardware kiosk provision in plan benefits, upgrade banners, and settings copy so paid tiers clearly include supplied visitor kiosks.
363 lines
14 KiB
PHP
363 lines
14 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',
|
|
// GHS 990/branch/mo (legacy FRONTDESK_PRO_PRICE_MINOR still honored).
|
|
'price_minor_per_branch' => (int) env(
|
|
'FRONTDESK_PRO_PRICE_PER_BRANCH_MINOR',
|
|
env('FRONTDESK_PRO_PRICE_MINOR', 99000),
|
|
),
|
|
'price_minor' => (int) env(
|
|
'FRONTDESK_PRO_PRICE_PER_BRANCH_MINOR',
|
|
env('FRONTDESK_PRO_PRICE_MINOR', 99000),
|
|
),
|
|
'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',
|
|
'branches',
|
|
'team',
|
|
'integrations',
|
|
'webhooks',
|
|
'scheduled_reports',
|
|
'custom_badge_templates',
|
|
],
|
|
],
|
|
'enterprise' => [
|
|
'label' => 'Enterprise',
|
|
// GHS 1990/branch/mo.
|
|
'price_minor_per_branch' => (int) env('FRONTDESK_ENTERPRISE_PRICE_PER_BRANCH_MINOR', 199000),
|
|
'max_branches' => null,
|
|
'max_kiosk_devices' => null,
|
|
'free_emails_per_month' => null,
|
|
'features' => [
|
|
'check_in',
|
|
'hosts',
|
|
'badges',
|
|
'watchlist',
|
|
'branches',
|
|
'team',
|
|
'integrations',
|
|
'webhooks',
|
|
'scheduled_reports',
|
|
'custom_badge_templates',
|
|
],
|
|
],
|
|
],
|
|
|
|
'enterprise' => [
|
|
'min_branches' => (int) env('FRONTDESK_ENTERPRISE_MIN_BRANCHES', 1),
|
|
],
|
|
|
|
'prepaid_months' => [6, 12, 24],
|
|
|
|
'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],
|
|
],
|
|
],
|
|
],
|
|
|
|
'upgrade_banner' => [
|
|
'title' => 'Unlock Frontdesk Pro or Enterprise',
|
|
'description' => 'Ladill-provided visitor kiosks, multi-branch, team, webhooks & reports — from GHS 990/branch/mo.',
|
|
'route' => 'frontdesk.pro.index',
|
|
],
|
|
|
|
];
|