BookYourPTO

Changelog

Stay up to date with the latest changes, improvements, and bug fixes in BookYourPTO.

BookYourPTO v1.0.14 release notes

v1.0.14

This release tightens up two areas that have been quietly accumulating rough edges: how billing limits are explained to admins, and how the app handles users whose personal timezone differs from their organisation's. It also adds plan-aware gating around the Document Templates feature so Free-plan customers see a clear upgrade path instead of empty screens, and closes a handful of quota loopholes that could let a single request push an org past its plan limit.

New Features

  • Per-user timezone, end-to-end across booking modals — Following on from v1.0.13's per-user timezone groundwork (searchable picker, profile field, calendar grid highlighting), every booking and date-picker modal now resolves "today" against the viewer's resolved timezone rather than UTC or the browser clock. A Vancouver-based employee in a Toronto-based org now sees their own calendar day pre-filled in Book Time Off, Group Booking, Lock Dates, the expense Add Meal / Add Travel cards, the document upload / assign / template send / personal upload modals, and the onboarding welcome DOB picker. The same rule used for calendar-grid highlighting is now applied everywhere date pickers default to "today".
  • Document Templates usage card on /billing — The Plan Usage panel gains a dedicated "Document Templates" row that shows your current template count against your plan cap (Free 0, Pro 5, Business 50, Enterprise unlimited). On Free plan the card shows an inline "Not available on the Free plan — Upgrade to use templates" prompt instead of an unhelpful 0 / 0 progress bar.
  • Per-counter reset timer on /billing — Each monthly metric (Documents, Receipts Scanning, Projects, Expense Claims) now displays when it next resets — "Resets in 7 days" up close, "Resets Jun 22" further out. The label is computed in the org's timezone and renders only on plans where the counter actually resets (Free is lifetime for most metrics).
  • Subscription-anniversary monthly resets — Counters now roll over on the date Stripe charges your card next, not on the 1st of the calendar month. An org that subscribed on the 22nd resets on the 22nd. Previously a customer who subscribed mid-month would get their counter reset on the 1st (sometimes only days after they paid), which was both confusing and inconsistent with how their invoices arrive.
  • Plan-aware Document Templates landing pages — /documents/templates and /documents/templates/create now render a clean upgrade card for Free-plan organisations explaining what Templates do and what unlocks them, instead of an empty list / disabled wizard. The data fetch is skipped on Free plan so there's no loading flicker before the upgrade card appears.
  • "Pro" lock badges on Template and Bulk Send entry points — The Templates and Bulk Send buttons on the documents toolbar, the "Use a Template" / "Bulk Send" items in the Start menu, and the Document Templates jump button on the onboarding / offboarding settings header now wear a small "Pro" lock pill on Free plan. Tooltips explain the dependency (e.g. "Pro plan required — depends on Document Templates" on Bulk Send).
  • Bulk Send page gated on Free — /documents/bulk-send now renders an upgrade card explaining that Bulk Send needs Document Templates, instead of letting Free users build a bulk-send wizard they can't submit.
  • Add Task modal explains the upgrade requirement inline — The "Attach Document Template" picker inside the onboarding / offboarding Add Task modal now swaps its dropdown for an inline upgrade prompt when the org is on Free, so admins know why the picker is empty and can still save the task without a template.

Improvements

  • State-aware trial-ending banner — The "Trial ending soon" banner previously fired a single "Upgrade Now" call-to-action for every trialing org, even when the trial was set to auto-convert and the customer had a card on file. The banner now picks one of two paths: a soft, no-CTA informational banner for trials that will auto-convert ("Your Pro subscription will start automatically on May 29. Cancel anytime."), and an actionable warning with a Reactivate CTA only for trials the customer has actively cancelled. Matches the pattern Stripe, Linear, and Notion all use.
  • /billing usage display now lines up with the actual server gate — Several monthly counters were computing "this month" using the server's local timezone (UTC in production), while the receipts counter already used the org's timezone. Around month boundaries the billing UI could show a different counter from what the gate enforced at submit time. Documents, Projects, Expense Claims, and the usage display all now bucket by the same boundary the gate uses, so the page and the API agree.
  • TypeScript hygiene in the Leave Request modal — Replaced a handful of string.split(':').map(Number) destructures with a shared hmToMinutes helper, resolving the "possibly undefined" complaints TypeScript was raising on every time-slot arithmetic. The /api/leaves/schedule client fetch was also switched from params to query to match how the Nitro handler reads its arguments and to resolve a type-instantiation-depth error.

Bug Fixes

  • Booking modal no longer prefills tomorrow's date in the evening — In any timezone west of UTC, opening the Book Time Off floating action button after roughly 5 PM local time used to pre-fill the date pickers with the next day's date (the UTC day had already rolled over even though the user's calendar still showed today). All booking, expense, document, and onboarding date pickers now resolve "today" in the user's resolved timezone, so the picker always matches the day the user sees on their wall clock.
  • Documents Templates feature respects the documented Pro / Business cap — The endpoint for creating reusable templates previously ran only a role check and never consulted the per-plan quota. A Pro org could create more than the documented 5 active templates. The endpoint now enforces the cap (Free 0, Pro 5, Business 50, Enterprise unlimited) and the billing page surfaces the live count.
  • Template send and direct upload can no longer overshoot the document quota — A single template send or document upload that creates multiple Document and DocumentAssignment rows is now pre-checked against the projected delta (1 file + N signers) rather than just the current count. An org at 49 / 50 documents sending a template to 10 signers used to push the count to 60; that request is now rejected up front with a message explaining how many units would be consumed.
  • Receipt-scan counter is now race-free — Two simultaneous receipt scans submitted at the per-month boundary used to both pass the limit check before either incremented, allowing one extra AI call past the cap. The counter is now reserved atomically through a single conditional update; the second concurrent request is rejected before the AI provider is called, and a failed AI call refunds the reserved slot so the user isn't billed against their quota for a scan that couldn't be read.
  • Dashboard "Book time off" picker honours the per-user timezone override — Earlier in the release the calendar grid started highlighting "today" in the viewer's per-user timezone, but the dashboard's Book Time Off modal was still pulling the user's timezone from a JWT-and-localStorage cache that isn't refreshed after a profile edit. The modal now sources the timezone from the same bootstrap data the grid uses, so a user who changes their personal timezone sees the change reflected everywhere immediately.
  • Group Booking and Lock Dates modals are now timezone-aware — Both modals defaulted "today" using UTC, which mismatched the highlighted day on the calendar in any negative-offset timezone late in the day. They now use the same per-user-then-org resolution rule as Book Time Off.
  • Add expense (Meal / Travel) date pickers no longer pre-fill UTC today — Same class of bug, same fix: meal and travel expense cards prefill the date in the viewer's resolved timezone instead of UTC.
  • Document upload, assign, and template send minDate honours the org timezone — The minimum-due-date constraints on document upload modals are now computed in the org's resolved timezone so users in negative-offset zones can still pick "today" late in the evening.
  • Onboarding DOB picker max bound is now in the viewer's timezone — Same fix applied to the onboarding welcome modal's max attribute on the date-of-birth input.