Changelog — FormsPro
All notable changes to this app are recorded here. Newest entries on top.
[2026-05-16]
- Fixed "Add staff" not submitting. The Add-staff form in Settings was opening but its fields and button were silently unclickable. The form is now fully interactive.
- Re-adding a revoked staff member with the same phone now works. Previously the database's unique-phone rule would block it with an opaque error; now the original record is revived with the new name, role, and PIN.
- "Generate forms with AI" prompt in Settings. New collapsible card under your form endpoint section. Open it, click Copy AI prompt, paste into ChatGPT / Claude / Gemini, fill in the bracketed parts (what the form is for, whether it takes a payment), and the AI gives back ready-to-paste HTML wired to your FormsPro endpoint. Covers both regular forms and booking forms — the prompt teaches the AI all the hidden fields, the response-handling JS, and the redirect-to-checkout flow.
- Archive abandoned bookings. Submissions stuck in Awaiting payment can now be archived from the detail sheet. The new "Archive abandoned" button moves the row to the Archived tab and marks the checkout link as failed, so a stale payment link can't reactivate the booking weeks later.
- Tighter booking-form snippet. The example HTML in Settings → Online Payments now gives the form a unique id, disables the submit button while processing, falls back to a thank-you message for non-payment forms, and shows a friendly error if the request fails. The previous snippet used
querySelector('form') which would break on pages with multiple forms.
Internal
api/submissions.php update-status action now writes payment_status='failed' alongside status='archived' when transitioning a pending_payment row, so the verify-paystack/verify-stripe guards (WHERE payment_status='pending') reject any late completion attempts.
- The "Generate forms with AI" prompt lives in [apps/formspro/views/partials/settings-sections.php](views/partials/settings-sections.php) as a
<details> block; the textarea is populated by __renderAiPrompt() so the prompt text always includes the live workspace endpoint URL.
- Booking / payment forms. Forms can now collect money before the submission lands in your inbox. Add three hidden fields to any form (
_payment="1", _amount, _description) and after the submitter clicks Send, FormsPro routes them to a clean checkout page where they pay with the card. Submissions show as Awaiting payment until the charge confirms; once paid, they appear in the inbox with a green Paid badge that includes the amount. Abandoned checkouts live in a new Awaiting payment tab so you can see who started but didn't complete. An optional _currency field lets a single form take payments in different currencies; otherwise it uses your workspace default.
- Online Payments settings. New Settings card for picking your provider (PayStack or Stripe) and saving your keys. Only one provider is active at a time; the other's keys can stay saved so you can switch with a dropdown. A copy-paste booking-form snippet is included so you can wire up a form in under a minute.
- Staff card. A Staff section in Settings where you can register team members with phone + PIN. Sign-in for staff is coming in the next release — adding people now means they'll be ready when it ships.
Internal
- New
payment_* columns on form_submissions (payment_status, payment_amount, payment_currency, payment_description, payment_provider, payment_reference, payment_token, paid_at) plus a unique index on payment_token. The lazy migrator adds them automatically on next request for existing installs.
- New
staff table mirrors the post-2026-05-11 DryCleanPro pattern (phone, pin_hash, role, status, entity_id). Legacy users table is left in place per the additive-only schema rule and marked deprecated in the schema comment.
- Payment plumbing lives in [apps/formspro/lib/payments.php](lib/payments.php), duplicated from PropertyPro's
lib/payments.php with an fp_ prefix so FormsPro stays standalone (uninstalling PropertyPro must not break booking forms). Mirror is tagged in the file header for an annual audit.
- New endpoints:
POST /api/payments/init-stripe, POST /api/payments/verify-paystack, POST /api/payments/verify-stripe, all CSRF-exempt and gated on the per-submission payment_token. Verify endpoints use a WHERE payment_status='pending' guard with rowCount() check for idempotent notification dispatch.
- New public route
/checkout in [apps/formspro/views/public/checkout.php](views/public/checkout.php), declared in app.json's public_routes. Loads Paystack or Stripe JS based on the active provider; uses app_public_url() so custom-domain installs render the same flow on the tenant's domain.
- Staff CRUD lifted verbatim from [apps/drycleanpro/api/staff.php](../drycleanpro/api/staff.php).
- New helper
fp_send_payment_receipt_notifications() in helpers.php fires NTFY/SMS/destination fan-out after a payment verifies. Adds a payment_received event toggle alongside the existing new_submission / status_change.
[2026-05-14]
- Added a Watch/Read tab on the tutorial page — every lesson now has a written version alongside the video for users who prefer to read.
[2026-04-20]
- Destinations — new Settings section that forwards every form submission to external services. Pick the ones you want (generic Webhook, EmailJS, FormToWeb), enter credentials, and submissions fan out automatically after each new arrival. Every delivery attempt is logged with success/failure — visible in the new "Recent delivery log" panel right under the destination fields, so you can see at a glance whether a destination is working or failing. Each destination has a Send test button that uses your most recent real submission (or a sample, if you haven't received any yet) to verify credentials without waiting.
- Demo and subscribe now work out of the box — finished migrating the app to Pancho's UUID identity model so Try Demo no longer errors with 'We could not start the demo'.
Internal
- Added the
tenant_members table to schema.sql (backed by the platform's _per_user_app_bootstrap_owner() hook).
- Destinations fan-out runs inside the submit handler after the existing ntfy/SMS notifications. New helpers
send_formspro_webhook(), send_formspro_emailjs(), send_formspro_formtoweb(), and formspro_fan_out() live in helpers.php; delivery outcomes are written to audit_log with actions destination_success / destination_failed. Existing NTFY + Twilio SMS plumbing is unchanged.
[2026-04-17]
- Updated subscription price to $47/month (USD) and ₦25,000/month (NGN); setup fee is now $497 (USD) and ₦450,000 (NGN)
[Baseline] — 2026-04-16
- Existing feature set captured as the baseline. Subsequent changes will be prepended above this entry.