Changelog
Version history and release notes for Deprixa Plus.
Major release: Complete SaaS multi-tenant billing engine, Paystack payment gateway, UltraMsg WhatsApp integration, Contracts & Commissions modules activated, public pricing page, 10-step onboarding checklist, subscription lifecycle with auto-renewal and grace periods, webhook security hardening, comprehensive audit logging, collapsible sidebar navigation, proration on plan changes, auto-reactivation after wallet recharge, GDPR notification opt-out, PDF invoice download, honeypot anti-bot protection, and full responsive design for all screen sizes.
Post-Audit Fixes (v1.4.0 Final)
- Collapsible sidebar: Navigation reorganized into expandable groups — Logistics, Customer Portal, Finance, SaaS Admin. Auto-collapses on screens < 1280px.
- Proration on plan change: When upgrading/downgrading, remaining days are credited back to wallet before switching plans.
- Auto-reactivation: Organizations in read-only or grace period are automatically reactivated when wallet balance becomes sufficient after recharge.
- GDPR notification opt-out: Customers can opt out of WhatsApp/email notifications via
/notification-preferences. - PDF SaaS invoices: Download invoices as PDF from
/my-billing/invoices/{id}/pdfvia DomPDF. - Honeypot anti-bot: Hidden form field on registration to prevent automated signups.
- Email verification: Three controllers created —
EmailVerificationPromptController,VerifyEmailController,EmailVerificationNotificationControllerwith InertiaVerifyEmailpage. - WhatsApp actually sends:
NotificationService::send()now reads rule channels and dispatches via queued Job with 3 retries. UltraMSG primary, Twilio fallback. - Notification logging: All WhatsApp/SMS sends logged in
notification_logstable viaNotificationLogmodel. - Template variables: 6 placeholders —
{{tracking}},{{status}},{{name}},{{sender}},{{company}},{{date}}— click-to-copy in editor. - Expiring-soon alerts: Email + in-app notification at 7, 3, and 1 days before subscription expiration with deduplication.
- API keys encrypted: Stripe/PayPal/Paystack credentials encrypted with
Crypt::encryptString()in database. - Storage & API tracking:
getStorageUsageGb()andtrackApiCall()methods with daily cache counter. - Responsive design: 16 table pages fixed with
overflow-x-auto, sidebar auto-collapse, main content overflow protection. - 80 database tables (added
notificationstable for Laravel DatabaseNotifications). - Upgrade command:
php artisan deprixa:upgrade— 6-step automated upgrade with maintenance mode. - i18n complete: All hardcoded strings replaced with
t()calls. 4,040+ keys in EN and ES. - 137 PHPUnit tests — 100% passing.
SaaS Billing Engine (NEW)
- 5 subscription plans: Free ($0), Starter ($29/mo), Growth ($79/mo), Pro ($199/mo), Enterprise ($499/mo) with shipment/user/branch limits
- Wallet system: organizations recharge via Stripe, PayPal, or Paystack; system auto-debits on subscription renewal
- Subscription lifecycle: Trial → Active → Grace Period → Read Only with automatic transitions via
saas:check-subscriptionsdaily cron - Plan limit enforcement:
SaasUsageServiceblocks shipment creation when monthly limit exceeded - CheckSubscriptionStatus middleware: blocks write operations for read_only/suspended organizations while allowing billing access
- SaaS Admin Dashboard: revenue metrics, subscription overview, wallet management, invoice tracking at
/admin/billing - SaaS Invoices: auto-generated on recharge and renewal; types: subscription, recharge, adjustment, refund
- Notifications: email + in-app alerts on every subscription transition (renewed, grace period, read-only)
- Audit logging: all admin billing operations logged (create/toggle plan, credit/debit wallet, assign/cancel subscription, mark invoice paid)
Payment Gateways
- Paystack: full integration — initialize transaction, redirect to checkout, verify payment, webhook with HMAC SHA-512 signature verification
- Stripe: existing integration hardened — webhook signature verification confirmed
- PayPal: webhook payload validation added, idempotency by reference ID
- All three gateways create
saas_invoiceandsaas_wallet_transactionautomatically on successful payment
Notifications
- UltraMsg WhatsApp: new notification channel — alternative to Twilio for WhatsApp messages via UltraMsg API
- Pre-test validation: all channels (SMTP, Twilio, UltraMsg) now validate credentials before testing connection
- Channel configuration stored in
notification_channelstable with encrypted tokens
Roles & Permissions
- 102 permissions (up from 97): added
saas.billing.admin,saas.plans.manage,saas.subscriptions.manage,saas.wallets.manage,saas.invoices.manage - Customer role: added
shipments.view(7 permissions total) — customers can now see their shipments - Driver role: added
pod.view,pod.create(11 permissions total) — drivers can capture proof of delivery - Admin role: 98/102 permissions including all SaaS management
Modules & UX
- Contracts module: activated for Plus edition (was premium-only)
- Commissions module: activated for Plus edition (was premium-only)
- Public pricing page: responsive plan comparison at
/pricing— landing page now redirects here - Onboarding checklist: expanded from 4 to 10 steps — branch, employee, payment gateway, branding, first shipment, subscription plan
- SaaS sidebar section: 5 navigation items for admin billing management
- i18n: 4,008 keys in both EN and ES (100% parity)
Security
- Paystack webhook: HMAC SHA-512 signature verification
- PayPal webhook: payload validation and logging
- Subscription middleware prevents unauthorized data modification
- Migration fix:
cleanup_orphaned_permissionsno longer crashes on fresh install - CSRF exception added for Paystack webhook endpoint
Database
- 79 tables (unchanged) — SaaS tables were already present
- 102 permissions in
deprixa_lite.sqlwizard - 5 SaaS plans pre-seeded (Free, Starter, Growth, Pro, Enterprise)
- UltraMsg channel pre-configured (inactive) in
notification_channels - 137 PHPUnit tests — 100% passing
Automatic locker assignment on web registration, pre-alert numbering, staff notification, complete security: active CORS, hardened security headers (COOP, CORP, preload HSTS, object-src none), and Row Level Security completed on all models with organization_id.
v1.3.2 Highlights
- Registration at
/register: customers of the main organization receive an automatic unique locker — the first registrant creates the organization (initial installation) - Pre-alerts: human-readable number generated on creation (
PA-YYYY-NNNNN, using DB ID — no race conditions) - Staff notification (admin/employees) on new pre-alert received via
broadcast() - CORS enabled:
config/cors.phpcreated +HandleCorsregistered in web and API stacks - Hardened security headers: COOP, CORP,
X-Permitted-Cross-Domain-Policies,preloadon HSTS,object-src 'none',worker-src - RLS completed:
BelongsToTenantadded toCustomerContactandGeocodedAddress(the only models withorganization_idthat were missing)
Locker & Web Registration
- RegisteredUserController — branching logic: if organization exists, create customer + locker; if not, create org + admin
- Locker assigned via
LockerCodeService::generate()— respects configured format (sequential or random) per organization - Uniqueness guaranteed: service-level check +
UNIQUE(organization_id, code)constraint in DB - After registration the customer is redirected to
/my-locker - NOTE: The route
/register/customer/{slug}keeps its behavior unchanged
Pre-Alerts
- New column
pre_alerts.pre_alert_number(migration2026_04_22_000001):VARCHAR(30)+ composite index - Number generated in
PreAlertController::store()formatPA-2026-00001using$preAlert->id - Field added to
PreAlert::$fillable - New listener
NotifyStaffOnPreAlertCreated: notifies all staff viaInAppNotificationService::broadcast()when a customer creates a pre-alert - Registered in
DomainEventServiceProvideras second listener ofPreAlertCreated - Language keys added in
lang/es/pre_alerts.phpandlang/en/pre_alerts.php:notification_staff_created_titleandnotification_staff_created_body
Security — CORS, Headers & RLS
- CORS (
config/cors.php): pathsapi/*+sanctum/csrf-cookie; allowed_origins fromCORS_ALLOWED_ORIGINSenv or APP_URL; methods: GET/POST/PUT/PATCH/DELETE/OPTIONS; credentials: true; max_age: 7200s HandleCorsregistered inbootstrap/app.php: prepend in web stack and API stack- New Security Headers:
X-Permitted-Cross-Domain-Policies: none— blocks Flash/Adobe crossdomain.xmlCross-Origin-Opener-Policy: same-origin— isolates browsing context (Spectre mitigation)Cross-Origin-Resource-Policy: same-origin— prevents other origins from embedding resourcesStrict-Transport-Security: addedpreload(eligible for browser HSTS preload list)Permissions-Policy: addedusb=(), bluetooth=(), serial=(), hid=()- CSP: added
object-src 'none'(blocks plugins),worker-src 'self' blob:andupgrade-insecure-requests
- RLS — Row Level Security completed:
BelongsToTenantadded toCustomerContactandGeocodedAddress. Total models with tenant scope: 34/34 (all withorganization_id). Correctly excluded:Organization(is the tenant),User(special management),PersonalAccessToken,SaasPlan,City,Country,State,Currency(global data without tenant)
Modified Files
app/Http/Controllers/Auth/RegisteredUserController.php— client/org-owner branchingapp/Http/Controllers/PreAlertController.php— generates pre_alert_numberapp/Models/PreAlert.php— pre_alert_number in fillableapp/Models/CustomerContact.php— BelongsToTenant addedapp/Models/GeocodedAddress.php— BelongsToTenant addedapp/Listeners/NotifyStaffOnPreAlertCreated.php— new fileapp/Providers/DomainEventServiceProvider.php— staff listener registeredapp/Http/Middleware/SecurityHeaders.php— additional headersbootstrap/app.php— HandleCors in web and APIconfig/cors.php— new filelang/es/pre_alerts.phpandlang/en/pre_alerts.php— staff keysdatabase/migrations/2026_04_22_000001_add_pre_alert_number_to_pre_alerts_table.php
Complete permission system overhaul — removed all premium/orphaned permissions, added all missing Plus module permissions (Pickups, Lockers, Pre-Alerts, Commissions, Contracts, Returns, COD, Locations, Import), hardened every module route with can: middleware, and corrected 9 nav visibility checks. Final state: 97 permissions, all belonging to Deprixa Plus (zero premium).
v1.3.1 Highlights
- 97 permissions in total — every permission belongs to Deprixa Plus; zero premium/SaaS permissions remain in the database
- 7 premium permissions removed from DB and routes reguarded:
manage organizations,view saas billing,manage saas billing,recharge wallet,view organizations,manage settings,manage users— routes now userole:super-admin - 5 settings API permissions removed:
settings.api.view,settings.api.tokens.manage,settings.api.clients.manage,settings.api.webhooks.manage,settings.api.logs.view— routes now userole:admin|super-admin - All module permissions properly added and gated: Pickups, Lockers, Pre-Alerts, Commissions, Contracts, Returns, COD, Locations, Import
- Roles matrix now shows all 97 permissions; Admin can toggle any permission for Employee, Driver, and Customer roles
- 9 nav config items corrected to use the right permission for sidebar visibility
- SQL dump (
database/sql/deprixa_lite.sql) fully synchronized — migrations 114–117 added,role_has_permissionsupdated for all roles
Permission System Remediation
- Removed premium permissions:
manage organizations,view saas billing,manage saas billing,recharge wallet,view organizations,manage settings,manage users— deleted from DB; routes changed torole:super-admin - Removed settings API permissions:
settings.api.view,settings.api.tokens.manage,settings.api.clients.manage,settings.api.webhooks.manage,settings.api.logs.view— deleted from DB; routes changed torole:admin|super-admin - Added Pickups:
pickups.view,pickups.create,pickups.manage - Added Lockers (admin):
lockers.view,lockers.manage - Added Pre-Alerts:
pre-alerts.view,pre-alerts.create,pre-alerts.manage - Added Commissions:
commissions.view,commissions.manage - Added Contracts:
contracts.view,contracts.create,contracts.manage - Added Returns:
returns.view,returns.create,returns.update - Added COD:
cod.view,cod.collect,cod.remit - Added Locations:
locations.view,locations.manage - Added Import:
shipments.import - Migrations:
2026_04_19_000001_cleanup_orphaned_permissions,2026_04_19_000002_add_missing_module_permissions
Routes & Middleware Hardening
GET /pickups/*→can:pickups.view; mutating routes →can:pickups.manageGET /lockers/*→can:lockers.view; mutating routes →can:lockers.manageGET /pre-alerts/*→can:pre-alerts.view; create →can:pre-alerts.create; admin actions →can:pre-alerts.manageGET /commissions/*→can:commissions.view+edition:commissions; mutating →can:commissions.manageGET /contracts/*→can:contracts.view+edition:contracts; create →can:contracts.create; mutating →can:contracts.manageGET /returns/*→can:returns.view; create →can:returns.create; update →can:returns.updateGET /cod/*→can:cod.view; collect →can:cod.collect; remit →can:cod.remitGET /locations/*→can:locations.view; mutating →can:locations.managePOST /shipments/import→can:shipments.import/settings/shipment-statuses→can:settings.shipment-statuses.view/manage/settings/services→can:settings.services.view/manage/settings/updates→can:settings.updates.view/settings/hs-codes→can:settings.hs-codes.view/manage/settings/integrations→can:settings.integrations.view/update/admin/*→role:super-admin(wascan:manage organizations)/my-billing/*→role:super-admin(wascan:view saas billing)/api-tokens+/settings/api/*→role:admin|super-admin
Navigation Config Fixes
- Warehouse nav item:
dispatch.create→warehouse.access - Pickups nav item:
dispatch.create→pickups.view - Lockers nav item:
dispatch.create→lockers.view - Pre-Alerts nav item:
dispatch.create→pre-alerts.view - Customers nav item:
manage users→customers.access - Contracts nav item:
customers.access→contracts.view - Commissions nav item:
finance.view→commissions.view - Rates nav item:
settings.shipping-config.view→settings.pricing.view - Locations nav item:
settings.company.view→locations.view
Roles Matrix
- Settings → Roles matrix now shows all 97 permissions
- All new module groups visible: Pickups, Lockers, Pre-Alerts, Commissions, Contracts, Returns, COD, POD, Customs, Locations
- Super-admin: 94/97 permissions; Admin: 97/97; Employee: 40; Driver: 8; Customer: 5
- Admin can toggle any permission for Employee, Driver, and Customer roles from the matrix
- Customer role (5 perms):
view dashboard,create shipments,tracking.view,pre-alerts.view,pre-alerts.create - Driver role (8 perms):
view dashboard,dashboard.kpi.view,dashboard.activity.view,dispatch.view,dispatch.update,dispatch.access,change status shipments,tracking.view - Employee role (40 perms): all operational permissions — shipments, dispatch, warehouse, customers, pickups, pre-alerts, lockers.view, import, returns, COD, POD, customs.view, contracts.view/create, locations.view, finance, billing.view, pricing.view, settings.shipment-statuses.view, settings.services.view
- Admin role (94 perms): all 94 Plus permissions
- Super-admin: synced to
Permission::all()— always 100%
Database & SQL Dump
database/sql/deprixa_lite.sqlfully synchronized with all permission changes- Migrations table: entries 114–117 added
role_has_permissionsupdated for all roles (super-admin, admin, employee, driver, customer)- Zero premium permissions in the SQL dump
- Migration
2026_04_18_000002_add_module_permissions— adds pickups, lockers, pre-alerts, commissions permissions - Migration
2026_04_19_000001_cleanup_orphaned_permissions— deletes all premium/orphaned permissions - Migration
2026_04_19_000002_add_missing_module_permissions— adds contracts, locations, shipment-statuses, services, updates permissions
Introduces the Customer Self-Registration Portal, a complete invitation system for staff and customers, My Locker customer dashboard, and critical role security hardening for the customer role.
v1.3.0 Highlights
- Customer self-registration portal at
/register/customer/{org-slug}— customers sign up independently with full org branding (logo, color) - Staff invitation system — creating a user sends a secure email invitation; no password is set by the admin
- Customer portal invitation from the Customers module — invite customers directly from admin panel or resend from their profile
- My Locker — dedicated customer dashboard at
/my-lockershowing the customer's locker, pre-alerts, and shipment counters - Customer Portal Link in Settings → Company — one-click copy and preview of the public registration URL
- Customer role security hardened: removed
customers.access,dashboard.kpi.view,dashboard.activity.view— customers can no longer access the admin area - All data scoped to the customer: pre-alerts and shipments filtered by
customer_id/created_bywhen the logged-in user has thecustomerrole - Customers redirected to
/my-lockeron login and dashboard access — never land on the admin logistics dashboard - SMTP fallback: if email is not configured, invitation URL displayed in the dashboard for manual sharing
- All new UI strings fully internationalized — English and Spanish (
en.json,es.json,lang/en/,lang/es/)
Customer Portal
- Public self-registration page per organization at
/register/customer/{slug} - Registration page inherits organization branding — logo, name, and primary color
- Fields: name, email, phone (optional), password, confirm password
- Email uniqueness is scoped per organization — the same email can exist in different organizations
- After registration, customer is auto-logged-in and redirected to My Locker
- Rate-limited: max 10 registration attempts per minute per IP
- Inactive organizations return a 404 — registration link only works for active organizations
- Translation files:
lang/en/customer_portal.phpandlang/es/customer_portal.php - Routes:
GET|POST /register/customer/{slug}→customer.portal.register/customer.portal.register.store
Invitation System
- Creating a staff user (Settings → Users) now sends a
UserInvitationMail— no password set by admin - Invitation token:
Str::random(64), stored inusers.invitation_token, valid 7 days - Resend Invitation action in user dropdown menu (visible for users with pending invitations)
- Creating a customer from the admin panel also sends a portal invitation email
- Customer Detail page shows portal status badge: Active / Pending / No Access
- Resend invitation button on Customer Detail page
- If SMTP not configured: invitation URL exposed in amber banner — admin can copy and share manually
- Translation files:
lang/en/invitation.phpandlang/es/invitation.php - DB columns added to
users:invitation_token(varchar 100, unique),invitation_sent_at(timestamp),invitation_accepted_at(timestamp) - Routes:
GET /invitation/{token}→invitation.show|POST /invitation/{token}/accept→invitation.accept - Routes:
POST /settings/users/{user}/resend-invitation→settings.users.resend-invitation - Routes:
POST /customers/{customer}/resend-portal-invitation→customers.resend-invitation
My Locker (Customer Dashboard)
- Dedicated customer dashboard at
/my-locker - Displays the customer's assigned locker: code, address, warehouse
- Pre-alert list scoped to the logged-in customer with status counters (pending, received, converted, cancelled)
- All data is strictly scoped to
customer_id = Auth::id()— no cross-customer data exposure - Navigation item visible to all authenticated users without additional permission
Security — Customer Role Hardening
- Removed
customers.accessfromcustomerrole — customers could previously access the customer management admin area - Removed
dashboard.kpi.viewanddashboard.activity.viewfromcustomerrole - Customer role now holds exactly:
view dashboard,create shipments,tracking.view LoginController: customers redirected to/my-lockerafter login (all other roles →/dashboard)DashboardController::index(): redirects customers to/my-lockeras a secondary guardPreAlertController::index(): scopes results tocustomer_id = Auth::id()for customer roleShipmentController::index(): scopes results tocreated_by = Auth::id()for customer role; stats follow same scoping- All role name references normalized to lowercase
'customer'throughout codebase (CustomerController,CustomersExport,CustomersImport,DeprixaProImporter,ContractController) - Migration:
2026_04_18_000001_fix_customer_role_permissions
Settings — Customer Portal Link
- Settings → Company now shows a Customer Portal Registration Link section
- Displays the full public URL for customer self-registration under this organization
- One-click Copy button with visual feedback (icon changes to checkmark after copy)
- Preview button opens the registration page in a new tab for testing
Database & Demo SQL
users: addedinvitation_token(varchar 100, unique),invitation_sent_at,invitation_accepted_at(timestamps)- Migration
2026_04_17_600001_add_invitation_fields_to_users_table - Migration
2026_04_18_000001_fix_customer_role_permissions— revokes excess permissions from customer role database/sql/deprixa_lite.sqlupdated:role_has_permissionsandmigrationstable aligned with all of the above
First public release of Deprixa Plus on Envato CodeCanyon — a complete courier and logistics management platform built with Laravel 12, React 18, and Inertia.js.
v1.2.0 Highlights
- Invoice number permanently stored in database at shipment creation — guarantees audit trail and financial traceability across all time
- Invoice search now covers both tracking number and invoice number simultaneously
- COD (Cash on Delivery) module: full field set on shipments —
is_cod,cod_amount,cod_currency,cod_status,cod_collected_at,cod_collected_by - Proof of Delivery module: capture signatures, photos, and recipient confirmation linked to each shipment
- Return Shipments module: manage reverse logistics with full status lifecycle
- HS Codes & Customs Declarations: international shipment compliance fields
- Import Jobs: bulk shipment import tracking with validation and error reporting
- Install wizard fully automated — imports database, runs pending migrations, and creates storage symlink in a single flow with zero manual steps
- Production-hardened CSP — all dev-server origins removed from security middleware
- Sequential numbering system: configurable prefix, padding, and periodic reset rules for both invoice numbers and tracking numbers
Shipments Module
- Full shipment lifecycle management: Created → Assigned → Picked Up → In Transit → Out for Delivery → Delivered
- Exception recording with reason codes and reattempt scheduling
- On Hold and Returned status branches with appropriate next-action flows
- Auto-generated tracking numbers in
TRK########format (8-digit zero-padded sequential) - Shipment creation wizard: Sender/Receiver → Package Details → Service Selection → Review & Confirm
- Bulk status updates with branch-level permission controls
- Shipment label PDF generation in four formats: A4 Full Page, A4 Half Page, Thermal 4×6, Thermal 4×4
- Clone shipment functionality for recurring senders and receivers
- Archive shipments to keep the active list clean without deleting records
- Full activity log per shipment capturing every status change, user action, and timestamp
- Multi-dimensional search and filter: status, date range, courier, branch, service type, zone, COD, exception flag, client, tracking number
- COD (Cash on Delivery) tracking with reconciliation flags
- Parcel dimensions and weight capture with volumetric weight calculation
- Fragile goods and declared value fields
- Internal reference number field for e-commerce order correlation
- File attachments per shipment (photos, documents, proof of delivery)
- Export shipment list to CSV
Dispatch Module
- Dispatch board showing unassigned and in-progress shipments for the current branch
- Individual and bulk assignment of shipments to couriers
- Auto-optimize route engine (
POST /dispatch/auto-optimize) — groups shipments by zone and assigns to optimal couriers - In-app courier notification on assignment
- Re-assignment and unassignment from the dispatch board
- Real-time driver locations map showing courier GPS positions, last update time, and assigned shipment count
- Driver location history playback for any courier and any date (retained 30 days)
- Dispatch board filters: branch, courier, zone, status, date, service type
Customers Module
- Individual and company client profiles with full field sets (name, type, ID/tax number, email, phone, address, tags, notes)
- Customer list with search by name, phone, email, or ID
- Filter by customer type, city, and tags
- Shipment history tab per customer showing all linked shipments with status and date
- Customer summary stats: total shipments, total billed, outstanding balance
- CSV import with downloadable template and import preview
- CSV export respecting active filters
- Quick-create modal from within the shipment wizard — create a customer without leaving the form
- Search-as-you-type customer lookup in shipment forms with address auto-fill
- Soft delete (archive) for customers with linked shipments
Rates & Pricing Module
- Geographic zone management — name, code, description, city assignments
- Rate card creation per origin zone → destination zone → service type combination
- Weight-tier rate rules with base price, per-kg surcharge, and dimensional weight factor
- Automatic price calculation at shipment creation based on zones, weight, and service type
- Price override capability for operators with appropriate permission
- Internal rate calculator (staff): enter origin, destination, weight, dimensions → get full price breakdown
- Public rate calculator at
/rate— no login required, for customer self-service quotes - Rate card active/inactive toggle for managing pricing changes without deleting history
Billing Module
- One invoice per shipment — auto-generated at shipment creation
- Billing list with filters by date range, payment status, and branch
- Invoice detail page with full company branding, line items, tax breakdown, and payment history
- Payment recording: date, method (cash, bank transfer, card, check), reference number, amount, notes
- Partial payment support — invoice status updates to Partially Paid with remaining balance tracked
- Invoice send via Email (PDF attachment), WhatsApp (link), and SMS (link)
- Single invoice PDF download from detail page
- Bulk PDF export with ZIP packaging from the billing list
- Invoice void capability
- Online payment endpoint (
/shipments/{shipment}/payment/success) for gateway integrations - Tax configuration per organization applied automatically to all invoices
Reports Module
- Financial Report at
/reports/financial— revenue by period, paid vs. unpaid, top clients, total shipments, delivered %, exception % - Revenue bar chart showing billed amounts over time (daily/weekly/monthly granularity)
- Payment status donut chart showing Paid / Partially Paid / Unpaid distribution with collection rate %
- Top 5 clients by revenue table with billed, collected, and outstanding columns
- Filters: date range (7 presets + custom) and branch
- PDF export of the full financial report with charts
- Access restricted to roles with
settings.billing.viewpermission
Dashboard
- KPI cards: Total Shipments, Pending Shipments, Delivered Today, Revenue (MTD), Exceptions (Open), Overdue Invoices
- Recharts-powered charts: daily shipment volume line chart, status distribution donut, revenue by period bar chart
- Logistics sub-dashboard at
/dashboard/logisticsfor operational metrics - Exception Alert Panel: live list of open exceptions with direct links to affected shipments
- Date range presets plus custom range picker
- Branch filter: Admins and Managers can switch between branches or view company-wide data
- Role-adapted dashboard views: Couriers see only their own assigned shipments; Accountants see financial KPIs
Users & Roles
- Five roles: Super Admin, Admin, Employee, Driver, Customer
- Spatie Laravel Permission for fine-grained RBAC — permissions covering Shipments, Dispatch, Customers, Billing, Reports, Settings, Rates/Pricing
- Full permission matrix with role-to-permission mapping, customizable per role in Settings → Roles
- Two-factor authentication (TOTP): optional per user or enforced by admin for specific roles
- Recovery codes for 2FA lockout scenarios
- Admin 2FA override for locked-out users (logged in audit trail)
- Password policies: minimum length, complexity requirements, history, expiry, lockout thresholds — configured in Settings → Security
- User deactivation (preserves history) vs. permanent deletion
- User invitation via email with 24-hour expiring activation link
- Role-adapted UI: navigation and features shown/hidden based on the logged-in user's role
Settings
- Company Profile: name, tax ID, address, phone, email, website, logo variants (main, dark, light, invoice, favicon)
- Branding: primary/secondary/accent color configuration, theme selection, font selection
- Locale: language (EN/ES), timezone, date/time format, weight/dimension units, currency with symbol configuration
- Branch management: multi-branch support with individual address, phone, and operational hours per branch
- Shipment status configuration: rename status labels, change indicator colors
- Service type configuration: add, rename, and set expected transit time for each service type
- Notifications: email event triggers with template preview and per-event enable/disable
- Security settings: password policy and session controls including login attempt limits and session timeout
- Tracking page: public tracking toggle, page headline, branded cover image, show/hide courier name
- Shipping config: COD settings, label formats, tracking number prefix
- Audit log: full user action log filterable by user, action type, and date
- Maintenance tools: clear cache, clear sessions, run database backup, enable maintenance mode
- Updates: License activation and OTA update management with version history
Public Tracking
- Public tracking page at
/tracking— no login required - Enter tracking number or scan QR code to view shipment status
- Full status timeline with timestamps, courier notes, and delivery confirmation
- Branded tracking page — shows company logo, colors, and custom headline from Settings → Tracking
- Optional show/hide of courier name on the public tracking page
Public Rate Calculator
- Public rate calculator at
/rate— no login required - Customer selects origin city, destination city, weight, and service type to get a price estimate
- Uses the same rate cards and rules configured in the Rates & Pricing module
- No account or purchase commitment required — purely informational quoting tool
REST API
- Laravel Sanctum token authentication with fine-grained ability scoping
- Base URL:
/api/v1— versioned for forward compatibility - Shipments endpoints: list, create, get by tracking number, update status, record exception, download label, cancel
- Public tracking endpoint: no authentication required, returns status history
- Customers endpoints: list, create, get, update
- Billing endpoints: list invoices, get invoice (with PDF option), record payment
- Reports endpoint: financial report summary
- Webhook support: shipment status events with HMAC-SHA256 signature verification and retry logic
- Rate limiting per token with differentiated limits for read/write/report endpoints
- Standardized pagination envelope with
metaandlinksobjects - Standardized error responses with
code,message,errors, andrequest_id
Platform & Infrastructure
- Laravel 12 (PHP 8.2+), React 18, Inertia.js 2 — full-stack SPA without a separate API layer for the web UI
- Tailwind CSS 4 + Vite 5 for asset compilation
- Spatie Laravel Permission for RBAC
- Spatie Laravel Activity Log for full audit trails across all models
- DomPDF for server-side PDF generation (invoices, labels, reports)
- Recharts for interactive dashboard analytics
- React i18next for EN/ES internationalization — UI strings, email templates, and PDF content
- Ziggy for exporting named Laravel routes to JavaScript
- Redis support for cache, sessions, and job queues
- Laravel Horizon for queue monitoring
- License activation and over-the-air update delivery integration
- S3-compatible object storage support for document uploads, invoice PDFs, and export files
- Multi-branch architecture: data scoped by branch with cross-branch views for Admin+
- Full dark mode UI with responsive layout (mobile-adaptive sidebar, touch-friendly shipment list)
- Distributed as a ZIP download via Envato/CodeCanyon — no GitHub repository