RentWorks+ Release Notes
The article contains all RentWorks+ release notes as of June 8, 2026
1.9.52LatestMay 18, 2026
1.9.51May 15, 2026
1.9.50May 15, 2026
1.9.49May 15, 2026
1.9.48May 14, 2026
1.9.47May 14, 2026
1.9.46May 14, 2026
1.9.45May 14, 2026
1.9.44May 14, 2026
1.9.43May 12, 2026
1.9.42May 12, 2026
1.9.41May 12, 2026
1.9.40May 11, 2026
1.9.39May 11, 2026
1.9.38May 11, 2026
1.9.37May 9, 2026
1.9.36May 9, 2026
1.9.35May 9, 2026
1.9.34May 9, 2026
1.9.33May 9, 2026
1.9.32May 9, 2026
1.9.31May 9, 2026
1.9.30May 9, 2026
1.9.29May 9, 2026
1.9.28May 6, 2026
1.9.27May 5, 2026
1.9.26May 5, 2026
1.9.25May 2, 2026
1.9.24May 2, 2026
1.9.23May 2, 2026
1.9.22May 2, 2026
1.9.21May 2, 2026
1.9.20May 2, 2026
1.9.19May 2, 2026
1.9.18May 2, 2026
1.9.17May 2, 2026
1.9.16May 2, 2026
1.9.15May 2, 2026
1.9.14May 2, 2026
1.9.13April 28, 2026
1.9.12April 27, 2026
1.9.11April 26, 2026
1.9.10April 26, 2026
1.9.8April 26, 2026
1.9.7April 26, 2026
1.9.6April 26, 2026
1.9.5April 25, 2026
1.9.4April 25, 2026
1.9.3April 25, 2026
1.9.2April 25, 2026
1.9.1April 25, 2026
1.9.0April 24, 2026
1.8.0April 24, 2026
1.7.0April 24, 2026
1.6.1April 23, 2026
1.6.0April 23, 2026
1.5.1April 23, 2026
1.4.0April 15, 2026
1.3.0April 10, 2026
1.1.0January 22, 2026
1.0.0January 21, 2025
Added
- No-Show Lifecycle — Per-Location Settings, Automatic Detection, Manual Controls, And A Dedicated Fee: Reservations now have a proper No-Show flow end to end. Each location has a new No-Show Settings card with a single toggle plus four configurable thresholds — grace hours before a reservation is flipped to No-Show, how long a Quote can sit past its pickup before being treated as a No-Show, and how many days a No-Show is allowed to age before it is auto-cancelled. With the toggle on, a background job checks hourly and flips eligible Open Reservations, Pending Reservations, and Quotes to No-Show, attaches a dedicated No-Show Fee read from the matching rate plan, releases the held vehicle back to available, and sends a notification to both staff (in-app) and the renter (email and SMS) within seconds. From the reservation page, agents can manually mark a reservation as No-Show (the button is shown only when the pickup time has actually passed), reopen a No-Show back to Open Reservation, or cancel a No-Show with a redesigned dialog that asks whether to keep the fee on the account or waive it. A new supervisor-only Edit No-Show Fee dialog lets authorised agents change the fee amount or remove it entirely while leaving the No-Show status in place, gated by a new privilege that administrators assign through the existing User Management screen. The live reservation form also previews the pending fee and bumped totals before the agent saves, so the financial impact is visible up front.
- Self-Inspection Integration — Customer-Driven Pickup And Dropoff Loop With Damage Pull-Back: For tenants using the Self-Inspection vendor, the system now drives the full pickup-to-dropoff loop without manual reconciliation. Counter checkout creates the vendor contract idempotently (a retry of the same Rental Agreement recovers cleanly instead of erroring), the renter completes the pickup inspection on their own device, and on Rental Agreement check-in the return odometer and fuel are posted to the vendor and any dropoff damages the renter captured are pulled back as a proper check-in inspection on the agreement. A polling loop watches open agreements for tenants with the integration enabled and closes the Rental Agreement automatically the moment the customer submits the dropoff inspection on the vendor side, so staff no longer have to chase completion manually.
- Vehicle Inspection History — Redesigned Tab Merging Self-Inspection Contracts With Manual Inspections: The Inspection History tab on a vehicle profile has been redesigned into two sections — a Current Vehicle State summary on top and a unified history list below — and now merges Self-Inspection contracts (looked up per vehicle by VIN) with the manual inspections recorded inside the system, deduplicating Self-Inspection rows against their matching manual rows by Rental Agreement number so each rental is shown once. The shared inspection card now renders the Self-Inspection pickup, dropoff, and employee status panel inline when the row is sourced from the vendor, so all the relevant context is one click away regardless of where the inspection was created.
- PDF Form Builder — Payment Fields And Human-Readable Payment Code: Four new fields — Payment Type, Description, Check #, and Reference # — are now available as draggable elements in the PDF Form Builder, so designers can place payment details onto custom contract templates instead of having to compose them outside the builder. The Payment Information cell on stock templates now also renders the human-readable payment type label (for example Cash or Visa) instead of the underlying internal code, so generated PDFs read naturally.
Changed
- Non-Revenue Pages — Visual And Functional Parity With Rental Agreements, Counter Route Retired: The Non-Revenue Open and Non-Revenue Details pages now share the same look and component set as the Rental Agreement pages — matching container width, section headers, brand green primary button, header card spacing, and mobile-friendly tab strip that horizontal-scrolls under 768px. The driver information block on the Details page renders an Employee driver as the same two-column read-only grid used on the Rental Agreement Drivers tab (name, date of birth, email, phone, address, license details, employee number), and the vehicle information view mode shows the same five-field card the Rental Agreement Details page uses. The Vehicle Selection block on the Open Non-Revenue form now mirrors the Counter Checkout walk-up flow one-for-one (the Rented As class and the Check Availability button are intentionally suppressed for Non-Revenue). The Non-Revenue list above the search bar gains a quick-status tab strip (Open, Closed, Cancelled, All) that filters the list with a single click, replaces the duplicate Status field in advanced filters, and persists in the URL so a bookmarked tab keeps its filter. Per-row Close and Cancel actions on the list have been removed because they were never appropriate at the list level — those actions are still available on the ticket details page. The Void label has been renamed to Cancel everywhere on Non-Revenue to match the rest of the app. The separate Counter Non-Revenue route has been retired so there is now a single dashboard entry point; Counter Fleet's Open-Non-Rev action and the status-modify dialog redirect now route to the dashboard page directly.
- Entity History — Undo And Redo Affordances Removed, Phantom Field Changes Filtered Out: Every clickable Undo and Redo button has been removed from the entity history surface across roughly twenty-five pages — vehicle, customer, claim, reservation, non-revenue, and twenty settings and admin modals — and legacy Undone or Redone history rows now render as plain Updated entries with the standard pencil icon. The history viewer no longer reports phantom field changes either: editing a single field on a form (for example flipping Taxable from No to Yes on a Misc Charge) used to render as Changed Taxable and 13 more because unset columns coalescing to empty values, plus audit metadata like Last Modified By User Id, were being counted as edits. Those have been filtered out so the user sees exactly the fields they touched and nothing else, both in the badge label and in the per-row details table.
- Counter Contract Inquiry — Location Filter And Refreshed Status List: The Counter Contract Inquiry page now has a location dropdown so an agent can narrow the inquiry results to a single location instead of always seeing every contract in the tenant. The status filter dropdown has also been refreshed to drop the Pending status and add Voided so the available filters reflect the actual contract states an agent will look up.
- Reservation Status Filter — Pending Reservation Status Hidden Where It No Longer Applies: The Pending Reservation status has been dropped from the Rental Agreement list page's advanced-filter dropdown as part of the broader cleanup that removed it from the canonical lifecycle on the reservation side. The same set of contract-stage statuses (Pending Open, Open Contract, Closed Contract, Voided Contract) continues to be available where it is relevant.
Fixed
- Counter Checkout — Five User-Reported Defects In The Checkout And Honor-Reservation Flow: The Counter Checkout page had drifted from the Reservations page after a recent layout split and lost feature parity. Five defects are fixed together in this release. (1) The inline driver search dropdown now shows the driver license number under the phone number so an agent can pick the right driver when two renters share a similar name. (2) The Delivery Service modal now opens correctly from the checkout page — it was bound only on the reservation page after the split, so an agent on checkout could not add or edit a delivery. (3) The live rate-calculation call no longer cascades when an agent picks a rate plan, applies a promo, or redeems loyalty — a deterministic auto-apply key plus tighter effect dependencies cut the request fanout down to a single call per real change. (4) Honoring an open reservation from checkout now correctly pre-selects the rate plan and the saved rate snapshot, including any per-line overrides, so the agent does not have to re-pick the rate the renter already chose. (5) Saving from checkout no longer returns the 'Pending Reservation is deprecated' validation error — the contract-stage statuses (Pending Open, Open Contract, Closed Contract, Voided Contract) are now correctly accepted by the reservation save endpoint, while the genuinely retired Pending Reservation status stays rejected.
- PDF Form Builder — Unsaved-Changes Guard Now Catches In-App Navigation And Browser Back: The PDF Form Builder used to warn about unsaved changes only on a hard refresh — clicking a sidebar link or hitting the browser back button would silently discard pending edits. The editor now intercepts in-app navigation and the browser back button in addition to the existing hard-refresh warning, so an agent is always given the chance to cancel and save instead of losing layout work. The native browser warning still fires on a hard refresh as a safety net.
- PDF Form Builder — Manage Allocations Dialog No Longer Carries Stale Selections Between Opens: The Manage Allocations dialog used to remember the rows that were selected the previous time it was opened, even if the user closed without saving. Its state is now reset every time the dialog opens so the user starts clean.
- Close Non-Revenue Modal — Unsaved-Changes Dialog No Longer Fires On A Pristine Form: Opening the Close Non-Revenue modal and closing it immediately used to pop the Unsaved Changes dialog even with no user edits, because the modal pre-fills the odometer-in field with the checkout odometer and the status-in field with the auto-detected Available code. The dirty check is now a diff against the snapshot the form was reset to, so the dialog fires only when an actual user edit has happened.
- Non-Revenue List — Closed And Cancelled Tabs Now Actually Filter The List: A persisted status filter from the old advanced-filter sheet was silently overriding the new tab filter, so the Closed tab was still showing Open rows. The persisted filter has been invalidated and the tab strip is now the single source of truth for status on the Non-Revenue list.
- Reservation Save On Rental Agreement Edit — Contract-Stage Statuses Now Accepted: The save endpoint on the reservation page used to reject a Rental Agreement edit that was already at a contract-stage status (Pending Open, Open Contract, Closed Contract, or Voided Contract) with a validation error before the service layer could process it. Those statuses are now accepted on the same endpoint so editing an Open Contract from the planner or list, or completing a check-out save, goes through normally; the genuinely retired Pending Reservation status stays rejected.
- Maintenance Alerts Endpoint — Missing Database Column Restored: The maintenance alerts endpoint was returning a server error because a column declared on the maintenance alerts schema had never been migrated to the database. The missing column has been added by an idempotent migration so the endpoint serves correctly on a fresh deploy.
- Notifications — External Recipient Picker Now Persists Its Configuration: The external recipients and the internal location filter on notification settings were silently not being saved because of a field-copy bug — the user could fill them in, click Save, and the change would vanish on the next reload. Both fields are now correctly persisted.
- Dashboard — Reservations Not Picked Up Widget Now Reflects The Real No-Show Status: The Operational Load widget's 'reservations due but not picked up' tile and the matching detail list were filtering on the now-retired Pending Reservation proxy and always returning zero. They now correctly filter on the No-Show status so the tile shows the actual count and the detail list shows the actual reservations.
Added
- Check-In — Exchange-Vehicle Mileage Now Included In Mileage Charge: When a rental includes one or more vehicle exchanges, the Check-In page now shows the miles driven on every prior vehicle leg and adds them to the live mileage charge preview and to the final saved charge, so the renter is billed for the full trip distance instead of just the current vehicle. A new hint panel in the Vehicle & Readings section makes the accumulated exchange miles and the combined total visible to the agent before commit, and the same totals are recalculated server-side on save so the persisted amount cannot drift from what the agent saw on screen.
- Vehicle Documents — New 'Override Expired Vehicle Documents' Permission: A new privilege is now available in User Management so administrators can authorize specific agents to rent a vehicle whose registration, insurance, or other document expiration has passed. Agents without the permission continue to see the existing block, preserving the default safety behaviour.
Fixed
- Corporate Accounts — Tax-Exempt Toggle Now Cascades To Active Reservations And Rental Agreements: Toggling a corporate account's Tax Exempt flag now immediately updates the Taxable / Tax Exempt Reason on every active reservation and rental agreement (Quote, Pending Reservation, Pending Open, Open Reservation, Open Contract) tied to that company, so the change is reflected in contract PDFs, invoices, and reports without anyone having to re-open and re-save each booking. Customer-level tax preferences still win over the corporate setting (a renter flagged tax-exempt at the customer level stays tax-exempt regardless of the company toggle), and closed, voided, cancelled, and no-show records are intentionally left untouched so historical data is not rewritten. If the cascade fails for any single reservation, the company-level flag change is rolled back so the data cannot drift apart.
- Payments — Adyen Webhook Notifications Now Verified Per-Tenant: Adyen webhook signature verification now uses the HMAC key configured on each tenant's credit-card terminal record instead of a single installation-wide key, so multiple tenants running on Adyen can each receive and validate webhook notifications correctly. Tenants that have not yet configured a per-terminal key continue to fall back to the original installation-wide key, so existing single-tenant setups are unaffected.
- Reservation Edit From Planner — Save No Longer Rejected: Editing a reservation from the planner and clicking Save was being rejected with a 'property sessionId should not exist' error after a recent backend update. The reservation update path now accepts the same session field that the create path already accepts, so edits go through normally and any deposit captured before the reservation was finalized stays linked to the new reservation. A related backend startup failure caused by missing wiring on the Vehicles module has also been corrected so the API serves traffic on a fresh deploy.
Added
- Claims Dashboard — New Table View, Shared Pagination, And Quick Status Filter: The Claims workspace now has a proper scannable Table view that becomes the default on /dashboard/claims, sitting alongside the existing Cards and Board views. Each row shows Claim #, Date of Loss, Type, Status, Priority, Customer, Vehicle, Outstanding, Created, and a per-row View action; clicking a row opens the claim detail and sortable column headers cycle desc → asc on Claim #, Date of Loss, Outstanding, and Created. Outstanding amounts in credit are clearly tagged with a CR suffix and colored. A shared pagination bar with a Rows-per-page selector (10 / 25 / 50 / 100) and a 'Showing X to Y of Z' counter is now used by both the Cards and Table views, and the toolbar gains a Status quick-select dropdown immediately before the Filters button so the most common filter is one click away. Existing /dashboard/claims?view=… bookmarks continue to work — the legacy list value maps to Cards, and the new default is Table.
Changed
- Claims Dashboard — Filters Sheet, KPI Strip, And Search Modernized: The Claims Filters sheet now matches the Reservations / Rental Agreements look — a title row with an active-count badge, each filter wrapped in its own card with a per-field Clear button, and a sticky footer with Clear All and Apply Filters that disable when no filters are set. The Sort dropdown has been removed because the date-range filter plus sortable column headers now cover the same ground, and the standalone 'Analytics insights' collapsible has been folded into a single six-tile KPI row at the top of the page: Total Open Claims, Avg Days to Close, Expenses MTD, Recovery Rate, Opened this month, and Closed this month. The search placeholder has been refreshed to reflect the broader coverage below.
Fixed
- Claims Dashboard — Customer And Vehicle Columns Now Populate, Global Search Now Matches Status, Priority, And Type: The Claims list API was returning empty Customer and Vehicle fields on every row — the Cards view masked it by only rendering those fields when present, but the new Table view exposed the gap. The list now pulls Customer name and Vehicle Unit # from the linked rental so the columns are filled. Global Claims search has also been broadened so what an agent sees in the table is what they can type — typing 'in review' finds claims with status In Review, 'urgent' finds Urgent priority, 'settle' finds Settled, and free-text 'damage' matches the Damage claim type — in addition to the existing Claim #, Customer name, Vehicle Unit / VIN / Plate, and Rental Agreement number matches.
Changed
- Reservations Dashboard — Status Options Simplified, KPI Strip Expanded To Six Tiles, Multi-Reservation # Search: The Reservations dashboard status filter and the reservation form's status dropdown now show only the lifecycle states that actually apply on this side of the business — Quote, Open Reservation, Cancelled, No Show, and Voided — with the contract-stage statuses (Pending Open, Open Contract, Closed Contract, Voided Contract) removed since they belong on the Rental Agreement dashboard. The KPI strip at the top of the page now shows six tiles instead of two: Total, Quote, Open Reservation, Cancelled, No Show, and Voided, so agents can read the reservation mix at a glance. The Reservation # search now accepts multiple numbers chipped in together (the same pattern Unit # already used) so an agent can pull up several reservations in one query, and the default landing filter has been moved from the deprecated Pending Reservation status to Open Reservation. On the backend, Quote reservations can no longer start a pickup directly — a Quote must be promoted to Open Reservation first — bringing the start-checkout path in line with the existing search-list behaviour.
- Reservation Planner — Rental Agreement Edits Now Show The Suggested-Changes Banner: Editing a Rental Agreement from the planner now shows the same blue 'Res Planner suggested changes' banner with per-row Apply buttons that reservation edits already showed, so the agent can review each pending change (date, time, vehicle) and accept them one at a time instead of having them silently applied on form load. Saving a routine reservation or rental-agreement update no longer pops the post-save Print / Email / eSignature dialog — that dialog stays in place on the dedicated checkout and check-in pages where it belongs.
- Reservation Planner — Drag To Unassigned Now Updates Inline, No Confirm Popover: Dropping a reservation onto the Unassigned row now updates the reservation immediately with a toast confirmation instead of opening a confirm popover and redirecting to the edit page. The conflict-resolution dropdown also no longer offers an Unassign action for active rental agreements or non-revenue tickets that cannot be unassigned by business rule, matching the protection that already existed in the drag-confirm flow. The booking detail modal footer now correctly reads 'View Details' for read-only bookings instead of the wrong 'See all changes' label.
- Reservation Edit — Vehicle Search Default Location No Longer Pre-Filled: When an agent opens the vehicle search modal while editing an existing reservation or rental agreement, the Location filter now starts on 'All Locations' instead of automatically pinning to the pickup location, so the agent can pick a replacement vehicle anywhere in the fleet without first having to clear the location filter.
- Vehicles & Non-Revenue Datatables — Redundant Free-Text Filters Removed: Plain-text fields like Product, Ticket #, Unit #, and Driver Name have been dropped from the Vehicles and Non-Revenue advanced-filter sheets because the global search box at the top of each page already covers them. Only enumerated values and date filters remain in the advanced sheet, making the filters more focused.
- Counter Checkout — Today's Reservations Queue Auto-Filters By Terminal Location And Is Paginated: The Today's Reservations queue and search results on the counter checkout contract-search step now default the Location filter to the workstation's terminal location so an agent at a specific counter sees their own location first instead of having to pick it from the dropdown every time (the dropdown can still be overridden manually). The queue and search-result lists now paginate five rows at a time with Previous / Next controls and a page counter, and the 'today' filter has been hardened to compare only the date portion so reservations starting at 00:00 on the current day are no longer hidden from the queue. Walkup and reservation selection now navigate straight to the matching dashboard page so the agent lands on the form a step sooner and the URL is always shareable.
- Driver Selection — Underage / Age-Constraint Check Now Knows The Reservation Context: When an agent selects a driver from the inline combobox or the search modal during checkout or reservation creation, the underage / age-constraint check now correctly receives the selected pickup location, return date, and vehicle class — previously this context was only passed in some paths, so the check could miss an underage driver depending on how the agent had selected them. The pickup location's minimum-driver-age threshold is also fetched live on the checkout page when the pickup location changes, so the combobox badge and blocking-issues check stay in sync with whatever location is currently selected.
- Driver Selection Section — Layout Refresh: The driver search, Add Driver / Add Employee, and Delivery Service buttons have been reorganized into two clean rows — full-width search on top, equal-width action buttons below — so long button labels no longer fight for space, and long driver names, emails, and phone numbers truncate cleanly in the selected-driver card instead of pushing the layout out of alignment.
- Rate Seasons Table — Multi-Date Seasons Are Now Expandable Inline: A rate season with more than one date range now has an expand chevron on the row; clicking it shows every date range inline as a clean list with a Recurring or Fixed badge per range, replacing the previous hover-tooltip that was hard to read on long lists. Rate Rules also now strip whitespace from the Rule Name field as you type so a code-style identifier like 'WEEKEND' cannot have spaces silently embedded in it.
Fixed
- Reservation Planner — Overdue Open Contracts Stay Visible Through The Overdue Period: An Open Contract whose original Due Back date has passed now keeps its timeline bar rendered all the way through to today, so the agent can still see the rental on the planner while it is late. Previously the bar disappeared as soon as the calendar paged past the original due-back date and only the side icons hinted that the rental was overdue. The overdue indicator itself has also been moved to the right edge of the row label so it no longer competes for space with the status block, and a duplicate 'Jump to pickup' tooltip action that did the same thing as 'View details' has been removed.
- User Management — Privilege Changes Now Take Effect Immediately Without Re-Login: When an administrator edits their own privileges and saves, the permissions cache is now force-refreshed immediately so menu items, page guards, and privilege-gated actions reflect the change in the same session — previously the admin had to wait out a roughly thirty-second cache window or sign out and back in for the new permissions to apply. If the refresh fails for any reason, a clear warning toast tells the admin to re-login so they are never left wondering why a newly granted privilege has not appeared.
- Bulk Check-In Settings Modal — Form Now Scrolls Properly And Location Checkboxes No Longer Double-Toggle: The Bulk Check-In Settings modal has been given a proper scrollable body with a sticky Save / Cancel footer so the bottom of the form is never clipped on shorter screens, and the location-list checkboxes now correctly stop click propagation so clicking the checkbox itself no longer toggles the row a second time.
Changed
- Unified Contract Summary Dialog Across Inquiry, Counter Checkout, And Reservations Save: Contract Inquiry's Print button previously generated a generic browser-print summary that bypassed the form-template system used everywhere else, and the post-checkout flow redirected the agent to a separate `/print-contracts` page that re-rendered the same contract data in a different layout. A new shared `ContractSummaryDialog` is now used by Contract Inquiry, the counter `ReviewSubmitStep`, and both `ReservationsPage` save sites (checkout-mode RA edit + RA create) — Print pipes through the real `useNativePdfPrint` Document/Invoice → form-template pickers and produces a backend-rendered PDF; Email pre-fills the renter address and routes through the standard email pipeline; "Send for eSignature" surfaces only on Open contracts and submits to Signiphi. Closing the dialog (X) navigates to the RA list with no full-page redirect. The standalone `/print-contracts` route, its `lazy()` import, the duplicate `PrintEmailPage`, and the sidebar entry have been removed.
Fixed
- Adyen CC Terminal Resolution — Wrong Terminal Picked At Multi-Terminal Locations (Payments Couldn't Start): `createAdyenSession` was sending only `locationCode` so when a location had multiple Terminal rows the backend's `resolveCcControl` used Prisma `findFirst` with no ordering and could pick a row whose `cardTerminalId` was the sentinel string `"NONE"` instead of the workstation's real terminal — the `CreditCardControl` lookup then failed with a 400 and the agent couldn't start the payment. The frontend now passes `terminalSettings.DeviceID` as a new `terminalCode` parameter so the backend lookup is pinned to the exact workstation terminal; the backend filter now adds `notIn: ['NONE', '']` to `cardTerminalId` so the sentinel string can never be matched even on stale rows; and the Terminal Settings form has been hardened to strip the literal `"NONE"` to `null` before save so the falsy-check no longer lets the sentinel be written to `card_terminal_id` in the first place.
Added
- Vehicle Photo Gallery + Primary Photo Across All Vehicle List Views: A new Photos tab on the vehicle profile supports multi-upload, set-primary, drag-to-reorder, lightbox, and source-filter pills (All / Gallery / Damage). The gallery also surfaces inspection-damage photos read-only, grouped by inspection event with color-coded type badges (Scratch / Dent / Missing / Photo), and a damage photo can be promoted to a vehicle's primary without re-upload (a new gallery row is created pointing at the same S3 key). The primary photo now flows through the Fleet datatable column 0, the vehicle profile / details modal, the vehicle form general-tab cover, the shared RE/RA/NR vehicle search modal, the `ReservationDataTableCard` card view (replacing the generic Lucide `Car` icon with `VehicleThumb` + `FaCar` fallback), and a brand-new Photo column at index 0 on the Reservations, Open Reservations (RA), and Non-Revenue datatables. The backend list endpoints (`/reservations`, RA list, `/non-revenue`) have been extended with `primaryPhotoUrl` using the same gallery → legacy `imageFile` fallback that the vehicles list endpoint already uses, so all four list endpoints now agree.
- Repair Orders + Maintenance Alerts: A Repair Orders tab, table, and modal land under Operations → Maintenance, with transaction-number-range integration and creation gated on at least one maintenance alert existing for the tenant (the form blocks with a helpful link to the alerts page when none exist). The status workflow advances OPEN → IN_PROGRESS → COMPLETED and the close action is gated on status. A warning-alert indicator is inlined next to the unit number on the Fleet, RA, and non-revenue datatables — red AlertTriangle for "RO required", amber Wrench for "IN_REPAIR" — with a count badge when multiple alerts exist on one unit; this replaces the standalone "Alert" column that was empty on nearly every row. schedule fields (`Pester` action, sub-day `freqSeconds`, free-text `groundedDescription`) are preserved alongside dev's parallel counter-based scheduling (`freqCounter`, `lastCounter`, `nextCounter`) so both feature sets coexist additively in `AlertModal` and `ProcedureModal`.
- Res Planner Booking-Detail Notes: The booking detail modal on the Reservation Planner now has an inline notes section with add, delete, pin / unpin, a count badge in the modal header, and lazy load with a per-booking cache in `useResplannerStore`, backed by `notesApi`. Notes survive a modal reopen and reflect changes immediately.
- Res Planner Overdue Open-Contract Indicator: Open contracts that are past their expected return now surface an "Overdue" badge on the vehicle row, a drag-confirm warning, and a jump-to-pickup action so the agent can quickly resolve the late return without leaving the planner.
Changed
- Datatable Column Version Bump To `_columns_v2` With Smarter Insert Logic: To make the new Photo column appear automatically without forcing every user to manually reset their datatable customizations, `useColumnSettings`' storage key has been bumped to `_columns_v2`; existing users' column order, width, and hidden-column preferences reset once on first load after this ships. New "insert at code-defined position" merge logic has been added so future column additions slot in at the right index without another version bump.
Fixed
- Res Planner Active-Booking Edits Now Route Through The Real Edit Pages: Res Planner was previously letting agents drag, resize, or unassign active rental agreements and non-revenue tickets in ways the data model forbids — most concretely, dragging an active RA whose start date is in the past, and unassigning vehicles from active RAs or non-revs. The planner now disables drag and resize at the source for any active RA whose start time is in the past, and a click on the block routes straight to `/dashboard/checkout/<raNumber>/edit`. Dropping an active RA or non-rev on the Unassigned lane is rejected at drop time (the popover never opens, the block snaps back, a toast explains why) and the Unassigned lane filters RAs and NRs out entirely. For future bookings, drag-confirm and the booking-detail modal's location editor now stage the proposed change in sessionStorage and redirect to the matching edit page (`/dashboard/checkout/<raNumber>/edit`, `/dashboard/reservations/<resNumber>/edit`, or `/dashboard/non-revenue/<number>?edit=1`) — the strict modification logic continues to live exactly where it already does, on the dedicated edit pages, not in the planner. The staged change carries a `returnTo` path so saving lands the agent back on Res Planner instead of the default list view, and the popover button is re-labelled "Show all changes" / "View all changes" with an external-link icon to convey the redirect intent.
- Res Planner Reservation Bars Off By One Day For Date-Only Strings: `YYYY-MM-DD` date strings were being parsed at UTC midnight, which rendered bars one column early or late for tenants outside UTC. A new `parseLocalDateTime` correctly handles date-only strings and is now used in every booking-position computation on the timeline.
- Res Planner Vertical Vehicle-Assignment Drag No Longer Shifts Dates Or Times: Vertical drags to assign a vehicle to a different row were shifting the booking's pickup / return by every horizontal pixel of cursor jitter, because the drag handler applied X delta unconditionally. The handler now detects the dominant axis per frame and freezes the X position when `|deltaY| > |deltaX|`, so vertical drags only change vehicle and horizontal drags only change time. Diagonal drags still allow both to change.
- Res Planner Class-Mismatch Confirmation Before Silent Upgrade/Downgrade: Dropping a reservation onto a vehicle of a different class than reserved was silently accepted. A new AlertDialog ("Vehicle class differs from reservation") now prompts the agent to Accept and update (treats as upgrade/downgrade) or Cancel (reverts the optimistic timeline update) before any drag-confirm popover renders. The pending drag is held behind the modal.
- Res Planner Modals Dismissed By Outside-Click On Child Popovers: Radix outside-click was firing when the user interacted with a child popover, dismissing the parent modal. Gated with `pointerDownOutside` capture so child popovers no longer dismiss their parent.
- Res Planner Drops On Unavailable / Sold Vehicles Now Blocked At Drop Time: Maintenance, grounded, and sold vehicles now render a row-spanning grey bar across their unavailable window and drops on those rows are rejected at drop time with a toast.
- Edit-Page Click-To-Apply Banner Replaces Silent Staged-Edit Cascade (Backend 30s Transaction Timeout Fix): The previous Res-Planner-to-edit-page staging consumer silently populated every staged field on form hydrate; when it touched rate-rule recompute paths it was blowing the backend's 30 s transaction timeout. Each staged field now exposes its own Apply button in a new suggestions banner; date and time are grouped per pickup/return so the form never sees an inverted-date window; Vehicle Apply opens the picker pre-filled with the unit number for the user to confirm. The backend save log now shows `Updating sections: ['rrmType','pickupReturn','vehicle']` (no `rateCharges`) and the save completes well under 30 s.
- Edit-Page Open Latency Dropped By ~1.25 Seconds: The `isSettled` timer that gates the staging banner, draft restore, and other UI was reduced from 1500 ms to 250 ms, so the edit page no longer sits in dead time for a second and a half after every API fetch. `getFormState()` was also deduplicated in the draft-snapshot block.
- Inspection History Tab Rules-Of-Hooks Crash On Self-Inspection Flag Flip: The canonical `InspectionHistoryTab` called `useSelfInspectionFeature()` (Zustand-backed) and `useSIContractData()` then conditionally returned before twelve subsequent `useState` / `useEffect` / `useCallback` hooks. Because the Zustand store hydrates async, the flag flipped between renders and React threw `Rendered fewer hooks than expected`. Split into `<SelfInspectionView>` and `<StaffInspectionView>` sub-components that own their own hooks; the top-level `InspectionHistoryTab` is now a thin picker.
- Vehicle Search Status Filter And Self-Inspection Page-Size Pre-Existing Bugs: `vehicleApi.searchVehicles` was sending `Status` (capital S) where the backend DTO expects `vehicleStatus`, silently dropping the filter on every search; `selfInspectionApi.checkLocationExists` was calling `searchLocations({ perPage: 500 })` against a Self-Inspection service that caps `perPage` at 50, returning a 400 on every check. Both fixed.
Fixed
- Loading Error After a New Release — No More Refresh-And-Hope: Users who kept the app open while a new version was deployed were occasionally seeing a "Loading Error" screen when clicking through to another page, because their browser was still trying to fetch files from the previous release. The app now recognises this situation and automatically refreshes itself once to pick up the latest version, so users keep working without having to manually reload or sign back in. If a page genuinely fails to load for another reason, the existing error screen still appears so issues are not hidden.
Added
- Counter Checkout — Unlinked Deposit Navigation Guard: The walk-up counter checkout flow now mirrors the reservation page's `UnlinkedDepositGuard`, intercepting back/forward/in-app navigation when a captured deposit exists on the active session but no rental agreement has been created yet. The guard wires `useUnlinkedDepositGuard` + `getPaymentsBySession` to a sessionId-scoped query and refetches on payment-modal close so a just-taken deposit is visible to the next nav attempt. A `bypassUnlinkedDepositGuardRef` flag flips inside the new `onBeforeNavigate` callback on `useCheckoutSubmit` so the post-submit redirect to `/print-contracts` is not intercepted; the bypass only flips on the success path (`raNumber` set) so stale leaks after a failed submit are still blocked. The guard is enabled in walk-up mode only — from-reservation mode is skipped because the existing reservation already owns the deposit. `UnlinkedDepositGuardModal` gains optional `stayButtonLabel` and `contextLabel` props so the checkout flow displays "Stay in Rental Agreement" / "rental agreement" wording while the reservation copy stays as the default.
Fixed
- Vehicle Fleet Page — KPI Tiles And List Now Agree (Total / On Rent No Longer Diverge): The Vehicle Fleet page tiles (Total Vehicles, Available, On Rent, etc.) and the underlying `/vehicles` list were silently disagreeing — KPI showed the real per-tenant count (e.g. 55) while the list returned only the subset the caller was allowed to rent (e.g. 15) because the `RENT_UNAVL` privilege ("Ability to rent a vehicle currently marked as unavailable") was being applied as a *viewing* filter inside `VehiclesService.findAll`, hiding every on-rent vehicle from any user without the privilege. The filter has been removed from the listing — the same privilege is still enforced at the actual rental-creation boundary in `reservation-validation.service.ts`, so removing it from the generic listing does not allow renting unavailable vehicles. Three accidental duplicate copies of the filter block (merge artifact across two prior PRs) were also collapsed, and the now-unused `PrivilegeService` injection, `PrivilegesModule` import and matching spec mock have been removed.
- Vehicle Profile Lookup — `GET /vehicles/:unitNumber` No Longer 404s On Legacy Whitespace, Now Scoped By Tenant: Calling the single-vehicle endpoint against a row whose stored `unit_number` carries leading or trailing whitespace (e.g. `"2352 "`) was returning 404 because the lookup was exact-match; trimming the path param alone did not help because the stored value still had the whitespace. A new `TrimPipe` is applied to the `:unitNumber` path param, and a new `resolveVehicleIdByUnitNumber` helper uses raw SQL (`WHERE TRIM(unit_number) = $1`) to find the canonical row id, after which the existing Prisma query re-fetches by primary key so all relation includes still work. `@CurrentUser` is now plumbed through the controller into the service and the tenant id is part of the lookup predicate, closing a tenant-scope gap where any authenticated user could fetch any tenant's vehicle by unit number. `@Transform(trim)` has been added to `VehicleCreateDto.unitNumber` and `VehicleImportRequestDto.unitNumber` so new writes can no longer reintroduce the whitespace.
Added
- Check-In — Dedicated CheckInEditPage Route: A new greenfield check-in route at `/dashboard/checkin/:resNumber/edit` replaces the legacy reuse of `ReservationsPage` for vehicle returns. The page composes five dedicated wrapper sections (Pickup & Return, Vehicle & Readings, Rate Selection, Misc Charges, Payments) with a Collapsible left column, a sticky right-column summary sidebar (gradient header, driver card, vehicle card, expandable Time & Mileage, Misc, Taxes, Fuel and Payments sections, balance-due banner, Add To Balance button), and a single shared `CheckInFormContext` carrying reservation number, vehicle inspection data, and check-in privileges. The submit button shows the outstanding balance amount, is disabled until odometer and fuel level are provided, and the page is isolated from `ReservationsPage` so the legacy form is no longer mutated by check-in flows.
- Locations — Disable-Impact Warning Before Deactivating a Location: Flipping a location's Status toggle from Active to Inactive now fetches a new read-only `GET /locations/:id/disable-impact` summary and, if any open RAs or reservations reference the location as their checkout or expected-return, surfaces a confirmation dialog showing the counts and a small sample of affected RA / Reservation numbers before the save proceeds. Operators can no longer silently break in-flight rentals by disabling their location.
Changed
- Counter Check-In — Refund / Void / Delete Payment Icons Aligned With ReservationsPage: The Counter Check-In payments timeline now uses the same icon language as the Reservations payments timeline — RotateCcw for refund, Ban for void, Trash2 for delete — and CC/DC payments correctly suppress the void action. The Total-Before-Payments row is now rendered above the Balance Due row and an Add $X to Balance button sits directly below the balance banner, matching the established pattern.
- Access Rights — Admin-Role and Permission Components for Configuration Surfaces: Configuration screens that should only be touched by tenant admins (Claims status rules, Insurance carriers, Letter templates, Equipment / Fuel / Source of Business / Source Referrals tables, Terminal Credit Cards table, Roles, User Management Access Rights, etc.) now wrap their controls in new `RequireAdminRole` and `RequirePermission` components and surface a `ReadOnlyBanner` to non-admin users instead of silently no-oping or letting unauthorised users hit a guarded API. Permission children definitions in Business Operations have been extended to drive the new banners.
Fixed
- Contract Modify — Rate-Rule Misc Charges Preserved Across Rate Switches: Misc charges tagged with `source: 'rateRule'` were being silently dropped on save and silently skipped when a new rate's rule did not include them. The initial load and rate-switch paths in `useContractModifyForm` now tag charges sourced from `rateRuleIncludedCharges` correctly so the `source` field survives the save round-trip; when the new rate's rule introduces a charge not on the contract the system now calls `qualifyCharges()` and auto-adds qualifying charges with `source: 'rateRule'` (silently skipping unqualified ones); and when the new rate's rule drops a charge the old rule included, the charge is immediately converted to `source: 'manual'` and a new `DroppedRateRuleChargesModal` lets the agent choose Keep (stays as manual) or Remove. The stale "add them manually if needed" warning toast has been removed.
Added
- Claims — Default Lookup Values Backfill, Document Required Badges, and Claim History Refresh: The Claims module ships a series of follow-ups discovered while testing end-to-end. Tenants that had never configured their Claims lookup tables (Claim Types, Expense Types, Recovery Sources, Document Types, Contact Types, Claim Payment Types) are seeded with the legacy AutoMate2 / RentWorks defaults; the Claims Setup page now exposes a Payment Types tab and renders an inline Required badge on Document Types via a new optional `metadataColumns` prop on the shared LookupsJokerPage; the Claim form auto-imports vehicle and renter when a valid RA is verified (the import dialog no longer auto-opens and the default option is `'all'`); the shared `MementoHistoryPanel` now refreshes its fetch when the parent entity's `auditInfo.updatedAt` changes; and `useUpdateClaim` / `useUpdateClaimStatus` now invalidate history queries via the prefix `['claims', 'history', id]` so every paginated history page reflects the latest edit.
Fixed
- Vehicle Class / Rate Configuration — Time & Mileage Modal No Longer Pops False "Unsaved Changes" Dialog (Urgent): In Vehicle Class / Rate Configuration → Time & Mileage, the unsaved-changes dialog was popping up on every close attempt even when the user had not touched a single field — confusing users into clicking Discard thinking it was harmless, which then surfaced as "Time and Mileage rate disappears after update". The edit-mode dirty check was falling back to `rateLines.length > 0`, which is true for every rate that has lines, so `isDirty` returned `true` on mount before any user interaction and the close-guard intercepted every close. The dirty check now compares against the initial form snapshot instead of the line count, so the dialog only appears on real changes.
Changed
- Reservations Page — Phase 0 Refactor: 9 Shared Components Extracted: Phase 0 of the ReservationsPage god-page split extracts 9 prop-driven components from `ReservationsPage.tsx` and wires them in-place — `TwoColumnPageLayout`, `ViewOnlyIndicator`, `NotesSection`, `DraftRestoreButton`, `TopSelectorBar` (`mode='checkin' | 'checkout' | 'reservation'`), `PrimaryDriverCard`, `MobileSaveBar`, the `ChargesSummary` parent + 6 breakdown children, and a `getSubmitLabel` helper for `SubmitMode` → label resolution. `ReservationsPage.tsx` drops from 7,335 to 6,558 LOC (-777) with no behaviour change. These components become the composition primitives for the upcoming `CheckInEditPage`, `CheckoutAgreementPage`, and `ReservationPage` phases so cross-page consistency is enforced by prop unification instead of fork-and-edit.
Added
- Contract Modify — Full Payment Actions Panel: The Contract Payment Section on the Contract Modify page has been expanded from a single Add Payment button into a fully-functional payment management panel. The list of payments is fetched and re-fetched on every action via `getPaymentsByContract` and capped at a scrollable height so it never pushes the Save button off-screen. An amber Auth-Hold panel surfaces AUTHORIZED deposits with `depositCaptured = false` and offers Capture Funds (routed to Adyen or the manual endpoint based on `processorTxnId`) and Void Hold actions. Each row carries per-row action buttons in the compact timeline variant — Pencil to edit a cash payment (amount + memo), RotateCcw to refund (modal pre-fills the remaining refundable balance and routes to `refundAdyenPayment` or `refundManualPayment`), Ban to void non-CC/DC, Trash to delete cash. Confirmation dialogs precede void and delete. The previous `balanceDue > 0` gate on the Add Payment button has been removed so payments can be added at any time, and the selected company name is now threaded through to the choose-payment modal.
- Custom Fields — End-to-End Custom Field Support on Vehicles, Customers, Non-Revenue, and Field Security: Custom field definitions are now first-class across the configuration and entity layers. The Field Security Configuration tab now manages custom field definitions inline with built-in fields and the screen selector uses the shared SearchableSelect, the Vehicles Finance tab is reorganized into a Card layout with a sticky section-navigation bar that scrolls between Finance subsections, custom fields are wired through the Vehicle Form, Customer Create / Profile, Non-Revenue Details, and Fleet / Equipment Overview reports, and the underlying field-security service exposes custom fields end-to-end.
Changed
- Rental Agreements Dashboard — Open / Voided / Closed Status Tiles: The Rental Agreements dashboard's Checked Out and Pending tiles have been replaced with Open, Voided, and Closed tiles that break Total Contracts out by contract status, so agents can see the contract mix at a glance. The Reservations dashboard tiles are unchanged.
- Vehicle Inventory — Clear Session Documentation Tightened: The `clearSession` mutator on the vehicle inventory service has been re-documented to make clear that it clears all line items from a session (not the manager-only backend action the previous comment implied), and the supporting access control on the physical-inventory clear path has been updated accordingly.
Added
- Reservations & Counter Checkout — Vehicle Planner-Conflict Warning Modal: When a walk-up rental agreement takes a vehicle that is already pre-assigned to one or more future reservations in the Reservation Planner, the agent now sees a yellow warning modal listing each conflicting reservation with its dates and RA/res numbers. The agent can either pick a different vehicle or click "Proceed with Conflict" to continue; the affected future reservations are then flagged in the database so the planner can display a purple conflict indicator next to them until they are reassigned. The same flow runs from both /counter/checkout and /dashboard/checkout/new.
- Reservation Planner — Vehicle Conflict Indicator on Timeline Rows: Reservations whose pre-assigned vehicle was taken by a walk-up RA now render with a visual conflict indicator on the Reservation Planner timeline, so agents can spot affected bookings at a glance and reassign them before their pickup date.
Fixed
- Counter Checkout — Walk-Up Conflict Flag No Longer Crashes Post-Commit: The planner-conflict flag write is now sent after the walk-up RA has been successfully created, and a failure to flag no longer rolls back or duplicates the just-committed RA. Agents see an inline toast if the flag call fails and the RA itself remains intact.
- Counter Checkout — No Stale Conflict IDs After Lock Failure: The list of acknowledged planner-conflict IDs is now only written to the checkout store after the vehicle lock has been confirmed. If another agent grabs the lock in the same instant, the local store stays clean so unrelated future reservations are not flagged in error.
- Vehicle Availability — Errors Now Surface Instead of Faking Success: A failed availability check no longer returns a fake "available" result; callers see a toast and can retry or pick another vehicle, preventing silent over-bookings.
Added
- Counter Checkout — Location Filter on Contract Search: The Counter Checkout contract search step now includes a Location dropdown alongside the search bar. Agents can scope today's reservation queue and free-text searches to a specific pickup location, and the selected location is appended to the “Today's Reservations” header so the active filter is always visible. The queue's status filter has also been retuned from Pending Open to No Show so cars that did not arrive surface alongside open reservations.
- Reservations — Edit Cash Payment Workflow: A new Edit Cash Payment dialog has been added to the Reservations payments timeline. Agents with the new edit-cash-payment permission can adjust the amount and notes on a recorded cash payment in place, with full validation and audit, instead of having to void and re-enter it. Users without the privilege see the existing read-only view.
- Reservations & Vehicle Picker — Override Vehicle Availability and Underage Driver Alerts: Privileged agents can now override vehicle availability when picking a car from the inline grid, vehicle search modal, or counter checkout vehicle step, and unavailable vehicles render with a clear override affordance instead of being hidden. The same flows now surface an underage driver alert before vehicle selection, with override controls gated by the underage-driver permission so the warning cannot be silently bypassed.
- Vehicle Fleet — Coming Soon Tab: A new Coming Soon tab is now rendered on the Vehicle Fleet page surfacing vehicles that have been pre-loaded but not yet placed in service. The page reads the new Coming Soon status seeded in 1.9.32 and renders each row with the same actions available on the standard fleet list, so fleet managers can track and activate inbound inventory from a single place.
- Checkout — Customer Override Modal for Blocking Issues: The checkout flow now consults a new `getCheckoutBlockingIssues` endpoint on `customerApi` and surfaces a `CustomerOverrideModal` listing every issue (expired licence, unqualified rate, underage driver, blacklisted customer, etc.) that would otherwise block the agreement. Authorized agents can review and override individual items; a `logCheckoutOverride` call records the override on the customer for audit. The existing hard-block is preserved for agents without override privileges. The override flow is wired through every counter checkout step (Driver Selection, Vehicle Selection, Rate & Charges, Vehicle Return on check-in, and Review & Submit) so blocking issues surface consistently before commit.
- Privileges — Auto-Refresh on Permission Change: A new `usePrivilegeAutoRefresh` hook and `NewSolProtectedRoute` wiring now keep the permissions store in sync with the server without requiring the agent to sign out and back in. When an admin grants or revokes a privilege from the Privileges tab, the affected user's session picks up the new permission set on the next protected-route transition and the UI re-evaluates privilege-gated actions immediately.
Fixed
- Misc Charges — Tax-Type Charges Can No Longer Be Marked Taxable: Sales Tax, Federal Tax, Other Tax, and Misc Fees charge types now hide the Taxable tab and force the taxable flag off in the Misc Charge form, preventing the circular configuration where a tax could be taxed by itself. Switching an existing charge to a tax type automatically jumps the user back to the General tab, clears the taxable flag, and disables the checkbox with an inline “tax charges cannot be taxable” hint. The Percent Calc tab's applicable-targets list is also filtered to exclude tax-type targets.
Added
- Rental Agreements Dashboard — Open / Voided / Closed Tiles: The Rental Agreements dashboard tiles have been re-cut from the legacy Checked Out and Pending tiles to a new Open / Voided / Closed split sourced from the dedicated KPI counts shipped in 1.9.31. Total Contracts and Total Revenue now sit alongside three colour-coded status tiles (Open in green, Voided in red, Closed in secondary) so agents can see the contract mix at a glance, and the Reservations page tiles continue to use the existing Active and Pending counts unchanged.
- Vehicle, Customer, and Company Lists — Toolbar Filters, Filter Presets, and Multi-Value Pickers: Continuing the filter UX cleanup started in 1.9.37, the Vehicle Fleet, Customer Management, and Companies list pages now share the same toolbar primitives. A new `toolbarFilters` slot on the shared DataTable carries multiple inline dropdowns next to the legacy status filter (so Companies can render both Status and Type pickers in the toolbar), Filter Presets snapshot toolbar state alongside advanced filters so customer and company pages — which have no advanced panel — can also save presets, and the Companies list adds a Company Type filter (Broker, Corporate, Insurance, Tour, Other, Partner) that filters server-side.
- Customer Form — Auto-Filled Badge on Postal-Code Lookups: A new AutoFilled badge is now rendered against the City and State fields when they are auto-populated from a postal-code lookup, so agents can see at a glance which fields were filled in by the system and which were entered manually. The renter form in checkout now shares the same lookup service used by the customer form so the experience matches across both surfaces.
- Driver Management — Employer Field: An employer field has been added to the Driver Management panel and is now threaded through the checkout API, counter checkout wizard, and reservation new-driver form, so agents can capture and edit the renter's employer alongside the rest of the driver record.
Changed
- Vehicle Class Modal — Reordered Fields and Auto-Derived Class Code: The Vehicle Class creation modal now opens with the Status toggle at the top, the Description input above the Class Code, and an auto-derived Class Code that lowercases and strips spaces from the Description until the user manually edits it (auto-derive then locks for that session so manual input is not clobbered). The Product field pre-selects from terminal settings on create, and the legacy Alternative Classes section has been removed.
Fixed
- Counter Checkout — Crash on Existing Agreements Fixed: Opening an existing reservation or rental agreement from the Counter Checkout flow (/counter/checkout) and from the Reservations Checkout details page no longer triggers a Loading Error screen on first render. The checkout wizard now renders reliably the moment the existing agreement finishes loading.
Added
- Misc Charges — Taxable Tab Available on Every Charge Type: The Taxable tab in the Misc Charge form is now visible for every charge type. The applicable-taxes list automatically filters out taxes of the same type as the charge being edited to prevent circular tax configurations, with a clear loading and empty state while the list is being computed.
- Rental Agreements & Reservations — Filter Presets, Multi-Unit Search, and Shared DataTable Cleanup: The Rental Agreement and Reservation list pages have been reworked to fix several long-standing filter inconsistencies. The RA browser status dropdown no longer offers reservation-only statuses (Quote, Open Reservation, Cancelled, etc.); Location Out and Location Due now write to distinct backend params instead of silently overwriting each other; the previously-shipped Filter Presets bar is now actually rendered in the toolbar; the Unit Number filter accepts a comma-separated list of units in a single search; the global search box matches across closed contracts so customer-name searches no longer miss them; and status pill labels truncate cleanly with an ellipsis instead of being clipped by the surrounding cell.
Changed
- Misc Charges — Tiers Checkbox Removed: The Hourly / Daily / Weekly / Monthly rate inputs in the Misc Charge form now render directly whenever a time-based Calculate By method is selected (24 Hour, Calendar Day, Modified 24 Hour) — the redundant Tiers checkbox toggle has been removed so the price grid appears in one step instead of two.
- Non-Revenue — Inspection and Vehicle Selection Flow Refactor: The Open Non-Revenue screen no longer carries an unused location state and now navigates straight to the dashboard non-revenue list. The shared Vehicle Selection Section has been updated alongside this change so the inspection modal opens against the actually-selected vehicle instead of falling back to the previously-selected one.
Fixed
- Counter Checkout — Added Driver No Longer Wipes Pre-Filled Charges: Adding a driver through the counter checkout step previously cleared the in-progress charge breakdown because the addition path passed through a different store mutator than the rest of the flow. The `addAdditionalDriver` mutator has been renamed and routed through a single `addDriverWithData` path used by both the renter-search and new-driver entry points, so the charge calculation survives a driver add and the additional-driver charge is reflected on the contract immediately.
Added
- UI — Full Keyboard Navigation in Searchable and Multi-Select Dropdowns: The shared searchable single-select and multi-select dropdowns used across country pickers, location filters, vehicle pickers, report filters, and dozens of other places throughout the app can now be driven entirely from the keyboard. Enter or arrow keys open the popover, typing a letter seeds the search, arrow keys with wrap and Home/End move the highlight, and Enter or Tab commit the selection and advance focus to the next field in one keystroke.
Changed
- Vehicle Fleet — Unavailable Badge on Reservation Tiles: The Open Reservations table now surfaces a clear Unavailable badge on each reservation tile whose pre-assigned vehicle is no longer available, so agents can spot affected bookings without opening each reservation. The Vehicle Class form modal and Vehicles datatable were updated alongside this change to align tile rendering with the new shared badge component.
- Vehicle Fleet — Custom Status Tiles in KPI Strip: The Vehicles datatable KPI strip now renders a tile for every tenant-defined custom vehicle status alongside the standard tiles, so the breakdown always reconciles with Total Vehicles instead of silently rolling non-standard rows into Available.
Fixed
- Exports — Export All No Longer Fails With Validation Errors: Clicking Export All from the Companies, Fleet, and other data tables no longer fails with a validation error. Exports now paginate within the server's row cap and assemble the full result set in the background.
- Contract Modify — Keep Dates No Longer Wipes Vehicle and Rate on OnRent Conflict (Critical Data-Loss Fix): When editing an OnRent rental agreement, changing the pickup date pops the vehicle-availability conflict modal. Clicking Keep Dates silently nulled the selected vehicle, dropped the conflict info, and made the agreement appear to lose its rate — destroying data on an active rental with no recovery path. Keep Dates now flags-and-keeps instead of wiping: the vehicle stays on the agreement with an amber Date Conflict badge and a banner listing the conflicting RA / RES, rate, equipment, odometer, fuel, and other agreement data are preserved, and Save is blocked until the agent picks a replacement vehicle, at which point the conflict clears automatically.
Changed
- Vehicle Profile — Unified Primary Action by Vehicle Status: The Vehicle Profile header no longer hard-codes a single Check-Out action. The page now resolves the appropriate primary action from the vehicle's current status — checkout for Available, check-in for On Rent, close work order for In Service, or return to service for Out of Service — and renders only that action button. The legacy `onCheckout` prop has been replaced with a more flexible `primaryAction` prop on the shared header, and supporting type definitions have been tightened.
- Customer Form — Phone Section Collapsed Into Single Searchable Country Selector: The phone-numbers section in the renter detail panel previously rendered three controls per row — a flag-only country dropdown with no search, a read-only "+1" box, and the phone-number input — which made the layout look broken and made non-top-of-list countries slow to find. The dropdown + read-only box pair is now replaced with a single searchable selector that renders the flag and dial code together (e.g. 🇺🇸 +1), matching the pattern already established for the customer form.
Fixed
- Reports — TAX/FEE Type Filter Now Tracks Report Mode: The TAX/FEE Type multi-select on the Tax, Fees & Misc. Charges report now mirrors the active Report Mode. Picking Tax & Fees hides misc-charge codes and picking Misc. Charges hides tax/fee codes, and any selections that no longer apply after a mode switch are pruned automatically.
Fixed
- Terminal Settings — Saved Location No Longer Wiped After Save: Saving a terminal Location no longer clears itself when the modal is reopened on tenants with many locations. The settings dialog now loads the full active-location list before validating the saved value, and the dashboard's location filter updates immediately when a new terminal Location is saved instead of requiring a hard refresh.
- Dashboard — Today's Operations Tile Shows Correct Times: The Today's Operations tile now renders pickup and due-back times exactly as entered on the reservation, without shifting by the browser's time-zone offset. The Pickups and No Show tabs also relabel their columns to "Date & Time Out" and "Date & Time Due" for reservation context; the Due Back and Overdue tabs keep the existing "Check Out" and "Check In" labels.
- Reservations — Closed Contract Edit Preserves Stored Return Date and Time (Critical Financial Fix): Editing a closed rental agreement was silently overwriting its return date and time with today's date and time, recalculating Time & Mileage charges from the new duration, and surfacing a false balance due on a fully-paid contract — an agent who did not notice the silent change could collect money that was not owed. The Edit button on a closed contract now routes through the Contract Modify page (not the check-in URL, which is reserved for live returns), and the form-loader now reads the actual `dateIn` / `timeIn` captured at close instead of the planned `dateDue` / `timeDue`, so closed contracts open with the correct stored return values.
- Reservations — Stale Reservation Default Return Auto-Populates To Pickup + 1 Day: Honoring a reservation whose return date is already in the past (or missing) previously loaded the stale `dateDue` / `timeDue` from the database and required the agent to manually correct it before continuing. The form-loader now detects a past or missing return at populate time and defaults the return to pickup + 1 day (24 hours); reservations whose original return is still in the future are unchanged.
Fixed
- Dashboard — Fleet Status Drill-Down Preserves Location: Clicking a status count on the Fleet Status widget now forwards the dashboard's current location filter to the Vehicle Fleet page, so the drill-down list matches the count that was clicked. When the dashboard is set to All Locations, no location filter is applied.
- Customers — Validation Details Now Surface on Create: The Add Customer page now shows the full list of validation errors returned by the server in the failure toast, so agents can see exactly which fields need fixing instead of a generic "Please fix the following validation errors" message. The Additional Personal Information section's "Start Date" field has also been relabeled to "License Issue Date" to match what it actually saves.
- Payments — Cash Receipts Auto-Refresh After Voiding a Direct-Bill Payment: When a Direct Bill payment is voided on a rental agreement, the linked corporate account's Outstanding Charges, Receipt History, and Total Receipts now refresh automatically. Agents no longer need to manually reload the Cash Receipts page to see the cascaded changes.
- Reservations — Adding Misc Charges Stops Freezing the Rate Breakdown: Adding a miscellaneous charge such as CDW or PAC to a reservation or rental agreement no longer causes the live rate calculation to silently fail and freeze on its last total. Charges and taxes now update on the breakdown as expected.
Added
- Claims — Default Lookup Values Seeded for Every Tenant: New tenants are seeded with the legacy AutoMate2 / RentWorks defaults for every Claims lookup category — Claim Types, Expense Types, Recovery Sources, Document Types (with Rental Agreement marked as required), Contact Types, and a new Claim Payment Types lookup — so the Claims module is usable out of the box without manual setup. Existing tenants whose lookup tables are empty are backfilled with the same defaults; tenants that have already configured their own values are left untouched.
- Claims — Configurable Expense and Payment Types: Claim Expense Types and Claim Payment Types are no longer hardcoded enums and can now be managed from Configuration → Claims Setup like the other claim lookups, so tenants can add, rename, or retire their own expense and payment categories.
- Notes & Claim Reminders — Author and Assignee Display Names: Note and claim-reminder responses now include the author's or assignee's full name alongside the existing user identifier, so the Notes panel and Reminder views can show 'First Last' instead of an email address or user id on every list, detail, and update response.
- Vehicles — Coming Soon Status Backfill and Filtering: A new Coming Soon vehicle status is now seeded across tenants and surfaced as a first-class slice on Fleet KPI metrics. Vehicle list and dashboard breakdowns recognise the status and filter on it, and existing custom statuses are handled consistently so non-standard rows are no longer silently rolled into Available.
- Counter & Locations — Privileged Location-Hours Override Audit Trail: Agents who use a privilege to check out a vehicle outside the location's configured operating hours now write an audit log entry recording the overridden window, the privilege that allowed the override, and the user who exercised it, so out-of-hours rentals are reviewable after the fact.
Fixed
- Claims — History Tab Now Records Every Edit: Editing money fields such as estimated damage and subrogation amount, along with other claim fields including status, description, total estimate, total paid, deductible, and settlement amount, produced no entries on the Claim History tab because the audit pipeline was watching column names that did not exist and silently dropped Decimal money values from snapshots. Tracked fields now align with the real claim columns and the audit pipeline preserves Decimal and Date values on both top-level claim fields and sub-records (contacts, vehicles, expenses, reminders), so every edit is captured in History and reflected in the before/after diff.
- Claims — Subrogation Recovered and Notes Save Correctly: Subrogation Recovered and Subrogation Notes were accepted by the form but silently dropped on save because the create and update paths never wrote them through to the database. Both fields now persist on create and update, with Subrogation Notes validated up to 2,000 characters.
- Claims — Newest Same-Date Expense and Payment Rows Appear First: Claim Expenses and Claim Payments now sort by date and then by id (descending), so a row added on the same date as existing rows appears at the top of the list instead of getting buried.
Added
- Privileges — RENT_UNAVL Now Enforced on Vehicle Search API: The vehicle search endpoint (GET /vehicles) now consults the caller's privileges and excludes On-Rent vehicles when the RENT_UNAVL privilege is not granted, instead of relying on client-side filtering that could be bypassed by any direct API call or by screens such as the Counter Fleet page that did not apply that filter. Privileged users see no change. The same WHERE clause is applied to both findMany and the paginated count so totals reconcile.
Fixed
- Rental Agreements Dashboard — Open / Voided / Closed KPI Counts: The Rental Agreements dashboard KPI endpoint now returns dedicated Open Contracts, Voided Contracts, and Closed Contracts counts and excludes pending-open rows from the Total Contracts figure, so the RA dashboard tiles reflect actual contract status totals. The Reservations dashboard tiles continue to use the existing Active and Pending counts unchanged.
- Dashboard — Fleet Status Widget Built Dynamically: The Dashboard Fleet Status widget no longer hardcodes eight status categories and silently drops anything else. The breakdown is now built from the tenant's actual `statuses` seed, so custom statuses such as Unavailable surface as their own slice instead of being rolled into Available. The Non-Revenue code mismatch that was inflating the Available count (dashboard constant `nonRevenue` versus seed code `nonRev`) has also been corrected.
- Customers — Blacklist Cascades to Upcoming Reservations Atomically: Marking a customer as blacklisted previously flipped the status flag only, leaving every upcoming reservation live so a blacklisted renter could still walk up at the counter with a confirmed booking. The status flip, audit note, and silent cancellation of every upcoming reservation now run inside a single transaction — any failure rolls the whole operation back so the customer is never left in a half-blacklisted state.
- Counter & Reservations — Primary Driver Auto-Promotion Closure Bug: Removing the primary driver from a counter checkout, reservation, or rental agreement that had additional drivers occasionally failed to promote the next driver because a stale closure in the remove handler read the pre-removal driver list. The auto-promote dialog now reads the post-removal list correctly and the first additional driver is silently promoted to primary as expected.
Added
- Vehicle Fleet — Custom Status Tiles in Fleet KPIs: The Vehicle Fleet summary tiles now include every tenant-defined custom vehicle status (for example 'Unavailable') alongside the standard Available / On Rent / In Service / Out of Service tiles. The KPI endpoint aggregates any non-standard status into its own count so the sum of every tile always reconciles with the Total Vehicles count, eliminating the gap where custom-status vehicles were counted in the total but invisible on the breakdown.
Fixed
- Payments — Voiding a Direct Bill Payment Now Cascades to Its Receipts: Voiding a Direct Bill payment from a rental agreement reversed the payment's AR contribution but left every Cash Receipts entry recorded against that payment active, so Receipt History kept showing the receipts and Total Receipts was overstated by the voided amount. Voiding a Direct Bill payment now soft-deletes every receipt attached to it in the same transaction, restores the corresponding corporate balance, and applies the same cascade when an entire rental agreement is voided.
- Internal — Test Coverage: Expanded unit tests for the misc-charge templates service, with a small follow-up cleanup to the service itself, to lock in commission-handling behaviour.
Fixed
- Dashboard — Operational Load Tile Times No Longer Shift by Timezone: Today's Operations tile was rendering pickup and return times shifted by the browser's UTC offset, so an early-morning pickup could appear on the previous day. The endpoint now returns the saved date and time as raw values exactly as recorded, so the tile displays the agreed pickup and return times regardless of the viewer's timezone.
- Reports — Charge-Code Options Match the Active Report Mode: On the Tax, Fees & Misc. Charges report, the TAX/FEE Type multi-select returned every misc-charge template regardless of the active Report Mode. The option list is now filtered to the codes that match the current mode (tax/fee codes in Tax & Fees view, misc-charge codes in Misc. Charges view), so the filter only ever shows codes that can actually appear on the report.
- Corporate Accounts — $0 Receipts and Credit Memos Rejected at the Service Layer: Direct Bill receipts and corporate credit memos now reject zero-amount records at the service layer as an additional safeguard on top of the existing form validation, so internal jobs or any future caller cannot plant $0 entries that would inflate Receipt History or pollute credit-memo totals and AR aging reports.
Added
- Contract Modification — Full Open Contract Edit Page: A new dedicated Contract Modify page lets agents edit any open rental agreement end-to-end — change the rate, swap the vehicle, edit drivers, add or remove miscellaneous charges, edit equipment, change pickup/return dates and locations, and update company information — with a live calculation sidebar that re-prices the contract as edits are made. A per-rental edit lock prevents two agents from working on the same agreement at the same time, and a session heartbeat keeps the lock alive while the page stays open. Saving routes the agent into the check-in flow with all updated values applied atomically.
- Contract Modification — Vehicle Exchange Within Open Contract: A new Vehicle Exchange section on the Contract Modify page lets agents swap the rented vehicle mid-rental. Agents enter the return fuel level and odometer for the outgoing vehicle, pick a new vehicle from the live availability list (with utilization score and a detail modal), and confirm the exchange — fuel and mileage charges accumulate per leg of the rental, and a full vehicle exchange history is preserved on the contract.
- Contract Modification — Closed Contract Editing: The Contract Modify page now also opens for closed contracts, letting accounting staff correct miscellaneous charges, taxes, and driver records on already-closed agreements (the Edit-button routing for closed contracts in the Reservations list, added in 1.9.24, is now backed by the full edit experience).
- Check-In — Late Return Overtime Charge: When a vehicle is returned after the due-back date, the system now automatically computes and posts a late-return overtime charge based on the contract's rate and the actual return date and time. The new charge is rolled into the balance-due total on check-in and printed on the closing rental agreement.
- Multi-Currency — Rate Snapshots on the Rental Agreement: At checkout, the location's currency and exchange rate to the system base currency are now frozen on the rental agreement. Every downstream calculation — rate, taxes, miscellaneous charges, late-return overtime — uses that snapshot rate, so prices on a contract no longer drift if the location currency or exchange rate is updated after checkout. The Contract Modify page surfaces the saved exchange rate for review and supports a manual override when the current location currency does not match the snapshot.
- Payments — Saved Cards on Rental Agreements (Adyen): Adyen card tokenization is now wired all the way through to the rental agreement. Agents can tokenize a card during checkout and reuse it for later payments on the same RA via a new Save to RA button in the payment modal; saved cards appear in the modal's saved-card list. A new Adyen tokenization webhook updates saved-card tokens automatically as Adyen rotates them, and duplicate cards (same last four + brand) on a customer, company, or rental agreement are deduplicated automatically.
- Insurance — Replacement Rental Insurance Fields: Open contracts now expose replacement-rental insurance fields end-to-end (bill-to, extension dates, coverage details), so insurance-paid replacement rentals can be edited and extended through the standard contract flow.
- Marketing — T&M Rates: Duplicate Rate Line Action: The Time & Mileage rate form now provides a Duplicate row action on every rate line, letting rate managers create a variant of an existing line in one click without re-entering shared values.
- Reservations — Tax-Exempt Removal Confirmation: Removing a tax-exempt customer or company from a reservation now prompts the agent with a confirmation explaining that taxes will be re-applied, preventing accidental loss of tax-exempt status.
- Counter — Rent Underage and Unqualified Rate Inline Hints: Continuing the privilege rollout from 1.9.26, expired-license, unqualified-rate, and rent-underage indicators are now surfaced directly in the driver-search and rate-selection steps of the Counter checkout, so agents can see at a glance which privilege gate would apply before selecting that driver or rate.
- Settings — Adyen Tokenization Webhook HMAC Key: The terminal credit-card configuration modal now exposes a Webhook HMAC Key field, so each tenant can configure its Adyen tokenization webhook secret directly from Settings.
- Contracts — Quick-Status Tab Filter: The Contracts list page now has a top bar with four instant-filter tabs — Open, Closed, Voided, and All — allowing staff to switch between contract status groups with a single click without opening the advanced filter panel. The active tab is preserved in the URL so the view survives a page refresh and can be shared as a direct link.
- Vehicles — Add Vehicle Section Navigation Strip: The Add Vehicle form now has a sticky navigation bar pinned below the page header with one button per section. Clicking any section name smoothly scrolls the form to that section and keeps the bar visible throughout the entire form. Required sections (Core Identifiers, Initial Status, Vehicle Identity) show a small Required badge so agents know at a glance what must be filled before saving.
Fixed
- Time & Mileage — Cascade Across Regular Tiers: Non-VP rate lines now cascade correctly across regular tier thresholds and route residual time and mileage units to overtime / extra-units lines, matching legacy AutoMate2 behaviour. Minimum-units thresholds now correctly use the rental duration in days. This eliminates a silent overcharge where the cascade rounded up.
- Vehicle License Fees — Half-Up Rounding: Per-day VLF charges now round half-up at every write site, eliminating 1-cent drift between the calculation preview and the posted total on the contract.
- Taxes — Auto-Apply No Longer Retroactive: Newly added auto-apply tax charges no longer re-apply to taxable charges that already exist on the contract, preventing double-tax scenarios when a tenant turns on a new auto-tax.
- Taxes — Recalculation on Misc Charge Edits: When a taxable miscellaneous charge is added, removed, or edited on a contract, dependent taxes now recompute automatically so totals stay in sync without requiring the agent to reopen and resave the contract.
- Check-In — Balance-Due Correctness: Balance-due calculations now correctly exclude voided and refunded transactions, account for credit balances, and write the Date In and Time In on the contract from the actual return date and time entered at check-in. Late-return charges persist on the contract after submit.
- Contract Modify — Driver Sync on Save: Updating a driver from the Contract Modify driver section now correctly synchronises phones, addresses, and driver-license records — removed entries are deleted, new entries are inserted, and database IDs are preserved across re-renders so existing records are updated rather than re-created. Drivers whose only change is a contact-detail edit are no longer skipped on save.
- Marketing — T&M Rates: Duplicate No Longer Mutates Source: Duplicating a Time & Mileage rate template no longer leaks rate-line IDs from the source template — the duplicate is now a clean copy and the original is no longer overwritten when the duplicate is saved. Rate template scope dropdowns (location, class, and similar) are also mono-select in edit and duplicate modes, preventing accidental multi-scope assignments.
- Reservations — Edit No Longer Sends Stale Session Lock ID: Saving an edit on an existing reservation no longer sends the editing-lock session ID as part of the update payload, removing a benign error log on the server.
- Contract Modify — Modal Scroll and Footer Overlap: The driver-edit and other modals on the Contract Modify page no longer have their footer overlap the body content; modals scroll cleanly even with tall driver records.
- Contract Modify — No False ‘Update Charge’ Flag on Page Load: Opening the Contract Modify page no longer falsely flags miscellaneous charges as edited before any user input, removing a spurious save-warning prompt.
- Contract Modify — Block Save When a Driver Has No License: Saving a contract modification is now blocked when any driver on the contract is missing a driver's licence, with an inline error pointing to the offending driver row.
- Reports & Vehicles — Misc Cleanup: Several smaller backend fixes across the rental-agreement report strategy, fleet-list report, vehicles service, payments service, physical-inventory service, and notes controller were applied to keep totals, statuses, and audit data consistent.
Changed
- Vehicle Classes — Category is Now Optional: Vehicle classes can now be created and saved without selecting a category. Operators that do not use the Product → Category → Class fleet grouping no longer need to invent a placeholder category to set up a vehicle class. The Category Code field now shows a 'No category' option and no longer carries a required indicator. Clearing the category from an existing class is also supported.
- Vehicle Form — Improved Page Performance: The vehicle add and edit form loads dropdown data more efficiently, reducing unnecessary re-renders and improving responsiveness when switching between fields.
Fixed
- Vehicle Class — Gas Tank Auto-Fill: Selecting a vehicle class that has a default gas tank size now correctly saves the vehicle without requiring the agent to manually re-enter the value. Previously the form would silently block submission even though the gas tank field appeared filled in.
Added
- Privileges — Unqualified Rate and Expired License: Two new privilege gates are now enforced in the checkout flow. Agents with the Unqualified Rate privilege can proceed when the rate presented does not meet qualification criteria; agents with the Expired License privilege can check out a vehicle when the driver's license has already expired. Both privileges must be explicitly granted to a role before agents can override these blocks.
- Privileges — Rent Unavailable Vehicle: A new privilege gate allows authorized agents to assign and check out a vehicle that is not in an Available status. Agents without this privilege cannot proceed when the selected vehicle is unavailable.
- Privileges — Rent Underage Indicator in Driver Search: When searching for a driver, the underage indicator is now surfaced directly in the search input results when a driver does not meet the minimum age requirement, giving agents clear visibility into whether the Rent Underage privilege is required before selecting that driver.
- Misc Charges — Auto-Apply with Privilege-Gated Removal: Misc charges configured for automatic application are now applied to the contract at the start of the rental. Agents with the Delete Auto Charges privilege can remove these system-applied charges from the RA; without the privilege, the auto-applied charges are locked in place.
- Rental Agreements — Edit Cash Payment: Agents with the Edit Cash Payment privilege can now edit the amount and memo of an existing cash payment directly from the Payments tab on a rental agreement, correcting entry mistakes without voiding and re-entering the payment.
Changed
- Privileges — Dynamic Privilege System Enhancement: The privilege enforcement flow across checkout controllers and services has been refactored for consistency, ensuring privilege checks are applied uniformly throughout the rental workflow and that unused or redundant privilege constants are removed from the codebase.
- Additional Drivers — Form Aligned with Customer Form: The Add Driver form now matches the structure of the customer creation form. The Phone Numbers, Address, and Driver's License sections open pre-expanded with one empty entry each so agents can fill in data immediately without manually expanding each section; the Add Phone button appears only when no phone entry exists, matching Address section behavior. Employer, Extension, and Apt/Suite fields have been removed. All required fields now show a red asterisk consistently.
Fixed
- Additional Drivers — Unique Email Enforcement: Adding a new driver with an email address already belonging to another customer now shows an inline error directly under the Email field, preventing form submission and identifying the conflicting address. Searching for and selecting an existing customer from the driver search correctly bypasses this check by passing the customer ID.
- Additional Drivers — Auto-Resolution of Customer Records After Contract Close: When a contract is closed through check-in, any additional driver snapshot added without a linked customer record is now automatically resolved — the system finds an existing customer by email or license number, or creates a new one, and links the snapshot to that customer record. Individual resolution failures are caught and logged without blocking the contract close.
- Misc Charges — Taxable Option Locked for Tax-Type Charges: Tax-type miscellaneous charges (Sales Tax, Federal Tax, Other Tax, and Misc Fees) can no longer be marked as taxable. The Taxable tab is hidden in the misc charge form for these charge types, the taxable checkbox on the General tab is disabled and grayed out with an explanatory hint, and tax-type charges are excluded from the Percent Calc applicable targets list to prevent tax-on-tax scenarios.
Added
- Miscellaneous Charges — Multiple Instances per Rental Agreement: The same miscellaneous charge can now be added to a rental agreement multiple times as independent line items, each with its own quantity and rate, so agents can record separate GPS rentals or other recurring charges without them collapsing into a single row.
- Corporate Accounts — Per-Class and Per-Location Rate Overrides: Rate managers can now configure class- and location-specific rate rules on any corporate account from the Company Rates tab, ensuring that reservations under that corporate automatically qualify only the designated rate for the selected vehicle class and pickup location.
- Corporate Accounts — Misc Charge Inclusion Rules: A new section in the Company Rates tab lets rate managers force-include or exclude individual miscellaneous charges for a specific corporate account, overriding the default charge rules for every reservation booked under that corporate.
- Counter — Contract Inquiry: A new Contract Inquiry screen on the Counter lets agents search rental agreements by agreement number, unit, plate, or renter name, view full agreement details, and immediately print, email, or send the contract for e-signature.
- Counter — Fleet Management: A new Fleet Management screen on the Counter shows the live status of all fleet units and lets agents modify unit status, open and close non-revenue tickets, initiate a checkout with the vehicle pre-selected, and run a vehicle inspection — all without leaving the Counter.
Fixed
- Rental Agreement Notes — Correct Dialog Title: The Add Note dialog on a rental agreement now reads 'Add Rental Agreement Note' instead of 'Add Reservation Note', matching the correct context of the page.
- Edit Agreement — Contract Details Field Alignment: The Rental Reason dropdown in the Contract Details section now aligns to the same horizontal baseline as the adjacent PO# and Referral # fields.
- Open Contract — Due Back Date and Time Labels: On an open rental agreement, the return date and time fields are now labelled 'Due Back Date' and 'Due Back Time' to reflect that the vehicle has not yet been returned; closed contracts, reservations, and the check-in flow keep the existing 'Return' labels.
- Advanced Filters — Apply Button Always Visible: The Apply Filters and Clear All buttons in every advanced filter panel now stay pinned at the bottom of the filter sheet regardless of how many filter values are selected, so agents no longer need to scroll down to apply a filter.
- Navigation Sidebar — Rental Agreements Highlighted During Checkout: When an agent begins the checkout workflow from a reservation, the sidebar now correctly highlights the Rental Agreements section instead of keeping Reservations active.
Changed
- Contract Modification — Closed Contracts Now Editable: Clicking Edit on a closed contract from the Reservations list now opens the Contract Modify page and the system accepts the update, allowing staff to adjust contract details such as miscellaneous charges on closed contracts; previously this workflow was blocked at both the page level and the server level.
Fixed
- Reservations — Edit Button Routing for Closed Contracts: The Edit button on a closed contract in the Reservations list now correctly navigates to the Contract Modify page; previously it incorrectly opened the check-in edit view.
Added
- Tax, Fees & Misc. Charges Report — a new Report Mode toggle allows switching between Tax & Fees view (showing Total Taxes and Total Fees KPIs) and Misc. Charges view (showing a Total Charges KPI), making both charge categories accessible from a single report.
- Tax, Fees & Misc. Charges Report — Location, Brand, and TAX/FEE Type filters now support multiple simultaneous selections, so results can be narrowed to any combination of locations, brands, or charge codes in a single run.
- Customer Form — entering a zip code on the create or edit customer form now automatically fills in the City and State fields, with support for both US ZIP codes and Canadian postal codes.
- Tenant 360 — a warning banner now appears on the tenant overview when a tenant is missing default system forms, with a one-click action to seed the missing forms and dismiss the banner immediately.
Changed
- Tax, Fees & Misc. Charges Report — renamed from "Tax & Fees Audit" and now restricted to closed contracts only, so all KPIs and line items reflect finalized rental data rather than mixing in open agreements.
- Reports — Tax-Exempt Rentals moved from the Compliance & Exceptions tab to the Accounting tab.
- Customer Form — address entry order updated to Country → Zip → City → State, and changing the Country now also clears the Zip field to prevent stale postal codes from triggering incorrect city and state lookups.
Fixed
- Rental Agreements Dashboard — the Total Contracts tile now correctly counts all contracts across every status (open, closed, void, and pending) instead of showing only open and pending agreements.
- Rental Agreements Dashboard — the Total Revenue tile now displays the actual sum of charges from closed contracts instead of always showing $0.00.
- Contract E-Signing — resolved an issue in the Ampliphi digital signature integration that was preventing the e-sign workflow from functioning correctly.
- Multi-select filter dropdowns — selected value badges now truncate long labels with an ellipsis and display the full text on hover, preventing them from overflowing their container.
Changed
- Misc Charges — Pricing Grid Visibility: When creating a new misc charge, the Hourly, Daily, Weekly, and Monthly rate inputs are now displayed by default, removing the extra step of enabling the pricing grid before entering rates.
- Vehicles — VIN Auto-Fill Scope: When a VIN is decoded during vehicle entry, only the core identifying fields — year, make, model, doors, seats, and fuel type — are automatically populated; engine, body type, drivetrain, and transmission are no longer overwritten by VIN data and remain under the agent's control.
Fixed
- Corporate Accounts — Cash Receipts Ledger: Direct Bill payments and refunds recorded against a company were not appearing in that company's Cash Receipts ledger — all transactions, including refund lines, now display correctly and the outstanding balance on the Account Summary tab matches the Cash Receipts totals.
- Vehicles — Vehicle Selection: An issue that caused incorrect behavior when selecting vehicles in certain workflows has been resolved.
- Vehicles — VIN Catalog Adoption: When scanning or entering a VIN that resolves to a make or model not yet in your catalog, the system previously displayed an error and required manual re-entry — the make and model are now automatically added to your catalog and pre-selected so the vehicle form can be submitted immediately.
- Misc Charges — Zero-Price Validation: Misc charges with no pricing configured could previously be saved, creating zero-rate charges on contracts — the system now requires at least one rate to be set and highlights the missing input if you attempt to save without pricing.
- Customers — Country Field: The Country field in the Add Customer form now accepts keyboard input immediately on focus without requiring a click first, and searching by ISO code such as "US" or "GB" now correctly surfaces the matching country.
- Rental Agreement Flow — Contextual Wording: Loading messages and driver confirmation toasts in the Rental Agreement workflow now correctly display "rental agreement" instead of "reservation" when working on checkout, check-in, or edit agreement flows.
Added
- Customer & Company Profiles — Taxable Status Change Warning: Toggling the taxable flag on a customer or company profile now shows a confirmation dialog listing all open reservations and contracts linked to that record, so agents can review the pricing impact before the change is saved.
Changed
- Contract Pages — Header Renamed to Contract Details: The page title across the check-out, check-in, and counter check-out flows now reads "Contract Details" instead of "Reservation Details", more accurately reflecting the document being created.
- Counter Check-Out — Vehicle Search No Longer Requires a Class Selection: The Search for Vehicle button in the counter check-out flow is now always active — a vehicle class no longer needs to be selected before the search can be initiated.
- Counter Check-Out — Automatic Redirect to Print Contracts After Completion: Completing a counter check-out or check-in now navigates directly to the Print Contracts page with the agreement number pre-loaded, so agents can immediately print or email the document without an additional search step.
- Company Billing Profile — Searchable Dropdowns for Country, State, and City: Address fields on the company billing profile now use searchable dropdown selectors instead of free-text inputs, with automatic clearing of dependent fields when a parent selection changes.
- Counter Check-Out — Driver Changes and Cancellation Locked After Payment: Once a payment is collected during a counter check-out session, driver edits and removals are blocked to prevent accidental changes; cancelling the session at that point automatically voids the most recent non-voided payment to keep the transaction clean.
- Counter Check-Out — Rented As Field Restricted by Privilege: The Rented As vehicle class field during check-out is now disabled for agents who do not hold the required privilege, preventing unauthorised overrides of the contracted vehicle class.
Fixed
- Additional Drivers — Driver Promotion Corrected: Promoting a secondary driver to primary on a rental agreement now saves correctly.
- Vehicle Fleet — Class Filter Results Corrected: The vehicle class filter on fleet and reservation search screens now returns the correct matching results.
- Additional Driver — Charge Amount Corrected: The additional driver charge is now calculated and displayed correctly on rental agreements.
- Counter Check-Out — Duplicate Driver Entry Resolved: Adding a driver through the counter check-out wizard no longer creates a duplicate driver entry on the contract.
- Vehicle Management — Import and Export Restored: Importing and exporting vehicle records now completes successfully without errors.
- Check-Out — Driver Charges Corrected: Driver-related charges in the checkout billing summary are now correctly reflected and applied to the contract.
Added
- Vehicle Revenue & Profitability — Revenue Charts: Two new chart panels now appear on the Vehicle Revenue & Profitability report — a horizontal bar chart showing Revenue and Utilization Percentage by Vehicle Group, and a stacked bar chart comparing Revenue versus Costs — giving fleet managers a visual summary of performance alongside the data table.
- Vehicle Revenue & Profitability — Detailed Revenue Breakdown: Revenue figures in the Vehicle Revenue & Profitability report can now be split into individual columns for Time & Mileage, CDW, Fuel, and Tax charges, available as opt-in fields under the Revenue & Charges group in the field selector.
- Vehicle Revenue & Profitability — Advanced Calculation Filters: Four new filters — Include Open Contracts, Include Sold Vehicles, Pro-Rate Revenue, and Accrual Method (Cash, As-of-date, or Due-date) — are now available on the Vehicle Revenue & Profitability report, giving users finer control over which rentals are factored into the results.
- Location Performance — New Operations Report: A new Location Performance report is now available under Operations, showing per-vehicle fleet metrics grouped by vehicle class with class subtotals and a grand total row, including columns for Days On Rent, utilization percentage, revenue per day, and Misc. Charges; the Location filter supports selecting multiple locations simultaneously.
Changed
- Vehicle Revenue & Profitability — Multi-Select Location and Class Filters: The Location and Class filters on the Vehicle Revenue & Profitability report have been upgraded from single-value to multi-select dropdowns, so users can include multiple locations or classes in a single report run.
- Vehicle Revenue & Profitability — Filter Help Tooltips and Collapsible Charts: Filter description text has moved from inline notes into help-icon tooltips beside each label, and the charts section is now collapsible so users can focus on the data table when preferred.
Fixed
- Vehicle Revenue & Profitability — Missing Vehicles in Filtered Results: Some vehicles were incorrectly excluded from the Vehicle Revenue & Profitability report when using the Location or Class filter, because a redundant case-sensitive check was silently dropping vehicles that the initial query had already returned — all matching vehicles now appear in results as expected.
Added
- Vehicle Options Catalog — Factory Option Codes: Administrators can now build a tenant-scoped library of vehicle option codes (such as navigation systems, sunroofs, and trailer hitches) under Business Setup, and fleet managers can assign or remove those codes from any vehicle profile via a new Factory Options tab — giving every team a permanent, searchable record of each vehicle's installed features.
- Rental Counter — Pickup and Return Time Validation: When setting rental start and end times at the counter, invalid hour entries are now caught and blocked before submission, preventing out-of-range time values and keeping rental period calculations accurate.
- Time & Mileage Rates — Duplicate Rate Action: A new Duplicate action on each rate row opens the rate creation form pre-filled with the source rate's pricing configuration but with Location, Product, and Vehicle Class left blank, so rate managers can quickly create a new rate combination without re-entering all pricing fields from scratch.
Changed
- Vehicle Profile — Unified View and Inline Editing: The vehicle detail page now shares a single layout for viewing and editing, mirroring the customer profile experience — General, Finance, and Custom Fields sections live directly on the profile page with an inline Edit button and a fixed save toolbar, replacing the previous separate edit page; existing bookmarks to the old edit URL are automatically redirected.
- Time & Mileage Rates — Single-Select Dropdowns When Editing: Editing an existing rate now uses single-select dropdowns for Location, Product, and Vehicle Class, making it explicit that changes apply only to that specific rate row rather than across all classes or locations simultaneously.
Fixed
- Time & Mileage Rates — Tier Cascade Corrected for Non-Optimal-Value-Pricing Rates: T&M rates without Optimal Value Pricing now correctly step down through regular tiers from largest to smallest — a 10-day rental on a weekly+daily rate now charges 1 week + 3 days instead of always rounding up to 2 full weeks.
- Time & Mileage Rates — Multi-Class Apply No Longer Fails: Applying a T&M rate across multiple vehicle classes at once no longer silently returns a 400 error — the rate now saves successfully to all selected classes in a single action.
- Vehicles — Equipment Usage: An issue preventing equipment usage records from displaying or functioning correctly on vehicle profiles has been resolved.
Added
- Reservations & Checkout — Rate Plan Access Code: Rate plans can now be protected with a private access code — rates assigned a code are hidden from the rate selection list until the agent enters the matching code, preventing use of restricted or negotiated rates without authorization during reservation creation and counter checkout. When reopening an existing reservation, the access code is pre-filled automatically so the previously selected locked rate remains qualified without re-entry.
- Reservations — Tax-Exempt Removal Warning: Removing the primary driver or the attached company currently responsible for a reservation's tax-exempt status now triggers a confirmation dialog warning that taxes will be restored; removing drivers or companies from non-tax-exempt reservations continues without interruption.
- Vehicles — Commission Status Tracking: A new Commission Status field is now available on the vehicle profile's General tab, allowing staff to tag each vehicle as None, Pending, Reported, Paid, or Excluded for franchise commission reporting workflows including HUF, SixSense, and BBARS.
- Configuration — Vehicle Commission Statuses Management: A new Vehicle Commission Statuses section is now available in the Configuration Settings sidebar, giving administrators full control over the commission status options that appear throughout the vehicle profile — including the ability to create custom statuses beyond the five built-in values.
Changed
- Reservations — Rate Disqualification Modal: When a rate plan access code change causes the currently selected rate to lose eligibility, the disqualification modal now only offers the option to switch to the most qualified available rate — keeping a disqualified rate is intentionally blocked for code-triggered disqualifications, while date and location changes continue to offer the existing keep-or-replace choice.
- User Management — Privileges Tab: The Privileges tab now shows only privileges that have a complete backend implementation, removing non-functional toggles that had no effect when switched on, so administrators see an accurate and actionable list of configurable permissions.
Fixed
- Reservations — Rate Disqualification Modal on Edit Load: The rate disqualification modal no longer appears incorrectly when opening an existing reservation in edit mode and API responses arrive out of order.
- User Management — Privilege Changes Reflected Immediately: An administrator who updates their own privileges now sees the changes applied to their active session without needing to reload the page.
Added
- Message of the Day — Expanded Page Targeting: The MOTD configuration form now supports five additional page destinations — Counter Check-Out, Counter Check-In, Checkout, Check-In, and Contract Modify — giving staff the ability to direct informational messages to those specific screens.
Changed
- Rental Agreement Report — Status Filter Refined: The "Void" option has been removed from the Status filter on the Rental Agreement report since no rental agreement can carry that status; the filter now offers only the four valid states — Open Contract, Pending Open, Closed Contract, and Void Contract — eliminating a selection that previously always returned zero results.
- Message of the Day — Cleaner Form Labels and Location Display: The priority type label for critical alerts has been shortened to "Critical", and the location selector in the MOTD form now shows location codes only rather than the full code-and-name format, making the list more compact and easier to scan.
Fixed
- Vehicle Inventory — Search Selections Preserved Across Navigation: Filters and selections made in the vehicle inventory screen are now correctly retained when navigating away and returning to the page, preventing users from losing their in-progress setup.
- Message of the Day — Location Dropdown Now Populates: The location selector in the MOTD configuration form now loads all available locations reliably, resolving a case where the list appeared empty.
- Message of the Day — Type and Priority Fields No Longer Overlap: The Type and Priority fields in the MOTD creation form are now displayed side by side correctly, and the Type dropdown no longer renders beneath other elements on screen.
- Message of the Day — Counter Check-Out Trigger Restored: MOTD messages targeted at the Check-Out page now correctly appear when staff navigate to the Counter Check-Out screen, which was previously not triggering message display.
- Interface — Visual Fixes: Several minor display inconsistencies across screens have been corrected, improving layout stability in affected areas.
Added
- Vehicle Inventory — A session lifecycle bar now appears at the top of the Vehicle Inventory screen, allowing ADMIN and MANAGER users to open, close, reopen, and reconcile inventory sessions; the bar displays the current session status (OPEN, IN_PROGRESS, CLOSED, or RECONCILED) at all times.
- Vehicle Inventory — Scanning a vehicle now accepts an optional physical odometer reading; if the entered value differs from the system record by more than 100 miles, a variance badge is shown on the vehicle card and the discrepancy is tallied in the session report.
- Vehicle Inventory — A Discrepancy Report is now available for the active session, listing missing, extra, mismatched, and odometer-variance vehicles, with an Export CSV button for off-system reconciliation.
- Cash Receipts — The Credit Memos section header on the Cash Receipts page and the company's Cash Receipts tab now shows a "Total Memo Balance" summing all available and partially-applied credit memos.
- Subrogation Report — The report can now be filtered by a date-of-loss date range.
Changed
- Vehicle Inventory — Session lifecycle actions (open, close, reopen, and reconcile) are now restricted to ADMIN and MANAGER roles; STAFF users can still scan vehicles but the session management buttons are hidden from their view.
- Cash Receipts — The action icon on each receipt history row has been changed from a trash icon to an undo icon, more accurately reflecting that the action voids the receipt rather than permanently deleting it.
Fixed
- Rate Selection — When no rates are configured for the selected vehicle class, the rate dropdown now shows an inline amber warning with a direct link to the rate configuration page, instead of silently disabling with a vague placeholder.
- Cash Receipts — The AR balance in the company panel now shows the live balance, matching the values displayed on the Company Summary and Billing tabs.
- Vehicle Inventory — Attempting to open a second active inventory session for the same location now shows a clear conflict error instead of a generic failure message.
- Vehicle Inventory — Attempting a restricted session action without the required role now shows a descriptive message specifying which role is needed, instead of a generic 'Forbidden resource' error.
- Claims — Several display issues in the Claims section have been corrected, improving the consistency of claim records as they appear in the interface.
- Coming Soon — Display and behavior issues with the Coming Soon feature have been resolved.
Fixed
- Vehicle Import — Initial Status Now Required: When importing vehicles using the bulk import template, rows without an Initial Status now produce a clear per-row validation error instead of silently defaulting to Available, ensuring import issues are visible and correctable before any records are saved.
- Vehicle Import — Historical In-Service Dates Accepted: Vehicle import rows with in-service dates in the past are now accepted and stored as provided; previously, any past date caused every row in the file to fail with a date-validation error.
- Vehicle Import — Long Color Names No Longer Rejected: Exterior and interior color values of up to 50 characters are now accepted during vehicle import, resolving failures for real-world color names such as "Lunar Silver" or "Medium Light Stone".
- Rental Agreements — Time & Mileage Rate Lines: Corrected an issue where rate line items were not rendering correctly on Time & Mileage rental agreements.
- Reservations — Return Date Preserved on Focus: When honoring a past reservation or editing a rental agreement, clicking into the return date field no longer clears it to a blank placeholder — the original date is preserved so agents can make deliberate corrections rather than re-entering the date from memory.
Added
- Vehicle Fleet — Vehicles with an expiring or expired registration or inspection certificate now display a yellow 'Doc Expiring' or red 'Doc Expired' status pill on fleet cards and in a new Documents column in the fleet table view, giving the fleet team at-a-glance visibility into document health without opening each vehicle profile.
- Vehicle Fleet — An inline alert on the Edit Vehicle page's License Information section updates live as the expiration date is changed, showing an amber 'expiring soon' or red 'expired' warning before the record is saved.
- Checkout — A document-expired modal now blocks vehicle selection at checkout across all three entry flows (standalone, counter, and dashboard/reservation). Agents who hold the OVERRIDE_EXPIRED_VEHICLE_DOC privilege see a 'Proceed Anyway' option; those without it see a Cancel-only dialog.
- NHTSA Recalls — A new Recalls dashboard under Maintenance lists all active recall matches with severity filters, an ingest-progress indicator, last-run timestamp, and a manual 'Run ingest now' button. Each vehicle profile also gains a Recalls tab showing the last NHTSA check date and a per-vehicle 'Check now' trigger.
- NHTSA Recalls — Fleet cards now display an amber or red recall badge when a vehicle has an active Warn or Ground recall, allowing staff to identify affected units at a glance. Vehicles with a Ground ('Do Not Drive') recall are automatically moved to In Maintenance status and revert automatically when the recall is cleared.
- NHTSA Recalls — Checkout is blocked for recalled vehicles: Ground recalls show a hard-block dialog with only a Cancel option; Warn recalls show an amber dialog requiring staff to tick a customer-notice acknowledgement before proceeding.
- Customers — When a customer with an expired driver's license is selected for a rental, a warning dialog appears. Agents with the RENT_EXP_DL privilege see an 'Override & Select' button; those without it see an acknowledgment-only message directing them to a manager.
- Rental Agreements — When a rental is finalized with an expired-DL override, a pinned amber warning banner is added to the rental agreement header, recording the override, the driver's name, and the license expiration date as a permanent audit trail.
- Reservations — When a pickup location is not yet synced to Self-Inspection, an amber modal now blocks rental agreement creation and provides a 'Check integration' button that navigates directly to the Self-Inspection settings tab. The in-progress draft is preserved in session storage so no data is lost during the fix.
Changed
- Payments — The combined 'Add Deposit / Issue Credit' button on the Reservations page and Counter Check-in Summary is replaced by two explicit buttons: 'Add Deposit' (always visible) and 'Issue Refund' (visible only when a credit balance exists). The refund modal opens with a read-only amount, excludes Adyen as a payment option, and submits the amount as a negative value.
- Customers — Expired driver licenses no longer hard-block customer profile creation or editing. The restriction is now enforced at the rental-selection step via a privilege-gated warning dialog, and the eligibility warnings section refreshes immediately after a customer save without requiring a page reload.
- Maintenance — Recall alerts in the Maintenance Alerts table are now labelled 'NHTSA Recall {campaign}' with severity-appropriate styling, and a new 'NHTSA Recalls' filter chip lets staff narrow the list to recall-related alerts only.
Fixed
- Security — Users no longer see data belonging to other tenants. The Location Code dropdown in T&M Rate Scope no longer surfaces cross-tenant locations, location data is cleared on logout, and switching impersonated sessions no longer carries over cached locations from the previous tenant.
- Rental Agreements and Reservations — Creating a rental agreement or reservation no longer fails with 'No active transaction number range configured' when a location-specific range exists but no global fallback is set. The system now falls back to any active range for the same record type.
- Customers — Active customers were silently re-blacklisted each time their profile page was refreshed. Blacklisting is now an explicit operation only and no longer occurs on page load.
- Check-in — The navigation controls and the Review/Submit button are now blocked when an outstanding balance (positive or negative, greater than \.01) exists, preventing accidental submission with an unresolved balance. An inline credit alert is shown in the Review/Submit step when the reservation carries a negative balance.
- Reservations — The Self-Inspection location sync check now shows a modal (previously a dismissible toast) so agents cannot bypass the block. The Integrations settings page pre-selects the Self-Inspection tab automatically when navigated to from this modal.
Added
- Physical Inventory — Full Session & Scan Workflow: Managers can now open, track, and reconcile dedicated inventory sessions per location with a full lifecycle audit trail (Open → In Progress → Closed → Reconciled). Each scan captures odometer and custom counter readings (engine hours, cycles, or any operator-defined metric) alongside system values, flags variances above the configured threshold for supervisor review, and records any units not found in the system as unresolved entries so nothing is silently dropped before sign-off.
- Promotions — Full Rental Window Validation: Applying a promotion code now checks that both the pickup and return date fall within the promotion's active date range. Previously, a promo could be applied even when the return date extended past the promotion's end date.
- Promotions — Live Re-Validation When Booking Details Change: During new reservation creation, applied promotions are automatically re-checked whenever rental dates or vehicle class are updated — promotions that no longer qualify are removed with a warning so pricing stays accurate as the booking evolves. Editing an existing saved contract is intentionally unaffected.
- Promotions — Specific Rejection Reasons: When a promotion code exists but does not apply to the current rental, the system now explains why — such as wrong vehicle class or wrong product type — instead of showing a generic 'code not found' message.
Changed
- Reservations & Walkup RAs — Return Date Defaults to Tomorrow: New rental agreements and reservations now pre-fill the return date and time to tomorrow at the same pickup time, and the number-of-days field defaults to 1. Agents no longer need to manually enter the return date for every new short-term booking. Existing saved bookings are unaffected.
- Promotions — Vehicle Class Dropdown Shows All Active Classes: The vehicle class list in the Add Promo Code form now loads all active classes regardless of which product is selected, fixing an empty dropdown for products such as TRUCK and EQUIPMENT.
- Promotions — Per-Row Remove Action: The Promotions dialog now shows a remove icon on each row, replacing the single top-level Remove button. Agents can delete individual promotions without having to select a row first, and the table adds horizontal scrolling for wide datasets.
- Vehicles — Status Dropdown Uses Statuses Management Labels: The Status field on the new vehicle form now shows the human-readable descriptions and colour-coded badges configured in Statuses Management instead of raw system codes. Statuses that do not apply to a brand-new vehicle (On Rent, Sold) are excluded, and the list is ordered to match the admin page.
Fixed
- Tenant Provisioning — New Accounts Now Fully Initialised on Creation: Creating a new tenant now guarantees all four default form templates (Rental Agreement, Invoice, Non-Revenue, Reservation) are set up as part of the same operation. If any step fails, the creation is rolled back entirely — preventing partially-configured accounts that previously required manual intervention to repair.
- Tenant Provisioning — Account Creation Was Failing on Certain Installations: New tenant creation was returning an error on environments that lacked a specific legacy data record, a regression introduced in April. All environments can now create new tenants successfully.
- Tenant Provisioning — Default Form Templates Were Blank in Production: Default form templates were being generated empty in production due to an incorrect internal path resolution. Templates are now correctly populated in all environments.
- Application Startup — Server No Longer Stalls When Background Job Service Is Unavailable: The application server now starts normally even when the background job service cannot be reached, instead of hanging indefinitely on startup.
- Setup Wizard — Status Configuration Warning No Longer Repeats After First Setup: The warning prompting users to configure required statuses was reappearing on every login even for tenants who had already done so manually. The check now correctly recognises both user-created and system-generated statuses, so the prompt is suppressed once the required statuses are in place.
- Reservations — On-Rent Vehicles No Longer Appear in Vehicle Search: The vehicle search no longer shows units that are currently out on rent, preventing agents from accidentally selecting an unavailable vehicle. Units due back before the requested pickup date still appear as available.
- Reservations — Vehicle Class Labels Corrected and Upgrade/Downgrade Selections Preserved: The 'Vehicle Class' and 'Rented As Vehicle Class' fields are now correctly labelled and no longer overwrite each other on save or reload. Upgrade and downgrade selections are preserved correctly across edits, and the upgrade/downgrade indicator now appears consistently on all booking paths.
- Reservations / Counter — Driver Completeness Check Now Includes Licence Fields: Contract creation blocked by a 'drivers incomplete' warning now clearly identifies every missing field — including Licence Number, Licence State, and Expiration Date — for each affected driver. Previously, missing licence information was an invisible blocker with no actionable error message.
Added
- What's New Page: A new /releases page gives every user a full, scrollable history of all product versions. A sticky sidebar highlights the release you are currently reading as you scroll, and each version has a permanent link you can share directly.
- Version Badge Quick-View: Clicking the version number in the sidebar now opens a compact popover showing the three most recent releases, each with a direct link to its entry on the What's New page.
- Misc Charges — Bracket Pricing Grid: When configuring a misc charge that uses a time-based pricing method (24-Hour, Calendar Day, or Modified 24-Hour), a new Tiers checkbox reveals a bracket pricing grid. Agents can now enter separate Hourly, Daily, Weekly, and Monthly rates for a single charge — for example, charge $5/hour up to $20/day up to $80/week. Unchecking the box collapses the grid and reverts the charge to a single flat rate, keeping straightforward charges uncluttered.
- Vehicle Maintenance Alerts — Custom Counter Support: Maintenance alert thresholds can now be tied to a vehicle's custom counter (such as engine hours, cycles, or any operator-defined reading) in addition to standard odometer mileage. When the counter crosses a configured critical threshold the alert fires and, if set to Ground, automatically changes the vehicle's status to In Maintenance.
Changed
- Release Notes — Always Available Offline: Release notes are now bundled with the application at build time instead of being fetched from GitHub at runtime. Notes load instantly, work in restricted network environments, and no longer require a GitHub token in the build pipeline.
- Misc Charges — Per-Tier Rate Storage: Each misc charge template now stores a distinct rate for every time bracket (Hourly, Daily, Weekly, Monthly) rather than a single override value. This is the data foundation that powers the new bracket pricing grid and ensures historical rental records are not affected when a template is later edited.
- Reservations — Cancellation Flow Overhauled: The cancel modal now calculates the balance against actual payments received rather than outstanding charges. A live Balance to Reconcile line must reach zero before the Confirm button enables — preventing accidental cancellations that would leave unreconciled payments on the record. The no-show fee pre-fills automatically to match the total paid, so for a standard no-show the agent can confirm in a single click.
- Reservations — Charges Cleared on Cancellation: When a reservation is cancelled all rental charges are removed so the booking settles at exactly $0. If a no-show fee was applied, only that fee remains, equal to the amount already collected.
- Statuses — Generate Defaults Button Removed: The Generate Defaults button has been removed from the Statuses configuration page. Default statuses are now provisioned automatically the moment a new tenant is created, making the manual button redundant and eliminating a potential source of accidental overwrites for tenants who have already customised their statuses.
Fixed
- Statuses — Startup Warning Modal Appears Repeatedly: The Required Statuses Missing modal was appearing on every login for tenants who had manually created their own statuses (such as 'Available' or 'Active') instead of using the system-generated defaults. The check now recognises both user-created and system-created statuses, so the modal no longer appears once the required statuses exist regardless of how they were created.
- Reservations — Tax Exemption Not Cleared When Driver Removed: Removing a tax-exempt primary driver from an existing reservation left the booking permanently tax-exempt — taxes never returned even after a non-exempt driver was added. The exemption is now cleared correctly when the exempt entity is removed.
- Reservation Charges — Events Routed Through Structured Logging: Internal charge-calculation events were written directly to stdout, bypassing the application's log aggregation pipeline. All charge events now flow through the standard structured logger so they appear in monitoring dashboards alongside other reservation activity.
- Reservation Charges — Soft Delete Policy Enforced: Two places in the reservation charge service were permanently deleting records instead of marking them as deleted. Charge records are now soft-deleted in line with the rest of the platform, preserving audit history.
- Loyalty Calculation — Customer Data No Longer Written to Logs: Full customer records (including personal details) were being serialised and written to the application log during loyalty calculations. The log statements have been removed.
Added
- Non-Exemptable Override Checkbox: The NonExemptable flag is now exposed in the Exemptions tab of the misc-charge template editor. When checked, the charge applies even when the customer or company is tax-exempt (tax types only: SALES_TAX, FEDERAL_TAX, OTHER_TAX).
- checkInDate sent to qualify endpoint: Reservation page now sends the return date to the misc-charge qualification endpoint so the backend MinMaxDaysExemptionValidator can compute rental days correctly.
Fixed
- classesExempt master-toggle gate removed: The class-exemption list now drives the gate directly, fixing an issue where configured class exemptions were silently disabled.
Fixed
- Initial Vehicle Status — Status Dropdown: The Status dropdown on the new vehicle form now displays the human-readable description (e.g. "Available") instead of the raw status code.
- Payments — Optimistic Refund Record Shape: Optimistic refund records aligned with the expanded PaymentDto shape, preventing undefined field access on immediate UI updates.
- Build — manualChunks Restored in Cloudflare Config: vite.config.build.ts was missing manualChunks, causing Cloudflare Pages builds to emit one monolithic bundle. Chunk split is now correctly applied.
Changed
- Bundle Chunking: Production builds now split into vendor chunks (react, ui, data, forms, utils, exceljs, zxing, adyen) instead of one monolithic bundle for faster page loads.
- Caching: Removed aggressive staleTime: 0 and refetchOnMount overrides from claim hooks and contract search — data now uses the global 5-minute cache default.
Fixed
- Debug Leaks: Removed console.log of auth URL and cookie headers from NewSolAuthStore; removed stray debug log from apiClient.
Added
- Loyalty Program — Full Implementation: Customer enrollment, tier management, points earning at check-in, reward redemption during checkout (modal + calculate API integration), loyalty sidebar card in ReservationsPage, and loyalty detail view inside the customer profile page.
- Scheduled Reports — BullMQ Cron System: Create, edit, pause/resume, and delete scheduled report configurations. Reports run automatically on daily/weekly/monthly schedules and are exported to S3 as PDF or CSV with email delivery to configured recipients.
- 10+ New Report Types: Revenue Summary, Fleet List, Location List, Reservations, Fleet & Equipment Overview, Equipment Transactions, Vehicle Revenue & Profitability, Tax & Fees Audit, Tax-Exempt Rentals, CC Payments, UK P11D — each with fields, KPIs, filters, and export support.
- Company Management — Full Tab Suite: Billing (credit status, limits, payment terms), Rates (rate codes, vehicle classes, charge overrides), Contacts (CRUD with primary contact), Contracts (CRUD with status, renewal type), Preferences (insurance, fuel, vehicle), and Activity (rental history, customers, notes, payments) tabs on the company profile.
- Multi-Step Company Create Wizard: 4-step wizard (Company Info → Primary Contact → Physical Address → Review) with 10 additional backend fields and reusable Stepper/StepNavigation components.
- Reservation Locking: Pessimistic per-tab locking prevents concurrent edits. Other users see a blocking modal with the lock holder's name. Cross-tab takeover notification invalidates the losing tab instantly.
- Maintenance Alert System: Mileage-triggered alerts checked at check-in; alerts with Ground action auto-change vehicle status to inMaintenance. Date-based alerts run via BullMQ cron with digest email and Pester/Ground actions.
- Privilege Enforcement: RENT_TO_BLACKLIST (bypass blacklist check), RENT_UNDERAGE (bypass age restriction), and RESERVE_SPECIFIC_VEHICLE (restrict specific-unit booking) privilege checks in reservation creation and updates.
- Equipment Tab on Reservation Details: Shows all equipment transactions with asset ID, type, daily rate, status, dates, and counter readings. Summary footer shows total daily rate of checked-out equipment.
- Primary Driver Tax Exemption: When primary driver's preference is tax-exempt, taxes are skipped in rate calculation and RRM.Taxable is set accordingly.
- Primary Driver Age Restriction: Validates driver age against pickup location min/max driver age settings on reservation create/update.
- Per-Tab Reservation Locking: lockSessionId (per-tab UUID) prevents the same user from silently re-acquiring their own lock across browser tabs.
- Flat-Fee Tax Support: Tax templates configured with calcMeth = FLAT now correctly apply rateUnit as a fixed dollar amount instead of silently producing zero.
- Inline Driver Search: Agents type a name or phone directly in the driver section without opening a modal. Auto-promotes first additional driver when primary is removed.
- Cross-Tab Lock Takeover Notification: Take Over in one tab immediately invalidates the other tab's lock via localStorage storage event.
Changed
- Loyalty moved into Customer Profile Page: Standalone Loyalty Page removed. Loyalty management lives inside each customer's profile with a compact banner, enrollment modal, and full detail view with AnimatePresence transitions.
- Loyalty Rewards Restructured: Replaced FREE_RENTAL_DAY/FREE_ADDON with TIME_AND_MILEAGE/MISC_CHARGE reward types. Rewards now link to child items (rate heads or misc charge templates) with per-item discount configuration.
- Reports rebuilt with strategy pattern: Each report is a self-contained strategy class. Frontend uses a Map-based registry with auto-registration via side-effect imports.
- Mileage charge integrated into rate calculation: odometerIn parameter added to the calculate endpoint; mileage charges persisted/cleaned up automatically during rate calculation instead of at check-in submission.
- Reservations — Corporate Account Integration: Real searchable CompanySelector fetches live corporate accounts. Auto-applies company rental preferences (fuel level, vehicle class, coverages) on selection.
- Company Rates Tab — Searchable Dropdowns: Default Rate Code, Rate Codes, and Vehicle Classes use SearchableSelect/MultiSelect fetching from live APIs. Charge Override modal uses a single searchable charge selector.
- Report Date Range No Longer Persists: Reports always open with default field visibility instead of loading saved preferences. Scheduled report link pre-applies that schedule's configuration for the session only.
- Customer statusType Badges in Statuses Management: Color-coded badges for canRent, vip, inactive, restricted, banned customer status types in the Statuses Management UI.
- Equipment Return Always Sets Available Status: Status dropdown removed from the return modal — returned equipment is always set to available.
- Equipment Tab Always Visible: Equipment tab shows an empty state instead of being hidden when no equipment transactions exist.
Fixed
- User-Level Privileges Ignored: hasPrivilege() now queries the UserPrivilege table as a fallback, so privileges assigned directly to a user (not via a role) are honored.
- Loyalty Redemptions Not Merged in /calculate: DB-saved and payload redemptions now always merged by rewardId — editing an existing contract correctly reflects both.
- Auto-Applied Misc Charges Not Visible: Auto-applied misc charges from rate calculation are now merged into selectedMiscCharges so they appear in the UI table with an "Auto" badge.
- Tax Types Double-Processed as Misc Charges: Auto-apply queries no longer return tax-type templates (SALES_TAX, FEDERAL_TAX, OTHER_TAX), preventing taxes from being calculated twice.
- Checkout Allows No Specific Vehicle for Class-Only Reservation: Guardrail added to block checkout submission when no specific vehicle is selected for a class-only reservation.
- Rate Cleared When Checking Out Class-Only Reservation: Reverted to keeping vehicleSelectionMode as 'class' for class-only reservations, fixing rate clearing regression.
- Duplicate Equipment on Reservation Edit: Idempotency check moved before both equipment steps; hasEquipmentChanged compares against original transactions instead of always returning true.
- Equipment Removal Not Persisted in Edit Mode: Removing equipment in edit mode now calls DELETE endpoint before updating local state.
- Vehicle Not Available When Editing Existing Contract: excludeCommonId parameter added to validateVehicleStatusForCheckout() so the current vehicle passes validation when editing.
- Check-In Balance Validation Missing Mileage Charge: Mileage charges now exist in RentalCharge before validateFullPaymentForCheckin runs.
- Check-In Return Date/Time Not Set to Now: Return Date and Time now default to today/current time in CheckIn mode and auto-update every 15 seconds.
- Charges Not Recalculated When Dates Change During Check-In: updateFull() detects date/time changes and triggers full charge recalculation automatically.
- Scheduled Reports Not Firing Automatically: Frontend now sends browser timezone with schedule payload; backend uses it for BullMQ tz parameter, fixing wrong-UTC-offset cron misfires.
- Loyalty Discounts Not Deducted from Outstanding Balance at Check-In: Backend validateFullPaymentForCheckin() now queries LoyaltyRedemption records and subtracts total discount from balance due.
Added
- Generate Defaults Dialog: Statuses Management page now shows a "Generate Defaults" button for vehicles and customers tabs, listing statuses to be created or repaired before calling POST /statuses/generate-defaults.
- Pre-flight Status Check: After terminal settings initialization, if the tenant is missing the required "available" vehicle or "active" customer status, a blocking modal redirects to the Statuses page. Super Admin accounts bypass the check.
Added
- Payments Timeline: PaymentsTimelineSection added to both the Reservations list collapsible and Charges & Payments detail tab. Shows a 2×2 totals grid (Charged / Authorized / Captured / Refunded), per-row lifecycle mini-timeline, refund-chain indentation, category badges, provider/card chips, and preserved Void/Refund/Delete actions via render-prop.
Changed
- Charges & Payments tab redesigned: Rate card compressed, charges collapsed into one card with inline section headers, Promotions + Loyalty merged into a Discounts section.
Added
- Company Management Overhaul: Financial data now reconciles across Summary, Billing, and Cash Receipts tabs. Cash Receipts rewritten with per-invoice allocation, partial payments, and overpayment credit memo creation.
- UserLabel component resolves user IDs to full names in Summary, sidebar, and Companies list.
- Tour Company type added to company type options.
Changed
- Contract modal now includes a Contact picker defaulting to Primary. Confirmation dialogs replaced with styled AlertDialog components. Payment type dropdown reads from live /payment-types API.
Added
- Inline Driver Search (#430): Agents type a name or phone directly in the driver section without opening a modal. Keyboard navigation supported. Already-selected drivers show a "Selected" badge; blacklisted drivers show "Blacklisted". Removing the primary driver auto-promotes the first additional driver.
Fixed
- Reservations — Rental Reason & Tax-Exempt (#436): Missing selectedRentalReason destructuring caused a runtime ReferenceError on the Reservations page. Tax-exempt identity now sent to server for live resolution.
- Misc Charges — Calc Method Reset (#437): Switching "Calculate By" now clears all rate fields so stale amounts from a prior calc method cannot persist on save.
Fixed
- Rate Seasons (#435): Day is now a dropdown with dynamically computed valid options per month/year. Auto-clamp on month/year change prevents impossible dates. "Save Date Range" disabled while any error is present.
- Rate Rules (#438): Booking and Departure Start Dates are now editable in create mode. End Date ≥ Start Date enforced via picker min, inline error, and submit guard.
Changed
- Dashboard Background Polling (#442): Fleet status, operational load, class availability, and revenue pipeline hooks no longer poll every 60 s when the browser tab is unfocused — eliminates 20+ unnecessary API requests per minute.
- Customer Dashboard Parallelization (#442): Customer details and contracts now fetched concurrently with Promise.all, saving ~500 ms per load.
Fixed
- Transaction Number Location Guard (#441): Availability check now passes the active terminal locationCode to the backend. Tenants with per-location ranges no longer see false "blocked" warnings.
- TypeScript Build Errors (#443): Contract modal no longer triggers spurious API calls before an account exists. Rate season date validation type mismatch resolved. Driver search uses the correct narrowed Customer type.
Added
- Searchable rate dropdown in reservation rate selection.
- Inline change-vehicle flow in reservation mode, replacing the older popup workflow.
Changed
- Reservation pricing, rate lines, misc charges, and summary UI refined for a cleaner workflow.
- Misc charges can now be surfaced earlier in the reservation flow without forcing initial rate selection.
Fixed
- Misc charges qualification no longer incorrectly requires a selected rate.
- Blacklist-check and related reservation UI follow-up issues cleaned up.
Added
- Direct unit-number lookup in reservation vehicle selection.
- Inline vehicle picker grid for reservation workflows — faster vehicle assignment without leaving the reservations form.
Fixed
- Vehicle-selection cleanup and small follow-up issues resolved as part of the new inline picker rollout.
Added
- Vehicle management dialogs for in-fleet confirmation, status changes, and in-service date workflows.
- New fleet-management actions in the vehicles data-table.
Fixed
- Fleet-management follow-up issues found during review and merge reconciliation.
Changed
- Vehicle import/export template handling centralized to make template maintenance easier.
- Vehicle import logic improved to better support template-driven workflows.
Fixed
- Vehicle management UI now guards invalid empty selection values more safely.
- Coming Soon flows now show clearer toast-based error feedback.
Added
- Rental Agreement Master Report: New report with dashboard deep-links into the rental agreement reporting flow.
Changed
- Report detail, summary, and shell components improved for a clearer reporting experience.
Changed
- Fuel pricing labels now use clearer Markup and Discount terminology.
- Promo code and transaction-number dialogs polished for a smoother workflow.
Fixed
- T&M Rate now correctly enforces Rate Rule as a required field.
- Reservation flows now warn when driver date of birth is missing and block submit until required data is present.
- Sidebar menu items now refresh correctly after permission updates.
- Add Line and Duplicate Rate Lines buttons no longer misfire due to shimmer overlay.
Added
- Manual Notification UI: Full manual notification flow — template/event selection, compatible RRM search, message preview, and send confirmation.
- PDF System Template Cloning: Browse system-level PDF templates and clone them into your tenant's PDF Builder.
- Test Suite — 158 Unit + 22 E2E: Customer and vehicle unit tests (Vitest); Playwright E2E rewrite; super-admin test runner redesigned with Backend/Frontend tabs.
Fixed
- Rate Field Formatting: Leading zero suppression in misc charge flat/unit rate input fields.
- UI Enhancements: "Start Rental" and "Start Reservation" dashboard buttons unified with + icon.
- Misc Charges — Taxable Flag: Taxable toggle added to misc charge form; flag respected in charge display and tax calculation.
- Reservations — Charges Display: Misc charges and taxes combined into a single summary section.
- Transaction Numbers — Modal Layout: Cleaned up; redundant helper text removed.
Added
- Tenant Initial Admin Creation: New tenant provisioning flow creates a default admin user automatically.
- Claim Notes & Linked Inspections: Claims detail now supports attaching notes and linking inspection records.
- CC Payments UI Redesign: Two-panel layout, ReportFilterPanel with responsive mobile Sheet drawer, status badges in table, header export actions.
Changed
- PromoCode Form: Refactored to use availableCalcMethods for calculation method selection instead of a hardcoded list.
- GitHub Actions Workflow: Added preprod environment option; removed sensitive env variables from workflow definitions.
Fixed
- TypeScript Build Errors: Resolved compile errors in PromoCodeFormModal and TenantModal.
Added
- Super Admin Impersonation: Super admins can now impersonate any tenant user account to diagnose issues.
- Dashboard Location Integration: Location-specific data integration for dashboard widgets.
- DataTable Export: Export functionality with enhanced components across data tables.
Changed
- UserAvatar Component: Added loading state during logout for better UX.
- Reservations Page: Extracted dialog components for better modularity.
Fixed
- Claim issues with editing and adding expenses and vehicles.
Added
- Customer Management: Customer eligibility alert component with enhanced customer information handling.
- PDF Builder: Complete PDF builder feature with drag-and-drop canvas, undo/redo functionality, and entity name handling.
- User Role Management: Role management features with simplified user roles display.
- Claims Management: Claims workflow with repair orders attachment and equipment store integration.
- Payments Feature: New payments functionality for rental transactions.
- Signiphi Billing (Super Admin): Client management features for Signiphi billing administration.
Changed
- Rate Qualification: Improved rate selection logic.
- Vehicle Fleet: Enhanced filters and added odometer/fuel level tracking during checkout.
- Settings Pages: Unified design across all settings pages using shared component.
- Misc Charges: Grouped misc charge rows and time/mileage rows for better organization.