Features Overview
A complete reference of every feature in Surveyor POS.
1. Day Rental System
The standard rental system tracks equipment rented by the day.
Data model:
Rental— the rental agreement (customer, branch, totals, deposit)RentalItems— one row per piece of equipment in the rentalSpecification— an individual unit of equipment (serial number, price per day, condition, status)Equipment→Category— the equipment type and its category
Lifecycle:
- Admin or worker opens the Rental POS and selects a customer
- Equipment is chosen by serial number; price is calculated automatically as
price_per_day × duration_days - Selected specs are marked
rented(hidden from future availability) - Items are returned individually via the Return workflow; specs revert to
available - Late fees accrue automatically via the nightly
app:calculate-rental-late-feescommand
Financial tracking per rental:
| Field | Description |
|---|---|
total_price |
Sum of all item prices at time of creation |
total_paid |
Sum of all recorded payments |
late_fee |
Total accumulated late fees |
damage_fee |
Manually entered damage charges |
discount |
Discount applied at creation |
deposit_amount |
Bond/deposit collected upfront |
deposit_returned |
Boolean — whether deposit was refunded |
Rental extension: Admins and workers can extend an active rental by adding extra days to all unreturned items. The due date shifts forward, the rental duration is recalculated, and the additional cost is added to total_price. Only items not yet returned are extended. An audit log entry is created for every extension.
PDF receipt: Available on every rental's show page via the Download PDF button.
2. Point Rental System
A parallel rental system that uses a point-based pricing model, typically for specialised survey instruments or project-based work.
Data model mirrors the day rental system:
PointRental→PointRentalItems→PointSpecification→PointEquipment→PointCategory
Key difference: Specifications use price_per_point instead of price_per_day. The PointRentalItems table also stores a points field.
Everything else (payments, deposits, late fees, PDF, CSV exports) works identically to the standard rental system.
3. Booking Requests
Customers can submit equipment booking requests from their dashboard without needing to visit in person.
Workflow:
Customer submits booking request
↓
SMS sent to customer (confirmation) + SMS sent to all branch workers (new request alert)
↓
Admin or Worker sees pending badge on sidebar
↓
Staff reviews items, dates, notes
↓
┌───────────┐
│ Approve │ → Rental/PointRental auto-created → SMS sent to customer
└───────────┘
┌───────────┐
│ Reject │ → Reason recorded → SMS sent to customer with reason
└───────────┘
Customer can cancel their own pending requests
Customer actions:
- Submit a booking for either day rental or point rental equipment
- Select multiple items and specify duration (days) per item
- See an estimated total before submitting
- The booking form shows a blue information banner confirming which branch will receive the request
- View status of all past requests (pending / approved / rejected / cancelled)
- Cancel pending requests
Admin and Worker actions:
- Filter requests by status (pending / approved / rejected / cancelled)
- Sidebar badge shows live pending count
- Approve → rental is created automatically, equipment marked as rented
- Reject → reason required, SMS sent
- Bulk approve / bulk reject — select multiple pending bookings from the list with checkboxes, then approve or reject them all in one action; a reason is required for bulk rejection
Availability check at approval time:
Equipment is not reserved when a booking is submitted. When the booking is approved, the system checks that every item is still available inside a database transaction. If any item is no longer available (e.g. rented out by another booking in the meantime), the approval is blocked and the admin/worker is shown an error. This prevents double-booking without locking equipment speculatively.
Booking auto-expiry:
The scheduled command app:auto-expire-bookings runs daily at 02:00 and automatically rejects any pending booking that has been waiting for more than 3 days. The customer is notified by SMS. The expiry window can be changed via the --days option.
SMS notifications (Wigal):
- On submission to customer:
"Your [day/point] booking request for [N] item(s) has been submitted to [Branch]. Our team will review it and notify you once a decision is made." - On submission to each branch worker (with phone):
"New [day/point] booking request from [Name] for [N] item(s) at [Branch]. Please review booking #[ID]." - Approval:
"Your [day/point] rental booking request has been approved! Please visit us to collect your equipment." - Rejection / cancellation / auto-expiry: SMS sent with the reason or expiry notice
4. Payment Recording
Partial and full payments can be recorded against any rental or point rental.
Payment methods: Cash, Mobile Money, Bank Transfer, Other
Each payment record stores:
- Amount
- Method
- Notes
- Who recorded it (polymorphic — admin or worker)
- Timestamp
The rental's total_paid is automatically recalculated as the sum of all payments when a new payment is saved. The financial summary on the rental show page colour-codes the balance row (green = fully paid, red = outstanding).
5. Deposit & Bond Tracking
Every rental can have an optional deposit collected upfront (deposit_amount). The rental show page displays:
- Deposit amount collected
- Whether it has been returned
- Date returned (if applicable)
Admins can mark a deposit as returned via the Return Deposit button, which requires a SweetAlert confirmation and records the action in the audit log.
6. Equipment Availability
The Equipment Availability page is available to both admins (/admin/availability) and workers (/worker/availability). It shows which equipment is currently available or rented for any date range.
- Default view: today → 7 days ahead
- Queries
RentalItemsandPointRentalItemswherereturned_at IS NULLto determine what is out - Four tables: Available Day Equipment, Rented Day Equipment, Available Point Equipment, Rented Point Equipment
7. Maintenance Logs
Track the service history of every piece of equipment.
Log fields:
| Field | Options |
|---|---|
| Equipment | Day or point specification (serial number) |
| Type | Routine, Repair, Inspection |
| Status | Scheduled, In Progress, Completed |
| Notes | Free text |
| Started at | Date/time |
| Completed at | Date/time |
| Recorded by | Admin or worker (polymorphic) |
Logs are paginated and filterable. Each spec's maintenance history is accessible from its detail page.
8. Project & Task Management
Projects are linked to a customer and can contain multiple tasks.
- Tasks can be assigned to workers
- Tasks have a status and comment thread
- Project files (documents, survey reports, images) can be uploaded and downloaded by the assigned customer
- Workers see their assigned tasks under My Tasks
9. Reports & CSV Exports
Available reports under Admin → Financial Reports:
| Report | Description | CSV Export |
|---|---|---|
| Revenue Summary | Income breakdown by period | — |
| Outstanding Balances | All rentals with unpaid balance | Yes |
| Overdue Items | All items past their due date | Yes |
| Equipment Revenue | Per-equipment income | — |
| Customer Statements | Per-customer financial summary | Yes |
| Worker Performance | Approvals, rejections, revenue per worker for a date range | — |
CSV files are downloaded directly from the browser (no server-side file storage).
10. Audit Log
Every significant action is recorded with:
- Action identifier (e.g.,
rental_created,booking_approved,deposit_returned) - Human-readable description
- Who performed it (admin or worker)
- What it was performed on (polymorphic — the affected model)
- Old and new values (JSON, where applicable)
- Branch and timestamp
The audit log is filterable by action type and date range. It is read-only — no records can be deleted from the UI.
11. Dashboards
15. Global Search
A search bar is available in the top navigation on every admin and worker page. Searches are scoped to the current branch.
Searchable entities:
| Entity | Matched on |
|---|---|
| Customers | Name, phone number, email |
| Day Rentals | Rental ID, customer name |
| Point Rentals | Point Rental ID, customer name |
| Equipment Serials (Day) | Serial number |
| Equipment Serials (Point) | Serial number |
| Booking Requests | Booking ID, customer name, customer phone |
Results are grouped by type and show up to 10 per category, each with a direct link to the record.
Admin search: GET /admin/search?q=...
Worker search: GET /worker/search?q=...
Admin & Worker Dashboard
The admin and worker dashboards each show two rows of operational stat cards and two data panels at the bottom.
Primary stats row:
- Open Tasks
- Day Rentals (total for branch)
- Point Rentals (total for branch)
- Customers
Operational stats row:
- Pending Booking Requests (amber — links to filtered booking list)
- Active Items Out (combined count of unreturned day + point rental items, with breakdown)
- Overdue Items (shows in red text with red border when count > 0)
- Revenue This Month (GHS sum of
total_paidacross day and point rentals for the current month)
Utilisation row (between stat cards and bottom panels):
- Day Equipment Utilisation — progress bar showing what percentage of day specifications at the branch are currently
rented - Point Equipment Utilisation — same for point specifications
Bottom panels:
- Recent Pending Booking Requests — the 5 most recent pending bookings with customer name, type, item count, preferred start date, and a Review link
- Due for Return Today — all rental items whose
due_dateis today (unreturned), showing equipment name, serial number, customer, and a View link to the rental
Customer Portal
Customers have their own portal at /user/dashboard with:
- Dashboard — total outstanding balance (highlighted red if > 0), overdue alert, active rented items with days remaining, rental counts
- Rentals — full history of day rentals with balances
- Point Rentals — full history of point rentals
- Bookings — submit and track booking requests
- Projects — view and download project files
12. Multi-Branch Support
All data is scoped to a branch. Admins select the active branch via a branch switcher on the dashboard. The selected branch ID is stored in the session (selected_branch_id) and applied to all queries automatically.
Workers are tied to a specific branch. Customers are also branch-scoped.
13. SMS Notifications (Wigal)
Wigal SMS is used for:
| Trigger | Recipient | Message |
|---|---|---|
| Booking request submitted | Customer | Submission confirmation with branch name |
| Booking request submitted | All workers at the branch (with phone) | New request alert with booking ID |
| Booking approved | Customer | Approval confirmation |
| Booking rejected | Customer | Rejection with reason |
| Booking cancelled | Customer | Cancellation confirmation |
| Booking auto-expired | Customer | Auto-rejection notice after 3 days pending |
| Rental item due tomorrow | Customer | Reminder SMS |
| Rental item overdue (daily) | Customer | Overdue notice including accrued late fee amount in GHS |
| Phone verification (OTP) | User/Worker | 6-digit OTP code |
| Equipment becomes available (waitlist) | Waiting customer | Availability notice with equipment name |
SMS failures are logged to storage/logs/laravel.log and do not interrupt the main operation.
14. Authentication & Security
Three independent auth guards:
| Guard | Login URL | Email verification |
|---|---|---|
admin |
/admin/login |
Required |
worker |
/worker/login |
Required |
web (user) |
/login |
Required |
Each guard has its own forgot-password, reset-password, and verify-email flows. Admin and worker accounts are created by admins; customer accounts can self-register.
Customer password policy: Customer accounts do not require a password. Customers log in via a phone OTP sent to their registered number. The password field is not shown on the registration form or the admin/worker "Add Customer" form. A random password is stored internally to satisfy database constraints but is never used for authentication.
15. Waitlist
When all units of a specific piece of equipment are rented out, customers can join a waitlist for that serial number.
Customer flow:
- From the equipment listing, click Join Waitlist to be queued for a specific serial.
- My Waitlist (
/user/waitlist) shows all active and historical entries with status badges. - Active entries (status
waiting) can be cancelled.
Status lifecycle: waiting → notified → fulfilled or cancelled
Automatic SMS notification: When a specification's status changes to available (e.g., after a return), all customers with waiting entries for that serial are automatically notified by SMS and their status is updated to notified. This is handled by Eloquent model observers (SpecificationObserver, PointSpecificationObserver) that fire on every status update.
Admin / Worker management:
- Bookings → Waitlist shows all entries for the current branch with filter tabs (status, rental type).
- Waiting count is shown as a badge on the Waitlist sidebar link.
- Staff can cancel individual entries from the table.
16. Branch Transfers
Admins can physically move an available piece of equipment from one branch to another. Every transfer is recorded with a full audit trail.
Rules:
- Only equipment with status
availablecan be transferred (rented items are blocked). - Cannot transfer to the same branch.
- Both day-rental (Specification) and point-rental (PointSpecification) equipment are supported.
What happens on transfer:
- The specification's
branch_idis updated to the target branch immediately. - A
SpecificationTransferrecord is created withfrom_branch_id,to_branch_id, the actor, and optional notes. - An audit log entry (
specification_transferred) is written.
Admin UI: Operations → Branch Transfers (/admin/specification-transfers)
- Left panel: form to initiate a new transfer (type toggle day/point, equipment selector, target branch, optional notes).
- Right panel: paginated history showing all transfers in/out of the current branch with direction badges (green "In", amber "Out").