39. Gawd Portal
Pixally CRM☑️ Login & Dashboard
Functional Requirements Document (FRD) Gawd Portal — Login & Dashboard
Module Name: Gawd Portal — Login & Dashboard Version: 2.0 Created Date: March 27, 2026 Last Updated: July 21, 2026
1. Module Overview
Module Name: Gawd Portal — Login & Dashboard
Purpose: The Gawd Portal is a super admin portal exclusively built for the Pixally owner to manage all platform-level operations, monitor subscriber activity, track revenue metrics, and oversee the health of the Pixally CRM business. The Login & Dashboard module serves as the secure entry point and the central command center, providing a consolidated, at-a-glance view of subscriber metrics, revenue performance, CRM migration tracking, overdue invoices, and active user activity across the entire platform.
Business Goals:
- Provide the Pixally owner with a single, secure access point to monitor and manage the entire subscriber ecosystem.
- Deliver consolidated KPI visibility across subscriber acquisition, retention, churn, and revenue streams, refreshed on every page load.
- Enable quick identification of overdue invoices, expiring payment methods, and CRM migration statuses to support proactive intervention.
- Centralize revenue analytics (MRR, ARR, YTD, subscription-level breakdown) for informed business decision-making.
- Track active user engagement to assess platform adoption and identify at-risk accounts.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all dashboard data, interact with all widgets, change CRM migration statuses, navigate to all sub-modules, access notification settings, toggle dark mode, use global search, access all tabs and "View All" pages.
Customer Support Executive
No Access
The Customer Support role does not have access to the Dashboard module. Their access is limited to the Subscribers listing page in view-only mode (covered in FRD #9).
Access Restrictions:
- The Gawd Portal is a single-user login platform restricted to the Pixally owner only.
- Access may be further restricted by IP whitelisting, ensuring only designated computers can access the portal.
- There is no sign-up functionality; the Pixally owner account is pre-provisioned.
- The portal is accessible via a unique, separate URL that is not publicly listed or discoverable.
3. User Flow
3.1 Login Flow
3.1.1 The user navigates to the Gawd Portal URL in their browser.
3.1.2 The system displays the Sign In page with the Pixally logo, a full-height image on the left panel, and the login form on the right panel titled "Sign in to Gawd Mode."
3.1.3 The user enters their email address in the "Email address" field.
3.1.4 The user enters their password in the "Password" field (minimum 6 characters).
3.1.5 The user may click the eye icon to toggle password visibility between masked and plain text.
3.1.6 The user clicks the "Sign in" button to submit the login form.
3.1.7 The system validates the email and password against stored credentials.
3.1.8 If the credentials are valid and the IP is whitelisted, the system authenticates the user and redirects them to the Dashboard page with the "Subscriber Overview" tab selected by default.
3.1.9 If the credentials are invalid, the system displays an inline error message below the respective field without clearing the form.
3.1.10 If the IP address is not whitelisted, the system displays an error message indicating that access is restricted from the current location.
3.2 Portal Shell & Navigation Flow
3.2.1 Upon successful login, the system loads the portal shell consisting of the left sidebar navigation, top header bar, and the main content area.
3.2.2 The left sidebar displays the Pixally logo at the top, followed by the navigation menu items: Dashboard, Subscribers, Payments, Reports, Lead Management, Referral, and Discounts.
3.2.3 The sidebar displays a "Help Center" link at the bottom, which opens the external Pixally Help page in a new browser tab when clicked.
3.2.4 The user can collapse or expand the sidebar by clicking the collapse/expand toggle icon at the top of the sidebar.
3.2.5 The top header bar displays the global search bar (Cmd+K / Ctrl+K shortcut), dark mode/light mode toggle, notification bell icon with unread badge count, and the user's profile avatar.
3.2.6 The user clicks the global search bar or presses Cmd+K (Mac) / Ctrl+K (Windows) to open the search overlay.
3.2.7 The system displays the global search overlay where the user can type a subscriber's name, agency/company name, or email address to search.
3.2.8 The system returns matching subscriber results as the user types, and the user can click on a result to navigate to that subscriber's profile page.
3.2.9 The user clicks the dark mode/light mode toggle icon to switch the portal's visual theme between light and dark modes.
3.2.10 The system applies the selected theme across the entire portal and persists the preference for future sessions.
3.2.11 The user clicks the notification bell icon to open the in-app notification center dropdown/panel.
3.2.12 The system displays a list of recent notifications organized by category, with unread notifications highlighted and the badge count reflecting the total unread count.
3.2.13 The user clicks on the profile avatar to access profile-related options including the Notification Settings page.
3.3 Dashboard Flow
3.3.1 The system loads the Dashboard page with the "Subscriber Overview" tab selected by default.
3.3.2 The user sees four tab options at the top of the Dashboard: Subscriber Overview, Free Trial Sign-ups, Cancelled Subscribers, and Paid Subscribers.
3.3.3 The user clicks on any tab to switch the view, and the system updates the KPI cards and Growth Trends chart to reflect the selected tab's data while keeping the bottom sections (Revenue Metrics, Revenue by Subscriptions, Switch-from-CRM Setup Deal, Recent Overdue Invoices, and Active Users) identical across all tabs.
3.3.4 The user scrolls through the Dashboard to review all widgets and data sections displayed on the page.
3.3.5 The user clicks the "View All" button on the Switch-from-CRM Setup Deal section, and the system navigates to the full CRM migration list page.
3.3.6 The user clicks the "View All" button on the Recent Overdue Invoices section, and the system redirects to the Payments page with the "Overdue" tab pre-selected.
3.3.7 The user clicks the "View All" button on the Active Users section, and the system redirects to the Subscribers page with the "Active" tab pre-selected.
3.3.8 The user clicks on the status dropdown in the Switch-from-CRM Setup Deal section to change a migration entry's status directly from the Dashboard widget.
3.3.9 The system updates the status and reflects the change immediately in the widget.
3.4 Notification Settings Flow
3.4.1 The user navigates to the Notification Settings page from the profile menu.
3.4.2 The system displays the notification preferences grouped into four categories: New User Activity, Payments & Billing, Account Status & Plan Changes, and Security & Account Integrity.
3.4.3 For each notification event, the user enables In-App, Email, or both; selecting "None" turns off both channels for that event.
3.4.4 The system saves the preference immediately upon selection (or upon clicking a save button, if applicable) and applies the setting to all future notifications.
4. Functional Logic
4.1 Login Page
- The Login page is the sole entry point to the Gawd Portal and is hosted on a unique, separate URL that is distinct from the Agency Portal, Client Portal, and Contractor Portal.
- The page layout consists of a left panel displaying a full-height editorial-style image with a "Photo by Iris & Light" credit overlay at the bottom, and a right panel containing the Pixally logo and the login form.
- The login form title reads "Sign in to Gawd Mode" and contains two input fields: "Email address" and "Password."
- The "Password" field includes an eye icon toggle that allows the user to switch between masked (dots) and plain text display of the entered password.
- The placeholder text for the Password field reads "6+ characters" to indicate the minimum password length requirement.
- The "Sign in" button is styled as a full-width yellow/gold primary action button and is always enabled regardless of field state.
- When the user clicks "Sign in," the system validates all fields on the client side first, then sends the credentials to the server for authentication.
- If any field is empty, the system displays an inline error message below the respective field prompting the user to fill it in.
- If the email format is invalid, the system displays an inline error message: "Please enter a valid email address."
- If the credentials do not match, the system displays an error message: "Invalid email or password. Please try again."
- If the user's IP address is not on the whitelist, the system blocks the login attempt and displays an error message: "Access denied. Your IP address is not authorized to access this portal."
- There is no "Forgot Password" or "Sign Up" functionality on this login page; account recovery is handled directly by the Pixally technical team.
- There is no "Remember Me" checkbox; the session is managed via secure session tokens with a defined timeout policy.
- Upon successful authentication, the system redirects the user to the Dashboard page with the "Subscriber Overview" tab selected by default.
- The system creates and stores a secure session token to maintain the authenticated state across page navigations.
4.2 Portal Shell — Left Sidebar Navigation
- The left sidebar displays the Pixally logo at the top, followed by vertically stacked navigation menu items.
- The sidebar navigation items in order are: Dashboard, Subscribers, Payments, Reports, Lead Management, Referral, and Discounts.
- Each navigation item displays an icon and a text label when the sidebar is in the expanded state.
- When the sidebar is collapsed, only the icons are displayed, and the text labels are hidden.
- The currently active page is highlighted in the sidebar with a distinct background color and bold text/icon styling to indicate the user's current location within the portal.
- Clicking any navigation item loads the corresponding module page in the main content area without a full page reload (or with a standard page navigation, depending on the technical architecture).
- A "Help Center" link is displayed at the bottom of the sidebar with a help/question-mark icon.
- Clicking "Help Center" opens the external Pixally Help page (on the Pixally website) in a new browser tab.
- The sidebar includes a collapse/expand toggle button (chevron icon) at the top-right edge of the sidebar.
- Clicking the toggle button collapses the sidebar to show only icons, and clicking it again expands the sidebar to show both icons and labels.
- The sidebar collapse/expand state persists across page navigations within the same session.
4.3 Portal Shell — Top Header Bar
- The top header bar is fixed at the top of the page and remains visible across all modules within the portal.
- The header bar contains, from left to right: the global search bar, the dark mode/light mode toggle, the notification bell icon with badge, and the user's profile avatar.
4.3.1 Global Search (Cmd+K)
- The global search bar is positioned on the left side of the header and displays a search icon with a "Cmd+K" shortcut hint badge.
- The user can activate the search by clicking the search bar or pressing Cmd+K (Mac) / Ctrl+K (Windows) from anywhere within the portal.
- The global search is restricted to subscribers only; it searches by subscriber's name (agency owner name), company/agency name, and email address.
- As the user types in the search field, the system performs a real-time search and displays matching results in a dropdown below the search bar.
- Each search result displays the subscriber's name, company name, and email address.
- Clicking on a search result navigates the user directly to that subscriber's profile page within the Subscribers module.
- If no results match the search query, the system displays a "No results found" message within the search dropdown.
- Pressing Escape or clicking outside the search overlay closes it and returns focus to the main content area.
4.3.2 Dark Mode / Light Mode Toggle
- The toggle icon displays a sun icon for light mode and a moon icon for dark mode, indicating the current active theme.
- Clicking the toggle switches the entire portal's visual theme between light mode and dark mode.
- The dark mode applies a dark background with light text across all pages, charts, tables, cards, and widgets within the Gawd Portal.
- The selected theme preference is persisted across sessions and is applied automatically on the next login.
4.3.3 Notification Bell
- The notification bell icon is displayed in the header with a numeric badge indicating the count of unread notifications.
- Clicking the bell icon opens the in-app notification center as a dropdown panel or overlay.
- The notification center displays a list of notifications in reverse chronological order (newest first).
- Each notification shows the event description, timestamp, and read/unread status.
- Clicking on a notification marks it as read and navigates the user to the relevant module or record (e.g., clicking a "Payment failed" notification navigates to the Payments module).
- The unread badge count decrements in real-time as notifications are read.
- The Pixally owner can configure notification preferences from the Notification Settings page (see Section 4.7).
4.3.4 Profile Avatar
- The profile avatar displays the Pixally owner's profile picture or a default avatar placeholder.
- Clicking the avatar opens a dropdown menu with options including: Notification Settings, and Log Out.
- Clicking "Log Out" ends the session, clears the session token, and redirects the user to the Login page.
4.4 Dashboard — Tab Structure
- The Dashboard page title "Dashboard" is displayed at the top of the main content area.
- Below the title, four horizontal tab buttons are displayed: Subscriber Overview, Free Trial Sign-ups, Cancelled Subscribers, and Paid Subscribers.
- The "Subscriber Overview" tab is selected by default when the Dashboard is loaded.
- Each tab has a visually distinct active state (filled/highlighted background) and an inactive state (outlined/transparent background).
- Clicking a tab updates only the top section of the Dashboard (KPI cards and Growth Trends chart) to reflect the selected tab's data.
- The bottom sections of the Dashboard (Revenue Metrics YTD, Revenue by Subscriptions, Switch-from-CRM Setup Deal, Recent Overdue Invoices, and Active Users) remain identical and unchanged regardless of which tab is selected.
- None of the dashboard data is real-time; all data is loaded/refreshed when the page is loaded or manually refreshed by the Pixally owner.
4.5 Dashboard — Tab-Specific Content
4.5.1 Subscriber Overview Tab
KPI Cards:
- Active Subscribers: Displays the total count of currently active subscribers (all statuses that have an active or paid subscription). Subscribers who have requested cancellation but whose paid term has not yet ended (status "Canceling") remain counted as Active Subscribers until their paid term actually ends, in line with industry-standard practice. Displayed with a person/group icon.
- New Paid Subscriber (24hr): Displays the count of new subscribers who have completed a paid subscription in the last 24 hours (from 12:00 AM Eastern). Displayed with a person-plus icon.
- Churn Rate: Displays the churn rate as a percentage, calculated as: (Number of subscribers whose paid term ended in the last 30 days ÷ Total number of subscribers at the start of that 30-day period) × 100. A cancellation is counted toward churn on the date the subscriber's paid term actually ends (the date their access lapses), not on the date they click cancel. For example, a yearly subscriber who cancels in month 9 is counted in churn at month 12 when their paid term ends. This follows the industry-standard approach of recording churn when a subscriber actually stops paying. Displayed with a percentage/trend icon. The churn rate card displays a tooltip on hover explaining the formula: "Percentage of subscribers whose paid term ended in the last 30 days, relative to the total subscribers at the start of that period. Cancellations are counted when the paid term ends, not when cancellation is requested."
Growth Trends Chart:
- Displays a line chart showing new subscriber registrations over the past 12 months.
- The X-axis represents months (January through December).
- The Y-axis represents the number of new sign-ups.
- The chart title reads "Growth Trends" with a subtitle "New subscriber registrations over the past 12 months."
- The data includes all subscriber registrations (free trial + paid) combined.
Revenue Metrics (YTD):
- This section title reads "Revenue Metrics (YTD)" with a subtitle "Monitor recurring revenue, subscription income, and transaction fees to track financial performance over time."
- Displays three metric cards:
- Total YtD Revenue: The total revenue generated year-to-date from all sources (subscriptions + transaction fees). Displayed in USD currency format (e.g., $123,480.00).
- MRR (Monthly Recurring Revenue): The total amount of predictable recurring subscription revenue generated monthly. The MRR card includes an Actual/Normalized toggle allowing the Pixally owner to switch between two views of the metric (defined below). Displayed in USD currency format.
- ARR (Annual Recurring Revenue): Projected annual recurring revenue, always calculated as MRR × 12. The ARR card includes an Actual/Normalized toggle mirroring the MRR card. Displayed in USD currency format.
- Each metric card displays a small line chart/sparkline beneath the value showing the trend over recent months.
- The MRR and ARR cards each provide an Actual / Normalized toggle so both values can be viewed on demand from the same card. The two views answer different business questions: Actual reflects what subscribers are paying right now (including temporary discounts), while Normalized reflects the steady-state price after temporary discounts expire.
MRR / ARR Calculation Logic:
- The following definitions apply per subscription (denoted i) at the measurement date (denoted t):
- list_price_monthly[i] is the current list price of the subscriber's plan expressed as a monthly equivalent.
- discount_monthlyi is the discount in effect at date t, expressed as a monthly equivalent.
- term_months[i] is 12 for annual plans and 1 for monthly plans.
- Annual plans are converted to a monthly equivalent before any calculation, using: monthly_equiv = total_contract_price ÷ term_months. For example, a $960/year plan paid upfront converts to $80/month even though the cash was collected as a single payment.
- Actual MRR represents what subscribers are paying right now, including any temporary discounts. It is calculated per subscriber as: actual_MRRi = list_price_monthly[i] − discount_monthlyi. The total actual MRR is the sum of actual_MRRi across all active subscribers at date t. Actual ARR is actual_MRR(t) × 12.
- Normalized MRR (also called Contracted MRR) represents the steady-state price after temporary discounts expire. It is calculated per subscriber as: normalized_MRRi = list_price_monthly[i] − permanent_discount_monthly[i], where temporary discounts are ignored but any permanent discounts are still deducted. The total normalized MRR is the sum of normalized_MRRi across all active subscribers at date t. Normalized ARR is normalized_MRR(t) × 12.
- The following rules apply to both Actual and Normalized methods: a subscriber is counted as Active as long as their paid term has not ended (pending-cancellation annual subscribers with status "Canceling" still count until their access ends). One-time fees, setup charges, non-recurring add-ons, and sales tax are excluded. Recurring add-ons are included at their recurring price. ARR is always MRR × 12 and is never the sum of cash collected or bookings. Free and 100%-discount accounts have an actual MRR of $0 but still count in the subscriber count, which correctly drags down average revenue per user.
- A derived metric, discount_burden(t) = normalized_MRR(t) − actual_MRR(t), represents the recurring revenue that will appear automatically as temporary promotional discounts expire (the "discount cliff"). This value falls out automatically when discounts are stored as fields and may be surfaced for the Pixally owner's planning.
Revenue by Subscriptions Chart:
- This section title reads "Revenue by Subscriptions" with an info icon (ⓘ) and a subtitle "Breakdown of revenue by plan type with trends over time."
- Displays a stacked bar chart showing revenue broken down by subscription plan type: Free, Basic, Pro, and Studio.
- The X-axis represents months (January through December).
- The Y-axis represents revenue in USD.
- A legend at the top-right displays each plan type with its corresponding color and total revenue amount (e.g., Free: $2.45k, Basic: $67.50k, Pro: $231.38k, Studio: $123.12k).
- Each bar shows the stacked contribution of each plan type for that month.
- Annual subscription revenue is divided by 12 and spread evenly across the 12 months of the subscription term rather than shown as a lump sum in the purchase month. For example, an annual subscription purchased in July 2026 has its revenue spread from July 2026 through June 2027. This ensures the chart reflects the true monthly trend of the business rather than being distorted by the timing of annual payments.
- Hovering over the info icon (ⓘ) displays a tooltip explaining that the chart includes subscription revenue, transaction fees, and extra seat revenue. The tooltip contains a clickable link that navigates the Pixally owner to the detailed breakdown in the Reports module (the Revenue Growth report showing the split across subscription, extra seat, and transaction fee revenue).
Switch-from-CRM Setup Deal:
- This section title reads "Switch-from-CRM Setup Deal" with a subtitle "Show users who qualified by sending last 2 months of receipts and track job setup completion."
- Displays a table with the following columns: User (agency name), Previous CRM, Contact Person (name and email with avatar), and Status.
- The "Status" column contains a dropdown on each row that allows the Pixally owner to change the migration status directly from the Dashboard.
- The available statuses are: "Waiting on Proof," "In Progress," "Ready to Setup," and "Completed."
- Each status is displayed with a distinct color-coded badge/tag.
- Agency owners who upload their last two months of invoices from a different CRM during sign-up or from the Dashboard stepper qualify for complimentary CRM data migration support from Pixally.
- The Dashboard widget displays a maximum of 3 recent CRM migration entries with a "View All" button in the top-right corner.
- Clicking "View All" navigates to a full-page listing with the same columns and status-change dropdown functionality.
- The migration process is manual; the Pixally team reviews the uploaded proof, performs the data migration, and updates the status accordingly.
Recent Overdue Invoices:
- This section title reads "Recent Overdue Invoices" with a subtitle "Stay on top of outstanding payments with a quick view of all overdue invoices."
- Displays a table with the following columns: Invoice Number (with expand/collapse chevron), Status, Subscriber (name, email, and avatar), Amount, Payment Date, and Reason.
- The Status column displays an "Overdue" badge in red for all entries in this widget.
- The "Reason" column shows the reason for the charge (e.g., "Monthly charge," "Additional seats"). If the system receives a failure reason from Stripe (e.g., "Insufficient funds," "Card declined"), this reason is displayed in the expanded row detail, not in the Reason column itself.
- The "Payment Date" column displays the date the payment was processed if applicable; if no payment has been made for the invoice, the column displays a dash ("–").
- All column headers support sorting (ascending/descending) by clicking the column header. A sort arrow (↓) is displayed next to each sortable column header. The default sort order is by Invoice Number descending (most recent first).
- Each row has a kebab menu (three-dot icon) for additional actions (actions are defined in the Payments FRD #3).
- The Dashboard widget displays a maximum of 6 recent overdue invoices with a "View All" button in the top-right corner.
- Clicking "View All" redirects the user to the Payments page with the "Overdue" tab pre-selected.
- Each row can be expanded by clicking the chevron icon to show additional payment details inline, including: Due Date, Reminder Sent (date of last reminder or "N/A"), Paid By (subscriber name), Payment Method (e.g., "Visa 8548"), Trace ID (transaction reference from Stripe), and a 3-step payment timeline (Charged → Processed → Deposited) with dates for each completed step. Only completed steps are highlighted with a green tick; pending steps remain unhighlighted.
- Clicking the chevron again collapses the expanded row back to the summary view.
Active Users:
- This section title reads "Active Users" with a subtitle "Track which users are currently active based on logins or recent activity across the platform."
- A user is considered "active" if the agency owner or any team member within that agency has logged in or visited any page across the entire portal. This includes activity from any user role (owner, admin, team member) within the agency's account.
- Displays a table with the following columns: Name & Company (with avatar, name, and company name), Status (Active badge), Projects (count of booked projects), Plan (plan name and price, e.g., "Basic $390/year"), Last Login (relative time, e.g., "2h ago"), Tickets Opened (count), and Subscription Length (e.g., "6 month," "3 month").
- The "Projects" column counts only the subscriber's booked projects. A project is counted as booked when at least one of its events is in a stage under the "Booked Stages" group (Proposal Signed, Deposit Paid, Planning, and any custom stages the subscriber has added under Booked Stages) or the "Post-Event Stages" group (Post Production, Completed, and any custom stages under Post-Event Stages) in the pipeline. Projects whose events are only in New Lead stages (New Lead, Follow-up, Proposal Sent, and custom lead stages), archived projects, and deleted projects are not counted. Because a project can contain multiple events, a project counts as long as at least one of its events qualifies; for example, a project with one event in a Booked stage and another event archived still counts as one. Hovering over the column header displays a tooltip clarifying that the count reflects booked projects only (from proposal-signed through post-event stages, excluding leads, archived, and deleted projects).
- All column headers support sorting (ascending/descending) by clicking the column header. A sort arrow (↓) is displayed next to each sortable column header.
- The table is sorted by "Last Login" in descending order (most recently active users first) by default.
- Each row has a kebab menu (three-dot icon) for additional actions (actions are defined in the Subscribers FRD #2).
- The Dashboard widget displays a maximum of 6 recent active users with a "View All" button in the top-right corner.
- Clicking "View All" redirects the user to the Subscribers page with the "Active" tab pre-selected.
4.5.2 Free Trial Sign-ups Tab
KPI Cards:
- Last 7 Days: Displays the count of new free trial sign-ups over the last 7 days on a rolling basis. Includes a percentage comparison indicator (green arrow up or red arrow down) showing the change versus the previous 7 days (e.g., "11.9% vs previous 7 days"). The comparison therefore measures the most recent 7 days against the 7 days immediately before them (a rolling 14-day window).
- Today: Displays the count of new free trial sign-ups today. Includes a percentage comparison indicator showing the change versus yesterday (e.g., "11.9% vs yesterday").
- Total (Lifetime): Displays the total cumulative count of all free trial sign-ups since the platform's launch. No comparison indicator is shown for lifetime metrics.
Growth Trends Chart:
- Displays the same line chart format as the Subscriber Overview tab, but filtered to show only free trial sign-up registrations over the past 12 months.
Bottom Sections:
- Revenue Metrics (YTD), Revenue by Subscriptions, Switch-from-CRM Setup Deal, Recent Overdue Invoices, and Active Users sections are displayed identically as described in Section 4.5.1.
4.5.3 Cancelled Subscribers Tab
Active / Pending Toggle:
- The Cancelled Subscribers tab includes a toggle at the top with two views: Active (default) and Pending.
- Active view: Shows cancellations that are counted when the subscriber's paid term has actually ended (their access has lapsed). This is the confirmed-cancelled view.
- Pending view: Shows subscribers who have clicked cancel but whose paid term has not yet ended (status "Canceling"). This lets the Pixally owner see who has requested cancellation so they can proactively reach out and attempt to retain them.
- The toggle affects the Last 7 Days and Today cards. The Total (Lifetime) card only reflects confirmed cancellations counted once the paid term ends; therefore, under the Pending view, the Total (Lifetime) card displays a dash ("–") because a lifetime count is not applicable to pending cancellations.
KPI Cards:
- Last 7 Days: Displays the count of subscription cancellations over the last 7 days on a rolling basis, scoped to the selected toggle view (Active or Pending). Includes a percentage comparison indicator showing the change versus the previous 7 days (e.g., "12.1% vs previous 7 days"). A red downward arrow indicates an increase in cancellations (negative trend), and a green upward arrow indicates a decrease. Under the Active view, a cancellation is counted on the date the subscriber's paid term ends; under the Pending view, it is counted on the date the subscriber clicked cancel.
- Today: Displays the count of subscription cancellations today, scoped to the selected toggle view. Includes a percentage comparison indicator showing the change versus yesterday.
- Total (Lifetime): Displays the total cumulative count of all confirmed subscription cancellations (counted when the paid term ends) since the platform's launch. Under the Pending view, this card displays a dash ("–").
Growth Trends Chart:
- Displays the same line chart format as the Subscriber Overview tab, but filtered to show only cancellation trends over the past 12 months.
Bottom Sections:
- Revenue Metrics (YTD), Revenue by Subscriptions, Switch-from-CRM Setup Deal, Recent Overdue Invoices, and Active Users sections are displayed identically as described in Section 4.5.1.
4.5.4 Paid Subscribers Tab
KPI Cards:
- Last 7 Days: Displays the count of new paid subscribers over the last 7 days on a rolling basis. A user who has paid for at least one month of subscription is counted as a paid subscriber. Includes a percentage comparison indicator showing the change versus the previous 7 days.
- Today: Displays the count of new paid subscribers today. Includes a percentage comparison indicator showing the change versus yesterday.
- Total (Lifetime): Displays the total cumulative count of all paid subscribers since the platform's launch, including subscribers who have since cancelled.
Growth Trends Chart:
- Displays the same line chart format as the Subscriber Overview tab, but filtered to show only paid subscriber registrations over the past 12 months.
Bottom Sections:
- Revenue Metrics (YTD), Revenue by Subscriptions, Switch-from-CRM Setup Deal, Recent Overdue Invoices, and Active Users sections are displayed identically as described in Section 4.5.1.
4.6 Dashboard — Data Refresh Behavior
- Dashboard data is not real-time; all metrics, charts, and tables are loaded when the page is initially rendered.
- Data refreshes when the Pixally owner visits the Dashboard page, reloads the page manually, or navigates away and returns.
- There is no automatic polling or live-updating mechanism for dashboard data.
- No "Last Updated" timestamp is displayed on the Dashboard.
4.7 Notification Settings
- The Notification Settings page is accessible from the profile avatar dropdown menu in the top header bar.
- The page displays a list of all notification events grouped into four categories. For each event, the Pixally owner chooses among three controls: None, In-App, and Email.
- In-App and Email are multi-select: the Pixally owner can enable both In-App and Email for the same event (by selecting both). Selecting "None" clears both In-App and Email for that event (no notification is sent through any channel).
- The selected control(s) are visually highlighted (e.g., with a filled/active border style). When both In-App and Email are enabled, both appear highlighted; "None" is not highlighted while either channel is enabled.
Category 1: New User Activity
- New free trial user signed up: Triggered when a new agency owner signs up for a free trial on the Pixally platform.
- Free trial user converted: Triggered when a free trial user purchases a paid subscription plan.
Category 2: Payments & Billing
- Pixally subscription payment successful: Triggered when a subscriber's subscription payment is successfully processed.
- Pixally subscription payment failed: Triggered when a subscriber's subscription payment attempt fails.
- Credit card expiring soon: Triggered when a subscriber's credit card on file is nearing its expiration date.
- New subscription receipt available: Triggered when a new subscription receipt/invoice is generated for any subscriber.
Category 3: Account Status & Plan Changes
- Account frozen due to non-payment: Triggered when a subscriber's account is suspended due to a failed payment exceeding the configured grace period.
- Subscription canceled: Triggered when a subscriber's subscription is canceled (either by the subscriber or by the Pixally owner).
- Subscription plan changed or renewed: Triggered when a subscriber upgrades, downgrades, or renews their subscription plan.
Category 4: Security & Account Integrity
- Suspicious login activity detected: Triggered when the system detects an unusual login pattern or attempt on any subscriber's account or on the Gawd Portal itself.
Notification Delivery Behavior:
- If "None" is selected for an event, no notification is sent through any channel for that event. Selecting "None" clears both the In-App and Email selections for that event.
- If "In-App" is enabled, the notification appears in the notification bell dropdown/panel within the Gawd Portal.
- If "Email" is enabled, the notification is sent to the Pixally owner's registered email address.
- In-App and Email can both be enabled for the same event. When both are enabled, the notification is delivered through both channels (it appears in the in-app notification center and is also emailed).
- Enabling In-App or Email automatically clears the "None" state for that event; conversely, selecting "None" clears both channels.
- Changes to notification preferences are saved immediately upon selection.
Default Notification Preferences (as per Figma design):
- New free trial user signed up → None
- Free trial user converted → None
- Pixally subscription payment successful → None
- Pixally subscription payment failed → In-App
- Credit card expiring soon → In-App
- New subscription receipt available → In-App
- Account frozen due to non-payment → None
- Subscription canceled → In-App
- Subscription plan changed or renewed → None
- Suspicious login activity detected → None
These defaults represent the initial state of each event. Because preferences are multi-select, the Pixally owner can add Email to any event already defaulting to In-App (or enable both on any event), and can turn any event off by selecting "None."
5. Field Details & Validations
5.1 Login Page Fields
Field Name
Field Type
Validation Rules
Email Address
Text Input
Required. Must be a valid email format (name@domain.com). Maximum 255 characters.
Password
Text Input (Masked)
Required. Minimum 6 characters. Maximum 128 characters. Masked by default with eye icon toggle for visibility.
Sign In Button
Button
Always enabled. Triggers client-side validation on click, then server-side authentication.
Password Visibility Toggle
Icon Button (Eye)
Toggles password field between masked (type="password") and visible (type="text") states.
5.2 Global Search Field
Field Name
Field Type
Validation Rules
Search Input
Text Input
No minimum character requirement to trigger search. Maximum 255 characters. Searches by subscriber name, company/agency name, and email address. Results display in real-time as the user types.
5.3 Dashboard KPI Cards (All Tabs)
Field/Metric
Data Type
Validation/Display Rules
Active Subscribers
Integer
Whole number, no decimals. Displays count of all currently active subscribers.
New Paid Subscriber (24hr)
Integer
Whole number. Counts new paid subscriptions from 12:00 AM Eastern of the current day.
Churn Rate
Percentage
Displayed with one decimal place (e.g., 3.2%). Calculated using the 30-day churn formula, counting cancellations on the date the paid term ends. Tooltip on hover explains the formula.
Last 7 Days (Free Trial / Cancelled / Paid)
Integer
Whole number. Rolling last 7 days, compared against the previous 7 days.
Today (Free Trial / Cancelled / Paid)
Integer
Whole number. Day starts at 12:00 AM Eastern.
Total (Lifetime)
Integer
Whole number. Cumulative count since platform launch.
Percentage Comparison
Percentage
Displayed with one decimal place. Green upward arrow for positive trend, red downward arrow for negative trend. Comparison period varies by metric (vs previous 7 days, vs yesterday).
Total YtD Revenue
Currency (USD)
Displayed with two decimal places and dollar sign (e.g., $123,480.00).
MRR
Currency (USD)
Displayed with two decimal places and dollar sign. Card includes an Actual/Normalized toggle. Actual = list price minus current (including temporary) discount; Normalized = list price minus permanent discounts only.
ARR
Currency (USD)
Displayed with two decimal places and dollar sign. Always calculated as MRR × 12. Card includes an Actual/Normalized toggle mirroring MRR.
5.4 Switch-from-CRM Setup Deal Fields
Field Name
Field Type
Validation Rules
User (Agency Name)
Text (Read-only)
Auto-populated from sign-up data.
Previous CRM
Text (Read-only)
Auto-populated from sign-up data (e.g., "HubSpot").
Contact Person
Text + Avatar (Read-only)
Displays name and email of the agency contact.
Status
Dropdown
Required. Options: "Waiting on Proof," "In Progress," "Ready to Setup," "Completed." Changeable by the Pixally owner from both the Dashboard widget and the View All page.
5.5 Notification Settings Fields
Field Name
Field Type
Validation Rules
Notification Preference (per event)
Multi-select Toggle Group
Required. Controls: None, In-App, Email. In-App and Email can both be enabled for an event; selecting "None" clears both. Defaults are pre-configured per the design.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Login
No explicit toast message; user is redirected to the Dashboard.
Valid email, password, and whitelisted IP.
System creates a session token and redirects to the Dashboard with the Subscriber Overview tab selected.
CRM Migration Status Change
"Status updated successfully."
Pixally owner changes the status dropdown value on a CRM migration entry.
The new status badge is immediately reflected in the table row on the Dashboard widget and/or the View All page.
Notification Preference Saved
"Notification preferences updated."
Pixally owner selects a new preference (None/In-App/Email) for any notification event.
The selected option is highlighted, and the preference is persisted immediately.
Dark Mode Toggle
No explicit message; theme changes instantly.
User clicks the dark/light mode toggle.
The portal theme switches immediately, and the preference is saved for future sessions.
Log Out
No explicit message; user is redirected to the Login page.
User clicks "Log Out" from the profile dropdown.
Session token is cleared, and the user is redirected to the Login page.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Empty Email Field
"Email address is required."
User clicks "Sign in" without entering an email.
Inline error displayed below the Email field. User must enter a valid email.
Invalid Email Format
"Please enter a valid email address."
User enters an email that does not match a valid email pattern (e.g., missing "@" or domain).
Inline error displayed below the Email field. User must correct the email format.
Empty Password Field
"Password is required."
User clicks "Sign in" without entering a password.
Inline error displayed below the Password field. User must enter a password.
Password Too Short
"Password must be at least 6 characters."
User enters a password with fewer than 6 characters.
Inline error displayed below the Password field. User must enter a longer password.
Invalid Credentials
"Invalid email or password. Please try again."
Email or password does not match stored credentials.
Inline error displayed below the form. Password field is cleared; email is retained. User must re-enter the correct credentials.
IP Address Not Whitelisted
"Access denied. Your IP address is not authorized to access this portal."
User attempts to log in from a non-whitelisted IP address.
Full-screen or prominent error message displayed. User must access the portal from an authorized IP address.
Account Locked (Excessive Failed Attempts)
"Your account has been temporarily locked due to multiple failed login attempts. Please try again after 30 minutes or contact the technical team."
User exceeds the maximum number of failed login attempts (e.g., 5 consecutive failures).
Login form is disabled for the lockout duration. User must wait or contact support.
Global Search — No Results
"No results found."
User types a query in the global search that does not match any subscriber name or company name.
Message displayed within the search dropdown. User can modify the search query.
CRM Status Change Failed
"Failed to update status. Please try again."
System encounters a server error while updating the CRM migration status.
Toast/inline error message displayed. The dropdown reverts to the previous status value. User can retry the action.
Notification Settings Save Failed
"Failed to save notification preferences. Please try again."
System encounters a server error while saving notification preferences.
Toast error message displayed. The selection reverts to the previously saved value. User can retry.
Session Expired
"Your session has expired. Please sign in again."
The user's session token has expired due to inactivity or timeout.
The user is redirected to the Login page. Any unsaved changes are lost.
Network / Connectivity Error
"Unable to connect to the server. Please check your internet connection and try again."
The user's browser cannot reach the server due to network issues.
Toast or banner error message displayed at the top of the page. Data on the page remains in its last loaded state.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
User attempts to access the Dashboard URL directly without logging in.
The system redirects the user to the Login page. After successful login, the system redirects to the originally requested page (or the Dashboard by default).
2
User opens the portal from a new IP address that is not whitelisted.
The system blocks the login attempt and displays the "Access denied" error message. No session is created.
3
Dashboard loads with zero subscribers (first-time setup).
All KPI cards display "0" values. Charts display empty states with placeholder axes. Tables display empty states with messages such as "No data available." The Revenue Metrics section shows $0.00 for all values.
4
Churn rate calculation when there are zero subscribers at the start of the period.
The system displays "0%" or "N/A" to avoid division-by-zero errors.
5
MRR and ARR calculation when there are no active paid subscribers.
Both Actual and Normalized MRR and ARR display "$0.00."
5a
A subscriber has status "Canceling" (clicked cancel, paid term not ended) when MRR/ARR is calculated.
The subscriber continues to be counted as active in both Actual and Normalized MRR/ARR until their paid term actually ends.
5b
All active subscribers are on a temporary 100% discount (Actual MRR = $0) but Normalized would be positive.
Actual MRR/ARR display "$0.00" while Normalized MRR/ARR display the full post-discount recurring value. The discount_burden equals the Normalized value.
5c
On the Cancelled Subscribers tab, the user toggles to the Pending view.
The Last 7 Days and Today cards recalculate to show subscribers who clicked cancel (status "Canceling") within the window. The Total (Lifetime) card displays a dash ("–").
6
Dashboard tab is clicked rapidly multiple times.
The system debounces the tab switch and loads data only for the final selected tab, preventing duplicate API calls or flickering.
7
Switch-from-CRM Setup Deal section has no entries (no users opted for CRM migration).
The section displays an empty state message: "No CRM migration requests yet." The "View All" button is still visible but leads to an empty full-page listing.
8
Overdue Invoices section has no overdue invoices.
The section displays an empty state message: "No overdue invoices." The "View All" button is still visible and redirects to the Payments page with the Overdue tab showing an empty state.
9
Active Users section has no active users.
The section displays an empty state message: "No active users." The "View All" button redirects to the Subscribers page with the Active tab showing an empty state.
10
User opens the portal in multiple browser tabs simultaneously.
Each tab maintains its own session state. Actions in one tab (e.g., changing a CRM status) are reflected in other tabs upon page refresh. No real-time cross-tab synchronization is required.
11
Browser back button pressed after logging out.
The system does not allow access to cached Dashboard pages after logout. The user is redirected to the Login page.
12
Global search is performed with special characters or empty spaces.
The system trims leading/trailing whitespace. Special characters are escaped and treated as literal search text. If no match is found, "No results found" is displayed.
13
Notification bell is clicked with zero unread notifications.
The notification center dropdown opens but displays a message: "No new notifications." The badge is hidden when the count is zero.
14
Network disconnection while on the Dashboard page.
The page displays the last loaded data. Any actions (e.g., status change) fail gracefully with a network error message. The system does not clear existing data from the screen.
15
Dark mode is toggled while charts are rendering.
The system applies the theme change after the current render cycle completes. Charts re-render with the new color scheme.
16
The "Free Trial Sign-ups" tab shows comparison percentage when there are zero sign-ups in the previous period.
The system displays "N/A" or "0%" for the comparison indicator to avoid misleading infinite-percentage calculations.
17
Subscriber's company name or contact person name contains very long text.
Text is truncated with an ellipsis ("...") in table cells and full text is shown on hover via a tooltip.
18
CRM status dropdown is opened and then the user clicks away without selecting.
The dropdown closes without making any changes. The status remains as it was before the dropdown was opened.
19
Notification Settings — Pixally owner wants both In-App and Email for the same event.
Supported. The owner enables both In-App and Email for that event, and notifications are delivered through both channels. Selecting "None" clears both.
20
Overdue Invoice row is expanded while another row is already expanded.
The system allows multiple rows to be expanded simultaneously. Alternatively, if single-expand is implemented, expanding a new row collapses the previously expanded row. (Behaviour to be confirmed with development team.)
21
Dashboard is loaded while a subscriber's payment is being processed in the background.
The Dashboard displays the data as of the last page load. The processing payment does not appear as "Paid" until the next page refresh after processing completes.
22
Column sort is applied on the Overdue Invoices table and then "View All" is clicked.
The sort state from the Dashboard widget is not carried over to the Payments page. The Payments > Overdue tab loads with its own default sort order.
23
Pixally owner changes a CRM migration status to "Completed" and then navigates to "View All" page.
The "View All" page reflects the updated status immediately since the change was persisted to the server. The entry remains in the list with "Completed" status.
9. Acceptance Criteria
9.1 Login
- The Login page loads with the correct layout (left image panel, right form panel) on the unique Gawd Portal URL.
- Login is only successful with valid credentials from a whitelisted IP address.
- Invalid credentials, empty fields, and non-whitelisted IPs all display appropriate error messages without clearing the email field.
- Successful login redirects to the Dashboard with the Subscriber Overview tab selected by default.
- No sign-up or forgot password functionality is present on the page.
- Password visibility toggle works correctly between masked and plain text.
- Account lockout activates after the configured number of consecutive failed login attempts.
9.2 Portal Shell
- The sidebar displays all seven navigation items in the correct order with proper icons.
- The sidebar collapse/expand toggle works correctly and persists state across page navigations.
- The Help Center link opens the external Pixally Help page in a new tab.
- The currently active module is visually highlighted in the sidebar.
- Global search (Cmd+K) activates correctly and returns subscriber results by name/company name only.
- Dark mode/light mode toggle applies the theme across the entire portal and persists the preference.
- The notification bell displays the correct unread count badge and opens the notification center with recent notifications.
- The profile avatar dropdown shows Notification Settings and Log Out options.
- Log Out correctly ends the session and redirects to the Login page.
9.3 Dashboard Tabs
- All four tabs (Subscriber Overview, Free Trial Sign-ups, Cancelled Subscribers, Paid Subscribers) are visible and clickable.
- Switching tabs updates only the KPI cards and Growth Trends chart; bottom sections remain unchanged.
- The Subscriber Overview tab displays all three KPI cards (Active Subscribers, New Paid Subscriber 24hr, Churn Rate) with correct values.
- The Free Trial Sign-ups, Cancelled Subscribers, and Paid Subscribers tabs each display three KPI cards (Last 7 Days, Today, Total Lifetime) with correct comparison percentages, where Last 7 Days compares against the previous 7 days on a rolling basis.
- The Cancelled Subscribers tab displays an Active/Pending toggle; the Pending view shows subscribers with status "Canceling" and displays a dash for the Total (Lifetime) card.
- Churn rate is calculated correctly using the 30-day formula, counting cancellations on the date the paid term ends, and displays the tooltip on hover.
- MRR and ARR each display an Actual/Normalized toggle with correct calculated values for both views, and Total YtD Revenue displays in proper currency format. ARR always equals MRR × 12 for the selected view.
9.4 Dashboard Widgets
- Growth Trends chart renders a 12-month line chart with correct data for the selected tab.
- Revenue by Subscriptions chart renders a stacked bar chart with Free, Basic, Pro, and Studio plan breakdowns with legend and totals, with annual revenue divided by 12 across the subscription term, and an info tooltip containing a link to the Reports breakdown.
- Switch-from-CRM Setup Deal table displays correct columns with a functional status dropdown on each row, showing a maximum of 3 entries.
- Status changes from the Dashboard widget are persisted immediately and reflected on the View All page.
- Recent Overdue Invoices table displays the correct overdue invoices (maximum 6 entries) with "View All" redirecting to Payments > Overdue tab.
- Overdue Invoice rows can be expanded to show detailed payment information including Due Date, Reminder Sent, Payment Method, Trace ID, and 3-step timeline.
- All table column headers in Overdue Invoices and Active Users support ascending/descending sort by click.
- Active Users table displays the correct active users (maximum 6 entries) with "View All" redirecting to Subscribers > Active tab.
- All "View All" buttons navigate to their correct destinations.
- All tables handle empty states with appropriate messaging.
- Payment Date column displays a dash ("–") when no payment has been made for an overdue invoice.
9.5 Notification Settings
- The Notification Settings page is accessible from the profile dropdown.
- All four notification categories and their respective events are displayed.
- Each event allows enabling In-App, Email, or both; selecting "None" clears both channels.
- Preferences are saved immediately upon selection.
- In-App notifications appear in the bell dropdown when triggered.
- Email notifications are sent to the registered email when triggered.
- "None" selection suppresses all notifications for that event.
10. Manual Test Cases
Link:
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
Users cannot log in to the Gawd Portal. The Login page displays a generic server error.
IP Whitelisting Service
Service Dependency
If unavailable, the system should fail-safe to blocking all logins (not allowing all) and display an error.
Subscription & Billing System (Stripe)
Data Dependency
Dashboard revenue metrics (MRR, ARR, YTD), overdue invoices, and subscriber plan data cannot be loaded. Widgets display empty states or cached data.
Agency Portal — User Registration
Data Dependency
New sign-ups, trial activations, and subscriber data originate from the Agency Portal's registration flow. Without this, the Dashboard shows no new subscriber activity.
Subscribers Module (Gawd Portal)
Internal Dependency
The Active Users "View All" and Global Search both redirect to the Subscribers module. If unavailable, these links return a "Module unavailable" error page.
Payments Module (Gawd Portal)
Internal Dependency
The Overdue Invoices "View All" redirects to the Payments module. If unavailable, the link returns a "Module unavailable" error page.
Email Service (SMTP / Transactional Email Provider)
External Service Dependency
Email notifications configured in Notification Settings cannot be delivered. In-app notifications are unaffected.
Notification Engine
Service Dependency
If unavailable, both in-app and email notifications fail. The bell icon shows stale data. Notification Settings page may display a save error.
CRM Migration Data Store
Data Dependency
Switch-from-CRM Setup Deal section cannot load migration entries. The widget displays an empty state.
12. References
- Figma Link:
☑️ Subscribers
Functional Requirements Document (FRD)
Gawd Portal — Subscribers
Module Name: Gawd Portal — Subscribers Version: 1.0 Created Date: March 27, 2026 Last Updated: March 27, 2026 Project: Pixally CRM Portal: Super Admin (Gawd Portal)
1. Module Overview
Module Name: Gawd Portal — Subscribers
Purpose: The Subscribers module provides the Pixally owner with a centralized view of all platform subscribers — including active, trial, expired, cancelled, and suspended users. It enables the Pixally owner to view subscriber details, manage subscription lifecycles (apply discounts, cancel subscriptions, delete accounts), monitor payment health via credit card expiry alerts, and export subscriber data for offline analysis. The module includes a comprehensive listing page with advanced filtering, individual subscriber profile pages with full subscription and payment history, and actionable popups for discount application and credit card expiration reminders.
Business Goals:
- Provide complete visibility into every subscriber's status, plan, payment health, and engagement metrics.
- Enable proactive subscriber retention through discount application and credit card expiry reminders.
- Support subscription lifecycle management with cancel and downgrade-to-Free workflows (with suspend and delete planned for V2).
- Facilitate data export for offline reporting and analysis.
- Track subscriber lifetime value (LTV) to measure revenue contribution per account.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all subscribers, access subscriber profiles, apply discounts, cancel subscriptions (now or at cycle end, which downgrades the subscriber to the Free plan), send credit card reminders, use search and filters, export subscriber data, change column sorting. Deletion of never-paid leads is performed from the Lead Management module (FRD #4). A Suspend/Delete capability on the subscriber profile is planned for V2.
Customer Support Executive
View-Only Access
View subscriber listing with limited fields (Name, Email, Phone, Company, Subscription Plan, Start Date, Next Billing Date, Status, Most Recent Payment Status, Payment Method, Last Login, Active Projects). Cannot perform any actions (no edit, no cancel, no delete, no discount, no export). Covered in detail in FRD #9.
3. User Flow
3.1 Subscribers Listing Flow
3.1.1 The user clicks "Subscribers" in the left sidebar navigation menu.
3.1.2 The system loads the Subscribers listing page with the "All" tab selected by default, displaying all subscribers across all statuses.
3.1.3 The system displays the page title "Subscribers," the "Export Data" button in the top-right corner, three tab filters (All, Active, Inactive), a search bar, a filter icon button, and the subscriber data table.
3.1.4 The user clicks the "Active" tab to filter the listing to show only Active, Paid, Trial, and Canceling subscribers.
3.1.5 The user clicks the "Inactive" tab to filter the listing to show only Expired, Cancelled, and Suspended subscribers.
3.1.6 The user types a subscriber name or company name in the search bar, and the system filters the table results in real-time to show matching rows.
3.1.7 The user clicks the filter icon button to open the Filters side panel.
3.1.8 The system displays the Filters panel with options for Status, Number of Projects, Tickets Opened, and Plan (Yearly and Monthly sub-options).
3.1.9 The user applies one or more filters, and the system updates the listing table to show only matching subscribers.
3.1.10 The user clicks the reset icon in the Filters panel header to clear all applied filters and restore the default unfiltered view.
3.1.11 The user clicks any sortable column header (Name & Company, Status, Projects, Plan, Last Login, Tickets, Subscription Length) to sort the table in ascending or descending order.
3.1.12 The user observes the credit card status icon next to each subscriber row — a red icon indicates the payment method is about to expire, and a green icon indicates no action is needed.
3.1.13 The user hovers over a red credit card icon, and the system displays a tooltip showing the number of reminders sent, the date of the last reminder, and a note about the 24-hour cooldown if the last reminder was sent within 24 hours.
3.1.14 The user clicks a red credit card icon to open the Credit Card Expiration Reminder popup.
3.1.15 The user clicks the kebab menu (three-dot icon) on any subscriber row to see the available actions based on that subscriber's status.
3.1.16 The user clicks on a subscriber's name or row to navigate to that subscriber's profile page.
3.1.17 The user clicks the "Export Data" button, and the system generates and downloads an Excel file containing the currently filtered/visible subscriber data.
3.1.18 The user uses the pagination controls at the bottom of the table (Rows per page dropdown and page navigation arrows) to navigate through the subscriber list.
3.2 Subscriber Profile Flow
3.2.1 The user clicks on a subscriber's row from the listing page, and the system navigates to the subscriber's profile page.
3.2.2 The system displays the subscriber's profile header with their avatar, name, last login time, email, phone number, company name, and active project count.
3.2.3 The system displays two action buttons in the top-right area: "Apply Discount" and "Cancel Subscription" (dropdown). No Delete button is shown, since paid subscribers are downgraded to Free on cancellation rather than deleted (deletion of never-paid leads is handled in the Lead Management module).
3.2.4 The system displays the Subscription Details section with the subscriber's current status badge, Lifetime Value breakdown, and subscription plan information.
3.2.5 The system displays the Payment History table below the subscription details with all past payment records.
3.2.6 The user clicks "Apply Discount" to open the Apply Discount popup.
3.2.7 The user clicks "Cancel Subscription" to reveal the dropdown with two options: "Cancel Now" and "Cancel at Cycle End."
3.2.8 The user selects a cancellation option, and the system displays a confirmation popup before proceeding.
3.2.9 The user scrolls through the Payment History table, sorts by any column header, and uses pagination to navigate through records.
3.2.10 The user clicks the download icon on any payment history row to download the invoice as a PDF file.
3.2.11 The user clicks "Subscribers" in the left sidebar to return to the subscriber listing page.
3.3 Apply Discount Flow
3.3.1 The user clicks the "Apply Discount" button on the subscriber profile page.
3.3.2 The system opens the Apply Discount popup with the title "Apply Discount" and a description: "Apply a percentage discount on the subscriber's subscription charges for a specified number of months."
3.3.3 The user enters the discount percentage in the "Amount" field.
3.3.4 The user selects the number of months from the "Number of Months" dropdown.
3.3.5 The system dynamically calculates and displays the price breakdown preview showing the current plan price, any existing discount already applied, the new discount being applied, the subtotal, the total for the discounted period, and the price after the discount period expires.
3.3.6 The user reviews the price breakdown and clicks "Save" to apply the discount.
3.3.7 The system applies the discount starting immediately from today for the specified number of months and displays a success message.
3.3.8 The user may click "Cancel" to close the popup without applying any discount.
3.4 Cancel Subscription Flow
3.4.1 The user clicks the "Cancel Subscription" button on the subscriber profile page.
3.4.2 The system displays a dropdown with two options: "Cancel Now" and "Cancel at Cycle End."
3.4.3 The user selects "Cancel Now," and the system displays a confirmation popup.
3.4.4 The confirmation popup states: "Are you sure you want to cancel this subscription immediately? The subscriber will be downgraded to the Free plan right away. This action cannot be undone." The popup also displays a box summarizing the impact on the subscriber's brands and projects.
3.4.5 The user clicks "Confirm" in the popup, and the system immediately cancels the subscription, updates the subscriber's status, and displays a success message.
3.4.6 Alternatively, the user selects "Cancel at Cycle End," and the system displays a confirmation popup.
3.4.7 The confirmation popup states: "Are you sure you want to cancel this subscription at the end of the current billing cycle? The subscriber will retain access until [End Date]. This action cannot be undone."
3.4.8 The user clicks "Confirm," and the system schedules the cancellation, updates the subscriber's status to "Canceling," and displays a note on the profile indicating the cancellation date and that the account will downgrade to the Free plan.
3.4.9 The user may click "Cancel" on the confirmation popup to abort the cancellation and return to the profile page without any changes.
3.5 Credit Card Expiration Reminder Flow
3.5.1 The user clicks a red credit card icon on the subscriber listing, and the system opens the Credit Card Expiration Reminder popup.
3.5.2 The system displays the popup with the title "Credit Card Expiration Reminder," subscriber name and company, the card expiry date (MM/YY), and an information note about the automatic reminder status.
3.5.3 If an automatic reminder has already been sent, the system displays a yellow warning note: "Please Note: An automatic reminder has already been sent to this user. Last automatic reminder: [Date]."
3.5.4 If no automatic reminder has been sent yet, the system displays a blue information note: "Please Note: An automatic reminder has not been sent yet to this user. Next scheduled automatic reminder: [Date]."
3.5.5 The system pre-fills the "Subject" field with: "Your Pixally payment method is about to expire."
3.5.6 The system pre-fills the email body with a rich text editor containing a default template with placeholders: [First Name], [Insert Update Billing Link].
3.5.7 The user may edit the subject line and email body content using the rich text editor (with heading, bold, italic, underline formatting options).
3.5.8 The user clicks "Send Reminder" to send the email to the subscriber.
3.5.9 The system sends the reminder email, updates the reminder count and last reminded date, and displays a success message.
3.5.10 The user may click "Cancel" to close the popup without sending a reminder.
3.6 Post-Cancellation (Downgrade to Free Plan)
3.6.1 When a subscriber's cancellation takes effect (either immediately via Cancel Now or when the paid term ends after Cancel at Cycle End), the system downgrades the subscriber to the Free plan rather than deleting them.
3.6.2 The system applies the brand and project retention logic for the Free plan: it keeps the brand with the most projects (deactivating other brands), and within the kept brand keeps projects at the proposal-signed stage or later, retaining the five most recent by payment-received date if there are more than five.
3.6.3 The subscriber's status is set to "Cancelled" and the Plan column displays "Free." The subscriber's record is retained in the Gawd Portal for reporting and marketing.
3.6.4 There is no Delete action for paid subscribers in Phase 1. Deletion of never-paid leads is performed from the Lead Management module (FRD #4).
4. Functional Logic
4.1 Subscribers Listing Page
4.1.1 Page Layout and Structure
- The Subscribers page displays the title "Subscribers" at the top of the main content area.
- An "Export Data" button is positioned in the top-right corner of the page.
- Below the title, three tab filter buttons are displayed horizontally: "All" (selected by default), "Active," and "Inactive."
- To the right of the tabs, a search bar and a filter icon button are displayed.
- Below the tabs and search area, the subscriber data table is displayed with column headers, data rows, and pagination controls at the bottom.
4.1.2 Tab Filtering
- The "All" tab displays every subscriber in the system regardless of their status, including Active, Paid, Trial, Canceling, Expired, Cancelled, and Suspended subscribers.
- The "Active" tab filters the listing to display only subscribers with the following statuses: Active, Paid, Trial, and Canceling. (Canceling subscribers still have full paid access until their term ends, so they appear under Active.)
- The "Inactive" tab filters the listing to display only subscribers with the following statuses: Expired, Cancelled, and Suspended. (Cancelled subscribers have been downgraded to the Free plan and show "Free" in the Plan column.)
- Active and Paid are essentially the same status; both indicate the subscriber currently has an active, paid subscription.
- Only one tab can be selected at a time, and the selected tab is visually highlighted with a filled background.
- When a tab is switched, any previously applied search query or filter remains active and is combined with the tab filter.
4.1.3 Subscriber Statuses
- Active / Paid: The subscriber has a current, active subscription with payments up-to-date. Displayed as a green "Active" or "Paid" badge.
- Trial: The subscriber is on a 14-day free trial period and has not yet purchased a subscription. Displayed as a purple/blue "Trial" badge.
- Expired: The subscriber's trial or subscription has ended without renewal. Displayed as a grey "Expired" badge.
- Cancelled: The subscriber's paid subscription has been cancelled and their paid term has ended. When a paid subscription is cancelled and the term ends, the subscriber is downgraded to the Free plan rather than being removed; their status is displayed as an orange "Cancelled" badge while the Plan column shows "Free." This allows the Pixally owner to retain a record of the former paid subscriber for marketing and churn analysis.
- Suspended: The subscriber's account has been suspended due to failed payment exceeding the configured grace period (managed via the Adjust Failed Payments settings in the Payments module). Displayed as a red "Suspended" badge.
- Canceling: The subscriber has requested cancellation (via Cancel at Cycle End) but their paid term has not yet ended, so they still have full paid access. Displayed as an orange "Canceling" badge with a note indicating the date the cancellation will take effect. When the paid term ends, the status changes to "Cancelled" and the plan downgrades to Free.
4.1.4 Table Columns
- The subscriber listing table displays the following columns, each with a sort arrow (↓) for ascending/descending sorting:
- Name & Company: Displays the subscriber's profile avatar, full name (agency owner name), and company name beneath it. This is the primary click target to navigate to the subscriber profile.
- Status: Displays the subscriber's current status as a color-coded badge (Active, Paid, Trial, Expired, Cancelled, Suspended, Canceling).
- Projects: Displays the count of the subscriber's booked projects. A project is counted as booked when at least one of its events is in a stage under the "Booked Stages" group (Proposal Signed, Deposit Paid, Planning, and any custom stages added under Booked Stages) or the "Post-Event Stages" group (Post Production, Completed, and any custom stages under Post-Event Stages) in the pipeline. Projects whose events are only in New Lead stages (New Lead, Follow-up, Proposal Sent, and custom lead stages), archived projects, and deleted projects are not counted. Because a project can contain multiple events, it counts as long as at least one event qualifies; for example, a project with one event in a Booked stage and another event archived still counts as one. The column header remains labeled "Active Projects," and hovering over it displays a tooltip clarifying that the count reflects booked projects only (from proposal-signed through post-event stages, excluding leads, archived, and deleted projects).
- Plan: Displays the subscription plan name and pricing (e.g., "Pro $99/month," "Basic $390/year"). For Trial users, this column displays "Trial" or the plan they are trialling. For subscribers who have cancelled and downgraded, this column displays "Free."
- Last Login: Displays the relative time since the subscriber (agency owner) last logged in (e.g., "2h ago," "3 days ago," "1 week ago").
- Tickets: Displays the count of open support tickets for the subscriber.
- Subscription Length: Displays the duration of the subscriber's subscription (e.g., "3 months," "1 year 7 months," "2 years"). The label in the column header is truncated to "Subscription Len..." due to column width constraints.
- After the Subscription Length column, two additional elements are displayed per row:
- Credit Card Status Icon: A small icon indicating the subscriber's payment method health. A red icon with a red dot indicates the credit card is about to expire. A green icon with a green dot indicates the payment method is healthy and no action is needed. Clicking the red icon opens the Credit Card Expiration Reminder popup.
- Kebab Menu (⋮): A three-dot vertical menu icon that opens a context menu with status-specific actions when clicked.
- The default sort order is by "Name & Company" in ascending alphabetical order.
- Clicking any column header toggles the sort between ascending and descending. The active sort column and direction are indicated by the arrow icon.
4.1.5 Kebab Menu Actions by Status
- Active / Paid subscribers: View Profile, Apply Discount, Cancel Now, Cancel at Cycle End.
- Trial subscribers: View Profile, Cancel Trial, Reset Trial.
- Expired subscribers: View Profile.
- Cancelled subscribers: View Profile. (These subscribers have been downgraded to the Free plan; they are not deletable from the Gawd Portal because they previously paid. See the Delete Subscriber Logic section.)
- Suspended subscribers (from failed payment): View Profile.
- Canceling subscribers: View Profile, Apply Discount. (Cancel options are removed since cancellation is already scheduled.)
- Clicking "View Profile" navigates to the subscriber's profile page.
- Clicking "Apply Discount" opens the Apply Discount popup for that subscriber.
- Clicking "Cancel Now" or "Cancel at Cycle End" triggers the respective cancellation confirmation popup.
- Clicking "Cancel Trial" immediately ends the subscriber's trial period and moves their status to Expired.
- Clicking "Reset Trial" resets the subscriber's 14-day free trial period starting from today. This action is also tracked in the Lead Management module (FRD #4).
4.1.6 Search
- The search bar is positioned to the right of the tab filters.
- The search performs a real-time filter on the subscriber listing as the user types.
- The search matches against the subscriber's name (agency owner name) and company name.
- The search is case-insensitive and supports partial matching (e.g., typing "Dav" matches "David Rolland").
- If no results match the search query, the table displays an empty state with the message: "No subscribers found matching your search."
- The search works in combination with the selected tab filter and any applied Filters panel options.
- Clearing the search bar (via the clear/X icon or deleting all text) restores the previously filtered or unfiltered view.
4.1.7 Filters Panel
- Clicking the filter icon button opens the Filters panel as a side drawer or overlay on the right side of the page.
- The Filters panel header displays "Filters" with a reset/refresh icon (↻) that clears all applied filters when clicked.
- The Filters panel contains the following filter options:
- Status: A dropdown with options: All, Active, Paid, Trial, Expired, Cancelled, Suspended. Default value is "All."
- Number of Projects: A dual-handle range slider with Min (default: 0) and Max (default: 50) input fields. The slider allows the user to set a numeric range. The scale displays markers at 0, 10, 20, 30, 40, 50.
- Tickets Opened: A dual-handle range slider with Min (default: 0) and Max (default: 20) input fields. The slider allows the user to set a numeric range. The scale displays markers at 0, 5, 10, 15, 20.
- Plan: Two subsections — "Yearly" and "Monthly" — each containing four checkboxes: Free, Basic, Pro, Studio. The user can select one or more plan/billing-cycle combinations to filter by.
- Filters are applied dynamically as the user adjusts them (no separate "Apply" button required).
- Filters work in combination with the selected tab and any active search query.
- The reset icon clears all filters: Status reverts to "All," range sliders reset to their full range defaults, and all Plan checkboxes are unchecked.
4.1.8 Pagination
- Pagination controls are displayed at the bottom-right of the subscriber table.
- The pagination displays: "Rows per page:" dropdown (default: 10, options: 10, 25, 50, 100), current range indicator (e.g., "6-10 of 11"), and previous/next page navigation arrows (< >).
- The left arrow is disabled on the first page, and the right arrow is disabled on the last page.
- Changing the "Rows per page" value resets the view to page 1 with the new page size applied.
- The row count shown reflects the total after all filters, search, and tab selections are applied.
4.1.9 Export Data
- Clicking the "Export Data" button generates an Excel (.xlsx) file containing the subscriber data currently displayed in the table (after all tab, search, and filter selections are applied).
- The exported file includes all visible columns: Name, Company, Status, Projects, Plan, Last Login, Tickets, and Subscription Length.
- The file is downloaded directly to the user's browser with a filename convention: "Pixally_Subscribers_Export_[YYYY-MM-DD].xlsx."
- If the table is empty (no subscribers match the current filters), the system displays a warning: "No data to export. Please adjust your filters and try again."
4.1.10 Credit Card Status Icon Logic
- The system checks each subscriber's payment method (credit card) expiration date.
- If the credit card is expiring within 30 days, the system displays a red icon with a red dot next to the subscriber's row. This 30-day threshold is fixed and is not configurable.
- If the credit card has a valid expiration date beyond 30 days, the system displays a green icon with a green dot.
- Hovering over a red icon displays a tooltip with the following information:
- "If the icon is red, the customer's payment method is about to expire. Click to open the 'Send Reminder' popup."
- The reminder count is displayed in the format "Reminders sent: [count]" showing the total number of reminders sent to this subscriber.
- "Last Reminded: [Date] at [Time]."
- If the last reminder was sent within the past 24 hours, the tooltip additionally displays: "You will be able to send next reminder after 24h after last one." The red icon is still clickable, but the "Send Reminder" button inside the popup is disabled until the 24-hour cooldown expires.
- For green icons, hovering displays a tooltip: "Payment method is up to date. No action needed."
- Trial subscribers who have not added a payment method do not display either icon.
4.1.11 Empty State
- If there are no subscribers in the system at all (first-time setup), the page displays an empty state with:
- An illustration/icon in the center of the table area.
- Heading: "No subscribers found"
- Description: "You don't have any subscribers yet. Once users subscribe to your plans, they'll appear here along with their status, projects, and billing details."
- The table column headers remain visible even in the empty state.
- The "Export Data" button remains visible but displays a warning when clicked with no data available.
- The tabs (All, Active, Inactive) remain visible and functional.
4.2 Subscriber Profile Page
4.2.1 Profile Header
- The profile page displays a header section with a dark/gradient background.
- The header contains the subscriber's profile avatar (circular, left-aligned), followed by:
- Subscriber Name (bold, large text) and last login time in relative format (e.g., "2 hours ago") displayed inline.
- Email address | Phone number (e.g., "+1 (123) 456 7890") displayed on the second line, separated by a pipe (|) character.
- Company Name: displayed with a "Company Name:" label (e.g., "Company Name: Photo Easy") | Active projects: displayed with count (e.g., "Active projects: 3").
- Two action buttons are displayed in the top-right area of the header:
- "Apply Discount" — Opens the Apply Discount popup. Enabled for Active, Paid, and Canceling subscribers. For Free-plan users (subscribers who have cancelled and been downgraded to Free), this button is shown in a disabled state (greyed out, not hidden), because a discount can only be applied to a paid subscription tier. Hovering the disabled button shows a tooltip: "This subscriber is on the Free plan. Discounts apply only to paid subscription plans." For Trial, Expired, and Suspended subscribers the button is not shown.
- "Cancel Subscription" — A dropdown button that reveals two options: "Cancel Now" and "Cancel at Cycle End." Enabled for Active and Paid subscribers. For Free-plan users (cancelled/downgraded subscribers), this button is shown in a disabled state (greyed out, not hidden), because there is no active paid subscription to cancel. Hovering the disabled button shows a tooltip: "This subscriber is already on the Free plan. There is no active subscription to cancel." Hidden for Trial subscribers (who instead have trial-specific actions) and for Suspended subscribers. For Canceling subscribers the button is hidden since a cancellation is already scheduled.
- The Free-plan (Cancelled) subscriber's profile remains fully viewable; only the action buttons are disabled as described.
- There is no "Delete" button on the subscriber profile in Phase 1. Subscribers who have paid are never deleted; when they cancel, they are downgraded to the Free plan. Only never-paid leads (free-trial users who never purchased) can be deleted, and that is done from the Lead Management module (FRD #4). A dedicated Suspend and Delete capability on the Gawd Portal subscriber profile is planned for V2 (see Delete Subscriber Logic).
- For subscribers with the "Canceling" status, a note is displayed in the header or beneath the status badge: "This subscription is scheduled to be cancelled on [End Date], after which the account will be downgraded to the Free plan."
4.2.2 Subscription Details Section
- The section title reads "Subscription Details" with a status badge displayed inline (e.g., "Active," "Active: Trial," "Cancelled," "Suspended").
- The section is divided into two parts: a left card and a right card.
Left Card — Lifetime Value:
- Lifetime Value: Displays the total amount Pixally has earned from this subscriber since sign-up, in large bold USD format (e.g., "$12,400").
- Subscription Income (ⓘ): Displays the revenue collected from subscription plan payments. An info icon (ⓘ) is displayed next to the label; hovering over it shows a tooltip: "Total revenue collected from user subscription plans."
- Processing Fee Income (ⓘ): Displays the revenue Pixally earns from credit card and ACH payment markup fees. An info icon (ⓘ) is displayed next to the label; hovering over it shows a tooltip: "Income Pixally keeps from credit card and ACH payments, based on the markup added to standard processing fees. This is not the total client payment volume."
- Most recent payment status: Displays the status of the subscriber's latest payment (e.g., "Success," "Failed," "Pending"). For trial users, this displays "N/A."
Right Card — Subscription Plan Details:
- Subscription Plan: Displays the plan name and billing cycle (e.g., "Pro Monthly," "Basic Yearly"). For trial users, displays "Trial."
- Upcoming plan change indicator: When the subscriber has a pending plan change that takes effect at the end of their current billing cycle — either a downgrade to a lower paid tier or a cancellation (which converts them to the Free plan) — the Subscription Plan field displays the current plan followed by an "Upcoming" badge and an arrow to the pending plan (e.g., "Pro Monthly [Upcoming] → Basic," or for a scheduled cancellation, "Pro Monthly [Upcoming] → Free"). This reflects that the plan does not change immediately; the subscriber keeps their current plan until the billing cycle end date. The plan change itself is initiated by the subscriber on the Agency side; the Gawd Portal displays the pending change. This indicator appears only on the profile page (the listing Plan column continues to show the current plan).
- Subscription Start Date: Displays the date the subscriber first started their subscription (e.g., "10/10/24"). For trial users, displays "N/A."
- Plan Changes On: When a pending plan change (downgrade or cancellation) is scheduled, this field displays the effective date of the change, which is the current billing cycle end date (e.g., "08/06/25"). If there is no pending change, this field is not shown (the Next Billing Date is shown instead).
- Next Billing Date: Displays the date of the subscriber's next scheduled payment (e.g., "08/06/25"). For trial users, displays "N/A." When a cancellation is pending (subscriber is "Canceling"), no further billing occurs after the cycle end, so the "Plan Changes On" date is shown in place of a future billing date.
- Payment Method: Displays the masked payment method (e.g., "Visa •••• 4242") due to Stripe restrictions. Only the card type and last four digits are shown. For trial users, displays "N/A."
- Credit card expiry status icon: Next to the masked payment method, the same credit-card expiry status icon used in the listing is displayed — a red icon with a red dot if the card is expiring within the fixed 30-day threshold (or already expired), or a green icon with a green dot if the card is valid beyond 30 days. Hovering over the icon shows the same tooltip as the listing icon (the number of reminders sent, the date of the last reminder, and a note about the 24-hour cooldown if the last reminder was within 24 hours). Clicking a red icon opens the same Credit Card Expiration Reminder popup available from the listing. For trial users and Free-plan users with no stored card, no icon is shown.
Trial User Profile Behavior:
- When a subscriber is on a free trial, the status badge displays "Active: Trial."
- The Lifetime Value displays "$0.00" since no payments have been made.
- Subscription Income and Processing Fee Income both display "$0.00."
- Most recent payment status displays "N/A."
- Subscription Plan displays "Trial," and Subscription Start Date, Next Billing Date, and Payment Method all display "N/A."
- The payment history table displays an empty state: "The user on a Free Trial. Your billing history will appear here once your trial period ends and your first payment is processed."
4.2.3 Payment History Table
- The payment history table is displayed below the Subscription Details section.
- The table displays the following sortable columns:
- Date (↓): The date and time of the payment transaction (e.g., "10/10/24 8:20 AM").
- Details (↓): The type of transaction. Possible values: First Payment, Renewal, Upgrade, Downgrade, Additional Seats, Additional Brands.
- Plan (↓): The subscription plan the subscriber was on for that transaction (e.g., "Basic," "Pro," "Studio," "Free"). This provides a plan history across transactions, which is useful for marketing and churn analysis (for example, seeing which plan a subscriber was on before downgrading).
- Billing Period (↓): The period the payment covers (e.g., "1 Month," "1 Year").
- Amount (↓): The payment amount in USD (e.g., "$100.00," "$50.00").
- Status (↓): The payment status displayed as a color-coded badge. Possible values: Success (green), Issued (yellow/amber), Failed (red), Pending (grey), Refunded (blue).
- Invoice: A download icon button that allows the Pixally owner to download the invoice as a PDF. The filename convention is: "INV[InvoiceNumber]_[SubscriberName].pdf" (e.g., "INV000001_DavidRolland.pdf").
- The table is sorted by Date in descending order (most recent first) by default.
- The table supports pagination with the same controls as the subscriber listing page (Rows per page dropdown and page navigation arrows).
- Clicking any column header toggles ascending/descending sort for that column.
4.3 Apply Discount Popup
- The popup title reads "Apply Discount."
- The popup description reads: "Apply a percentage discount on the subscriber's subscription charges for a specified number of months. The discount starts immediately."
- The discount type is percentage only; fixed/flat amount discounts are not supported from the subscriber profile. (Fixed discounts are available through the Discounts module via discount codes — FRD #6.)
- The discount applies only to the subscription tier amount. It never applies to extra seats the subscriber has purchased or to any other add-ons or future additions. Only the base subscription plan price is discounted.
- The popup contains two input fields:
- Amount: A numeric input field for entering the discount percentage. Displays a percentage icon (%). The value must be between 1 and 100.
- Number of Months: A dropdown selector for choosing the duration of the discount in months. The duration is always expressed in months even for yearly subscribers (e.g., 24 months represents two years).
- The discount starts immediately from today's date and runs for the specified number of months.
- Existing discount override: If the subscriber already has a discount applied when the Apply Discount popup is opened, the popup displays an inline info/warning message at the top: "A discount is already applied to this subscriber. Applying a new discount will override the existing one." When the owner applies the new discount, it replaces the existing discount entirely — the new percentage and new duration take effect from today, and the previous discount (its remaining months and percentage) is discarded. The discounts do not stack or compound.
- For monthly subscribers, the discount applies to each monthly charge for the specified number of months. For yearly subscribers, the discount is prorated using the subscriber's monthly-equivalent rate: the system computes (annual cost ÷ 12) × discount percentage × number of months to determine the total discount value applied against the yearly subscription.
- Below the input fields, the system displays a dynamic price breakdown preview that updates in real-time as the user changes the Amount or Number of Months:
Price Breakdown Logic:
- Current plan price: Displays the subscriber's current plan price (e.g., "$39.50"). If a discount is already applied, the existing discount (e.g., "50% OFF" badge) and its discounted price (e.g., "$19.75") are shown for reference, along with a note that it will be replaced.
- Existing discount (to be replaced): If a discount is currently applied, the preview labels it clearly as the discount that will be overridden, including its percentage and its current end date, so the owner understands what they are replacing.
- New discount applied: Shows the new discount percentage being applied and the deducted amount in green text (e.g., "10% OFF" → "-$3.95"). The new discount is calculated on the original plan price (the existing discount is removed first, since the new discount overrides it — discounts are not stacked).
- Total: The final price the subscriber will pay during the new discount period (e.g., "$35.55").
- Discount behavior on a plan switch: If a subscriber has an active multi-month discount and switches to a different plan partway through that discount period, only the remaining months of the discount carry over to the new plan, at the same discount percentage. For example, a subscriber granted a 6-month discount who switches plans after using 2 months retains the discount for the remaining 4 months on the new plan. The plan switch itself is performed by the subscriber on the Agency side; the Gawd Portal reflects the resulting plan and the remaining discount. (The discount duration/proration mechanics are defined in FRD #6.)
- After the new discount period ends, the system shows the full price the subscriber will revert to:
- After [New Discount End Date]: Displays the original full plan price (e.g., "After February 5, 2026: $39.50").
- Discounts stack cumulatively. For example, if a subscriber already has a 50% discount and the Pixally owner applies an additional 10% discount, the subscriber pays the 50%-discounted price minus an additional 10% during the overlap period.
- The popup has two action buttons: "Cancel" (closes the popup without changes) and "Save" (applies the discount).
4.4 Cancel Subscription Logic
- The "Cancel Subscription" button is a dropdown that reveals two options: "Cancel Now" and "Cancel at Cycle End."
- This button is visible only for Active and Paid subscribers. It is hidden for Trial, Expired, Cancelled, Suspended, and Canceling subscribers.
- Both cancellation options show a simple confirmation popup (with "Confirm" and "Close" buttons) stating that the subscription will be canceled (now or at the end of the cycle) and that the subscriber will be converted to a Free plan user. The popup does not enumerate the features the subscriber will lose, since this action is taken by the Pixally owner rather than the subscriber.
Cancel Now:
- When the user selects "Cancel Now," the system displays a confirmation popup with the message: "Are you sure? This subscription will be canceled now and the subscriber [Subscriber Name] ([Company Name]) will be converted to a Free plan user." The popup does not list the specific features the subscriber will lose, because this action is performed by the Pixally owner (an informed internal user), not the subscriber.
- The popup has two buttons: "Confirm" (proceeds with the cancellation) and "Close" (aborts without changes).
- Upon confirmation, the system immediately cancels the paid subscription, changes the subscriber's status to "Cancelled," and downgrades the subscriber to the Free plan. The Plan column then displays "Free."
- The subscriber retains access at the Free plan level; the brand and project retention logic described in the Downgrade-to-Free section is applied immediately.
- Paid-tier automations, scheduled payments from clients, and paid-only workflows are stopped in accordance with the Free plan's feature set.
- The cancellation is logged in the subscriber's payment history.
Cancel at Cycle End:
- When the user selects "Cancel at Cycle End," the system displays a confirmation popup with the message: "Are you sure? This subscription will be canceled at the end of the cycle on [Billing Cycle End Date] and the subscriber [Subscriber Name] ([Company Name]) will be converted to a Free plan user." The popup does not list the specific features the subscriber will lose, because this action is performed by the Pixally owner, not the subscriber.
- The popup has two buttons: "Confirm" (proceeds) and "Close" (aborts without changes).
- The [Billing Cycle End Date] is dynamically calculated based on the subscriber's billing cycle:
- If the subscriber is on a monthly plan, the cancellation takes effect at the end of the current month of the billing cycle.
- If the subscriber is on a yearly plan, the cancellation takes effect at the end of the current year of the billing cycle. For example, if a subscriber is in month 7 of a yearly plan and cancellation is scheduled, they retain access for the remaining 5 months.
- Upon confirmation, the system changes the subscriber's status to "Canceling" and displays a note on the profile: "This subscription is scheduled to be cancelled on [End Date], after which the account will be downgraded to the Free plan."
- The subscriber retains full paid access to the portal until the cancellation date and continues to be counted as an active subscriber during this period.
- No further charges are made after the cancellation date.
- On the cancellation date, the system automatically changes the subscriber's status to "Cancelled" and downgrades the subscriber to the Free plan, applying the brand and project retention logic described below.
- There is no "Undo" or "Reactivate" option in Phase 1. Once cancellation is scheduled, it proceeds as planned.
Downgrade-to-Free Retention Logic (summary):
- When a subscriber is downgraded to the Free plan (through cancellation), the system retains a limited set of the subscriber's brands and projects according to the Free plan's limits, and deactivates the rest (the data is deactivated, not deleted).
- Brands: if the subscriber has multiple brands and the Free plan allows only one, the system keeps the brand with the highest number of projects and deactivates the remaining brands.
- Projects within the kept brand: the system keeps projects that are at the proposal-signed stage or later. If the number of such projects exceeds the Free plan limit (five), the system keeps the five most recent by payment-received date and deactivates the rest.
- The detailed implementation of this downgrade and retention logic (including brand/project deactivation behavior and gallery handling) is owned by the Agency Portal subscription and cancellation flow; this FRD summarizes it so the Gawd Portal cancellation experience is understood. The full logic should be kept in sync with the Agency Portal FRD to avoid divergence.
4.5 Credit Card Expiration Reminder Popup
- The popup title reads "Credit Card Expiration Reminder" with a close (X) icon in the top-right corner.
- Below the title, a contextual message is displayed: "The customer [User / Company Name] has a credit card that is about to expire ([MM/YY]). You can manually send a reminder to update their payment details." The subscriber name and expiry date are dynamically populated.
- Below the contextual message, an information banner is displayed with one of two states:
State 1 — Automatic reminder already sent:
- Yellow/warning background with text: "Please Note: An automatic reminder has already been sent to this user. Last automatic reminder: [Date]."
State 2 — Automatic reminder not yet sent:
-
Blue/info background with text: "Please Note: An automatic reminder has not been sent yet to this user. Next scheduled automatic reminder: [Date]."
-
Below the banner, the popup contains:
- Subject: A text input field pre-filled with "Your Pixally payment method is about to expire." The Pixally owner can edit this subject.
- Email Body: A rich text editor (with heading dropdown, bold, italic, underline formatting tools) pre-filled with a default email template containing:
- The greeting line addresses the subscriber by first name using the placeholder format "Hi [First Name]," which is auto-populated with the subscriber's first name.
- The body text explains that the credit card linked to the Pixally account is about to expire and prompts the subscriber to update their payment information.
- A call-to-action link reads "Update your card now → [Insert Update Billing Link]" where the system auto-inserts the subscriber's billing update link.
- The email closes with a signature: "Best, The Pixally Team."
- The Pixally owner can edit any part of the subject and email body before sending.
-
The popup has two action buttons: "Cancel" (closes without sending) and "Send Reminder" (sends the email).
-
The "Send Reminder" button is disabled if a manual reminder was sent within the last 24 hours. In this case, the tooltip on the button or a message in the popup reads: "You will be able to send next reminder after 24h after last one."
-
Upon clicking "Send Reminder," the system sends the email to the subscriber's registered email address, increments the reminder count, updates the "Last Reminded" timestamp, and displays a success message.
-
The reminder count and last reminded date are displayed in the tooltip when hovering over the credit card icon on the subscriber listing.
4.6 Delete Subscriber Logic
- In Phase 1, there is no "Delete" action for subscribers who have ever paid. The Gawd Portal subscriber profile and listing do not present a Delete option for Active, Paid, Trial, Canceling, Cancelled, Suspended, or Expired subscribers.
- Deletion is available only for never-paid leads — free-trial users who never purchased a subscription — and that action is performed from the Lead Management module (FRD #4), not from the Subscribers module.
- When a paid subscriber cancels, they are downgraded to the Free plan rather than deleted, so their record is retained for marketing and revenue reporting. This is why no Delete option is offered for former paid subscribers in Phase 1.
- Account self-deletion (a subscriber deleting their own account for privacy/GDPR reasons) is not available in Phase 1. For launch, the requirement is met by providing a way for users to request deletion (handled off-platform); a self-service delete button is not required for GDPR compliance. Full account self-delete and GDPR data-erasure handling are planned for V2.
- In V2, both a Suspend and a Delete capability are planned for the Gawd Portal subscriber profile, allowing the Pixally owner to suspend an account (e.g., for a security or terms-of-service reason, blocking login) or delete an account on the subscriber's behalf. The retention and hard-delete behavior for that V2 capability will be defined at that time.
- For never-paid leads deleted via Lead Management, the soft delete plus 1-year retention rules defined in FRD #4 apply (subscriber email retained; agency data removed after the retention period).
4.7 Subscriber Profile — Back Navigation
- There is no dedicated "Back" button on the subscriber profile page.
- The Pixally owner navigates back to the subscriber listing by clicking "Subscribers" in the left sidebar navigation.
- The sidebar continues to highlight "Subscribers" as the active module while on a subscriber's profile page.
5. Field Details & Validations
5.1 Subscribers Listing Table Fields
Field Name
Field Type
Validation / Display Rules
Name & Company
Text + Avatar (Read-only)
Displays subscriber's avatar, full name, and company name. Clickable — navigates to profile. Long names truncated with ellipsis; full name on hover tooltip.
Status
Badge (Read-only)
Displays one of: Active, Paid, Trial, Expired, Cancelled, Suspended, Canceling. Color-coded per status definition. "Canceling" is orange.
Projects (header: "Active Projects")
Integer (Read-only)
Whole number. Displays count of booked projects only (events in Booked Stages or Post-Event Stages; excludes New Lead stages, archived, and deleted). Header tooltip clarifies the booked-projects definition.
Plan
Text (Read-only)
Displays plan name and price (e.g., "Pro $99/month"). For Trial users: "Trial" or plan being trialled. For cancelled/downgraded subscribers: "Free."
Last Login
Relative Timestamp (Read-only)
Displayed as relative time (e.g., "2h ago," "3 days ago"). If never logged in: "Never."
Tickets
Integer (Read-only)
Whole number. Displays count of open support tickets.
Subscription Length
Text (Read-only)
Displayed as human-readable duration (e.g., "3 months," "1 year 7 months"). Column header truncated to "Subscription Len..."
Credit Card Icon
Icon (Clickable)
Red icon with red dot = card expiring soon. Green icon with green dot = healthy. No icon for Trial users without payment method.
Kebab Menu
Icon Button (Clickable)
Opens context menu with status-specific actions.
5.2 Subscriber Profile Header Fields
Field Name
Field Type
Validation / Display Rules
Avatar
Image (Read-only)
Circular avatar. Displays subscriber's profile picture or default placeholder.
Subscriber Name
Text (Read-only)
Agency owner's full name in bold.
Last Login
Relative Timestamp (Read-only)
Displayed inline next to name (e.g., "2 hours ago").
Text (Read-only)
Subscriber's registered email address.
Phone Number
Text (Read-only)
Formatted phone number (e.g., "+1 (123) 456 7890").
Company Name
Text (Read-only)
Displayed with "Company Name:" label prefix.
Active Projects
Integer (Read-only)
Displayed with "Active projects:" label prefix and count. Counts booked projects only (events in Booked or Post-Event stages; excludes leads, archived, deleted). Header tooltip explains this.
5.3 Subscription Details Fields
Field Name
Field Type
Validation / Display Rules
Status Badge
Badge (Read-only)
Inline with "Subscription Details" heading. Color-coded.
Lifetime Value
Currency (Read-only)
USD format with two decimals (e.g., "$12,400"). Sum of Subscription Income + Processing Fee Income. For Trial users: "$0.00."
Subscription Income
Currency (Read-only)
USD format with two decimals. Info tooltip on hover. For Trial users: "$0.00."
Processing Fee Income
Currency (Read-only)
USD format with two decimals. Info tooltip on hover. For Trial users: "$0.00."
Most Recent Payment Status
Text/Badge (Read-only)
Displays "Success," "Failed," "Pending," or "N/A" (for Trial users).
Subscription Plan
Text (Read-only)
Plan name + billing cycle (e.g., "Pro Monthly"). For Trial: "Trial." For cancelled/downgraded: "Free."
Subscription Start Date
Date (Read-only)
Format: MM/DD/YY. For Trial users: "N/A."
Next Billing Date
Date (Read-only)
Format: MM/DD/YY. For Trial users: "N/A."
Payment Method
Text (Read-only)
Masked card: "[Card Type] •••• [Last 4]" (e.g., "Visa •••• 4242"). For Trial users: "N/A."
5.4 Apply Discount Popup Fields
Field Name
Field Type
Validation Rules
Amount
Numeric Input (%)
Required. Integer or decimal. Min: 1, Max: 100. Must be a positive number. Displays percentage icon.
Number of Months
Dropdown
Required. Options: 1 through 24 months (allowing multi-year discounts to be expressed in months, e.g., 24 = two years). The duration is always expressed in months even for yearly subscribers.
Price Breakdown
Calculated Display (Read-only)
Auto-calculated based on current plan price, existing discounts, and new discount inputs. Updates dynamically.
5.5 Credit Card Reminder Popup Fields
Field Name
Field Type
Validation Rules
Subject
Text Input
Required. Pre-filled with default value. Editable. Maximum 255 characters.
Email Body
Rich Text Editor
Required. Pre-filled with default template. Editable. Supports heading, bold, italic, underline. Placeholders: [First Name], [Insert Update Billing Link] are auto-populated.
5.6 Filters Panel Fields
Field Name
Field Type
Validation Rules
Status
Dropdown
Options: All, Active, Paid, Trial, Expired, Cancelled, Suspended. Default: All. Single-select.
Number of Projects (Min)
Numeric Input + Slider
Default: 0. Min: 0, Max: 50. Must be ≤ Max value.
Number of Projects (Max)
Numeric Input + Slider
Default: 50. Min: 0, Max: 50. Must be ≥ Min value.
Tickets Opened (Min)
Numeric Input + Slider
Default: 0. Min: 0, Max: 20. Must be ≤ Max value.
Tickets Opened (Max)
Numeric Input + Slider
Default: 20. Min: 0, Max: 20. Must be ≥ Min value.
Plan — Yearly (Free, Basic, Pro, Studio)
Checkbox (Multi-select)
Default: all unchecked. Multiple selections allowed.
Plan — Monthly (Free, Basic, Pro, Studio)
Checkbox (Multi-select)
Default: all unchecked. Multiple selections allowed.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Apply Discount
"Discount applied successfully. The subscriber will be charged at the new rate starting from the next billing cycle."
Pixally owner saves a valid discount from the Apply Discount popup.
The popup closes. The subscriber's subscription details are updated to reflect the new discounted pricing.
Cancel Now
"Subscription cancelled successfully. The subscriber has been downgraded to the Free plan."
Pixally owner confirms "Cancel Now" from the confirmation popup.
The popup closes. The subscriber's status changes to "Cancelled" and the Plan column shows "Free." Brand/project retention logic is applied.
Cancel at Cycle End
"Subscription scheduled for cancellation on [End Date]. The subscriber will retain access until then, after which they will be downgraded to the Free plan."
Pixally owner confirms "Cancel at Cycle End" from the confirmation popup.
The popup closes. Status changes to "Canceling" with a cancellation date note.
Send Credit Card Reminder
"Reminder sent successfully to [Subscriber Name]."
Pixally owner clicks "Send Reminder" in the Credit Card Expiration Reminder popup.
The popup closes. Reminder count increments. Last Reminded date updates. 24-hour cooldown begins.
Delete Subscriber
"Subscriber deleted successfully. Data will be retained for 1 year before permanent deletion."
Pixally owner confirms deletion from the confirmation popup.
The popup closes. Subscriber is removed from the listing. If on the profile page, user is redirected to the subscriber listing.
Export Data
"Export completed. File downloaded."
Pixally owner clicks "Export Data" with data available.
Excel file downloads to the browser. No page navigation.
Reset Trial (via kebab)
"Free trial reset successfully for [Subscriber Name]. The new 14-day trial period starts today."
Pixally owner clicks "Reset Trial" from the kebab menu.
Subscriber's trial period resets. Status remains "Trial." Trial expiry date updates.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Apply Discount — Empty Amount
"Please enter a discount percentage."
User clicks "Save" without entering an amount.
Inline error below the Amount field. User must enter a value.
Apply Discount — Amount Out of Range
"Discount percentage must be between 1 and 100."
User enters a value less than 1 or greater than 100.
Inline error below the Amount field. User must correct the value.
Apply Discount — No Months Selected
"Please select the number of months."
User clicks "Save" without selecting a duration.
Inline error below the Number of Months dropdown.
Apply Discount — Save Failed
"Failed to apply discount. Please try again."
Server error during discount application.
Toast error message. Popup remains open. User can retry.
Cancel Subscription — Server Error
"Failed to cancel subscription. Please try again."
Server error during cancellation processing.
Toast error message. Confirmation popup remains open. User can retry.
Credit Card Reminder — 24hr Cooldown
"You can only send one reminder per 24 hours. Next reminder available at [Time]."
User attempts to send a reminder within 24 hours of the last one.
"Send Reminder" button is disabled. Informational message displayed in the popup.
Credit Card Reminder — Send Failed
"Failed to send reminder. Please try again."
Server error or email service failure.
Toast error message. Popup remains open. User can retry.
Credit Card Reminder — Empty Subject
"Subject line is required."
User clears the subject field and clicks "Send Reminder."
Inline error below the Subject field.
Credit Card Reminder — Empty Body
"Email body cannot be empty."
User clears the email body and clicks "Send Reminder."
Inline error below the email body editor.
Delete Subscriber — Active Subscriber
"Cannot delete an active subscriber. Please cancel the subscription first."
User attempts to delete a subscriber with Active, Paid, or Trial status (this scenario should not occur in the UI since the Delete button is hidden for these statuses, but serves as a backend safeguard).
Toast error message. No action taken.
Delete Subscriber — Server Error
"Failed to delete subscriber. Please try again."
Server error during deletion processing.
Toast error message. Confirmation popup remains open. User can retry.
Export Data — No Data
"No data to export. Please adjust your filters and try again."
User clicks "Export Data" when the table is empty.
Warning toast message. No file is downloaded.
Export Data — Generation Failed
"Failed to generate export file. Please try again."
Server error during Excel file generation.
Toast error message. User can retry.
Search — No Results
"No subscribers found matching your search."
Search query does not match any subscriber name or company.
Message displayed in the table body area. Table headers remain visible.
Filter — Min Greater Than Max
"Minimum value cannot be greater than maximum value."
User sets a Min value higher than the Max value on a range slider.
Inline error near the range slider. Filter is not applied until corrected.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
Subscriber's credit card expires today.
The red icon is displayed. The subscriber is eligible for a reminder. The expiry date in the reminder popup shows the current month/year.
2
Pixally owner sends a credit card reminder and immediately tries to send another.
The "Send Reminder" button is disabled. The tooltip/message shows the 24-hour cooldown message with the time remaining.
3
Pixally owner applies a 100% discount for 1 month.
The system accepts this as a valid discount. The subscriber's charge for 1 month is $0.00. After the discount period, the full price resumes.
4
Subscriber already has a 50% discount, and Pixally owner applies another discount.
The Apply Discount popup shows an inline warning that a discount is already applied and will be overridden. The new discount replaces the existing one entirely (percentage and duration reset from today); discounts do not stack or compound.
5
Pixally owner cancels subscription at cycle end for a subscriber on a yearly plan in month 12.
The cancellation takes effect at the end of the current billing cycle (within the same month). The subscriber retains access until the cycle end date.
6
Subscriber's status is "Canceling" and the Pixally owner applies a discount.
The discount is applied successfully. The cancellation is still scheduled. The subscriber benefits from the discount until the cancellation date, after which they are downgraded to the Free plan.
7
Subscriber has zero projects, zero tickets, and never logged in.
All numeric fields display "0." Last Login displays "Never." The subscriber row is still displayed in the listing.
8
Multiple filters applied result in zero matching subscribers.
The table displays: "No subscribers found matching your filters." The "Export Data" button shows a warning if clicked.
9
Pixally owner applies a discount and then immediately cancels the subscription.
Both actions are processed independently. The discount is applied first, and then the cancellation confirmation proceeds. If "Cancel Now" is selected, the subscriber is downgraded to the Free plan immediately regardless of the discount.
10
Subscriber profile is loaded for a deleted subscriber (accessed via a direct URL or bookmark).
The system displays an error page: "Subscriber not found or has been deleted." The user is prompted to return to the subscriber listing.
11
Pixally owner tries to delete a subscriber that has active projects with ongoing client work.
The system proceeds with the soft delete as designed. A warning in the confirmation popup reminds the Pixally owner that all agency data (projects, clients, files) will be deleted after 1 year.
12
The payment history table for a long-time subscriber has 100+ invoice records.
The table uses pagination (default 10 rows per page). The user can navigate through pages using the pagination controls.
13
Credit card reminder email template contains a placeholder [First Name] but the subscriber's first name is not available.
The system falls back to the subscriber's full name or "Valued Customer" as a default if the first name field is empty.
14
Pixally owner clicks "Export Data" while on the "Inactive" tab with search active.
The exported Excel contains only the subscribers visible in the current filtered, searched, and tab-selected view.
15
A subscriber's status changes from "Active" to "Suspended" (due to failed payment) while the Pixally owner is viewing their profile.
The profile page does not update in real-time. The stale status is displayed until the page is refreshed. The Pixally owner can still perform actions based on the displayed status, but the server validates the current status before processing.
16
Subscriber name or company name contains special characters (e.g., apostrophes, accents, ampersands).
The system displays special characters correctly in the listing, profile, and exported data. Search functionality handles special characters without errors.
17
Pixally owner rapidly clicks "Save" on the Apply Discount popup multiple times.
The system debounces the action and processes the discount only once. The button is disabled after the first click to prevent duplicate submissions.
18
The rich text editor in the credit card reminder popup loses focus when switching to another browser tab.
The editor retains its content and formatting state. No data is lost when the user returns to the tab.
19
Subscriber listing is loaded with a large dataset (10,000+ subscribers).
The system loads data in paginated batches. Only the current page's data is fetched from the server. Sorting and filtering may require server-side processing for large datasets.
20
Pixally owner opens the Apply Discount popup for a subscriber who already has an active discount.
The popup shows the inline override warning. Applying a new discount replaces the existing one; there is never more than one active discount on a subscriber at a time.
21
Subscriber downgrades their plan (Agency side) mid-cycle; Pixally owner views the profile.
The Subscription Plan field shows the current plan with an "Upcoming" badge and an arrow to the new plan (e.g., "Pro Monthly [Upcoming] → Basic"), and "Plan Changes On" shows the billing cycle end date. The current plan remains in effect until that date. The listing Plan column continues to show the current plan only.
22
Subscriber schedules a cancel-at-cycle-end; Pixally owner views the profile.
The Subscription Plan field shows the current plan with an "Upcoming" badge and "→ Free," and "Plan Changes On" shows the cycle end date. On that date the status moves to Cancelled and the plan becomes Free.
23
Pixally owner opens the profile of a Free-plan (cancelled) subscriber.
The profile is fully viewable. The "Apply Discount" and "Cancel Subscription" buttons are shown disabled (greyed out) with explanatory tooltips. No credit card expiry icon is shown if no card is on file.
24
A subscriber with a 6-month discount switches plans (Agency side) after 2 months.
The remaining 4 months of the discount carry over to the new plan at the same percentage. The Gawd Portal reflects the new plan and the remaining discount period.
25
Pixally owner clicks the credit card expiry icon on the profile (red state).
The same Credit Card Expiration Reminder popup used from the listing opens, pre-filled for that subscriber.
9. Acceptance Criteria
9.1 Subscribers Listing
- The Subscribers page loads with the "All" tab selected by default, displaying all subscribers.
- The three tabs (All, Active, Inactive) correctly filter subscribers by the defined status groupings.
- The table displays all required columns with correct data and sortable headers.
- The search bar filters results in real-time by subscriber name and company name.
- The Filters panel opens correctly and all filter options (Status, Projects range, Tickets range, Plan checkboxes) function as expected.
- The reset icon clears all filters and restores the default view.
- Pagination controls work correctly with configurable rows per page.
- The "Export Data" button downloads an Excel file with the currently filtered data.
- Credit card icons (red/green) display correctly based on card expiry status.
- Kebab menu shows the correct actions for each subscriber status.
9.2 Subscriber Profile
- Clicking a subscriber row navigates to the correct profile page with all header information populated.
- The Subscription Details section displays correct Lifetime Value, income breakdown, and plan details.
- Tooltips for Subscription Income and Processing Fee Income display the correct explanatory text.
- The Payment History table displays all payment records with correct data and supports sorting and pagination.
- Invoice download produces a correctly formatted PDF file with the expected filename convention.
- Trial user profiles display all values as "$0.00" or "N/A" as appropriate with the correct empty state message in the payment history.
- The "Canceling" status (orange) displays the cancellation date note correctly, including that the account will downgrade to the Free plan.
9.3 Apply Discount
- The Apply Discount popup opens with the correct subscriber context.
- The Amount field accepts only valid percentage values (1–100).
- The Number of Months dropdown displays the correct options.
- The price breakdown preview updates dynamically and shows correct calculations for current price, existing discounts, new discounts, and future pricing.
- Stacked discounts are calculated correctly (new discount applied to the already-discounted subtotal).
- The "Save" button applies the discount immediately from today for the specified months.
- The "Cancel" button closes the popup without changes.
9.4 Cancel Subscription
- "Cancel Subscription" dropdown shows "Cancel Now" and "Cancel at Cycle End" options for Active/Paid subscribers.
- Both options display a confirmation popup with the correct contextual message.
- "Cancel Now" immediately downgrades the subscriber to the Free plan and changes status to "Cancelled" (Plan column shows "Free").
- "Cancel at Cycle End" schedules cancellation, changes status to "Canceling," and displays the cancellation date and Free-plan downgrade note.
- Both cancellation popups show a simple confirmation message (no feature-loss/impact box) and are confirmed with a "Confirm" button.
- The confirmation popup "Close" button aborts the action without changes.
9.5 Credit Card Reminder
- Red icon correctly identifies subscribers with expiring credit cards.
- Green icon correctly identifies subscribers with healthy payment methods.
- The reminder popup displays the correct auto-reminder status (sent or not sent) with dates.
- Subject and email body are pre-filled and editable.
- The "Send Reminder" button sends the email and updates reminder count/date.
- The 24-hour cooldown is enforced correctly.
9.6 Delete Subscriber
- No "Delete" action is presented for any subscriber who has ever paid (Active, Paid, Trial, Canceling, Cancelled, Suspended, Expired) in Phase 1.
- Deletion is available only for never-paid leads, performed from the Lead Management module (FRD #4).
- Paid subscribers who cancel are downgraded to the Free plan rather than deleted.
- Account self-deletion and a Gawd Portal Suspend/Delete capability are correctly deferred to V2.
10. Manual Test Cases
Test cases for this module are maintained in a separate Excel file for direct upload to the project management tool.
File: TC_FRD02_Subscribers.xlsx
Test Case Summary:
- Total Test Cases: See attached Excel file
- Categories Covered: Listing & Tabs, Search & Filters, Subscriber Profile, Apply Discount, Cancel Subscription, Credit Card Reminder, Delete Subscriber, Export Data, Edge Cases
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
Cannot verify the Pixally owner's session. The Subscribers page returns an authentication error.
Subscription & Billing System (Stripe)
Data Dependency
Subscriber plan data, payment method details, card expiry dates, and payment history cannot be loaded. Credit card icons default to a neutral state.
Agency Portal — User Registration
Data Dependency
New subscriber data (sign-ups, trial activations) originates from the Agency Portal. Without it, the Subscribers listing does not show new entries.
Payments Module (Gawd Portal — FRD #3)
Internal Dependency
Overdue invoice kebab actions and payment-related statuses (Failed, Processing) are managed in the Payments module. If unavailable, payment-related actions are disabled.
Lead Management Module (Gawd Portal — FRD #4)
Internal Dependency
Trial reset actions from the kebab menu are tracked in Lead Management. If unavailable, reset is still processed but may not appear in Lead Management reports.
Discounts Module (Gawd Portal — FRD #6)
Internal Dependency
Apply Discount logic references the discount stacking rules. If unavailable, existing discount data may not be fully reflected in the Apply Discount popup.
Email Service (SMTP / Transactional Email Provider)
External Service Dependency
Credit card expiration reminders cannot be sent. The "Send Reminder" button fails gracefully with an error message.
Agency-Side Impact Module (Gawd Portal — FRD #8)
Cross-Module Dependency
Cancel and Suspend actions trigger agency-side impact screens (warning banners, suspended account screens). If unavailable, the agency-side experience for cancelled/suspended subscribers is not displayed.
Customer Support Role (Gawd Portal — FRD #9)
Internal Dependency
Customer Support view-only access depends on the subscriber listing being available.
12. References
- Figma Screens:
- Subscribers Listing (with data) — Image 7 (Batch 1)
- Subscribers Filters Panel — Image 8 (Batch 1)
- Reminder Icon Tooltip (red icon states) — Image 9 (Batch 1)
- Subscriber Profile — Active/Paid User — Image 10 (Batch 1)
- Subscription Income / Processing Fee Income Tooltips — Image 11 (Batch 1)
- Apply Discount Popup — Image 12 (Batch 1)
- Credit Card Reminder — Auto Sent State — Image 13 (Batch 1)
- Credit Card Reminder — Not Yet Sent State — Image 14 (Batch 1)
- Subscribers Empty State — Image 15 (Batch 1)
- Subscriber Profile — Trial User — Image 16 (Batch 1)
- Source of Truth: Gawd Portal Meeting Transcript (JSON) — March 26, 2026 (timestamps 07:22–16:27)
- Supporting Document: Super Admin — The Gawd Portal (Initial Client Document) — Sections 2 & 3
- Related FRDs:
- FRD #1 — Gawd Portal: Login & Dashboard
- FRD #3 — Gawd Portal: Payments
- FRD #4 — Gawd Portal: Lead Management
- FRD #6 — Gawd Portal: Discounts
- FRD #8 — Gawd Portal: Agency-Side Impact (Failed Payment & Suspension)
- FRD #9 — Gawd Portal: Customer Support Role & Permissions
Open Items / Notes for Client Confirmation:
- "Active" vs "Paid" Badge Consolidation: Active and Paid are confirmed as the same status. Should the Figma be updated to show only one badge (e.g., always "Active"), or should both badges continue to be displayed as visual variety? This is a cosmetic decision with no functional impact.
- Downgrade-to-Free — Galleries Handling: The brand/project retention logic on downgrade to Free is defined. The handling of the subscriber's galleries on downgrade was noted by the client as still to be determined and is not specified here; it should be defined (likely in the Agency Portal cancellation flow) before implementation.
- Downgrade-to-Free — Detailed Logic Ownership: The brand/project deactivation and Free-plan retention logic is summarized in this FRD but owned by the Agency Portal subscription/cancellation flow. The two documents must be kept in sync to avoid divergence.
- V2 — Suspend / Delete on Subscriber Profile: Suspend (block login for security/ToS reasons) and Delete (account erasure, including GDPR self-service) are planned for V2 and will require defined retention and confirmation behavior at that time.
- "Canceling" Status Badge Color: The "Canceling" status is specified as orange per client instruction. Figma should be updated to reflect the new single-word "Canceling" label (replacing any prior "Active - Cancelling" wording) in orange.
Resolved in this round: the credit card expiry threshold is confirmed as a fixed 30 days (not configurable); and the cancellation confirmation popups are simplified (Confirm/Close buttons, no feature-loss/impact box) since the action is performed by the Pixally owner.
☑️ Payments
Functional Requirements Document (FRD) Gawd Portal — Payments
Module Name: Gawd Portal — Payments Version: 2.0 Created Date: March 27, 2026 Last Updated: July 21, 2026
1. Module Overview
Module Name: Gawd Portal — Payments
Purpose: The Payments module provides the Pixally owner with a centralized view of all subscription payment activity across the platform. It enables tracking of payment statuses (upcoming, overdue, processing, paid, failed, and refunded), manual intervention on payments (charge, retry, refund, send reminders/notifications), configuration of automated failed payment handling (notifications, account suspension, and account deletion), and invoice management. Subscription payments are always processed through Stripe using a credit card (subscriptions cannot be paid by ACH, cash, or other methods, because recurring subscription charges require automatic billing without manual intervention). This module is the financial operations center of the Gawd Portal, ensuring revenue continuity and proactive management of subscriber payment issues.
Business Goals:
- Provide complete visibility into all subscription payment transactions across every status lifecycle stage.
- Enable the Pixally owner to take manual action on payments — charge, retry, refund (full or partial), and send reminder/failure notifications.
- Configure automated failed payment workflows including retry schedules, notification triggers, account suspension timelines, and account deletion policies.
- Support proactive overdue payment management through reminder emails.
- Track refund activity in a dedicated view for financial reconciliation.
- Provide invoice download capability for record-keeping and audit purposes.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all payments, filter and search payments, expand payment rows for detail, use all kebab menu actions (charge, refund, retry, send reminders/notifications, download invoice), configure Adjust Failed Payments settings, access all tabs including Refunds.
Customer Support Executive
No Access
The Customer Support role does not have access to the Payments module.
3. User Flow
3.1 Payments Listing Flow
3.1.1 The user clicks "Payments" in the left sidebar navigation menu.
3.1.2 The system loads the Payments page with the "All" tab selected by default, displaying all payment records across all statuses.
3.1.3 The system displays the page title "Payments," the "Adjust Failed Payments" button, seven status tabs (All, Upcoming, Overdue, Processing, Paid, Failed, Refunds), a search bar, a filter icon button, and the payments data table with pagination controls.
3.1.4 The user clicks any status tab to filter the listing to show only payments matching that status.
3.1.5 The user types a subscriber name or invoice number in the search bar, and the system filters the table results in real-time.
3.1.6 The user clicks the filter icon button to open the Filters side panel.
3.1.7 The user applies one or more filters (Date Issued, Payment Due Date, Amount range, User), and the system updates the listing table to show only matching payment records.
3.1.8 The user clicks any sortable column header to sort the table in ascending or descending order.
3.1.9 The user clicks the expand/collapse chevron on a payment row to view or hide the expanded payment detail section.
3.1.10 The user clicks the kebab menu (three-dot icon) on any payment row to see the available actions based on that payment's status.
3.1.11 The user uses the pagination controls at the bottom of the table to navigate through payment records.
3.2 Charge Manually Flow
3.2.1 The user clicks the kebab menu on an Upcoming or Overdue payment and selects "Charge Manually."
3.2.2 The system displays a confirmation popup: "Are you sure you want to charge [Subscriber Name] the amount of [Amount] for invoice [Invoice Number]? This will immediately process the payment using their payment method on file."
3.2.3 The user clicks "Confirm" to proceed, and the system initiates a Stripe charge against the subscriber's stored payment method.
3.2.4 If the charge is successful, the system updates the payment status to "Paid," records the payment date, and displays a success message.
3.2.5 If the charge fails, the system displays an error message with the failure reason from Stripe and the payment status remains unchanged.
3.2.6 The user may click "Cancel" on the confirmation popup to abort the action without processing any charge.
3.3 Refund Flow
3.3.1 The user clicks the kebab menu on a Paid payment and selects "Refund."
3.3.2 The system opens the Refund popup displaying the subscriber's name, email, payment method (masked), and the original payment amount.
3.3.3 The user enters the refund amount in the "Amount" field and optionally enters a note in the "Note (Optional)" field. To issue a full refund, the user enters the full original amount; to issue a partial refund, the user enters a smaller amount.
3.3.4 The system displays a helper text below the Amount field indicating the maximum refund limit: "Cannot exceed [Original Amount]."
3.3.5 The popup displays a note: "Please Note: Refunds may take 5–10 business days to process, depending on the customer's bank or provider."
3.3.6 The user clicks "Refund [Entered Amount]" to process the refund.
3.3.7 The system validates that the amount is greater than $0 and does not exceed the original payment amount, then initiates the refund through Stripe. If the entered amount equals the full original amount, the payment status is updated to "Refunded"; if it is less, the status is updated to "Partial Refund." A success message is displayed.
3.3.8 The user may click "Cancel" to close the popup without processing any refund.
3.5 Retry Payment Flow
3.5.1 The user clicks the kebab menu on a Failed payment and selects "Retry Payment."
3.5.2 The system displays a confirmation popup: "Are you sure you want to retry the payment of [Amount] for invoice [Invoice Number]? This will attempt to charge [Subscriber Name]'s payment method on file."
3.5.3 The user clicks "Confirm" to proceed, and the system initiates a Stripe charge against the subscriber's stored payment method.
3.5.4 If the retry is successful, the system updates the payment status to "Paid," records the payment date, and displays a success message.
3.5.5 If the retry fails, the system displays an error message with the failure reason from Stripe, sends an email notification to both the subscriber and the Pixally owner informing them of the failed retry, and the payment status remains "Failed."
3.5.6 The user may click "Cancel" to abort the retry without processing any charge.
3.6 Send Reminder Email Flow (Overdue)
3.6.1 The user clicks the kebab menu on an Overdue payment and selects "Send Reminder Email."
3.6.2 The system opens the Overdue Payment Reminder popup with the subscriber's name, company, invoice number, overdue amount, and an editable subject line and rich text email body pre-filled with a default overdue payment reminder template.
3.6.3 The user may edit the subject and email body content.
3.6.4 The user clicks "Send Reminder" to send the email to the subscriber.
3.6.5 The system sends the email, updates the reminder tracking, and displays a success message.
3.6.6 The user may click "Cancel" to close the popup without sending.
3.7 Send Failure Notification Flow
3.7.1 The user clicks the kebab menu on a Failed payment and selects "Send Failure Notification."
3.7.2 The system opens the Payment Failure Notification popup with the subscriber's name, company, invoice number, failed amount, and an editable subject line and rich text email body pre-filled with a default payment failure notification template.
3.7.3 The user may edit the subject and email body content.
3.7.4 The user clicks "Send Notification" to send the email to the subscriber.
3.7.5 The system sends the email and displays a success message.
3.7.6 The user may click "Cancel" to close the popup without sending.
3.8 Adjust Failed Payments Flow
3.8.1 The user clicks the "Adjust Failed Payments" button at the top of the Payments page.
3.8.2 The system opens the Adjust Failed Payments popup with the current configuration for automated retries, notifications, and account suspension/deletion settings.
3.8.3 The user configures the desired settings across the two sections: Automated Notifications, and Suspend and Delete Account. (Retry behavior is handled in Stripe and is not configured here.)
3.8.4 The user clicks "Save Changes" to apply the new configuration.
3.8.5 The system saves the settings, and all future failed payment handling follows the updated configuration.
3.8.6 The user may click "Cancel" to close the popup without saving any changes.
3.9 Download Invoice Flow
3.9.1 The user clicks the kebab menu on any payment row and selects "Download Invoice."
3.9.2 The system generates and downloads the invoice as a PDF file to the user's browser.
4. Functional Logic
4.1 Payments Listing Page
4.1.1 Page Layout and Structure
- The Payments page displays the title "Payments" at the top of the main content area.
- One action button is positioned in the top-right corner: "Adjust Failed Payments" (outlined/secondary style with a settings icon). There is no "+ Create Invoice" button — this was removed because subscription payments are always handled through Stripe (credit card only), and any additional invoicing can be done directly in Stripe if ever needed.
- Below the title and action buttons, seven horizontal tab filter buttons are displayed: All, Upcoming, Overdue, Processing, Paid, Failed, and Refunds.
- To the right of the tabs, a search bar and a filter icon button are displayed.
- Below the tabs and search area, the payments data table is displayed with column headers, expandable data rows, and pagination controls at the bottom.
4.1.2 Tab Filtering
- The "All" tab is selected by default when the Payments page is loaded, displaying all payment records across all statuses.
- Each tab filters the listing to display only payments matching that specific status:
- All: All payments regardless of status.
- Upcoming: Payments that are scheduled but not yet due.
- Overdue: Payments that have passed their due date without being paid.
- Processing: Payments that are currently being processed by Stripe.
- Paid: Payments that have been successfully processed and completed.
- Failed: Payments where the charge attempt was unsuccessful.
- Refunds: Payments that have been fully or partially refunded.
- Only one tab can be selected at a time, and the selected tab is visually highlighted with a filled background.
- When a tab is switched, any previously applied search query or filter remains active and is combined with the tab filter.
- The tab counts are not displayed on the tab buttons; tabs serve as filter toggles only.
4.1.3 Table Columns
- The payments listing table displays the following sortable columns:
- Invoice Number (↓): The unique invoice identifier (e.g., "INV000001"). Displayed with an expand/collapse chevron icon to the left. Clicking the chevron expands or collapses the row detail section.
- Status (↓): The current payment status displayed as a color-coded badge. Possible values: Upcoming (yellow/amber), Overdue (red), Processing (blue), Paid (green), Failed (red/dark), Refunded (purple/blue), Partial Refund (purple/blue).
- Subscriber (↓): The subscriber's name, email address, and avatar. Displays the agency owner's full name with their email address below.
- Amount (↓): The payment amount in USD (e.g., "$99," "$20").
- Due Date (↓): The date by which the payment is due (e.g., "10/10/24"). Displays a dash ("–") if no due date is applicable.
- Payment Date (↓): The date the payment was successfully processed (e.g., "10/10/24"). Displays a dash ("–") if the payment has not been made.
- Reason (↓): The reason for the charge (e.g., "Monthly charge," "Additional seats," "Annual renewal").
- Each row has a kebab menu (three-dot icon) on the far right for status-specific actions.
- The default sort order is by Invoice Number in descending order (most recent first).
- Clicking any column header toggles the sort between ascending and descending.
4.1.4 Expanded Row Detail
- Each payment row can be expanded by clicking the chevron icon to the left of the Invoice Number.
- The expanded section displays the following additional details:
- Due date: The payment due date (e.g., "10/10/24").
- Reminder sent: The date the last payment reminder was sent, or "N/A" if no reminder has been sent.
- Paid by: The name of the person/entity who made the payment (e.g., subscriber name), or a placeholder if not yet paid.
- Payment Method: The masked payment method used (e.g., "Visa 8548"). Only the card type and last four digits are shown.
- Trace ID: The transaction reference identifier from Stripe (e.g., "TD55645").
- Below the detail fields, a 3-step payment timeline is displayed horizontally:
- Charged: The date the payment was charged (e.g., "Mar 10, 2024"). Displayed with a green dot when completed.
- Processed: The date the payment was processed by the payment gateway (e.g., "Mar 11, 2024"). Displayed with a green dot when completed.
- Deposited: The date the funds were deposited to the Pixally owner's account (e.g., "Mar 12, 2024"). Displayed with a green dot when completed.
- Only completed steps are highlighted with a green dot and date. Pending steps remain unhighlighted without a date.
- For payments that are not yet Paid (e.g., Upcoming, Overdue), the timeline steps are all unhighlighted.
- For a Failed payment, the timeline reflects the failed state, indicating the point at which the payment failed and the number of times the payment has failed. This helps the Pixally owner understand the payment's history at a glance.
- The Deposited step is typically completed a few days after Charged and Processed (which for credit cards usually complete within minutes of each other); retaining the Deposited date helps the Pixally owner reconcile deposits against their banking records.
- Clicking the chevron again collapses the expanded row back to the summary view.
4.1.5 Kebab Menu Actions by Payment Status
- Upcoming: Charge Manually, Download Invoice.
- Overdue: Charge Manually, Send Reminder Email, Download Invoice.
- Processing: Download Invoice.
- Paid: Refund, Download Invoice.
- Failed: Retry Payment, Send Failure Notification, Download Invoice.
- Refunded / Partial Refund: Download Invoice.
- Each menu action opens its respective popup or triggers its respective action as described in the individual flow sections.
4.1.6 Search
- The search bar is positioned to the right of the tab filters.
- The search performs a real-time filter on the payments listing as the user types.
- The search matches against the subscriber's name, subscriber's email, and invoice number.
- The search is case-insensitive and supports partial matching (e.g., typing "INV000" matches "INV000001," "INV000002," etc.).
- If no results match the search query, the table displays an empty state with the message: "No payments found matching your search."
- The search works in combination with the selected tab filter and any applied Filters panel options.
4.1.7 Filters Panel
- Clicking the filter icon button opens the Filters panel as a side drawer on the right side of the page.
- The Filters panel header displays "Filters" with a reset/refresh icon (↻) that clears all applied filters when clicked.
- The Filters panel contains the following filter options:
- Date Issued: A date picker that allows the user to select a specific date or date range for when the invoice was issued.
- Payment Due Date: A date picker that allows the user to select a specific date or date range for the payment due date.
- Amount: A dual-handle range slider with Min ($) (default: $0) and Max ($) (default: $200) input fields. The slider scale displays markers at $0, $40, $80, $120, $160, $200.
- User: A searchable list of subscribers. The user can search by name and select one or more subscribers to filter payments by that specific subscriber.
- Filters are applied dynamically as the user adjusts them.
- Filters work in combination with the selected tab and any active search query.
- The reset icon clears all filters: date pickers are cleared, the amount range slider resets to $0–$200, and all user selections are cleared.
4.1.8 Pagination
- Pagination controls are displayed at the bottom-right of the payments table.
- The pagination displays: "Rows per page:" dropdown (default: 10, options: 10, 25, 50, 100), current range indicator (e.g., "6-10 of 11"), and previous/next page navigation arrows (< >).
- The left arrow is disabled on the first page, and the right arrow is disabled on the last page.
- Changing the "Rows per page" value resets the view to page 1 with the new page size applied.
4.1.9 Refunds Tab
- The Refunds tab displays all refunded payment records in the system.
- The Refunds tab table displays the following columns, in order:
- Invoice Number: The invoice number of the original payment that was refunded (with an expand/collapse chevron to reveal additional detail).
- Status: The refund status displayed as a color-coded badge (see status list below).
- Subscriber: The subscriber's name (and company/email as applicable).
- Amount: The original payment amount in USD.
- Payment Date: The date the original payment was made.
- Refund Type: "Full Refund" or "Partial Refund," derived automatically from whether the refunded amount equaled the original payment (full) or was less than it (partial).
- Refund Amount: The amount refunded in USD (e.g., "$99.00," "$10.00").
- Refund Date: The date the refund was initiated or processed.
- Notes: Any notes entered during the refund process. Displays "–" if no notes were provided.
- Each row can be expanded (via the chevron on the Invoice Number) to reveal the following additional details:
- Refunded by: The name of the Pixally-side user who processed the refund.
- Payment Method: The masked payment method the refund was issued back to (e.g., "Visa •••• 4242").
- Trace ID: The transaction reference identifier from Stripe for the refund.
- The Refunds tab has the following status badges: Refunded (full refund completed), Partial Refund (partial refund completed), Processing (refund is being processed), Failed (refund attempt failed).
- Each row in the Refunds tab has a kebab menu with "Download Invoice" as the only available action.
- The Refunds tab supports the same search, sort, and pagination functionality as other tabs.
4.2 Charge Manually
- The "Charge Manually" action is available in the kebab menu for payments with the "Upcoming" or "Overdue" status. It is primarily used when a payment has failed or is overdue and the subscriber has since added funds or fixed their payment method and asked to be charged, allowing the Pixally owner to trigger the charge immediately rather than waiting for Stripe's next automatic retry.
- When the user selects "Charge Manually," the system displays a confirmation popup with the subscriber's name, the invoice number, and the charge amount.
- The confirmation popup message reads: "Are you sure you want to charge [Subscriber Name] the amount of [Amount] for invoice [Invoice Number]? This will immediately process the payment using their payment method on file."
- The popup has two action buttons: "Cancel" (aborts the action) and "Confirm Charge" (proceeds with the charge).
- Upon confirmation, the system sends a charge request to Stripe using the subscriber's stored payment method.
- If the charge is successful, the payment status is updated to "Paid," the Payment Date is set to the current date/time, the 3-step timeline begins (Charged step is completed), and a success message is displayed.
- If the charge fails, the system displays an error message containing the failure reason returned by Stripe (e.g., "Card declined," "Insufficient funds"). The payment status remains unchanged (Upcoming or Overdue). The Pixally owner may retry the charge or take alternative action.
4.3 Refund
- The "Refund" action is available in the kebab menu for payments with the "Paid" status only.
- When the user selects "Refund," the system opens a single Refund popup that handles both full and partial refunds (the two were combined into one screen so the Pixally owner simply enters the amount they wish to refund).
- The popup displays the title "Refund" at the top.
- The popup description reads: "Enter the amount to refund for Invoice [Invoice Number]. The refund will be issued back to the customer's original payment method."
- The popup displays the subscriber's name and email address in a card-style layout, followed by the payment details showing the Payment Method (masked, e.g., "Visa •••• 4242") and the original payment Amount.
- The popup contains an Amount input field — a currency input field prefixed with "$" where the user enters the desired refund amount, with a helper text below the field that reads: "Cannot exceed [Original Amount]."
- The popup contains a Note (Optional) field — a multi-line text area for the Pixally owner to enter a reason for the refund.
- The popup includes an information note: "Please Note: Refunds may take 5–10 business days to process, depending on the customer's bank or provider."
- The popup has two action buttons: "Cancel" (closes without action) and "Refund [Entered Amount]" (processes the refund). The refund button dynamically updates to show the entered amount.
- The refund amount must be greater than $0 and must not exceed the original payment amount. The system validates this before processing.
- The refund type is determined automatically from the amount entered: if the entered amount equals the full original payment amount, it is processed as a full refund and the payment status is updated to "Refunded"; if the entered amount is less than the original, it is processed as a partial refund and the payment status is updated to "Partial Refund."
- Upon clicking the refund button, the system initiates the refund through Stripe for the specified amount.
- If the refund is successful, the record appears in the Refunds tab (with the refund amount and any notes), and a success message is displayed.
- If the refund fails, the system displays an error message with the failure reason from Stripe. The payment status remains "Paid."
- Multiple partial refunds may be issued against the same payment, as long as the cumulative refund total does not exceed the original payment amount. Once the cumulative refunds equal the original amount, the payment is considered fully refunded.
4.4 Retry Payment
- The "Retry Payment" action is available in the kebab menu for payments with the "Failed" status only.
- When the user selects "Retry Payment," the system displays a confirmation popup.
- The confirmation popup message reads: "Are you sure you want to retry the payment of [Amount] for invoice [Invoice Number]? This will attempt to charge [Subscriber Name]'s payment method on file."
- The popup has two action buttons: "Cancel" (aborts the action) and "Confirm Retry" (proceeds with the retry).
- Upon confirmation, the system sends a charge request to Stripe using the subscriber's stored payment method.
- If the retry is successful, the payment status is updated to "Paid," the Payment Date is set to the current date/time, and a success message is displayed.
- If the retry fails, the system displays an error message with the failure reason from Stripe, the payment status remains "Failed," and the system sends an automatic email notification to both the subscriber and the Pixally owner informing them that the manual retry attempt has also failed.
- The retry failure email to the subscriber includes a prompt to update their payment method.
- The retry failure email to the Pixally owner includes the subscriber's name, invoice number, amount, and the Stripe failure reason.
4.5 Send Reminder Email (Overdue Payments)
- The "Send Reminder Email" action is available in the kebab menu for payments with the "Overdue" status only.
- When the user selects "Send Reminder Email," the system opens a popup similar in structure to the Credit Card Expiration Reminder popup (defined in FRD #2 — Subscribers).
- The popup displays the title "Overdue Payment Reminder" at the top, followed by contextual information including the subscriber's name, company name, invoice number, and the overdue amount.
- The popup contains a Subject field — a text input pre-filled with a default subject line (e.g., "Your Pixally payment is overdue — action required") that the Pixally owner can edit.
- The popup contains an Email Body field — a rich text editor pre-filled with a default overdue payment reminder template, including the subscriber's name, overdue amount, invoice number, and a link to update their payment method or pay the invoice.
- The Pixally owner can edit the subject and email body before sending.
- The popup has two action buttons: "Cancel" (closes without sending) and "Send Reminder" (sends the email).
- Upon clicking "Send Reminder," the system sends the email to the subscriber's registered email address and displays a success message.
4.6 Send Failure Notification
- The "Send Failure Notification" action is available in the kebab menu for payments with the "Failed" status only.
- When the user selects "Send Failure Notification," the system opens a popup with editable content.
- The popup displays the title "Payment Failure Notification" at the top, followed by contextual information including the subscriber's name, company name, invoice number, and the failed amount.
- The popup contains a Subject field — a text input pre-filled with a default subject line (e.g., "Your Pixally payment could not be processed") that the Pixally owner can edit.
- The popup contains an Email Body field — a rich text editor pre-filled with a default payment failure notification template, including the subscriber's name, failed amount, invoice number, failure reason (if available from Stripe), and a link to update their payment method.
- The Pixally owner can edit the subject and email body before sending.
- The popup has two action buttons: "Cancel" (closes without sending) and "Send Notification" (sends the email).
- Upon clicking "Send Notification," the system sends the email to the subscriber's registered email address and displays a success message.
4.7 Download Invoice
- The "Download Invoice" action is available in the kebab menu for all payment statuses.
- When the user selects "Download Invoice," the system generates a PDF invoice and downloads it directly to the user's browser.
- The filename convention is: "INV[InvoiceNumber]_[SubscriberName].pdf" (e.g., "INV000001_DavidRolland.pdf").
- The invoice PDF includes: Pixally branding, invoice number, issue date, due date, subscriber details, payment method (masked), line items with amounts, total amount, payment status, and transaction reference (Trace ID) if available.
4.8 Adjust Failed Payments
- The "Adjust Failed Payments" button is displayed at the top-right of the Payments page with a settings/gear icon.
- Clicking this button opens the Adjust Failed Payments popup, which allows the Pixally owner to configure the automated handling of failed payments across the platform.
- The popup is divided into two configuration sections: Automated Notifications, and Suspend and Delete Account.
- Automatic retry handling (how many times a failed payment is retried and the interval between retries) is not configured in this popup. Payment retry logic is handled directly and globally in Stripe. When a subscription payment fails, Stripe automatically retries the charge according to the retry rules configured in Stripe, and the Gawd Portal reflects the resulting payment status.
4.8.1 Automated Notifications
- Send email and text reminders: A checkbox toggle (default: checked/enabled). When enabled, the system automatically sends email and text reminders to subscribers when their payment fails.
- Reminder: A multi-line text area where the Pixally owner can enter or edit the custom reminder text that is included in the automated notification sent to subscribers. Placeholder text reads: "Enter your text reminder here."
- When the checkbox is unchecked, no automated notifications are sent for failed payments. The Pixally owner can still send manual notifications via the kebab menu.
4.8.2 Suspend and Delete Account
- Suspend account after: Two dropdowns side by side — a numeric value dropdown (options: 1 to 100) and a unit dropdown (options: weeks, days, months). This configures the grace period after a payment failure before the subscriber's account is suspended. The confirmed default grace period is 28 days (4 weeks) of non-payment, consistent with the suspension behavior documented in FRD #8 (Agency-Side Impact).
- During the grace period, the subscriber retains full access to the portal even though their payment has failed.
- Once the grace period expires, the system automatically suspends the subscriber's account. The subscriber can no longer access any portal features and is redirected to the subscription settings page to update their payment method (detailed in FRD #8 — Agency-Side Impact).
- Delete account after: Two dropdowns side by side — a numeric value dropdown (options: 1 to 100) and a unit dropdown (options: months, years). This configures the retention period after account suspension before the account data is permanently deleted.
- A yellow information note is displayed below the Delete account after setting: "Please Note: Account deletion only applies to suspended accounts." This clarifies that only accounts that have been suspended (due to failed payments) are subject to this automatic deletion policy.
- The delete action follows the same soft delete + hard delete logic defined in FRD #2 (Subscribers): subscriber metadata is retained, but agency data (projects, clients, files) is permanently deleted after the configured period.
- The popup has two action buttons: "Cancel" (closes without saving) and "Save Changes" (applies the configuration).
- Changes to these settings take effect immediately for all future failed payment events. Existing suspended accounts are not retroactively affected by changes to the suspension timeline; they follow the configuration that was in place at the time of their suspension.
4.9 Payment Status Lifecycle
- Upcoming → Paid: When an upcoming payment is successfully charged (automatically on the due date or manually by the Pixally owner).
- Upcoming → Overdue: When the due date passes without successful payment.
- Overdue → Paid: When an overdue payment is successfully charged manually.
- Overdue → Failed: When Stripe's automatic retry attempts are exhausted without success.
- Failed → Paid: When a manual retry is successful.
- Paid → Refunded: When a full refund is processed.
- Paid → Partial Refund: When a partial refund is processed.
- Processing → Paid: When the payment gateway completes processing successfully.
- Processing → Failed: When the payment gateway returns a failure during processing.
- Status transitions are logged and visible in the payment's expanded detail and the subscriber's payment history (in the Subscribers module).
5. Field Details & Validations
5.1 Payments Listing Table Fields
Field Name
Field Type
Validation / Display Rules
Invoice Number
Text (Read-only)
Format: "INV" followed by 6 digits (e.g., "INV000001"). Clickable chevron to expand/collapse row detail.
Status
Badge (Read-only)
Color-coded badge. Values: Upcoming (yellow), Overdue (red), Processing (blue), Paid (green), Failed (dark red), Refunded (purple), Partial Refund (purple).
Subscriber
Text + Avatar (Read-only)
Displays subscriber's avatar, full name, and email address.
Amount
Currency (Read-only)
USD format (e.g., "$99"). Whole number or two decimals as applicable.
Due Date
Date (Read-only)
Format: MM/DD/YY. Displays "–" if not applicable.
Payment Date
Date (Read-only)
Format: MM/DD/YY. Displays "–" if payment has not been made.
Reason
Text (Read-only)
Charge reason (e.g., "Monthly charge," "Additional seats," "Annual renewal").
5.2 Expanded Row Detail Fields
Field Name
Field Type
Validation / Display Rules
Due date
Date (Read-only)
Format: MM/DD/YY.
Reminder sent
Date/Text (Read-only)
Displays last reminder date or "N/A" if no reminder sent.
Paid by
Text (Read-only)
Subscriber name or placeholder.
Payment Method
Text (Read-only)
Masked: "[Card Type] [Last 4 digits]" (e.g., "Visa 8548").
Trace ID
Text (Read-only)
Stripe transaction reference (e.g., "TD55645").
Charged
Date (Read-only)
Date with green dot if completed. Empty if pending.
Processed
Date (Read-only)
Date with green dot if completed. Empty if pending.
Deposited
Date (Read-only)
Date with green dot if completed. Empty if pending.
5.3 Refunds Tab Fields
Field Name
Field Type
Validation / Display Rules
Invoice Number
Text (Read-only)
The original payment's invoice number, with an expand/collapse chevron.
Status
Badge (Read-only)
Values: Refunded, Partial Refund, Processing, Failed.
Subscriber
Text (Read-only)
Subscriber name (and company/email as applicable).
Amount
Currency (Read-only)
Original payment amount in USD.
Payment Date
Date (Read-only)
Format: MM/DD/YY. Date the original payment was made.
Refund Type
Text (Read-only)
Values: "Full Refund" or "Partial Refund."
Refund Amount
Currency (Read-only)
USD format (e.g., "$99.00," "$10.00").
Refund Date
Date (Read-only)
Format: MM/DD/YY. Date the refund was initiated.
Notes
Text (Read-only)
Refund note or "–" if none provided.
Refunded by (expanded)
Text (Read-only)
Name of the Pixally-side user who processed the refund.
Payment Method (expanded)
Text (Read-only)
Masked payment method the refund was issued to (e.g., "Visa •••• 4242").
Trace ID (expanded)
Text (Read-only)
Stripe transaction reference for the refund.
5.4 Refund Popup Fields
Field Name
Field Type
Validation Rules
Subscriber Name
Text (Read-only)
Auto-populated.
Subscriber Email
Text (Read-only)
Auto-populated.
Payment Method
Text (Read-only)
Masked card display. Auto-populated.
Original Amount
Currency (Read-only)
Full original payment amount. Auto-populated.
Amount
Currency Input
Required. Must be > $0. Must not exceed original payment amount. Prefix: "$". Helper text: "Cannot exceed [Original Amount]." Entering the full amount = full refund (status "Refunded"); a lesser amount = partial refund (status "Partial Refund").
Note (Optional)
Multi-line Text
Optional. Free-text. No character limit enforced in UI.
Refund Button
Button
Label: "Refund [Entered Amount]." Dynamically updates. Triggers Stripe refund on click.
5.5 Adjust Failed Payments Popup Fields
Field Name
Field Type
Validation Rules
Send email and text reminders
Checkbox
Default: checked. Toggle on/off.
Reminder text
Multi-line Text
Optional (only required if checkbox is checked). Placeholder: "Enter your text reminder here."
Suspend account after (value)
Dropdown
Required. Options: 1 through 100.
Suspend account after (unit)
Dropdown
Required. Options: weeks, days, months.
Delete account after (value)
Dropdown
Required. Options: 1 through 100.
Delete account after (unit)
Dropdown
Required. Options: months, years.
5.6 Filters Panel Fields
Field Name
Field Type
Validation Rules
Date Issued
Date Picker
Optional. Select single date or date range.
Payment Due Date
Date Picker
Optional. Select single date or date range.
Amount (Min $)
Numeric Input + Slider
Default: $0. Min: $0, Max: $200. Must be ≤ Max value.
Amount (Max $)
Numeric Input + Slider
Default: $200. Min: $0, Max: $200. Must be ≥ Min value.
User
Searchable Multi-select List
Optional. Lists all subscribers with search. Multiple selections allowed.
5.7 Send Reminder / Failure Notification Popup Fields
Field Name
Field Type
Validation Rules
Subject
Text Input
Required. Pre-filled with default. Editable. Maximum 255 characters.
Email Body
Rich Text Editor
Required. Pre-filled with default template. Editable. Supports heading, bold, italic, underline formatting.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Charge Manually
"Payment of [Amount] charged successfully to [Subscriber Name]."
Stripe charge succeeds for an Upcoming or Overdue payment.
Popup closes. Payment status updates to "Paid." Payment Date populated.
Refund (Full)
"Full refund of [Amount] processed successfully for [Subscriber Name]."
Stripe refund succeeds when the entered amount equals the original payment.
Popup closes. Payment status updates to "Refunded." Record appears in Refunds tab.
Refund (Partial)
"Partial refund of [Amount] processed successfully for [Subscriber Name]."
Stripe refund succeeds when the entered amount is less than the original payment.
Popup closes. Payment status updates to "Partial Refund." Record appears in Refunds tab with notes.
Retry Payment
"Payment retry successful. [Amount] charged to [Subscriber Name]."
Stripe retry charge succeeds for a Failed payment.
Popup closes. Payment status updates to "Paid." Payment Date populated.
Send Reminder Email
"Overdue payment reminder sent successfully to [Subscriber Name]."
Email sent for an Overdue payment.
Popup closes. Reminder tracking updated.
Send Failure Notification
"Payment failure notification sent successfully to [Subscriber Name]."
Email sent for a Failed payment.
Popup closes.
Download Invoice
No explicit toast. File downloads automatically.
User selects "Download Invoice" from kebab.
PDF file downloads to browser.
Adjust Failed Payments — Save
"Failed payment settings updated successfully."
User clicks "Save Changes" with valid settings.
Popup closes. New settings apply to all future failed payment events.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Charge Manually — Stripe Failure
"Payment charge failed: [Stripe Reason]. Please verify the subscriber's payment method or try again."
Stripe returns a failure (e.g., card declined, insufficient funds).
Toast error. Popup closes. Payment status remains Upcoming/Overdue.
Refund — Empty Amount
"Please enter a refund amount."
User clicks "Refund" without entering an amount.
Inline error below the Amount field.
Refund — Amount Exceeds Original
"Refund amount cannot exceed the original payment of [Amount]."
User enters a refund amount greater than the original payment.
Inline error below the Amount field.
Refund — Amount Zero or Negative
"Refund amount must be greater than $0."
User enters $0 or a negative value.
Inline error below the Amount field.
Refund — Cumulative Exceeds Original
"Total refunds cannot exceed the original payment amount of [Amount]. Remaining refundable: [Remaining]."
User enters an amount that, combined with previous partial refunds, exceeds the original payment.
Inline error below the Amount field.
Refund — Stripe Failure
"Refund failed: [Stripe Reason]. Please try again or contact Stripe support."
Stripe returns a refund failure.
Toast error. Popup remains open. User can retry.
Retry Payment — Stripe Failure
"Payment retry failed: [Stripe Reason]. An email notification has been sent to the subscriber and yourself."
Stripe returns a failure during retry.
Toast error. Popup closes. Status remains "Failed." Email sent to subscriber and Pixally owner.
Send Reminder Email — Empty Subject
"Subject line is required."
User clears the subject field and clicks "Send."
Inline error below the Subject field.
Send Reminder Email — Empty Body
"Email body cannot be empty."
User clears the email body and clicks "Send."
Inline error below the email body editor.
Send Reminder Email — Send Failure
"Failed to send reminder. Please try again."
Server or email service error.
Toast error. Popup remains open. User can retry.
Send Failure Notification — Empty Subject
"Subject line is required."
User clears the subject field and clicks "Send."
Inline error below the Subject field.
Send Failure Notification — Empty Body
"Email body cannot be empty."
User clears the email body and clicks "Send."
Inline error below the email body editor.
Send Failure Notification — Send Failure
"Failed to send notification. Please try again."
Server or email service error.
Toast error. Popup remains open. User can retry.
Adjust Failed Payments — Missing Required Fields
"Please fill in all required fields before saving."
User clicks "Save Changes" with one or more required dropdowns empty.
Inline errors near the empty fields. Popup remains open.
Adjust Failed Payments — Save Failure
"Failed to save settings. Please try again."
Server error during save.
Toast error. Popup remains open. User can retry.
Download Invoice — Generation Failure
"Failed to generate invoice. Please try again."
Server error during PDF generation.
Toast error. No file downloaded.
Search — No Results
"No payments found matching your search."
Search query matches no payment records.
Message displayed in table body. Table headers remain visible.
Filter — Min Greater Than Max
"Minimum amount cannot be greater than maximum amount."
User sets Amount Min > Max in filters.
Inline error near the slider. Filter not applied until corrected.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
Pixally owner attempts to refund more than the original payment amount via partial refund.
The system rejects the refund with an error: "Refund amount cannot exceed the original payment of [Amount]."
2
Multiple partial refunds are issued against the same payment until the full amount is refunded.
The system tracks cumulative refund totals. Once the total reaches the original amount, no further refunds are allowed. The payment status changes to "Refunded" when fully refunded through partial refunds.
3
Pixally owner issues another refund for a payment that already has a partial refund.
The single Refund popup enforces that the newly entered amount plus all prior refunds cannot exceed the original payment. The helper text and validation reflect the remaining refundable balance, so the owner can refund up to the remaining amount. When cumulative refunds reach the original amount, the payment is fully refunded.
4
Payment is in "Processing" status and the Pixally owner clicks the kebab menu.
Only "Download Invoice" is available. All charge, refund, and retry actions are unavailable while processing.
5
Pixally owner charges an Upcoming payment manually before the due date.
The system processes the charge. If successful, the payment moves to "Paid" immediately. The scheduled automatic charge for the due date is cancelled.
6
Stripe is temporarily unavailable when the Pixally owner attempts a manual charge.
The system displays a network/service error: "Unable to process payment. Stripe service is temporarily unavailable. Please try again later."
7
Adjust Failed Payments settings are saved with "Suspend account after: 0 days."
The dropdown minimum is 1, so 0 is not selectable. If somehow submitted, the system rejects it with a validation error.
8
Subscriber's stored payment method is expired when the Pixally owner attempts a manual charge.
Stripe returns a "Card expired" failure. The system displays the error and suggests sending a reminder to the subscriber to update their card.
9
The Refunds tab is loaded but no refunds have been issued yet.
The tab displays an empty state: "No refunds found." Table column headers remain visible.
10
Pixally owner expands a payment row for a "Failed" payment.
The expanded detail shows the due date and reminder sent information, but the 3-step timeline (Charged/Processed/Deposited) is entirely unhighlighted since no charge was completed.
11
Payment record has a very long subscriber name or email address.
Text is truncated with an ellipsis in the table cell. Full text is shown on hover via a tooltip.
12
Pixally owner changes the Adjust Failed Payments settings while a subscriber is in an active grace period.
The change applies only to future failed payment events. The subscriber currently in a grace period continues under the settings that were in effect when their payment failed.
13
All automatic retries are exhausted, and the payment remains failed.
The system stops retrying automatically. The payment remains in "Failed" status. The Pixally owner can still manually retry via the kebab menu. The suspension countdown begins based on the Adjust Failed Payments configuration.
14
Pixally owner rapidly clicks "Confirm Charge" on the manual charge confirmation popup.
The system debounces the action and processes the charge only once. The button is disabled after the first click.
15
The Payments page is loaded with 10,000+ payment records.
Data is loaded in paginated batches. Only the current page's data is fetched from the server. Sorting and filtering may require server-side processing.
16
Pixally owner downloads an invoice for a "Refunded" payment.
The downloaded PDF reflects the original charge details with a "Refunded" status indicator. Refund details (amount, date) are included on the invoice.
17
Subscriber has no payment method on file and the Pixally owner attempts to charge manually.
Stripe returns an error: "No payment method on file." The system displays the error and the charge is not processed.
18
Pixally owner opens the Adjust Failed Payments popup and clicks "Cancel" without making changes.
The popup closes without any changes. All existing settings remain intact.
19
Filter by User is applied, selecting a subscriber who has no payments.
The table displays: "No payments found matching your filters."
20
Pixally owner issues a partial refund with a note containing 1000+ characters.
The system accepts the note. There is no character limit enforced in the UI for the note field.
9. Acceptance Criteria
9.1 Payments Listing
- The Payments page loads with the "All" tab selected by default, displaying all payment records.
- All seven tabs (All, Upcoming, Overdue, Processing, Paid, Failed, Refunds) correctly filter payments by status.
- The table displays the correct columns: Invoice Number, Status, Subscriber, Amount, Due Date, Payment Date, Reason.
- All column headers support ascending/descending sorting.
- The search bar filters results in real-time by subscriber name, email, and invoice number.
- The Filters panel opens correctly with all filter options (Date Issued, Payment Due Date, Amount range, User search) functioning as expected.
- Pagination controls work correctly with configurable rows per page.
9.2 Expanded Row Detail
- Clicking the chevron expands the row to show Due Date, Reminder Sent, Paid By, Payment Method, Trace ID, and the 3-step payment timeline.
- Only completed timeline steps are highlighted with green dots and dates.
- Clicking the chevron again collapses the expanded section.
9.3 Kebab Menu Actions
- Each payment status shows the correct kebab menu options as defined.
- "Charge Manually" shows confirmation popup and processes charge via Stripe for Upcoming/Overdue payments.
- "Refund" opens a single refund popup with an editable amount field and optional note for Paid payments; entering the full amount processes a full refund and a lesser amount processes a partial refund.
- "Retry Payment" shows confirmation popup and processes retry via Stripe for Failed payments, with email notification on retry failure.
- "Send Reminder Email" opens an editable email popup for Overdue payments.
- "Send Failure Notification" opens an editable email popup for Failed payments.
- "Download Invoice" downloads a correctly formatted PDF for all statuses.
9.4 Refunds Tab
- The Refunds tab displays all refunded records with columns: Invoice Number, Status, Subscriber, Amount, Payment Date, Refund Type, Refund Amount, Refund Date, Notes.
- Expanding a row reveals Refunded by, Payment Method, and Trace ID.
- Correct status badges are shown: Refunded, Partial Refund, Processing, Failed.
- Search, sort, and pagination work correctly within the Refunds tab.
9.5 Adjust Failed Payments
- The popup opens with the current saved configuration.
- All dropdown options display the correct value ranges.
- The "Send email and text reminders" checkbox enables/disables the reminder text field.
- The information note about account deletion applying only to suspended accounts is displayed.
- Saving applies the settings globally for all future failed payment events.
- Existing grace periods are not retroactively affected by setting changes.
10. Manual Test Cases
Test cases for this module are maintained in a separate Excel file for direct upload to the project management tool.
File: TC_FRD03_Payments.xlsx
Test Case Summary:
- Total Test Cases: See attached Excel file
- Categories Covered: Listing & Tabs, Search & Filters, Expanded Row, Charge Manually, Refund (Full/Partial combined), Retry Payment, Send Reminder, Send Failure Notification, Download Invoice, Adjust Failed Payments, Refunds Tab, Edge Cases
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Stripe Payment Gateway
External Service Dependency
All charge, retry, and refund operations fail. The system displays "Payment service unavailable" errors. Payment statuses cannot be updated. Existing data remains visible in read-only mode.
Authentication Service
Service Dependency
Cannot verify the Pixally owner's session. The Payments page returns an authentication error.
Subscribers Module (Gawd Portal — FRD #2)
Internal Dependency
Subscriber details displayed in payment rows, refund popups, and reminder popups originate from the Subscribers module. If unavailable, subscriber name/email may show as "Unknown."
Email Service (SMTP / Transactional Email Provider)
External Service Dependency
Overdue reminder emails, failure notifications, and retry failure emails cannot be sent. Manual send actions fail with an error message. Automated notifications from Adjust Failed Payments settings also fail.
Agency-Side Impact Module (Gawd Portal — FRD #8)
Cross-Module Dependency
Account suspension triggered by the Adjust Failed Payments settings manifests as agency-side impact screens (dashboard warning banners, suspended account redirects). If FRD #8 is not implemented, the suspension logic executes but the agency-side experience is not displayed.
Dashboard Module (Gawd Portal — FRD #1)
Internal Dependency
The Dashboard's "Recent Overdue Invoices" widget links to the Payments > Overdue tab via "View All." If Payments is unavailable, the "View All" link returns a "Module unavailable" error.
Notification Engine
Service Dependency
Automated retry failure emails and reminder emails fail silently if the notification engine is unavailable.
12. References
- Figma Link:
☑️ Lead Management
Functional Requirements Document (FRD) Gawd Portal — Lead Management
Module Name: Gawd Portal — Lead Management Version: 2.0 Created Date: March 27, 2026 Last Updated: July 21, 2026
1. Module Overview
Module Name: Gawd Portal — Lead Management
Purpose: The Lead Management module provides the Pixally owner with visibility into all non-converted free trial users on the platform. It tracks users who signed up for a free trial but have not yet purchased a paid subscription, enabling the Pixally owner to monitor sign-up activity, identify active vs. expired trial users, reset trial periods to encourage conversion, and remove fake or inactive accounts. This module serves as the primary tool for lead nurturing and trial-to-paid conversion analysis.
Business Goals:
- Track daily, weekly, and lifetime free trial sign-up metrics to measure acquisition performance.
- Identify non-converted trial users and segment them by active vs. expired trial status to prioritize outreach.
- Enable the Pixally owner to manually reset trial periods for users who need more evaluation time, increasing conversion chances.
- Support automatic trial resets every 3 months to give expired trial users additional opportunities to convert.
- Provide the ability to remove fake or spam accounts through soft delete functionality.
- Monitor trial reset frequency per user to identify high-engagement leads versus disengaged users.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all KPI cards, view non-converted trial user listing, search leads, reset free trial periods, delete trial users, export lead data, access all tabs.
Customer Support Executive
No Access
The Customer Support role does not have access to the Lead Management module.
3. User Flow
3.1 Lead Management Listing Flow
3.1.1 The user clicks "Lead Management" in the left sidebar navigation menu.
3.1.2 The system loads the Lead Management page displaying three KPI cards at the top (Today Sign-ups, Last 7 Days Sign-ups, Lifetime Sign-ups) and the non-converted free trial users listing below.
3.1.3 The system displays three tab filters below the KPI cards: All (selected by default), Active, and Expired.
3.1.4 The user observes the KPI cards showing today's sign-up count, the last 7 days' sign-up count, and lifetime total sign-ups.
3.1.5 The user clicks the "Active" tab to filter the listing to show only users whose 14-day free trial is still active (not yet expired).
3.1.6 The user clicks the "Expired" tab to filter the listing to show only users whose 14-day free trial has ended without converting to a paid subscription.
3.1.7 The user types a user name or email in the search bar, and the system filters the table results in real-time to show matching rows.
3.1.8 The user clicks any sortable column header to sort the table in ascending or descending order.
3.1.9 The user navigates between pages of results using the pagination controls at the bottom of the table.
3.2 Manual Trial Reset Flow
3.2.1 The user identifies a trial user in the listing and clicks the reset icon (↻) in the "Actions" column for that row.
3.2.2 The system displays a confirmation popup: "Are you sure you want to reset the free trial for [User Name]? This will give them a new 14-day trial starting today."
3.2.3 The user clicks "Confirm" to proceed with the trial reset.
3.2.4 The system resets the user's trial period to 14 days starting from today, increments the reset count in the "Reset Info" column, updates the trial expiry date, and displays a success message.
3.2.5 The user may click "Cancel" on the confirmation popup to abort the reset without any changes.
3.3 Delete Lead Flow
3.3.1 The user identifies a trial user in the listing and clicks the delete icon (🗑) in the "Actions" column for that row.
3.3.2 The system displays a confirmation popup: "Are you sure you want to delete this user? This is a soft delete — the user's agency data will be permanently removed after 1 year. Only the user's email address will be retained. This action cannot be undone."
3.3.3 The user clicks "Confirm" to proceed with the deletion.
3.3.4 The system performs a soft delete on the user, initiates the 1-year data retention countdown, removes the user from the listing, and displays a success message.
3.3.5 The user may click "Cancel" to abort the deletion without any changes.
3.4 Export Data Flow
3.4.1 The user clicks the "Export Data" button in the top-right corner of the Lead Management page.
3.4.2 The system generates a single Excel (.xlsx) file containing three tabs — All, Active, and Expired — each listing the leads for that tab.
3.4.3 The file downloads to the user's browser, and the system displays a success message.
3.4.4 If there are no leads matching the current view, the system informs the user that there is no data to export.
4. Functional Logic
4.1 Lead Management Page Layout
- The Lead Management page displays the title "Lead Management" at the top of the main content area.
- An "Export Data" button is displayed in the top-right corner of the page (with a download/export icon). It allows the Pixally owner to export the lead (non-converted free trial user) data so it can be used elsewhere, such as manually adding leads to an email marketing tool.
- Below the title, three KPI cards are displayed horizontally in a single row.
- Below the KPI cards, three tab filter buttons are displayed: All (selected by default), Active, and Expired.
- To the right of the tabs, a search bar is displayed. There is no separate filters panel or filter icon button; the tabs and search bar are the only ways to narrow the listing.
- Below the tabs and search area, the non-converted free trial users table is displayed with the section heading "Non-Converted Free Trial Users."
4.2 KPI Cards
- The KPI cards display simple numeric counts without percentage comparison indicators.
- Today Sign-ups: Displays the count of new free trial sign-ups for the current day (from 12:00 AM Eastern). Displayed with a calendar icon in a green circular badge.
- Last 7 Days Sign-ups: Displays the count of new free trial sign-ups over the last 7 days on a rolling basis. Displayed with a clock icon in a purple circular badge.
- Lifetime Sign-ups: Displays the total cumulative count of all free trial sign-ups since the platform's launch. Displayed with a calendar-check icon in an orange circular badge.
- All three KPI cards count only free trial sign-ups; paid subscribers who bypassed the free trial are not included.
- The KPI card data is loaded on page load and refreshes when the page is manually reloaded by the Pixally owner.
4.3 Tab Filtering
- The "All" tab is selected by default when the page is loaded, displaying all non-converted free trial users regardless of their trial status.
- The "Active" tab filters the listing to show only users whose 14-day free trial period is currently active (the trial has not yet expired).
- The "Expired" tab filters the listing to show only users whose 14-day free trial period has ended without the user converting to a paid subscription.
- Only one tab can be selected at a time, and the selected tab is visually highlighted with a filled red/primary background.
- Users who have converted to paid subscribers are not displayed in this module at all; they are managed in the Subscribers module (FRD #2).
- When a tab is switched, any previously entered search query remains active and is combined with the tab filter.
4.4 Non-Converted Free Trial Users Table
4.4.1 Table Columns
- The table displays the following columns, each with a sort arrow (↓) for ascending/descending sorting:
- User Details: Displays the user's full name and email address on two lines. The name is displayed in bold and the email in a lighter/secondary text style.
- Signed Up (↓): Displays the date the user signed up for the free trial. Format: DD/MM/YYYY (e.g., "15/08/2024").
- Expires (↓): Displays the date the user's current trial period expires (or expired). Format: DD/MM/YYYY. If the trial has been reset, this date reflects the new expiry date based on the most recent reset.
- Last Active (↓): Displays the date the agency owner was last active on the platform (the agency owner's last login or page visit). For leads, only the agency owner's activity is tracked here — team member activity is not counted. Format: DD/MM/YYYY.
- Status (↓): Displays the user's trial status as a color-coded badge: "Active" (green badge) if the trial is currently running, or "Expired" (red/pink badge) if the trial has ended.
- Reset Info (↓): Displays two pieces of information on two lines: "Resets: [count]" showing how many times the trial has been manually reset by the Pixally owner, and "Next auto: [DD/MM/YYYY]" showing the date of the next automatic trial reset.
- Actions: Displays two icon buttons per row: a reset icon (↻) to manually reset the user's trial period, and a delete icon (🗑) to soft-delete the user.
- The default sort order is by "Signed Up" in descending order (most recent sign-ups first).
- Clicking any sortable column header toggles the sort between ascending and descending.
4.4.2 Trial Reset Logic — Manual
- The Pixally owner can manually reset a user's free trial period at any time by clicking the reset icon (↻) in the Actions column.
- Clicking the reset icon opens a confirmation popup before processing the reset.
- Upon confirmation, the system resets the user's trial period to a new 14-day period starting from today's date (the date the reset is performed). Because a manual reset is triggered by the Pixally owner in the moment, the 14-day clock starts immediately on the reset date.
- The "Expires" column is updated to reflect the new expiry date (reset date + 14 days).
- The "Next auto" date is recalculated to 3 months after the new expiry date. For example, if a user's trial runs Jan 1–14 (making the next auto reset Apr 14) and the Pixally owner manually resets on Jan 10, the new expiry becomes Jan 24 and the next auto reset date becomes Apr 24.
- The "Resets" count in the Reset Info column is incremented by 1.
- If the user's trial was "Expired," the status changes back to "Active" after the reset.
- There is no maximum limit on the number of manual resets the Pixally owner can perform for a single user.
- Each manual reset is logged and visible in the Reset Info column.
4.4.3 Trial Reset Logic — Automatic
- The system schedules an automatic free-trial reset for expired trial users 3 months after their trial expiry date. The "Next auto" date in the Reset Info column shows this scheduled date for each user.
- The automatic reset makes a fresh 14-day trial available to the user, but the 14-day clock does not start on the auto-reset date. Instead, the 14-day period begins when the user next logs in. This lets a user return and claim their renewed trial at any time after the auto-reset date — they are not required to return exactly on the auto-reset date.
- Status between auto-reset and next login: From the auto-reset date until the user actually logs in again, the user's status remains "Expired." There is no period during which the trial shows as "Active" without the user having logged in (no phantom active state).
- When the user next logs in (on or after the auto-reset date), the system starts a new 14-day trial from the login date, sets the "Expires" date to login date + 14 days, changes the status to "Active," and increments the Resets count by 1.
- The "Next auto" date then recalculates to 3 months after the new expiry date. Until the user logs in and claims the trial, the "Next auto" date is a projected/rolling date that continues to advance (it always reflects 3 months after the most recent available-trial expiry).
- The automatic reset continues indefinitely; there is no maximum number of automatic resets.
Worked example (illustrating the full lifecycle):
- A user is on a free trial from Jan 1 to Jan 14, so the initial next auto reset date is Apr 14 (3 months after Jan 14).
- The Pixally owner manually resets the trial on Jan 10 → the new expiry becomes Jan 24, and the next auto reset date becomes Apr 24 (3 months after Jan 24).
- The user does not use the trial and it expires on Jan 24. The auto reset is scheduled for Apr 24. Between Jan 24 and their next login, the user's status is "Expired."
- On Apr 24 the auto reset fires, making a fresh 14-day trial available — but the clock has not started because the user has not logged in. The user's status remains "Expired."
- The user returns and logs in on Jun 10. They now get a 14-day trial from Jun 10, expiring Jun 24, and their status becomes "Active." The next auto reset date becomes Sep 24 (3 months after Jun 24).
- If the user had instead never returned, the trial would have remained available and the "Next auto" date would continue to roll forward accordingly.
4.4.4 Delete Logic
- The Pixally owner can delete a non-converted trial user at any time by clicking the delete icon (🗑) in the Actions column.
- Clicking the delete icon opens a confirmation popup before processing the deletion.
- Upon confirmation, the system performs a soft delete:
- The user is removed from the Lead Management listing immediately.
- The user's agency data (projects, clients, files, team members) is retained for 1 year from the date of soft deletion.
- After 1 year, the system performs a hard delete, permanently removing all agency data. Only the user's email address is retained permanently.
- The Pixally owner can delete any trial user regardless of whether their trial is active or expired; this is useful for removing fake or spam accounts.
- Unlike the Subscribers module where delete is restricted to cancelled/suspended/expired statuses, Lead Management allows deletion of any trial user at any time.
4.5 Search
- The search bar is positioned to the right of the tab filters.
- The search performs a real-time filter on the lead listing as the user types.
- The search matches against the user's name and email address.
- The search is case-insensitive and supports partial matching.
- If no results match the search query, the table displays an empty state message: "No leads found matching your search."
- The search works in combination with the selected tab filter.
4.6 Pagination
- The lead listing table supports pagination to handle large numbers of leads without overwhelming a single page.
- Pagination controls are displayed at the bottom of the table and include a "Rows per page" dropdown (default: 10; options: 10, 25, 50, 100), a current range indicator (e.g., "1–10 of 240"), and previous/next page navigation arrows.
- Pagination works in combination with the selected tab and any active search query; when the tab or search changes, the listing returns to the first page of the new result set.
- Sorting a column re-orders the full result set and the table returns to the first page.
4.7 Export Data
- The "Export Data" button in the top-right corner allows the Pixally owner to export the lead (non-converted free trial user) data.
- The export is generated as a single Excel (.xlsx) file containing three tabs, one per listing tab: All, Active, and Expired. Each tab contains the leads that belong to that tab (All = every non-converted trial user; Active = users with a currently active trial; Expired = users whose trial has expired).
- Each tab includes the following columns, matching the listing table columns:
- Name: The user's full name.
- Email: The user's email address.
- Signed Up: The date the user signed up for the free trial (DD/MM/YYYY).
- Expires: The user's current trial expiry date (DD/MM/YYYY).
- Last Active: The date the agency owner was last active (DD/MM/YYYY).
- Status: The trial status (Active or Expired).
- Resets: The number of times the trial has been manually reset.
- Next Auto Reset: The date of the next scheduled automatic reset (DD/MM/YYYY).
- The "User Details" listing column (which stacks name and email in one cell) is split into separate Name and Email columns in the export for usability. The "Reset Info" listing column (which stacks resets count and next-auto date) is split into separate Resets and Next Auto Reset columns. The "Actions" column is not exported (it contains interactive controls only).
- The file downloads to the Pixally owner's browser with a filename convention such as "Pixally_Leads_Export_[Date].xlsx."
- This export is primarily intended as a temporary measure so the Pixally owner can manually add leads to an external email marketing tool until a direct integration is available.
- If there are no leads at all, the system displays a message indicating there is no data to export; otherwise each tab is generated (a tab with no matching leads shows only the column headers).
4.8 Empty State
- If there are no non-converted free trial users in the system, the page displays an empty state in the table area.
- The KPI cards display "0" for all three metrics.
- The table column headers remain visible, and the body area displays an empty state message such as: "No leads found. New free trial sign-ups will appear here."
- The tabs (All, Active, Expired) remain visible and functional.
5. Field Details & Validations
5.1 KPI Cards
Field/Metric
Data Type
Validation / Display Rules
Today Sign-ups
Integer
Whole number. Counts sign-ups from 12:00 AM Eastern today. No comparison indicator.
Last 7 Days Sign-ups
Integer
Whole number. Rolling last 7 days. No comparison indicator.
Lifetime Sign-ups
Integer
Whole number. Cumulative since platform launch. No comparison indicator.
5.2 Non-Converted Free Trial Users Table Fields
Field Name
Field Type
Validation / Display Rules
User Details
Text (Read-only)
Displays user name (bold) and email address (secondary text) on two lines.
Signed Up
Date (Read-only)
Format: DD/MM/YYYY. The date the user signed up for the free trial.
Expires
Date (Read-only)
Format: DD/MM/YYYY. Trial expiry date. Updates when trial is reset.
Last Active
Date (Read-only)
Format: DD/MM/YYYY. Last login or page visit date. Displays "Never" if the user has never logged in after sign-up.
Status
Badge (Read-only)
Values: Active (green), Expired (red/pink). Determined by whether the current date is before or after the Expires date.
Reset Info
Text (Read-only)
Two lines: "Resets: [count]" (integer, starts at 0) and "Next auto: [DD/MM/YYYY]" (date of next automatic reset).
Actions — Reset (↻)
Icon Button (Clickable)
Opens confirmation popup. Available for both Active and Expired users.
Actions — Delete (🗑)
Icon Button (Clickable)
Opens confirmation popup. Available for both Active and Expired users.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Manual Trial Reset
"Free trial reset successfully for [User Name]. The new 14-day trial period starts today."
Pixally owner confirms the trial reset from the confirmation popup.
Popup closes. "Expires" date updates to today + 14 days. "Next auto" updates to 3 months after the new expiry. "Resets" count increments by 1. Status changes to "Active" if it was "Expired."
Delete Lead
"User deleted successfully. Data will be retained for 1 year before permanent deletion."
Pixally owner confirms the deletion from the confirmation popup.
Popup closes. User row is removed from the listing. KPI counts update accordingly.
Export Data
"Lead data exported successfully."
Pixally owner clicks "Export Data" and the file is generated.
The Excel (.xlsx) file with All, Active, and Expired tabs downloads to the browser. No page navigation.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Trial Reset — Server Error
"Failed to reset trial period. Please try again."
Server error during trial reset processing.
Toast error message. Popup closes. No changes made. User can retry.
Trial Reset — User Already Converted
"This user has already converted to a paid subscription and is no longer eligible for a trial reset."
Backend detects the user has purchased a subscription between the time the page was loaded and the reset was attempted (race condition).
Toast error message. The user's row should be removed from the listing on the next refresh.
Delete Lead — Server Error
"Failed to delete user. Please try again."
Server error during deletion processing.
Toast error message. Popup closes. No changes made. User can retry.
Search — No Results
"No leads found matching your search."
Search query does not match any user name or email.
Message displayed in table body. Table headers remain visible.
Network / Connectivity Error
"Unable to connect to the server. Please check your internet connection and try again."
Network failure during any action.
Toast or banner error. Page data remains in its last loaded state.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
User signs up for a free trial and converts to paid before the trial expires.
The user is removed from the Lead Management listing and appears in the Subscribers module. The KPI "Lifetime Sign-ups" count is not decremented (it's a historical count), but the table no longer shows this user.
2
Pixally owner resets a trial for a user who is already on an active trial (not expired).
The system resets the trial to a new 14-day period starting today. If the user had 10 days remaining, they now have 14 days. The "Next auto" date recalculates to 3 months after the new expiry. The Resets count increments. This is a valid action for extending a trial.
3
Automatic 3-month reset date arrives for a user who was manually reset 2 days ago.
The user's trial is currently active (not expired), so no fresh trial is made available yet. The "Next auto" date remains as scheduled (3 months after the current expiry) and only comes into effect once the trial expires and that date is reached.
4
User is deleted from Lead Management and then attempts to sign up again with the same email.
The system should allow re-registration since only the email is retained after hard delete (and even before hard delete, the user's account is soft-deleted). The new sign-up creates a fresh trial entry in Lead Management.
5
Lead Management is loaded with zero sign-ups (first-time setup).
All KPI cards display "0." The table shows an empty state message. Tabs remain visible and functional.
6
Pixally owner clicks the reset icon and then quickly clicks the delete icon before the confirmation popup appears.
The system shows one popup at a time. The first click opens the reset confirmation popup. The second click is ignored until the first popup is dismissed.
7
Auto-reset date arrives for an expired user, but the user does not log in for several weeks.
On the auto-reset date, a fresh 14-day trial becomes available but the 14-day clock does not start; the user's status stays "Expired." When the user eventually logs in, the 14-day trial starts from that login date and the status changes to "Active." The "Next auto" date rolls forward in the meantime.
8
A user's auto-reset date passes, but the user has been inactive for 6+ months.
A fresh trial is made available on the auto-reset date, but the trial does not become "Active" until the user logs in. The "Last Active" date remains stale (the agency owner's last actual activity date). If the user never logs in, no active trial is consumed and the "Next auto" date continues to roll forward.
9
The "Next auto" date for a user has passed and the user logs in.
On login (on or after the auto-reset date), the system starts the new 14-day trial from the login date, sets the status to "Active," increments the Resets count, and recalculates "Next auto" to 3 months after the new expiry.
10
Pixally owner rapidly clicks the reset icon multiple times for the same user.
The system debounces the action. Only one confirmation popup appears. If confirmed, the reset is processed once. The Resets count increments by 1, not by the number of clicks.
11
A user with 100+ manual resets appears in the listing.
The "Resets: [count]" value displays correctly regardless of how large the number is. No truncation or overflow issues.
12
Pixally owner searches for a user by partial email (e.g., "@gmail").
The search matches all users with "@gmail" in their email address, displaying all matching rows.
13
User signed up today and appears in both the "Today Sign-ups" KPI and the table listing.
Both the KPI card and the table listing reflect the new user. The user appears in the "Active" tab with 14 days remaining and "Resets: 0."
14
Pixally owner deletes a user who has an upcoming automatic trial reset scheduled.
The user is deleted. The automatic reset schedule for this user is cancelled since the user no longer exists in the system.
15
Pixally owner exports leads while on the "Active" tab.
The export is unaffected by the currently selected tab or search — it always produces all three tabs (All, Active, Expired) in the single .xlsx file.
16
Pixally owner exports when one category has no leads (e.g., no Expired users).
The .xlsx is still generated with all three tabs; the empty tab (e.g., Expired) contains only the column headers with no data rows.
17
The lead list spans multiple pages and the Pixally owner changes tabs or types a search.
The listing returns to the first page of the new result set, and the pagination range indicator updates to reflect the filtered count.
9. Acceptance Criteria
9.1 KPI Cards
- The three KPI cards (Today Sign-ups, Last 7 Days Sign-ups, Lifetime Sign-ups) display correct counts.
- Today counts from 12:00 AM Eastern; Last 7 Days counts on a rolling basis.
- Lifetime count includes all historical free trial sign-ups.
- KPI cards count only free trial sign-ups, not paid subscribers.
9.2 Listing & Tabs
- The page loads with the "All" tab selected, displaying all non-converted free trial users.
- The "Active" tab shows only users with currently active trials (trial not yet expired).
- The "Expired" tab shows only users whose trial has ended without converting to paid.
- Users who have converted to paid subscriptions do not appear in any tab.
- The table displays all required columns with correct data and sortable headers.
- Default sort is by Signed Up date descending.
9.3 Search & Pagination
- The search bar filters results in real-time by user name and email.
- Search works in combination with the selected tab.
- There is no filters panel; tabs and search are the only ways to narrow the listing.
- Pagination controls (Rows per page, range indicator, previous/next) work correctly and reset to the first page when the tab or search changes.
9.4 Manual Trial Reset
- Clicking the reset icon opens a confirmation popup with the user's name.
- On confirmation, the trial is reset to 14 days from today (the reset date).
- The Resets count increments, the Expires date updates, the "Next auto" date recalculates to 3 months after the new expiry, and the status changes to Active (if expired).
- No maximum limit on manual resets.
9.5 Automatic Trial Reset
- On the "Next auto" date, an expired user is made a fresh 14-day trial available, but the 14-day clock starts only when the user next logs in.
- Between the auto-reset date and the user's next login, the user's status remains Expired (no phantom Active state).
- On the user's next login, the trial starts from the login date (Expires = login + 14 days), status changes to Active, the Resets count increments, and "Next auto" recalculates to 3 months after the new expiry.
- The "Next auto" date is displayed correctly and rolls forward until the user claims a trial. Automatic resets continue indefinitely.
9.6 Delete Lead
- Clicking the delete icon opens a confirmation popup with deletion consequences.
- On confirmation, the user is soft-deleted and removed from the listing.
- Data is retained for 1 year, then hard-deleted (only email retained permanently).
- Deletion is available for both Active and Expired trial users.
9.7 Export Data
- The "Export Data" button generates a single Excel (.xlsx) file with three tabs: All, Active, and Expired.
- Each tab contains the leads for that tab, with columns matching the listing table (Name, Email, Signed Up, Expires, Last Active, Status, Resets, Next Auto Reset).
- The file downloads with the expected filename convention (Pixally_Leads_Export_[Date].xlsx).
- An appropriate message is shown when there is no data to export.
10. Manual Test Cases
Test cases for this module will be generated in a separate phase after all FRDs are finalized.
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
Cannot verify the Pixally owner's session. The Lead Management page returns an authentication error.
Agency Portal — User Registration
Data Dependency
Free trial sign-up data originates from the Agency Portal registration flow. Without it, no new leads appear in the listing.
Subscribers Module (Gawd Portal — FRD #2)
Internal Dependency
When a trial user converts to paid, they are removed from Lead Management and added to Subscribers. If Subscribers is unavailable, the conversion transition may not be reflected immediately.
Dashboard Module (Gawd Portal — FRD #1)
Internal Dependency
The Dashboard's "Free Trial Sign-ups" tab KPI cards display similar metrics. Data consistency between Dashboard and Lead Management must be maintained.
Scheduled Job / Cron Service
Service Dependency
The automatic 3-month trial reset depends on a scheduled background job. If the job service is unavailable, automatic resets do not occur. The "Next auto" date becomes stale until the service is restored.
Email Service (SMTP / Transactional Email Provider)
External Service Dependency
If automated trial reset notifications are sent to users (future enhancement), the email service would be required. Currently, no emails are triggered from this module.
12. References
- Figma Link:
☑️ Referral
☑️ Discounts
Functional Requirements Document (FRD)
Gawd Portal — Discounts
Module Name: Gawd Portal — Discounts Version: 1.0 Created Date: March 27, 2026 Last Updated: March 27, 2026 Project: Pixally CRM Portal: Super Admin (Gawd Portal)
1. Module Overview
Module Name: Gawd Portal — Discounts
Purpose: The Discounts module enables the Pixally owner to create, manage, and track promotional discount codes that agency owners can apply during sign-up or subscription purchase. It supports both percentage-based and fixed-amount discount types with configurable redemption windows, discount durations, user eligibility restrictions, and single-use enforcement. This module provides visibility into discount code performance through usage tracking and serves as a key lever for customer acquisition and retention campaigns.
Business Goals:
- Enable the Pixally owner to create targeted promotional campaigns through discount codes with flexible configuration options.
- Support both percentage and fixed-amount discount types to accommodate various pricing strategies.
- Control the redemption window (Valid From / Valid To) and the discount duration (how long the subscriber benefits after applying) independently for maximum campaign flexibility.
- Ensure discounts apply only to the base subscription tier amount, never to extra seats or other add-ons.
- Restrict eligibility to new users only when needed for acquisition-focused campaigns.
- Enforce single-use per subscriber to prevent abuse while allowing the same code to be used by multiple different subscribers.
- Track usage metrics per code to measure campaign effectiveness.
- Maintain historical discount data in the Reports module (FRD #7) even after codes are deleted from the Discounts listing.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all discount codes, create new codes, edit existing codes (with field-level lock rules), delete codes, filter and search codes, access all tabs.
Customer Support Executive
No Access
The Customer Support role does not have access to the Discounts module.
3. User Flow
3.1 Discounts Listing Flow
3.1.1 The user clicks "Discounts" in the left sidebar navigation menu.
3.1.2 The system loads the Discounts page with the "All" tab selected by default, displaying all discount codes across all statuses.
3.1.3 The system displays the page title "Discounts," the "+ Create discount code" button in the top-right corner, three tab filters (All, Active, Expired), a search bar, and the discount codes data table with pagination controls.
3.1.4 The user clicks the "Active" tab to filter the listing to show only currently active discount codes.
3.1.5 The user clicks the "Expired" tab to filter the listing to show only expired discount codes.
3.1.6 The user types a discount code name in the search bar, and the system filters the table results in real-time.
3.1.7 The user clicks any sortable column header to sort the table in ascending or descending order.
3.1.8 The user uses the pagination controls at the bottom of the table to navigate through discount code records.
3.2 Create Discount Code Flow
3.2.1 The user clicks the "+ Create discount code" button in the top-right corner of the Discounts page.
3.2.2 The system opens the "Create New Discount Code" popup with all input fields empty (or with default values where applicable).
3.2.3 The user enters a discount code name in the "Code" field, or clicks the "Random" button to auto-generate a random code.
3.2.4 The user selects a Discount Type: "Percentage" or "Fixed" using the toggle selector.
3.2.5 The user enters the discount amount in the "Amount" field.
3.2.6 The user enters the discount duration in the "Duration" field, specifying the number of months (1 to 24) for how long the subscriber benefits from the discount after applying the code.
3.2.7 The user selects the "Valid From" date (start of the redemption window) and the "Valid To" date (end of the redemption window) using the date pickers.
3.2.8 The user optionally checks the "New Users Only" checkbox to restrict the code to new subscribers only.
3.2.9 The user optionally checks the "Can't use the code more than once" checkbox to enforce single-use per subscriber.
3.2.10 The user reviews the information note displayed at the bottom of the popup regarding usage rules.
3.2.11 The user clicks "Create Code" to save the new discount code.
3.2.12 The system validates all fields, creates the discount code, adds it to the listing table, and displays a success message.
3.2.13 The user may click "Cancel" to close the popup without creating the code.
3.3 Edit Discount Code Flow
3.3.1 The user clicks the edit icon (✏️) in the Actions column for a discount code row.
3.3.2 The system opens the "Edit Discount Code" popup, pre-filled with the existing values of the selected discount code.
3.3.3 The system displays the "Code" field and "Discount Type" field as read-only/locked (greyed out) since these cannot be changed after creation.
3.3.4 If the discount code has already been redeemed by at least one subscriber, the "Amount" field is also displayed as read-only/locked.
3.3.5 If the code is currently in its active validity period (past the Valid From date), the "Valid From" date field is displayed as read-only/locked.
3.3.6 The user edits the unlocked fields: Amount (if not yet redeemed), Duration, Valid To date, New Users Only checkbox, and Can't use the code more than once checkbox.
3.3.7 The user clicks "Save Changes" to update the discount code.
3.3.8 The system validates the changes, updates the discount code, and displays a success message.
3.3.9 The user may click "Cancel" to close the popup without saving any changes.
3.4 Delete Discount Code Flow
3.4.1 The user clicks the delete icon (🗑) in the Actions column for a discount code row.
3.4.2 The system displays a confirmation popup: "Are you sure you want to delete the discount code '[Code Name]'? Subscribers who have already applied this code will retain their discount until their current discounted period ends. This action cannot be undone."
3.4.3 The user clicks "Confirm" to proceed with the deletion.
3.4.4 The system deletes the discount code from the listing, and the code can no longer be redeemed by any subscriber.
3.4.5 The system displays a success message.
3.4.6 The user may click "Cancel" to abort the deletion without any changes.
4. Functional Logic
4.1 Discounts Listing Page
4.1.1 Page Layout and Structure
- The Discounts page displays the title "Discounts" at the top of the main content area.
- A "+ Create discount code" button is positioned in the top-right corner, styled as a primary action button with a plus icon.
- Below the title, three horizontal tab filter buttons are displayed: All (selected by default), Active, and Expired.
- A search bar is positioned to the right of the tabs.
- Below the tabs and search bar, the discount codes data table is displayed with column headers, data rows, and pagination controls at the bottom.
- There is no filter panel icon on this page; filtering is accomplished through the tabs and search bar only.
4.1.2 Tab Filtering
- The "All" tab is selected by default when the page is loaded, displaying all discount codes regardless of their status.
- The "Active" tab filters the listing to show only discount codes whose "Valid To" date has not yet passed (the current date is on or before the "Valid To" date). This includes both currently-redeemable codes (status "Active") and future-dated codes that have not started yet (status "Upcoming"), since neither is expired. The status badge on each row distinguishes Active from Upcoming.
- The "Expired" tab filters the listing to show only discount codes whose "Valid To" date has passed (the current date is after the "Valid To" date).
- Only one tab can be selected at a time, and the selected tab is visually highlighted with a filled background.
- When a tab is switched, any active search query remains applied.
4.1.3 Table Columns
- The discount codes listing table displays the following sortable columns:
- Code (↓): The discount code string (e.g., "GREATE50," "CJNK20," "BOOST"). Displayed in uppercase.
- Discount (↓): The discount value. For percentage-type discounts, displayed as a percentage (e.g., "50%," "20%," "12%"). For fixed-type discounts, displayed as a dollar amount (e.g., "$20," "$10").
- Duration (↓): The length of time the subscriber benefits from the discounted price after applying the code, expressed in months (e.g., "3 months," "6 months," "12 months"). This is distinct from the Valid Period.
- Valid period: The redemption window during which the code can be applied by subscribers. Displayed as a date range (e.g., "01/08/2024 - 31/12/2024"). This column is not sortable.
- Usage (↓): The number of subscribers who have redeemed the code (e.g., "47 users," "21 users").
- Status (↓): The current status of the discount code displayed as a color-coded badge: "Active" (green badge) if the current date is within the valid period, "Upcoming" (grey badge) if the Valid From date is still in the future, or "Expired" (red badge) if the valid period has ended.
- Actions: Two icon buttons per row: an edit icon (✏️) to edit the discount code, and a delete icon (🗑) to delete the discount code.
- The default sort order is by "Code" in ascending alphabetical order.
- Clicking any sortable column header toggles the sort between ascending and descending.
4.1.4 Search
- The search bar is positioned to the right of the tabs.
- The search performs a real-time filter on the discount listing as the user types.
- The search matches against the discount code name only.
- The search is case-insensitive (searching "boost" matches "BOOST").
- If no results match the search query, the table displays an empty state message: "No discount codes found matching your search."
- The search works in combination with the selected tab filter.
4.1.5 Pagination
- Pagination controls are displayed at the bottom-right of the discount codes table.
- The pagination follows the same pattern as other modules: "Rows per page:" dropdown (default: 10, options: 10, 25, 50, 100), current range indicator (e.g., "6-10 of 11"), and previous/next page navigation arrows.
4.2 Create Discount Code Popup
- The popup title reads "Create New Discount Code" with a close (X) icon in the top-right corner.
- The popup contains the following fields:
4.2.1 Code Field
- A text input field labeled "Code" with placeholder text "Enter Code."
- A "Random" button is displayed to the right of the input field with a dice/generate icon.
- Clicking the "Random" button generates a random 8-character uppercase alphanumeric code (e.g., "PIXL8K2M") and populates the Code field. The user can manually edit the generated code before saving.
- The code input auto-converts all entered characters to uppercase.
- Only letters (A–Z) and numbers (0–9) are allowed. Spaces, special characters, and lowercase letters are not accepted.
- Minimum length: 3 characters. Maximum length: 20 characters.
- The code must be unique across all discount codes (active, expired, and deleted). If a duplicate is entered, the system displays a validation error.
4.2.2 Discount Type Toggle
- A toggle selector labeled "Discount Type" with two options: "Percentage" and "Fixed."
- "Percentage" is the default selection.
- Selecting "Percentage" configures the Amount field to accept a percentage value.
- Selecting "Fixed" configures the Amount field to accept a dollar amount.
4.2.3 Amount Field
- A numeric input field labeled "Amount."
- If Discount Type is "Percentage," the field accepts values from 1 to 100 (representing 1% to 100%). A percentage icon (%) is displayed inside the field.
- If Discount Type is "Fixed," the field accepts a dollar amount greater than $0. A dollar sign ($) prefix is displayed inside the field. There is no upper limit enforced, but the discount amount should logically not exceed the plan price.
- Decimal values are allowed (e.g., "8.5" for 8.5% or "$8.50").
4.2.4 Duration Field
- A field (numeric input labeled "Duration" with the unit fixed to months, or a numeric input plus a unit indicator showing "months").
- This field specifies how long the subscriber receives the discounted price after applying the code.
- The duration is expressed in months, with values from 1 to 24. Months is used even for yearly subscribers; to express multiple years, the Pixally owner enters the equivalent number of months (for example, 24 months for two years). This keeps the discount duration consistent between discount codes and profile-applied discounts (see FRD #2).
- For monthly subscribers, the discount applies to the specified number of monthly charges. For yearly subscribers, the discount is prorated using the monthly-equivalent rate: (annual cost ÷ 12) × discount percentage × number of months (see the Discount Code Application Rules section for the full proration logic).
- Duration is independent of the Valid Period (Valid From / Valid To). The Valid Period defines when the code can be redeemed; Duration defines how long the discount lasts once applied.
- For example, a code with Valid Period "Aug 1 – Dec 31" and Duration "3 months" means the code can be redeemed anytime between Aug 1 and Dec 31, and once a subscriber applies it on Oct 15, they get the discount for 3 months (until Jan 15 of the next year).
4.2.5 Valid From and Valid To Date Pickers
- Two date picker fields labeled "Valid From" and "Valid To" with format MM/DD/YYYY and calendar icons.
- "Valid From" defines the start date of the code's redemption window. The code cannot be used before this date.
- "Valid To" defines the end date of the code's redemption window. The code cannot be used after this date.
- "Valid From" must be on or before "Valid To."
- "Valid From" can be today's date or a future date. Past dates are not allowed for new codes.
- "Valid To" must be on or after "Valid From" and can be any future date.
4.2.6 New Users Only Checkbox
- A checkbox labeled "New Users Only" with a default state of checked (enabled).
- When checked, only new subscribers (users who are purchasing their first subscription) can apply this discount code.
- When unchecked, any subscriber (new or existing) can apply the code.
- If an existing subscriber attempts to apply a "New Users Only" code, the system displays a warning message on the Agency Portal: "This discount code is for new users only."
4.2.7 Can't Use the Code More Than Once Checkbox
- A checkbox that enforces single-use per subscriber.
- When checked, a subscriber who has already redeemed this code cannot use it again. However, other subscribers who have not yet used the code can still redeem it.
- When unchecked, a subscriber can reuse the same code multiple times (e.g., applying it again after their discounted period ends and they renew).
- This is a per-subscriber restriction, not a global single-use restriction. The same code can be used by an unlimited number of different subscribers.
4.2.8 Information Note
- A yellow information banner is displayed at the bottom of the popup with the text: "Please Note: Users cannot apply multiple discount codes simultaneously. Only one code per transaction. The 50% first-year discount does not count as a code."
- This note clarifies three important business rules:
- A subscriber can only use one discount code at a time; they cannot stack multiple codes.
- Only one code can be applied per transaction (subscription purchase or renewal).
- The platform-wide 50% first-year discount is a separate offer from Pixally and does not count as a "discount code." A subscriber can apply a discount code on top of the 50% first-year discount.
4.2.9 Action Buttons
- "Cancel" button: Closes the popup without creating the code. Any entered data is discarded.
- "Create Code" button: Validates all fields and creates the discount code. Styled as a primary action button (yellow/gold).
4.3 Edit Discount Code Popup
- The popup title reads "Edit Discount Code" with a close (X) icon in the top-right corner.
- The popup layout is identical to the Create popup, pre-filled with the existing values of the selected discount code.
- The following field-level locking rules apply:
4.3.1 Locked Fields (Always Read-Only After Creation)
- Code: The code name is permanently locked after creation and cannot be changed. Displayed as greyed-out/read-only. Changing the code name would break any distributed or shared codes.
- Discount Type: The discount type (Percentage/Fixed) is permanently locked after creation. Changing the type would create accounting inconsistencies.
4.3.2 Conditionally Locked Fields
- Amount: Locked if at least one subscriber has redeemed the code. If no subscriber has used it yet, the amount remains editable. Changing the amount after redemption would be unfair to early users.
- Valid From: Locked if the code is currently in its active validity period (current date is on or after the Valid From date). If the Valid From date is still in the future (code hasn't started yet), it remains editable.
4.3.3 Always Editable Fields
- Duration: Can always be changed. The updated duration applies to future redemptions; subscribers who have already applied the code retain their original duration.
- Valid To: Can always be changed. This allows the Pixally owner to extend or shorten the redemption window.
- New Users Only: Can always be toggled. Changing this affects only future redemptions.
- Can't use the code more than once: Can always be toggled. Changing this affects only future usage attempts.
4.3.4 Save Behavior
- The "Save Changes" button saves the updated values.
- Changes to editable fields take effect immediately.
- Changes to Duration, New Users Only, and the single-use checkbox do not retroactively affect subscribers who have already applied the code.
4.4 Delete Discount Code
- Both the edit and delete icons are displayed in the Actions column for every discount code row, regardless of whether the code is Active or Expired.
- Clicking the delete icon opens a confirmation popup.
- The confirmation message reads: "Are you sure you want to delete the discount code '[Code Name]'? Subscribers who have already applied this code will retain their discount until their current discounted period ends. This action cannot be undone."
- Upon confirmation, the discount code is removed from the Discounts listing and can no longer be redeemed by any subscriber.
- Subscribers who have already applied the deleted code are not affected; their discounted pricing continues for the remainder of their discount duration period.
- The deleted code's historical usage data (usage count, revenue impact) is retained in the Reports module (FRD #7) for the "Discount Code Usage" report.
- If a subscriber attempts to apply a deleted code, the system displays a message: "This discount code is no longer valid."
- Upon clicking "Cancel," the popup closes without any changes.
4.5 Discount Code Application Rules (Agency Portal Side)
- The following rules govern how discount codes are applied by agency owners on the Agency Portal. These rules are documented here for completeness, but the UI for code application is on the Agency Portal, not the Gawd Portal.
- A subscriber can apply only one discount code at a time. Multiple codes cannot be stacked.
- Only one discount code can be applied per transaction.
- The 50% first-year discount offered by Pixally to all subscribers is a platform-wide offer and does not count as a discount code. A subscriber can apply a discount code in addition to the 50% first-year discount.
- If a code has the "New Users Only" restriction and an existing subscriber attempts to use it, the system displays: "This discount code is for new users only."
- If a code has expired (current date is past the "Valid To" date) and a subscriber attempts to use it, the system displays: "This discount code has expired."
- If a code has been deleted and a subscriber attempts to use it, the system displays: "This discount code is no longer valid."
- If a code has the single-use restriction and the subscriber has already used it, the system displays: "You have already used this discount code."
- When a valid code is successfully applied, the subscriber receives the discounted price for the duration specified by the code, starting from the date of application.
- A discount (whether a discount code or a discount applied from the subscriber profile) applies only to the subscription tier amount. It never applies to extra seats the subscriber has purchased or to any other add-ons or future additions; only the base subscription plan price is discounted.
- The discount duration is expressed as a number of months. For monthly subscribers, the discount applies to the specified number of monthly charges. For yearly subscribers, the discount is prorated using the subscriber's monthly-equivalent rate: the system computes (annual cost ÷ 12) × discount percentage × number of months to determine the total discount value applied against the yearly subscription. For example, a 30%-off-for-6-months discount on a yearly plan applies 30% to six months' worth of the monthly-equivalent price.
- A discounted charge can never be negative. For a fixed-amount discount that is greater than the amount it applies to, the charge is floored at $0 — the discount reduces the charge to $0 but never below it, and the system does not issue a credit, refund, or carry-over for the difference. For example, a fixed $50 discount applied to a $19 charge results in a $0 charge (not −$31).
- Discount duration on a plan switch: If a subscriber has an active discount with months remaining and switches to a different plan partway through the discount period, only the remaining months of the discount carry over to the new plan, at the same discount percentage. The months already consumed are not restored. For example, a subscriber with a 6-month discount who switches plans after 2 months keeps the discount for the remaining 4 months on the new plan (the discount percentage is unchanged; only the remaining duration continues). The plan switch itself is performed by the subscriber on the Agency Portal; the Gawd Portal reflects the resulting plan and the remaining discount period.
4.6 Discount Status Logic
- A discount code's status is one of three values, automatically determined by the system based on the current date relative to the code's Valid From and Valid To dates:
- Active (green): The current date falls within the Valid From and Valid To date range (inclusive). The code can be redeemed.
- Upcoming (grey): The current date is before the Valid From date. The code is scheduled for a future start and cannot be redeemed yet, but it is not expired. This replaces the earlier behavior of showing future-dated codes as "Active."
- Expired (red): The current date is after the Valid To date. The code can no longer be redeemed.
- The status badge in the listing is automatically determined by the system based on the current date and the code's Valid From / Valid To dates. There is no manual status override.
- When a code's Valid From date arrives, its status automatically transitions from "Upcoming" to "Active"; when its Valid To date passes, it transitions from "Active" to "Expired."
4.7 Empty State
- If there are no discount codes in the system, the page displays an empty state in the table area.
- The table column headers remain visible.
- The body area displays an empty state message such as: "No discount codes found. Create your first discount code to start offering promotions."
- The "+ Create discount code" button remains visible and functional.
- The tabs (All, Active, Expired) remain visible.
5. Field Details & Validations
5.1 Discounts Listing Table Fields
Field Name
Field Type
Validation / Display Rules
Code
Text (Read-only)
Uppercase alphanumeric. Displayed as entered during creation.
Discount
Text (Read-only)
Percentage: "[X]%" (e.g., "50%," "12%"). Fixed: "$[X]" (e.g., "$20," "$10").
Duration
Text (Read-only)
Format: "[X] months" (e.g., "3 months," "12 months," "24 months").
Valid period
Text (Read-only)
Format: "DD/MM/YYYY - DD/MM/YYYY" (e.g., "01/08/2024 - 31/12/2024"). Not sortable.
Usage
Text (Read-only)
Format: "[count] users" (e.g., "47 users," "0 users").
Status
Badge (Read-only)
Values: Active (green), Upcoming (grey), Expired (red). Auto-determined by system based on current date vs. Valid From / Valid To.
Actions — Edit (✏️)
Icon Button
Opens Edit Discount Code popup pre-filled with existing values.
Actions — Delete (🗑)
Icon Button
Opens delete confirmation popup.
5.2 Create / Edit Discount Code Popup Fields
Field Name
Field Type
Validation Rules
Code
Text Input
Required. Uppercase A–Z and 0–9 only. Auto-converts to uppercase. Min: 3 chars, Max: 20 chars. Must be unique across all codes. Locked on edit.
Random Button
Button
Generates random 8-character uppercase alphanumeric code. Populates Code field. User can edit after generation.
Discount Type
Toggle (Percentage / Fixed)
Required. Default: Percentage. Locked on edit.
Amount
Numeric Input
Required. Percentage: 1–100 (decimals allowed, e.g., 8.5). Fixed: > $0 (decimals allowed). Conditionally locked on edit if already redeemed.
Duration (Value)
Numeric Input
Required. Integer. Min: 1, Max: 24 (months). Expressed in months even for yearly subscribers (e.g., 24 = two years).
Valid From
Date Picker (MM/DD/YYYY)
Required. Cannot be a past date (for new codes). Must be ≤ Valid To. Conditionally locked on edit if already active.
Valid To
Date Picker (MM/DD/YYYY)
Required. Must be ≥ Valid From. Must be a future date (for new codes). Always editable.
New Users Only
Checkbox
Default: checked. When checked, only new subscribers can redeem. Always editable.
Can't use the code more than once
Checkbox
Default: unchecked. When checked, each subscriber can redeem the code only once. Always editable.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Create Discount Code
"Discount code '[Code Name]' created successfully."
Pixally owner clicks "Create Code" with all valid fields.
Popup closes. New code appears in the listing table.
Edit Discount Code
"Discount code '[Code Name]' updated successfully."
Pixally owner clicks "Save Changes" with valid editable fields.
Popup closes. Updated values reflected in the listing table.
Delete Discount Code
"Discount code '[Code Name]' deleted successfully. Existing discounts for subscribers will remain active until their period ends."
Pixally owner confirms deletion.
Popup closes. Code removed from listing.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Empty Code Field
"Discount code is required."
User clicks "Create Code" without entering a code.
Inline error below the Code field.
Code Too Short
"Discount code must be at least 3 characters."
User enters fewer than 3 characters.
Inline error below the Code field.
Code Too Long
"Discount code cannot exceed 20 characters."
User enters more than 20 characters.
Inline error below the Code field.
Invalid Code Characters
"Only letters (A–Z) and numbers (0–9) are allowed."
User enters special characters, spaces, or non-alphanumeric characters.
Inline error below the Code field. Input is auto-rejected or stripped.
Duplicate Code
"This discount code already exists. Please choose a different code."
User enters a code that matches an existing active, expired, or deleted code.
Inline error below the Code field.
Empty Amount
"Discount amount is required."
User clicks "Create Code" without entering an amount.
Inline error below the Amount field.
Percentage Amount Out of Range
"Percentage must be between 1 and 100."
User enters a percentage value < 1 or > 100.
Inline error below the Amount field.
Fixed Amount Zero or Negative
"Amount must be greater than $0."
User enters $0 or a negative value for a fixed discount.
Inline error below the Amount field.
Empty Duration
"Duration is required."
User clicks "Create Code" without entering a duration value.
Inline error below the Duration field.
Duration Out of Range
"Duration must be between 1 and 24 months."
User enters a duration outside the allowed range.
Inline error below the Duration field.
Empty Valid From
"Valid From date is required."
User clicks "Create Code" without selecting a Valid From date.
Inline error below the Valid From field.
Empty Valid To
"Valid To date is required."
User clicks "Create Code" without selecting a Valid To date.
Inline error below the Valid To field.
Valid From After Valid To
"Valid From date cannot be after Valid To date."
User selects a Valid From date that is later than the Valid To date.
Inline error below the date fields.
Valid From in the Past
"Valid From date cannot be in the past."
User selects a past date for Valid From when creating a new code.
Inline error below the Valid From field.
Save Failed — Server Error
"Failed to save discount code. Please try again."
Server error during create or edit.
Toast error message. Popup remains open. User can retry.
Delete Failed — Server Error
"Failed to delete discount code. Please try again."
Server error during deletion.
Toast error message. Confirmation popup closes. User can retry.
Search — No Results
"No discount codes found matching your search."
Search query matches no code names.
Message displayed in table body. Headers remain visible.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
Pixally owner creates a code with Valid From = today and Valid To = today.
The code is valid for one day only. It becomes "Expired" at the end of today. Usage is permitted throughout the day.
2
Pixally owner creates a 100% percentage discount code.
The system accepts this as valid. Subscribers who apply the code pay $0 for the duration period. After the duration ends, full pricing resumes.
3
A subscriber applies a code on the last day of the Valid Period.
The code application is valid. The subscriber receives the discounted price for the full duration (e.g., 3 months) starting from the application date, even though the code's redemption window has closed.
4
Pixally owner edits the Valid To date to extend an expired code back to active.
The system allows this. The code status changes from "Expired" back to "Active." The code becomes redeemable again by subscribers.
5
Pixally owner deletes an Active code that 50 subscribers are currently using.
The code is removed from the listing. All 50 subscribers retain their discounted pricing until their individual duration periods end. No new subscribers can redeem the code.
6
Two discount codes have overlapping Valid Periods, and a subscriber tries to apply both.
The system allows only one code per transaction. The subscriber must choose one code. If they have already applied Code A, they cannot apply Code B until Code A's duration expires and they are on a new transaction.
7
Pixally owner clicks "Random" multiple times rapidly.
Each click generates a new random code, replacing the previous one in the Code field. The system does not create multiple codes; only the final value in the field is used when "Create Code" is clicked.
8
A "New Users Only" code is created, and an existing subscriber tries to apply it during plan renewal.
The Agency Portal displays: "This discount code is for new users only." The code is not applied.
9
A subscriber applies a code with a 3-month duration, then cancels their subscription after 1 month, then resubscribes.
The discount does not carry over to the new subscription. The remaining 2 months of discount are forfeited upon cancellation. If the code does not have single-use restriction, the subscriber could apply it again. If it has the single-use restriction, they cannot.
10
The Code field receives a mix of uppercase and lowercase input (e.g., "BoOsT").
The system auto-converts all characters to uppercase, resulting in "BOOST" being stored and displayed.
11
Pixally owner tries to create a code that was previously deleted.
The system rejects the code with a duplicate error: "This discount code already exists." Deleted codes remain in the uniqueness check to prevent confusion.
12
Pixally owner edits the "New Users Only" checkbox on a code that has already been redeemed by existing users.
The change applies to future redemptions only. Existing users who already applied the code are not affected.
13
A discount code has 0 usage (never redeemed) and the Pixally owner deletes it.
The code is deleted cleanly. No subscribers are affected. The code's usage data (0 users, $0 revenue impact) may still appear in the Reports module if it was tracked.
14
Valid From is set to a future date (e.g., next month).
The code is shown with the "Upcoming" (grey) status badge and appears under the "Active" tab (since it is not expired). It cannot be redeemed until the Valid From date; if a subscriber tries to apply it before then, the system displays: "This discount code is not yet active." On the Valid From date, the status automatically becomes "Active" (green).
15
Pixally owner creates a fixed $50 discount code, but a subscriber's plan costs only $19/month.
The subscriber's charge for the discounted period is floored at $0 (never negative). The discount reduces the $19 charge to $0; the system does not issue a "credit," refund, or carry-over for the remaining $31. After the duration ends, normal pricing ($19/month) resumes.
16
Multiple users edit/delete the same code simultaneously (concurrent access).
The system uses optimistic locking or last-write-wins. The second save may overwrite the first, or the second action fails with: "This code has been modified by another user. Please refresh and try again."
17
Pixally owner searches for a code while on the "Expired" tab.
The search filters within the Expired tab only. If the code is Active, it will not appear in the results. The user must switch to the "All" or "Active" tab to find it.
18
A subscriber has extra seats and applies a percentage discount code.
The discount applies only to the base subscription tier amount. The extra seat charges are billed at full price and are not discounted.
19
A yearly subscriber applies a discount code with a duration of a few months.
The discount is prorated using the monthly-equivalent rate: (annual cost ÷ 12) × discount percentage × number of months. The subscriber's yearly charge is reduced by that prorated amount rather than by a full-year discount.
20
A subscriber with a 6-month discount switches plans (on the Agency Portal) after using 2 months.
Only the remaining 4 months of the discount carry over to the new plan, at the same percentage. The 2 consumed months are not restored. The Gawd Portal reflects the new plan and the remaining discount period.
9. Acceptance Criteria
9.1 Listing & Tabs
- The Discounts page loads with the "All" tab selected, displaying all discount codes.
- The "Active" tab shows codes that are not expired (both currently-redeemable "Active" codes and future-dated "Upcoming" codes). The "Expired" tab shows only codes past their Valid To date.
- The status badge correctly shows Active (green), Upcoming (grey), or Expired (red) based on the current date versus the code's Valid From / Valid To dates, and transitions automatically as those dates are reached.
- A fixed discount that exceeds the amount it applies to floors the charge at $0 and never goes negative (no credit for the difference).
- The table displays all required columns with correct data and sortable headers (except Valid period).
- Search filters results in real-time by code name (case-insensitive).
- Pagination controls work correctly.
9.2 Create Discount Code
- The "+ Create discount code" button opens the create popup with all fields.
- The "Random" button generates an 8-character uppercase alphanumeric code.
- Input auto-converts to uppercase and rejects non-alphanumeric characters.
- Both Percentage and Fixed discount types work correctly with proper Amount validation.
- Duration field accepts a value in months (1–24) independently from Valid Period dates.
- Valid From and Valid To date pickers validate date range logic.
- "New Users Only" and "Can't use the code more than once" checkboxes function correctly.
- The information note is displayed with the correct text about usage rules.
- "Create Code" validates all fields and creates the code successfully.
9.3 Edit Discount Code
- The edit popup opens pre-filled with existing values.
- Code and Discount Type are always locked (read-only).
- Amount is locked if the code has been redeemed by at least one subscriber.
- Valid From is locked if the code is currently active (past its start date).
- Duration, Valid To, New Users Only, and single-use checkbox are always editable.
- Changes apply to future redemptions only and do not retroactively affect existing subscribers.
9.4 Delete Discount Code
- The delete confirmation popup displays the code name and impact warning.
- Upon confirmation, the code is removed from the listing.
- Subscribers with active discounts from the deleted code retain their discount until the duration period ends.
- The deleted code's historical usage data is preserved in the Reports module.
- Deleted code names remain in the uniqueness check (cannot be recreated).
9.5 Agency-Side Application Rules
- Only one code per transaction is enforced.
- "New Users Only" restriction is enforced correctly.
- Expired codes display the correct expiry message.
- Deleted codes display the correct "no longer valid" message.
- Single-use restriction is enforced per subscriber.
- The 50% first-year discount is independent of discount codes and can be combined.
10. Manual Test Cases
Test cases for this module will be generated in a separate phase after all FRDs are finalized.
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
Cannot verify the Pixally owner's session. The Discounts page returns an authentication error.
Agency Portal — Subscription Purchase / Sign-up
Integration Dependency
Discount codes are redeemed on the Agency Portal during subscription purchase or sign-up. If the Agency Portal is unavailable, codes cannot be redeemed, but they can still be created and managed in the Gawd Portal.
Reports Module (Gawd Portal — FRD #7)
Internal Dependency
The "Discount Code Usage" section in Reports references discount code data. Deleted codes retain historical data in Reports. If Reports is unavailable, the data is still stored but not visible.
Subscribers Module (Gawd Portal — FRD #2)
Cross-Module Reference
The "Apply Discount" popup on subscriber profiles (FRD #2) applies per-subscriber percentage discounts, which are separate from the discount codes managed in this module. These are two distinct discount mechanisms.
Subscription & Billing System (Stripe)
External Service Dependency
Discount code application affects billing amounts processed through Stripe. If Stripe is unavailable, the code may be applied in the system but the billing adjustment may not be reflected until Stripe is available.
12. References
- Figma Screens:
- Discounts Listing — Batch 2, Image 7
- Create Discount Code — Percentage — Batch 2, Image 8
- Create Discount Code — Fixed — Batch 2, Image 9
- Source of Truth: Gawd Portal Meeting Transcript (JSON) — March 26, 2026 (timestamps 25:57–29:09)
- Supporting Document: Super Admin — The Gawd Portal (Initial Client Document) — Section 6
- Related FRDs:
- FRD #2 — Gawd Portal: Subscribers (Apply Discount popup — per-subscriber percentage discount, separate from codes)
- FRD #7 — Gawd Portal: Reports (Discount Code Usage report)
Open Items / Notes for Client Confirmation:
- Duration Field — Missing from Figma: The Create/Edit Discount Code popup in Figma does not include a Duration field. Since Duration and Valid Period are confirmed as separate concepts, a Duration field (numeric input in months, range 1–24) needs to be added to the Figma design.
- "Can't use the code more than once" Checkbox — Missing from Figma: This checkbox is confirmed as a required feature but is not shown in the current Figma design. It needs to be added alongside the "New Users Only" checkbox.
- "Upcoming" Status Badge — Figma: Future-dated codes now use an "Upcoming" (grey) status badge (instead of showing as "Active"). The Figma should be updated to include the grey "Upcoming" badge alongside the green "Active" and red "Expired" badges.
- 50% First-Year Discount — Possible "First 500 Members" Model: The client is considering changing the platform-wide 50% first-year discount to a "first 500 members" urgency-based offer. If adopted, the system needs to determine whether the discount can be limited to the first 500 subscribers (with the ability to change or disable it in Stripe afterward) rather than applying as a default to all users. This is under client consideration and pending confirmation.
Resolved in this round: future-dated codes now carry an "Upcoming" (grey) status; and a fixed discount that exceeds the amount it applies to floors the charge at $0 (never negative, no credit for the difference).
☑️ Reports
Functional Requirements Document (FRD)
Gawd Portal — Reports
Module Name: Gawd Portal — Reports Version: 1.0 Created Date: March 27, 2026 Last Updated: March 27, 2026 Project: Pixally CRM Portal: Super Admin (Gawd Portal)
1. Module Overview
Module Name: Gawd Portal — Reports
Purpose: The Reports module provides the Pixally owner with a comprehensive financial and business performance reporting dashboard. It consolidates key performance indicators (total revenue, paid subscriber growth, churn rate), revenue breakdowns by source (subscriptions, extra seats, transaction fees), revenue segmentation by plan type and agency service type, and discount code usage analytics. All data is filterable by date range. The Discount Code Usage table can be exported as an Excel (.xlsx) file for offline analysis.
Business Goals:
- Provide a unified financial reporting view of all Pixally revenue streams across configurable time periods.
- Track new paid subscriber acquisition and churn rate trends to measure business health.
- Break down revenue by source type (subscription fees, extra seat fees, transaction fee markup) for granular financial analysis.
- Segment revenue by subscription plan type (Free, Basic, Pro, Studio) to identify the most profitable tiers.
- Segment revenue by agency service type (Photography, Videography, Photo/Video, Content Creation) to understand customer demographics and target marketing efforts.
- Measure discount code effectiveness through usage counts and revenue impact analysis.
- Support Excel (.xlsx) export of the Discount Code Usage data for offline analysis.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access
View all KPI cards, view all charts, view Discount Code Usage table, change date filter, export the Discount Code Usage table as Excel (.xlsx).
Customer Support Executive
No Access
The Customer Support role does not have access to the Reports module.
3. User Flow
3.1 Reports Page Flow
3.1.1 The user clicks "Reports" in the left sidebar navigation menu.
3.1.2 The system loads the Reports page displaying the date filter (defaulting to "This Quarter"), the "Export" button, four KPI cards, the Total Revenue Overview section with two charts, the Revenue by Subscriptions and Revenue by Service Types charts side by side, and the Discount Code Usage table at the bottom.
3.1.3 The user observes the four KPI cards showing Total Revenue, New Paid Subscribers, Churn Rate, and Customer Acquisition Cost (CAC) for the selected date period.
3.1.4 The user clicks the date filter dropdown in the top-right corner to change the time period.
3.1.5 The system displays the date picker with preset options (Custom Range, Today, Last 7 days, Last 30 days, Last 90 days, Last 365 days) and a dual-month calendar for custom date range selection.
3.1.6 The user selects a date preset or defines a custom date range by clicking a start date and end date on the calendar.
3.1.7 The system updates the top KPI cards to reflect data within the selected date range. The charts and the Discount Code Usage table below the cards are not driven by this date filter; they follow their own logic (for example, the revenue charts display their own time series regardless of the top-card date filter).
3.1.8 The user scrolls through the page reviewing the Total Revenue Overview line chart and grouped bar chart.
3.1.9 The user reviews the Revenue by Subscriptions stacked bar chart and the Revenue by Service Types pie chart displayed side by side.
3.1.10 The user scrolls to the bottom to review the Discount Code Usage table showing code performance and revenue impact.
3.1.11 The user clicks the "Export" button in the top-right corner.
3.1.12 The system generates an Excel (.xlsx) file containing only the Discount Code Usage table and downloads it to the user's browser.
4. Functional Logic
4.1 Reports Page Layout
- The Reports page displays the title "Reports" at the top of the main content area.
- The top-right corner contains two elements: a date filter dropdown (defaulting to "This Quarter" with a calendar icon) and an "Export" button (with a download/export icon).
- Below the title, the page is organized into the following sections in vertical order:
- Key Performance Indicators (4 KPI cards)
- Total Revenue Overview (line chart + grouped bar chart)
- Revenue by Subscriptions (stacked bar chart) and Revenue by Service Types (pie chart) — displayed side by side
- Discount Code Usage (table)
- The date filter applies to the top KPI cards only. When the date range changes, the top KPI cards update accordingly; the charts and Discount Code Usage table below are not driven by this filter and retain their own logic.
- Report data is not real-time; it is loaded on page load and refreshes when the date filter is changed or the page is manually reloaded.
4.2 Date Filter
- The date filter is positioned in the top-right corner of the page, to the left of the "Export" button.
- The default selection when the page is first loaded is "This Quarter."
- Clicking the date filter opens a date picker panel with two sections:
- Left panel — Presets: A vertical list of clickable preset options: Custom Range, Today, Last 7 days, Last 30 days, Last 90 days, Last 365 days.
- Right panel — Calendar: A dual-month calendar display (e.g., July 2025 and August 2025) with navigation arrows to move between months. The user can click a start date and end date to define a custom range.
- When "Custom Range" is selected or the user clicks dates on the calendar, the selected date range is displayed in a top banner within the picker showing the start and end dates (e.g., "July 1, 2025 → July 30, 2025").
- The selected dates are highlighted on the calendar with a filled background, and the range between them is shaded.
- When a preset is selected (e.g., "Last 30 days"), the system automatically calculates the date range relative to today and highlights the corresponding dates on the calendar.
- Upon selecting a date range, the system updates the top KPI cards to reflect data within the selected period. The charts and Discount Code Usage table are not affected by the date filter.
- The selected date filter persists while the user remains on the Reports page but resets to "This Quarter" when the user navigates away and returns.
4.3 Key Performance Indicators (KPI Cards)
- The KPI section heading reads "Key Performance Indicators" with a subtitle "Breakdown of discount code performance and revenue impact."
- Four KPI cards are displayed in a single horizontal row.
- All KPI values are scoped to the selected date filter period. (The date filter applies to these top KPI cards; the charts and Discount Code Usage table below are not driven by this filter.)
- Comparison indicator logic: The "% previous period" indicator on each KPI card compares the selected date range against the same-length period immediately preceding it. For example, if the selected range is "This Quarter," the comparison is against the prior quarter of equal length; if the selected range is "Last 30 days," the comparison is against the 30 days immediately before that range; a custom range of N days is compared against the N days immediately preceding it. The indicator shows the percentage change and an up/down arrow accordingly.
Card 1 — Total Revenue:
- Displays the total revenue generated by Pixally across all sources (subscriptions + extra seats + transaction fee markup) during the selected period.
- Displayed with a dollar/coin icon in a blue circular badge.
- Format: USD with two decimal places and comma separators (e.g., "$847,392.00").
- Includes a percentage comparison indicator (green upward arrow or red downward arrow) showing the change versus the previous equivalent period (e.g., "23.9% previous period").
Card 2 — New Paid Subscribers:
- Displays the count of new subscribers who purchased a paid subscription during the selected period.
- Displayed with a person icon in a green circular badge.
- Format: Whole number (e.g., "34").
- Includes a percentage comparison indicator showing the change versus the previous equivalent period (e.g., "73.1% previous period").
Card 3 — Churn Rate:
- Displays the churn rate as a percentage for the selected period, calculated as: (Number of subscribers whose paid term ended during the period ÷ Total subscribers at the start of the period) × 100. Consistent with the Dashboard (FRD #1), a cancellation is counted toward churn on the date the subscriber's paid term actually ends, not on the date they click cancel.
- Displayed with a trend/chart icon in an orange circular badge.
- Format: One decimal place (e.g., "2.4%").
- Includes a percentage comparison indicator. A red downward arrow indicates an increase in churn (negative trend for the business), and a green upward arrow indicates a decrease in churn (positive trend).
Card 4 — Customer Acquisition Cost (CAC):
- Displays the average cost to acquire a new paid subscriber. This metric is a v2 feature and is not calculated in v1.
- Displayed with a dollar/target icon in a purple circular badge.
- In v1, the card displays a placeholder value (e.g., "$2,320.00") with a label "Coming in v2" beneath it, indicating that the calculation logic will be implemented in a future release.
- The card is visible but non-functional in v1. No comparison indicator is shown.
4.4 Total Revenue Overview
- The section heading reads "Total Revenue Overview" with a subtitle "Monthly revenue breakdown with comparative analysis." An info icon (ⓘ) is displayed next to the heading. Hovering over the info icon displays a tooltip: "Shows actual revenue received each month. Annual payments appear in full in the month they were collected (not spread across 12 months). Includes subscription revenue, extra seat revenue, and transaction fee markup."
- This section reflects actual revenue received (cash basis): each month shows the revenue actually collected in that month. Annual subscription payments appear in full in the month they were received rather than being spread across 12 months. This differs from the "Revenue by Subscriptions" chart below (§4.5), which spreads annual subscription revenue evenly across the term. The distinction is intentional: this "Total Revenue Overview" answers "what did Pixally actually take in each month" (and includes inherently variable transaction-fee revenue), whereas "Revenue by Subscriptions" is a normalized monthly-trend view of subscription revenue by plan.
- This section contains two complementary visualizations stacked vertically within a single card container:
Line Chart (Top):
- Displays three trend lines showing monthly revenue over the selected period:
- Subscription Revenue (green line): Revenue from subscription plan payments.
- Extra Seat Revenue (purple line): Revenue from additional seat purchases by subscribers who buy extra users beyond their plan's included seats.
- Transaction Fees (yellow/orange line): Revenue from the processing fee markup that Pixally adds to credit card and ACH payments.
- The X-axis represents months (January through December).
- The Y-axis represents revenue in USD with automatic scaling (e.g., $0 to $100k).
- A legend is displayed in the top-right area of the chart with color-coded labels for each data series.
- The line chart shows cumulative trends to help the Pixally owner identify overall growth trajectories.
Grouped Bar Chart (Bottom):
- Displays the same three data series (Subscription Revenue, Extra Seat Revenue, Transaction Fees) as a grouped bar chart showing monthly breakdowns.
- The X-axis represents months (January through December).
- The Y-axis represents revenue in USD with automatic scaling.
- Each month displays three adjacent bars (one per revenue type) using the same colors as the line chart legend.
- The bar chart enables direct monthly comparison of the three revenue streams, making it easy to identify which source dominates in each month.
4.5 Revenue by Subscriptions
- This section is displayed on the left side of a two-column layout, alongside "Revenue by Service Types" on the right.
- The section heading reads "Revenue by Subscriptions" with an info icon (ⓘ). Hovering over the info icon displays a tooltip: "Includes both subscription and transaction fee markup revenue. Annual subscriptions are divided by 12 and spread evenly across the subscription term, so this shows a normalized monthly trend rather than the actual cash received each month."
- A subtitle reads "Distribution of revenue across different subscriptions."
- The section displays a legend above the chart showing four plan types with their color codes and total revenue amounts: Free (light green, e.g., "$2.45k"), Basic (blue, e.g., "$67.50k"), Pro (purple, e.g., "$231.38k"), Studio (yellow, e.g., "$123.12k").
- The chart is a stacked bar chart:
- The X-axis represents months (January through December).
- The Y-axis represents revenue in USD.
- Each monthly bar is divided into colored segments representing each plan type's contribution.
- Each plan-type segment includes both the subscription revenue for that plan and the transaction fee markup revenue generated by that plan's subscribers, so the chart reflects the total revenue attributable to each plan tier.
- Annual subscription revenue is divided by 12 and spread evenly across the 12 months of the subscription term rather than shown as a lump sum in the purchase month, so the chart reflects the true monthly revenue trend. This is consistent with the Revenue by Subscriptions chart on the Dashboard (FRD #1).
- This chart shows its own monthly time series and is not driven by the top-card date filter.
4.6 Revenue by Service Types
- This section is displayed on the right side of a two-column layout, alongside "Revenue by Subscriptions" on the left.
- The section heading reads "Revenue by Service Types" with an info icon (ⓘ). Hovering over the info icon displays a tooltip: "This shows the subscription revenue you earn from Pixally subscribers, broken down by the service types they offer. It's not their client revenue — it's your revenue, categorized by the types of businesses using Pixally."
- A subtitle reads "Distribution of revenue across different services."
- The section displays a legend above the chart showing four service types with their color codes and total revenue amounts: Photography (green, e.g., "$67.38k"), Videography (purple, e.g., "$86.12k"), Photo/Video (yellow, e.g., "$86.12k"), Content Creation (blue, e.g., "$112.45k").
- The chart is a pie/donut chart:
- Each segment represents the revenue contribution from subscribers categorized by their agency service type.
- Each segment displays its percentage value inside the chart (e.g., "35%," "15%," "5%," "45%").
- Agency service types are captured during the sign-up process when the agency owner indicates whether they are a Photography, Videography, Photo/Video, or Content Creation agency.
- This chart shows its own revenue distribution and is not driven by the top-card date filter.
4.7 Discount Code Usage
- The section heading reads "Discount Code Usage" with a subtitle "Breakdown of discount code performance and revenue impact."
- The section displays a table with the following columns:
- Code: The discount code string (e.g., "GREATE50," "SUMMER50").
- Type: The discount type — "Percentage" or "Fixed."
- Discount: The discount value. For percentage: displayed as a percentage (e.g., "20%"). For fixed: displayed as a dollar amount (e.g., "$50.00").
- Usage Count: The number of subscribers who have redeemed the code during the selected period (e.g., "245," "189").
- Revenue Impact (ⓘ): The total revenue brought in by subscribers who used the code, displayed as a positive USD value (e.g., "$49,000," "$94,500"). This measures how much revenue a code has generated for the business — the cumulative revenue from all subscribers who redeemed that code, and it continues to accrue even after the code's discount period has ended (for example, a subscriber who used the code for six months and is now paying full price still contributes their ongoing revenue to that code's total). It is not the revenue lost or the discount amount given. An info icon (ⓘ) displays a tooltip clarifying: "Total revenue generated by all subscribers who used this code, cumulative to date, even after the discount has ended."
- Status: The current status of the code displayed as a color-coded badge: "Active" (green) or "Expired" (red).
- The table includes data from both active and expired discount codes, as well as deleted codes whose historical usage data is retained from the Discounts module (FRD #6).
- The table supports pagination with the standard controls (Rows per page dropdown and page navigation arrows).
- The table does not support sorting or searching; it is a read-only summary report (sorting is confirmed as not required). Detailed discount code management is handled in the Discounts module (FRD #6).
- Usage Count reflects redemptions within the filtered date range (subject to the date-filter scope described in the KPI cards section). Revenue Impact is cumulative revenue generated by users of the code and is a positive number.
4.8 Export (Discount Code Usage)
- The "Export" button is positioned in the top-right corner of the page, to the right of the date filter.
- The button is styled as an outlined/secondary button with a download/export icon and the label "Export."
- Clicking the button generates an Excel (.xlsx) file containing only the Discount Code Usage table. The KPI cards and the charts (Total Revenue Overview, Revenue by Subscriptions, Revenue by Service Types) are not included in the export.
- The exported .xlsx contains one sheet with the Discount Code Usage columns: Code, Type, Discount, Usage Count, Revenue Impact, and Status. All rows in the table are included (the export is not limited by the table's on-screen pagination).
- The file downloads with the filename convention "Pixally_Discount_Code_Usage_[Date].xlsx" (e.g., "Pixally_Discount_Code_Usage_2025-09-30.xlsx").
- If there are no discount codes to report, the .xlsx is still generated with the column headers and no data rows.
4.9 Data Refresh Behavior
- All report data is loaded when the page is initially rendered with the default date filter ("This Quarter").
- Data refreshes when the Pixally owner changes the date filter or manually reloads the page.
- There is no automatic polling or live-updating mechanism.
- Charts and KPI values may take a moment to recalculate when the date filter is changed, especially for large date ranges (e.g., "Last 365 days"). A loading indicator should be shown during this recalculation.
4.10 Empty State
- If there is no data for the selected date period:
- All KPI cards display "$0.00" / "0" / "0%" as applicable. Comparison indicators display "N/A" or "0%."
- The Total Revenue Overview charts display empty axes with no data points or bars.
- The Revenue by Subscriptions chart displays empty axes with no bars.
- The Revenue by Service Types pie chart displays an empty/grey circle or a "No data" placeholder.
- The Discount Code Usage table displays: "No discount code usage found for the selected period."
- The date filter and Export button remain functional in the empty state.
5. Field Details & Validations
5.1 KPI Cards
Field/Metric
Data Type
Validation / Display Rules
Total Revenue
Currency (USD)
Two decimal places with comma separators (e.g., "$847,392.00"). Comparison: "% previous period" with green/red arrow.
New Paid Subscribers
Integer
Whole number. Comparison: "% previous period" with green/red arrow.
Churn Rate
Percentage
One decimal place (e.g., "2.4%"). Red arrow = churn increased (bad). Green arrow = churn decreased (good). Comparison: "% previous period."
Customer Acquisition Cost (CAC)
Currency (USD)
v2 only. Displays placeholder with "Coming in v2" label. No comparison indicator.
5.2 Date Filter
Field Name
Field Type
Validation Rules
Date Preset
Selectable List
Options: Custom Range, Today, Last 7 days, Last 30 days, Last 90 days, Last 365 days. Default: This Quarter.
Custom Range — Start Date
Date Picker (Calendar)
Required when Custom Range is used. Must be ≤ End Date.
Custom Range — End Date
Date Picker (Calendar)
Required when Custom Range is used. Must be ≥ Start Date. Cannot be a future date beyond today.
5.3 Discount Code Usage Table Fields
Field Name
Field Type
Validation / Display Rules
Code
Text (Read-only)
Discount code string. Uppercase.
Type
Text (Read-only)
Values: "Percentage" or "Fixed."
Discount
Text (Read-only)
Percentage: "[X]%" (e.g., "20%"). Fixed: "$[X]" (e.g., "$50.00").
Usage Count
Integer (Read-only)
Whole number. Count of redemptions within the selected date range.
Revenue Impact
Currency (Read-only)
USD format (e.g., "$49,000"). Positive value. Total revenue brought in by subscribers who used the code, cumulative to date (continues after the discount ends). Tooltip explains this. Not the discount amount given.
Status
Badge (Read-only)
Values: Active (green), Expired (red). Reflects current code status from Discounts module.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Date Filter Change
No explicit success message. Data updates silently.
User selects a new date preset or custom range.
All sections update to reflect the selected period. Loading indicator shown during recalculation.
Export
"Discount code usage exported successfully."
User clicks "Export" and the .xlsx is generated.
The .xlsx file downloads to the browser. No page navigation.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Custom Range — Start After End
"Start date cannot be after end date."
User selects a custom range where start > end.
Inline error in the date picker. Data does not reload.
Custom Range — Future End Date
"End date cannot be a future date."
User selects an end date beyond today.
Inline error in the date picker. Data does not reload.
Data Load Failure
"Unable to load report data. Please try again."
Server error when loading KPIs, charts, or table data.
Toast error. Page shows empty state or last loaded data.
Chart Render Failure
"Unable to render chart. Please refresh the page."
JavaScript or rendering error for any chart.
Error message in the chart area. Other sections unaffected.
Export — Generation Failure
"Failed to export. Please try again."
Server error during .xlsx generation.
Toast error. No file downloaded. User can retry.
Export — Large Data Timeout
"Export is taking longer than expected. Please try again later."
Export generation exceeds the timeout threshold for a very large number of codes.
Toast warning. User can retry.
Network / Connectivity Error
"Unable to connect to the server. Please check your internet connection and try again."
Network failure during page load, filter change, or export.
Toast or banner error. Last loaded data remains visible.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
Date filter is set to "Today" but no transactions occurred today.
All KPIs show $0 / 0 / 0%. Charts show empty axes. Discount Code Usage table shows empty state. Export still generates an .xlsx with only column headers.
2
Churn Rate calculation when there are zero subscribers at the start of the period.
Churn Rate displays "0%" or "N/A" to avoid division-by-zero. Comparison indicator shows "N/A."
3
"Last 365 days" is selected, resulting in a large dataset.
Charts render with monthly aggregation. A loading indicator is displayed during data fetching. If rendering is slow, charts load progressively. Discount Code Usage table uses pagination.
4
A discount code was deleted from the Discounts module but has historical usage.
The deleted code's data (Code, Type, Discount, Usage Count, Revenue Impact) still appears in the Discount Code Usage table. The Status column may show "Expired" or a specific "Deleted" indicator.
5
Revenue by Service Types has zero revenue for one service type (e.g., no Content Creation agencies).
The pie chart displays only the segments with revenue > $0. The missing segment is omitted from the chart and the legend shows "$0" for that type.
6
The Pixally owner exports while the date filter is on "This Quarter" and the quarter just started.
The .xlsx of the Discount Code Usage table is generated. If no codes have usage yet, it contains only the column headers.
7
CAC card is clicked or hovered in v1.
No action is triggered. The card displays the placeholder value and "Coming in v2" label. No tooltip or interaction beyond the visual display.
8
Comparison indicator for Total Revenue when the previous period had zero revenue.
The comparison indicator displays "N/A" or shows the current period's value as 100% growth, depending on the calculation approach. Infinite percentage is avoided.
9
Date filter is changed rapidly between presets.
The system cancels any pending data request from the previous filter and loads only the data for the latest selected filter. No stale data is displayed. A loading indicator may briefly appear.
10
Pixally owner exports with a custom range spanning 3 years.
The system generates the .xlsx of the Discount Code Usage table. All qualifying codes are included as rows.
11
Revenue by Subscriptions chart has data for only 2 months out of 12.
The chart renders with data for only those 2 months. The remaining months display empty/zero-height bars.
12
Discount Code Usage table has 100+ codes for the selected period.
The table uses pagination (default 10 rows per page). All codes are included in the exported .xlsx without pagination truncation.
9. Acceptance Criteria
9.1 KPI Cards
- All four KPI cards display correct values scoped to the selected date filter.
- Total Revenue displays in USD format with comparison indicator.
- New Paid Subscribers displays as a whole number with comparison indicator.
- Churn Rate displays as a percentage with the correct comparison direction (red = churn up = bad, green = churn down = good).
- CAC displays placeholder with "Coming in v2" label and is non-functional in v1.
9.2 Date Filter
- The date filter defaults to "This Quarter" on page load.
- All six presets (Custom Range, Today, Last 7 days, Last 30 days, Last 90 days, Last 365 days) function correctly.
- Custom Range allows start and end date selection via the dual-month calendar.
- The selected date range is displayed in the top banner of the picker.
- Changing the filter updates the top KPI cards only; the charts and Discount Code Usage table are not affected.
9.3 Total Revenue Overview
- The line chart displays three trend lines (Subscription Revenue, Extra Seat Revenue, Transaction Fees) with correct colors and legend.
- The grouped bar chart displays the same three data series as monthly grouped bars.
- Both charts scale automatically based on the data range.
- The info tooltip on the section heading displays the correct explanatory text on hover, making clear that this chart shows actual revenue received (annual payments in the month collected, not spread across 12 months).
- These charts display their own time series and are not driven by the top-card date filter.
9.4 Revenue by Subscriptions
- The stacked bar chart displays monthly revenue breakdown by plan type (Free, Basic, Pro, Studio), with annual revenue divided by 12 across the subscription term.
- The legend displays each plan type with color and total revenue amount.
- The info tooltip displays the correct explanatory text on hover.
- The chart displays its own monthly time series and is not driven by the top-card date filter.
9.5 Revenue by Service Types
- The pie chart displays revenue breakdown by agency service type (Photography, Videography, Photo/Video, Content Creation).
- Each segment shows its percentage value inside the chart.
- The legend displays each type with color and total revenue amount.
- The info tooltip displays the correct explanatory text on hover.
- The chart displays its own revenue distribution and is not driven by the top-card date filter.
9.6 Discount Code Usage Table
- The table displays all required columns (Code, Type, Discount, Usage Count, Revenue Impact, Status).
- Data includes active, expired, and deleted discount codes with historical usage.
- Pagination controls work correctly.
- Revenue Impact shows the cumulative revenue brought in by users of each code as a positive value (not the discount given), with an explanatory tooltip. The table is not driven by the top-card date filter.
9.7 Export (Discount Code Usage)
- The "Export" button generates an Excel (.xlsx) file containing only the Discount Code Usage table.
- The .xlsx includes the columns Code, Type, Discount, Usage Count, Revenue Impact, and Status, with all rows (not limited by on-screen pagination).
- The .xlsx filename follows the convention: "Pixally_Discount_Code_Usage_[Date].xlsx."
- When there are no codes to report, the .xlsx is still generated with column headers only.
10. Manual Test Cases
Test cases for this module will be generated in a separate phase after all FRDs are finalized.
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
Cannot verify the Pixally owner's session. The Reports page returns an authentication error.
Subscription & Billing System (Stripe)
Data Dependency
Revenue data (subscription fees, transaction fees, seat revenue) originates from Stripe. Without it, all revenue metrics display $0 or stale data.
Agency Portal — User Registration
Data Dependency
New Paid Subscribers count and service type categorization originate from the Agency Portal sign-up flow.
Subscribers Module (Gawd Portal — FRD #2)
Internal Dependency
Churn rate calculation requires subscriber count and cancellation data from the Subscribers module.
Discounts Module (Gawd Portal — FRD #6)
Internal Dependency
Discount Code Usage table data references discount codes from the Discounts module, including historical data from deleted codes.
Spreadsheet Export Service
Service Dependency
The "Export" function requires a spreadsheet (.xlsx) generation service. If unavailable, export fails with an error message.
12. References
- Figma Screens:
- Reports Full Page — Batch 2, Image 10
- Reports Date Picker — Batch 2, Image 11
- Reports Tooltips (Revenue by Subscriptions, Revenue by Service Types) — Batch 2, Image 12
- Source of Truth: Gawd Portal Meeting Transcript (JSON) — March 26, 2026 (timestamps 29:17–31:57)
- Supporting Document: Super Admin — The Gawd Portal (Initial Client Document) — Section 4
- Related FRDs:
- FRD #1 — Gawd Portal: Login & Dashboard (Revenue Metrics YTD and Revenue by Subscriptions also appear on Dashboard)
- FRD #6 — Gawd Portal: Discounts (Source of discount code data)
Open Items / Notes for Client Confirmation:
- CAC (Customer Acquisition Cost): Confirmed as a v2 feature. The card is displayed as a placeholder in v1 with "Coming in v2" label. No calculation logic is implemented. The exact CAC formula will be defined in v2 scope.
Resolved in this round: (1) the KPI comparison indicator compares the selected range against the same-length period immediately preceding it (documented in §4.3); (2) sorting on the Discount Code Usage table is confirmed as not required; and (3) the Revenue-by-Subscriptions vs. Dashboard consistency question is settled — the "Revenue by Subscriptions" chart (§4.5) divides annual revenue by 12 to match the Dashboard, while the separate "Total Revenue Overview" chart (§4.4) uses actual/cash-basis timing. The client has approved this split, with the condition that each chart's tooltip explains its basis clearly; both tooltips have been updated accordingly (§4.4 explains actual/cash basis; §4.5 explains the ÷12 normalized trend).
☑️ Agency-Side Impact
Functional Requirements Document (FRD) Gawd Portal — Agency-Side Impact (Failed Payment & Suspension)
Module Name: Gawd Portal — Agency-Side Impact (Failed Payment & Suspension) Version: 2.0 Created Date: March 27, 2026 Last Updated: July 21, 2026
1. Module Overview
Module Name: Gawd Portal — Agency-Side Impact (Failed Payment & Suspension)
Purpose: This FRD documents the impact on agency-side users (agency owners, team members, clients, and contractors) when a subscription payment fails and when an account is subsequently suspended by the Gawd Portal's automated failed payment handling system. It covers three distinct phases: the grace period (payment failed but account not yet suspended), the suspended state (account access revoked), and the reactivation process (payment method updated and outstanding invoice paid). This module ensures that all user types across all portals receive appropriate messaging and are guided toward resolution.
Business Goals:
- Ensure agency owners are immediately and clearly informed of payment failures with actionable resolution steps.
- Maintain full portal access during the configurable grace period to minimize disruption while encouraging prompt payment resolution.
- Enforce account-level access restrictions upon suspension to protect Pixally's revenue and incentivize payment recovery.
- Provide clear, non-alarming messaging to non-owner users (team members, clients, contractors) when the agency account is suspended.
- Support multi-agency contractors by restricting access only to the suspended agency's data while preserving access to other active agencies.
- Define a clear reactivation path for agency owners to resolve payment issues and restore full account access.
2. User Roles & Permissions
Role
Portal
Grace Period Behavior
Suspended State Behavior
Agency Owner
Agency Portal
Full access to all features. Warning banner displayed on Dashboard from day 1 of failure.
Redirected to Settings > Subscription page. No access to any other module or data. Can only update payment method and pay the outstanding invoice. Cannot change plan, cancel, or convert to Free until the outstanding balance is paid.
Agency Admin / Team Member
Agency Portal
Full access (same as normal). No warning banner displayed to them.
Blocked from the portal entirely. Sees "Account is Suspended" screen on login.
Client
Client Portal
Full access (same as normal).
Blocked from the portal entirely. Sees "Account is Suspended" screen on login.
Contractor (single agency)
Contractor Portal
Full access (same as normal).
Blocked from the portal entirely. Sees "Account is Suspended" screen on login.
Contractor (multi-agency)
Contractor Portal
Full access to all agencies (same as normal).
Blocked from the suspended agency's data, events, and projects only. Retains full access to all other active agencies. Sees "Account is Suspended" message when attempting to access the suspended agency's workspace.
3. User Flow
3.1 Grace Period — Agency Owner Flow
3.1.1 The system detects that the agency owner's subscription payment has failed.
3.1.2 The system calculates the suspension date based on the failed payment date and the Pixally owner's configured grace period (e.g., "Suspend account after 4 weeks" as set in the Adjust Failed Payments settings in the Gawd Portal — FRD #3).
3.1.3 The next time the agency owner logs in to the Agency Portal, the system displays a yellow warning banner at the top of the Dashboard page.
3.1.4 The agency owner reads the warning message which includes the suspension date and the actions required to avoid suspension.
3.1.5 The agency owner clicks "Update Payment" on the banner, and the system navigates them to the Settings > Subscription page.
3.1.6 The agency owner clicks "Manage Payment Method" on the Subscription page to update their credit card or payment method.
3.1.7 The agency owner updates their payment method and either the system auto-charges the outstanding invoice or the agency owner manually clicks "Pay Invoice" on the failed invoice in the Subscription Receipts table.
3.1.8 If the payment is successful, the system clears the warning banner, restores the account to normal status, and the grace period countdown is cancelled.
3.1.9 Alternatively, the agency owner clicks "Contact Support" on the banner, and the system opens the external Pixally support contact page.
3.1.10 If the agency owner takes no action and the grace period expires, the system automatically suspends the account.
3.2 Suspended State — Agency Owner Flow
3.2.1 The agency owner logs in to the Agency Portal after the account has been suspended.
3.2.2 The system immediately redirects the agency owner to the Settings > Subscription page, regardless of which URL or page they attempt to access.
3.2.3 The system displays a red error banner at the top of the Subscription page: "Your account has been suspended due to failed payment."
3.2.4 The agency owner sees the Subscription page with their current plan details, the payment method (showing "Expired" status if applicable), seat information, billing cycle details, and the Subscription Receipts table showing the failed invoice.
3.2.5 The agency owner clicks "Manage Payment Method" to update their payment details.
3.2.6 Upon updating the payment method, the system attempts to automatically charge the outstanding invoice using the new payment method (preferred approach — if Stripe supports auto-charge on payment method update).
3.2.7 If auto-charge is not supported by Stripe, the agency owner must manually click "Pay Invoice" on the failed invoice row in the Subscription Receipts table.
3.2.8 If the payment is successful, the system lifts the suspension, restores full account access, clears the error banner, and the agency owner can navigate to all portal modules normally.
3.2.9 If the payment fails again, the system displays an error message and the account remains suspended.
3.2.10 The "Cancel Subscription" option is not available during suspension. To cancel or downgrade, the agency owner must first pay the outstanding balance, after which the account returns to active status and normal cancellation options apply.
3.2.11 If a suspended subscriber does not wish to pay and wants to leave, they contact Pixally support, and the Pixally owner cancels the account on their behalf from the Gawd Portal.
3.3 Suspended State — Non-Owner Users Flow (Team Members, Clients, Contractors)
3.3.1 A team member, client, or contractor attempts to log in to their respective portal (Agency Portal, Client Portal, or Contractor Portal) while the agency account is suspended.
3.3.2 The system displays the "Account is Suspended" screen instead of the normal portal interface.
3.3.3 The screen displays the Pixally logo, a warning icon, the heading "Account is Suspended," and two paragraphs of explanatory text.
3.3.4 The user reads the message and contacts the account owner or agency administrator to resolve the issue.
3.3.5 There are no action buttons on this screen for non-owner users; they cannot resolve the issue themselves.
3.4 Suspended State — Multi-Agency Contractor Flow
3.4.1 A contractor who works with multiple agencies logs in to the Contractor Portal while one of their agencies has been suspended.
3.4.2 The system allows the contractor to access the Contractor Portal normally.
3.4.3 The contractor can view and interact with all data, events, projects, and workspaces belonging to their active (non-suspended) agencies.
3.4.4 When the contractor attempts to access the suspended agency's workspace, data, events, or projects, the system displays the "Account is Suspended" message for that specific agency.
3.4.5 The contractor is not blocked from the entire portal; only the suspended agency's data is restricted.
4. Functional Logic
4.1 Phase 1 — Grace Period (Payment Failed, Account Not Yet Suspended)
4.1.1 Grace Period Trigger
- The grace period begins when a subscriber's subscription payment fails (either through automatic billing or a manual charge attempt from the Gawd Portal).
- The system calculates the suspension date by adding the configured grace period duration (set in the "Adjust Failed Payments" popup in the Gawd Portal — FRD #3) to the failed payment date. The confirmed grace period before suspension is 28 days of non-payment.
- For example, if the payment fails on April 10 and the grace period is 28 days (4 weeks), the suspension date is May 8.
- Because subscribers pay in advance for the upcoming period, by the time the 28-day grace period elapses the subscriber has already received a full period of service that remains unpaid; this is why the outstanding balance must be settled before any further account changes (see the reactivation logic).
- The grace period applies globally to all subscribers using the configuration active at the time of the payment failure. If the Pixally owner changes the grace period duration, existing grace periods are not retroactively affected.
4.1.2 Dashboard Warning Banner (Agency Owner Only)
- A yellow warning banner is displayed at the top of the Agency Portal Dashboard page, above the main content and below the header bar.
- The banner displays a warning icon (⚠️) followed by the message text and two action buttons.
- The banner message reads: "Your last payment failed. If payment is not completed, your account will be suspended on [Suspension Date]. Please update your payment method or pay the invoice to avoid losing access to your account."
- The [Suspension Date] is dynamically calculated based on the failed payment date and the configured grace period.
- The banner includes two action buttons on the right side:
- "Update Payment" — Navigates the agency owner to the Settings > Subscription page where they can update their payment method.
- "Contact Support" — Opens the external Pixally support contact page in a new browser tab.
- The banner is displayed only on the Dashboard page, not across all pages in the Agency Portal.
- The banner is visible only to the agency owner. Team members, admins, clients, and contractors do not see this banner during the grace period.
- The banner is not dismissible; it remains visible on the Dashboard until the payment issue is resolved or the account is suspended.
- The warning banner is shown starting from day 1 of the failed payment (as soon as the payment fails), and it is also shown after 3 failed retry attempts. In other words, the agency owner is warned immediately when the first failure occurs and continues to be warned as retries fail, rather than only near the end of the grace period.
- The banner displays every time the agency owner visits or refreshes the Dashboard during the grace period.
4.1.3 Grace Period — Access and Feature Behavior
- During the grace period, the agency owner retains full access to all Agency Portal features and modules without any restrictions.
- All automations continue to run normally during the grace period.
- All client payment processing continues normally during the grace period.
- Team members, clients, and contractors are not affected during the grace period and retain full access to their respective portals.
- No notifications or warning messages are displayed to non-owner users during the grace period.
4.1.4 Grace Period — Automatic Retry Integration
- During the grace period, payment retries are handled by Stripe according to the retry rules configured in Stripe (the retry schedule is not configured in the Adjust Failed Payments popup in the Gawd Portal). When a subscription payment fails, Stripe automatically retries the charge, and the Gawd Portal and Agency Portal reflect the resulting status.
- If a Stripe retry succeeds during the grace period, the payment issue is resolved, the warning banner is removed from the Dashboard, and the grace period countdown is cancelled.
- If Stripe's automatic retries are exhausted without success and the 28-day grace period expires, the account is suspended.
4.2 Phase 2 — Suspended State (Account Access Revoked)
4.2.1 Suspension Trigger
- The system automatically suspends the account when the grace period expires without the outstanding payment being resolved.
- Upon suspension, the subscriber's status in the Gawd Portal changes from "Active" or "Paid" to "Suspended."
- The following actions are triggered immediately upon suspension:
- All automations belonging to the agency are stopped.
- All automatic client payment processing through the agency is stopped.
- All scheduled tasks and workflows are paused.
- The agency owner is locked out of all portal modules except the Settings > Subscription page.
- All team members are locked out of the Agency Portal entirely.
- All clients are locked out of the Client Portal entirely.
- All contractors lose access to this agency's data (but retain access to other active agencies if applicable).
4.2.2 Agency Owner — Subscription Page (Suspended State)
- When a suspended agency owner logs in to the Agency Portal, the system immediately redirects them to the Settings > Subscription page, regardless of which URL they enter or which page they attempt to navigate to.
- Any attempt to navigate to another page via the sidebar, URL bar, or bookmarks results in an automatic redirect back to the Subscription page.
- A red error banner is displayed at the top of the Subscription page with the message: "Your account has been suspended due to failed payment." The banner includes two action buttons: "Pay Invoice" and "Contact Support."
- The "Pay Invoice" button scrolls the page to the Subscription Receipts section where the failed invoice is highlighted.
- The "Contact Support" button opens the external Pixally support contact page in a new browser tab.
Subscription Page Content During Suspension:
- The page displays the full Subscription settings layout including:
- Plan details: Current plan name, description, and pricing.
- Payment Method: Displays the current payment method with its status (e.g., "Visa 3456 • Expired"). A "Manage Payment Method" button (styled with a warning icon and blue/teal background) is prominently displayed to encourage the user to update their payment details.
- Seat information: Current seat count and pricing (e.g., "4 Seats — $27 (3 additional seats $9 each)"). The "Add Team Member" button is displayed but should be disabled during suspension.
- Billing cycle: Current billing cycle (Annual/Monthly) with pricing details. The "Switch to Monthly/Annual" button is displayed but should be disabled during suspension.
- "Change Plan" button: Disabled during suspension. The agency owner must pay the outstanding balance before changing plans.
- "Cancel Subscription" button: Disabled during suspension. The agency owner must first pay the outstanding balance before they can cancel or downgrade. This is because they have already received a full period of service that remains unpaid (payment is taken in advance), so the amount owed must be settled first. If a suspended subscriber does not wish to continue and would rather not pay, they can contact Pixally support, and the Pixally owner can cancel the account on their behalf from the Gawd Portal.
- The requirement to settle the outstanding balance first applies to every account-changing action during suspension: the subscriber cannot change plan, cancel, or convert to the Free plan until the outstanding invoice is paid.
- Subscription Receipts table: Displays the payment history with columns: Receipt ID, Status, Plan, Date, Amount, and Actions.
- The failed invoice row is highlighted (e.g., with a red/pink background) and displays a "Pay Invoice" button in the Actions column.
- Paid invoices display a "Download Receipt" button in the Actions column.
- Expandable rows show additional details: Payment Method, Plan Price, Additional Seats Price, and Total.
4.2.3 Payment Resolution — Auto-Charge Logic
- When the agency owner updates their payment method via "Manage Payment Method," the system follows this priority logic:
- Option 1 (Preferred): If Stripe supports automatic charge on payment method update, the system immediately attempts to charge the outstanding invoice using the new payment method. If the charge succeeds, the account is reactivated automatically without requiring the user to manually click "Pay Invoice."
- Option 2 (Fallback): If Stripe does not support auto-charge on payment method update, the user must manually click "Pay Invoice" on the failed invoice in the Subscription Receipts table after updating their payment method. The system should display instructional text near the failed invoice: "Your payment method has been updated. Please click 'Pay Invoice' to complete the payment and reactivate your account."
- The development team must confirm with Stripe which option is supported and implement accordingly.
4.2.4 Account Reactivation
- When the outstanding invoice is successfully paid (either through auto-charge or manual Pay Invoice), the system performs the following actions:
- The subscriber's status is changed from "Suspended" back to "Active" / "Paid."
- The red error banner is removed from the Subscription page.
- The agency owner regains full access to all Agency Portal modules and pages.
- All team members regain access to the Agency Portal.
- All clients regain access to the Client Portal.
- All contractors regain access to this agency's data in the Contractor Portal.
- All paused automations, scheduled tasks, and workflows are resumed.
- Automatic client payment processing is resumed.
- The reactivation is immediate upon successful payment; there is no waiting period or manual approval required.
- A success message is displayed to the agency owner: "Your payment has been processed successfully. Your account has been reactivated."
4.2.5 Cancellation During Suspension
- The agency owner cannot self-cancel or downgrade while suspended. The "Cancel Subscription" action is disabled on the Subscription page during suspension, because the outstanding balance (for the period already served) must be paid first.
- To cancel or downgrade, the agency owner must first pay the outstanding invoice. Once paid, the account returns to active status and the normal cancellation options (Cancel Now / Cancel at Cycle End, which downgrade to the Free plan) become available.
- If a suspended subscriber does not wish to pay and simply wants to leave, they contact Pixally support. The Pixally owner can then cancel the account on their behalf from the Gawd Portal. When the Pixally owner cancels a suspended account this way, the account follows the standard cancellation process (downgrade to Free with the associated brand/project retention, or the standard soft-delete timeline as applicable), and any outstanding failed invoice is voided/written off on the Pixally owner's side.
4.2.6 Non-Owner Users — "Account is Suspended" Screen
- When a team member, client, or contractor (single agency) attempts to log in while the agency account is suspended, the system displays a full-screen "Account is Suspended" page instead of the normal portal interface.
- The page layout is identical to the Login page layout: a left panel with a full-height editorial-style image (with "Photo by Iris & Light" credit), and a right panel with the content.
- The right panel displays:
- The Pixally logo at the top.
- A red/pink warning icon (hexagonal exclamation mark).
- Heading: "Account is Suspended."
- Paragraph 1: "Looks like this account is currently on hold, so access to portals, files, and other resources isn't available right now."
- Paragraph 2: "Please reach out to the account owner or agency administrator to get things back up and running."
- There are no action buttons on this screen. The user cannot resolve the issue from this page.
- The user cannot navigate to any other page within the portal. All URLs redirect to this suspension screen.
- Once the agency owner resolves the payment issue and the account is reactivated, this screen is replaced by the normal login/portal experience on the user's next visit or page refresh.
4.2.7 Multi-Agency Contractor — Selective Access Restriction
- A contractor who works with multiple agencies is not blocked from the Contractor Portal entirely.
- The contractor can log in and access the Contractor Portal normally.
- The contractor retains full access to all data, events, projects, calendars, tasks, and payments associated with their active (non-suspended) agencies.
- When the contractor attempts to switch to or access the suspended agency's workspace, or navigate to that agency's events, projects, or data, the system displays the "Account is Suspended" message for that specific agency context.
- The message is displayed inline within the Contractor Portal (not as a full-screen redirect), allowing the contractor to navigate back to their other active agencies without being locked out.
- The suspended agency's workspace does not appear as a selectable option in workspace switchers, or if it does appear, selecting it shows the suspension message instead of loading the agency's data.
4.3 Phase 3 — Auto-Deletion After Suspension
- If the account remains suspended for the duration configured in the "Delete account after" setting in the Adjust Failed Payments popup (e.g., "1 year"), the system automatically performs a hard delete of the agency's data.
- The auto-deletion follows the same soft-delete + hard-delete process defined in FRD #2 (Subscribers): subscriber metadata (email, company name, plan, lifetime value, invoices) is retained in the Gawd Portal, but all agency-level data (projects, clients, contractors, files, team members, automations) is permanently deleted.
- Account deletion only applies to suspended accounts, as noted in the Adjust Failed Payments settings.
- If the agency owner reactivates the account by paying the outstanding invoice before the auto-deletion period expires, the deletion countdown is cancelled and all data is preserved.
- If the agency owner cancels the subscription during suspension, the auto-deletion timeline from the suspension settings is replaced by the standard cancellation deletion timeline (1 year from cancellation date).
5. Field Details & Validations
5.1 Dashboard Warning Banner (Grace Period)
Field Name
Field Type
Validation / Display Rules
Warning Icon
Icon (Read-only)
Yellow triangle exclamation mark (⚠️).
Banner Message
Text (Read-only)
Dynamic text including the calculated suspension date. Not editable by the agency owner.
Suspension Date
Date (Read-only)
Dynamically calculated: Failed Payment Date + Configured Grace Period. Format: "Month Day, Year" (e.g., "September 1, 2025").
"Update Payment" Button
Button
Navigates to Settings > Subscription page.
"Contact Support" Button
Button
Opens external Pixally support contact page in a new tab.
5.2 Suspended State — Subscription Page Banner
Field Name
Field Type
Validation / Display Rules
Error Icon
Icon (Read-only)
Red circular exclamation mark.
Banner Message
Text (Read-only)
Static text: "Your account has been suspended due to failed payment."
"Pay Invoice" Button
Button
Scrolls to the Subscription Receipts section with the failed invoice highlighted.
"Contact Support" Button
Button
Opens external Pixally support contact page in a new tab.
5.3 Subscription Page — Button States During Suspension
Button
State During Suspension
Behavior
Manage Payment Method
Enabled
Opens payment method update flow (Stripe).
Change Plan
Disabled
Greyed out. Tooltip: "Resolve your payment issue before changing plans."
Cancel Subscription
Enabled (Cancel Now only)
Opens cancellation confirmation popup. "Cancel at Cycle End" option is hidden.
Add Team Member
Disabled
Greyed out. Not functional during suspension.
Switch to Monthly / Annual
Disabled
Greyed out. Not functional during suspension.
Pay Invoice (on failed receipt)
Enabled
Initiates payment via Stripe for the outstanding invoice.
Download Receipt (on paid receipts)
Enabled
Downloads the receipt PDF for historical paid invoices.
5.4 "Account is Suspended" Screen (Non-Owner Users)
Field Name
Field Type
Validation / Display Rules
Pixally Logo
Image (Read-only)
Displayed at the top of the right panel.
Warning Icon
Icon (Read-only)
Red/pink hexagonal exclamation mark.
Heading
Text (Read-only)
"Account is Suspended."
Paragraph 1
Text (Read-only)
"Looks like this account is currently on hold, so access to portals, files, and other resources isn't available right now."
Paragraph 2
Text (Read-only)
"Please reach out to the account owner or agency administrator to get things back up and running."
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
Payment Method Updated + Auto-Charge Successful
"Your payment has been processed successfully. Your account has been reactivated."
Agency owner updates payment method and auto-charge succeeds.
Banner removed. Full access restored. All users regain access. Automations resume.
Manual Pay Invoice Successful
"Your payment has been processed successfully. Your account has been reactivated."
Agency owner clicks "Pay Invoice" and the charge succeeds.
Banner removed. Full access restored. All users regain access. Automations resume.
Automatic Retry Successful (During Grace Period)
Banner removed silently. No explicit success message (agency owner may not be logged in when retry succeeds).
System's automatic retry successfully charges the payment during the grace period.
Warning banner removed on next Dashboard visit. Grace period countdown cancelled.
Pay Outstanding Invoice (Suspended)
"Payment successful. Your account has been reactivated."
Agency owner pays the outstanding invoice while suspended (auto-charge or Pay Invoice).
Account moves from "Suspended" to "Active." Full access restored. Normal cancellation options become available.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Pay Invoice — Stripe Failure
"Payment failed: [Stripe Reason]. Please update your payment method and try again."
Stripe returns a failure when the agency owner clicks "Pay Invoice."
Toast error on the Subscription page. Account remains suspended. User should update payment method and retry.
Auto-Charge on Update — Stripe Failure
"Your payment method has been updated, but the payment could not be processed: [Stripe Reason]. Please click 'Pay Invoice' to retry."
Auto-charge fails after payment method update.
Toast error. Instructional text displayed near the failed invoice. User must manually click "Pay Invoice."
Payment Method Update — Stripe Error
"Failed to update payment method. Please check your card details and try again."
Stripe returns an error during payment method update (e.g., invalid card number, expired card).
Toast error. Manage Payment Method flow remains open. User must correct card details.
Cancellation — Server Error
"Failed to cancel subscription. Please try again."
Server error during cancellation processing.
Toast error. Confirmation popup closes. User can retry.
Navigation Attempt During Suspension
No explicit error message. System silently redirects to Settings > Subscription page.
Agency owner attempts to navigate to any module other than Subscription during suspension.
Automatic redirect to Subscription page. No toast or error displayed.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
Agency owner updates payment method during grace period (before suspension).
The warning banner navigates them to the Subscription page. Upon successful payment, the banner is removed and the grace period is cancelled. No suspension occurs.
2
Grace period expires while the agency owner is actively using the portal.
The system does not immediately interrupt the user's active session. The suspension takes effect on the next page load or navigation. The user may complete their current action but will be redirected to the Subscription page on the next navigation.
3
Multiple payments fail in succession (e.g., monthly subscriber fails 3 consecutive months).
Each failed payment may trigger its own grace period. The system should consolidate these — the suspension timeline is based on the earliest unresolved failed payment. Only one grace period / suspension applies at a time.
4
Agency owner resolves the payment on the exact day the account is scheduled to be suspended.
If the payment is resolved before the system's suspension job runs, the suspension is cancelled. If the suspension job runs first, the account is suspended momentarily and then reactivated upon payment confirmation.
5
Contractor works with 5 agencies, and 3 of them are suspended.
The contractor retains access to the 2 active agencies. The 3 suspended agencies' data is blocked individually. The contractor can still log in and work normally with the active agencies.
6
Client portal link is shared in an email while the agency is suspended.
The client clicks the link and sees the "Account is Suspended" screen instead of the portal content. The link remains valid; it will work again once the agency is reactivated.
7
Agency owner tries to add a team member during suspension.
The "Add Team Member" button is disabled. No action is possible. The agency owner must resolve the payment first.
8
Team member tries to access a deep link (e.g., specific project URL) while the agency is suspended.
The system redirects to the "Account is Suspended" screen regardless of the URL. No project data is accessible.
9
Auto-charge succeeds on payment method update, but the agency has multiple failed invoices.
The auto-charge processes only the most recent / primary outstanding invoice. If multiple invoices are outstanding, the remaining invoices appear in the Subscription Receipts table for manual payment via "Pay Invoice." The account may remain suspended until all outstanding invoices are resolved.
10
Agency owner cancels subscription during suspension, then tries to log in again later.
The agency owner sees a "Your subscription has been cancelled" message or is redirected to a resubscription page. They no longer see the suspension screen since the account status is now "Cancelled," not "Suspended."
11
Pixally owner changes the grace period from 4 weeks to 2 weeks while an agency is in a 4-week grace period at week 3.
The agency continues under the 4-week grace period that was in effect when their payment failed. The new 2-week setting applies only to future payment failures.
12
Agency owner updates payment method but does not click "Pay Invoice" (fallback scenario).
The account remains suspended. The system displays instructional text: "Your payment method has been updated. Please click 'Pay Invoice' to complete the payment and reactivate your account." The user must manually pay.
13
The suspended agency has active automations that send emails to clients.
All automations are stopped immediately upon suspension. No emails, notifications, or automated workflows are executed. Automations resume automatically upon reactivation.
14
Agency owner successfully pays during suspension, but a new billing cycle payment is due the next day.
The account is reactivated. The next day's billing cycle payment is processed normally through the standard billing flow. If it also fails, a new grace period begins.
15
The "Account is Suspended" screen is accessed on a mobile device.
The screen is responsive and displays correctly on mobile. The layout adapts: the left image panel may be hidden or stacked above the content on small screens.
16
Agency has been suspended for 11 months (auto-deletion set to 1 year). The agency owner pays the invoice.
The account is reactivated. The auto-deletion countdown is cancelled. All data is preserved. The agency owner regains full access immediately.
9. Acceptance Criteria
9.1 Grace Period
- The warning banner is displayed on the Agency Portal Dashboard when the agency's payment has failed.
- The banner message includes the dynamically calculated suspension date.
- The "Update Payment" button navigates to Settings > Subscription.
- The "Contact Support" button opens the external Pixally support page.
- The banner is not dismissible and is visible only to the agency owner.
- The agency owner retains full access to all features during the grace period.
- Team members, clients, and contractors are not affected during the grace period.
- If the payment is resolved during the grace period (via manual payment or auto-retry), the banner is removed.
9.2 Suspended State — Agency Owner
- Upon suspension, the agency owner is redirected to Settings > Subscription on every login and navigation attempt.
- The red suspension banner is displayed with "Pay Invoice" and "Contact Support" buttons.
- "Manage Payment Method" is enabled and functional.
- "Change Plan," "Add Team Member," and "Switch to Monthly/Annual" are disabled.
- "Cancel Subscription" shows only "Cancel Now" (no "Cancel at Cycle End").
- The failed invoice is highlighted in the Subscription Receipts table with a "Pay Invoice" action button.
- Auto-charge on payment method update is implemented (or fallback manual Pay Invoice with instructions).
9.3 Suspended State — Non-Owner Users
- Team members, clients, and single-agency contractors see the "Account is Suspended" full screen on login.
- The screen displays the correct heading, paragraphs, and Pixally branding.
- No action buttons are available to non-owner users.
- All URLs redirect to the suspension screen.
9.4 Multi-Agency Contractors
- Multi-agency contractors can log in and access the Contractor Portal.
- Access to active agencies is fully preserved.
- Access to the suspended agency's data is blocked with a suspension message.
- Switching between active agencies works normally.
9.5 Account Reactivation
- Successful payment immediately lifts the suspension.
- All users (owner, team, clients, contractors) regain access upon reactivation.
- Automations, scheduled tasks, and client payment processing resume.
- The red banner is removed from the Subscription page.
9.6 Cancellation During Suspension
- Self-cancellation and downgrade are disabled during suspension; the agency owner must pay the outstanding balance first.
- After the outstanding invoice is paid, the account returns to active status and normal cancellation options become available.
- A suspended subscriber who does not want to pay can request cancellation via support, and the Pixally owner can cancel on their behalf from the Gawd Portal.
- When cancelled by the Pixally owner, the account follows the standard cancellation process and any outstanding failed invoice is voided on the Pixally owner's side.
10. Manual Test Cases
Test cases for this module will be generated in a separate phase after all FRDs are finalized.
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Payments Module (Gawd Portal — FRD #3)
Internal Dependency
The Adjust Failed Payments settings (grace period, retry schedule, suspension timing) are configured in FRD #3. Without it, the suspension timeline and auto-retry logic cannot be determined.
Subscribers Module (Gawd Portal — FRD #2)
Internal Dependency
Subscriber status changes (Active → Suspended → Cancelled) are managed in the Subscribers module. Without it, status transitions may not be reflected in the Gawd Portal.
Stripe Payment Gateway
External Service Dependency
Payment method updates, manual Pay Invoice, and auto-charge logic all depend on Stripe. If Stripe is unavailable, the agency owner cannot resolve the payment issue and the account remains suspended.
Agency Portal — Settings > Subscription
Agency Portal Dependency
The Subscription page is the only page accessible during suspension. If this page is unavailable or broken, the agency owner has no way to resolve the payment issue from the portal.
Agency Portal — Dashboard
Agency Portal Dependency
The warning banner is displayed on the Dashboard during the grace period. If the Dashboard is unavailable, the agency owner may not see the warning (though the payment failure emails from the Gawd Portal notification system provide backup alerting).
Client Portal
Cross-Portal Dependency
The "Account is Suspended" screen must be rendered on the Client Portal. If the Client Portal is unavailable, clients may see a generic error instead of the branded suspension screen.
Contractor Portal
Cross-Portal Dependency
The selective access restriction for multi-agency contractors depends on the Contractor Portal's workspace switching logic. If unavailable, contractors may see incorrect data or errors.
Email Service (SMTP)
External Service Dependency
Automated retry failure notifications and payment reminder emails depend on the email service. If unavailable, the agency owner may not receive email alerts about payment issues.
Scheduled Job / Cron Service
Service Dependency
The automatic suspension trigger (grace period expiry) and auto-deletion trigger depend on scheduled background jobs. If the job service is unavailable, suspension and deletion may be delayed.
12. References
- Figma Link:
☑️ Customer Support Role & Permissions
Functional Requirements Document (FRD) Gawd Portal — Customer Support Role & Permissions
Module Name: Gawd Portal — Customer Support Role & Permissions Version: 2.0 Created Date: March 27, 2026 Last Updated: July 21, 2026
1. Module Overview
Module Name: Gawd Portal — Customer Support Role & Permissions
Purpose: The Customer Support Role provides Pixally's customer support executives with a restricted, view-only interface to access basic subscriber information needed to assist customers with inquiries. The CS view is a stripped-down version of the Gawd Portal that exposes only the Subscribers listing page with a limited set of fields, without any ability to modify, create, delete, or manage subscriber data. This role enables the support team to quickly look up subscriber details (name, email, plan, status, payment info) to resolve common support requests without exposing sensitive business data such as revenue metrics, financial reports, or administrative controls.
Business Goals:
- Enable customer support executives to efficiently look up subscriber information to handle support inquiries.
- Restrict access to only the data necessary for support operations — no revenue data, no administrative actions, no financial reports.
- Maintain data security by providing view-only access with no ability to modify any subscriber or system data.
- Support an unlimited number of CS users without impacting the Pixally owner's administrative access.
- Provide a separate, dedicated login URL for CS users to maintain clear separation from the Pixally owner's super admin portal.
2. User Roles & Permissions
Role
Access Level
Permissions
Pixally Owner (Super Admin)
Full Access (separate portal)
Full access to all Gawd Portal modules. CS users are created/managed from the backend in Phase 1.
Customer Support Executive
View-Only (restricted)
View subscriber listing with 12 specific fields. Search and filter subscribers. No create, edit, delete, cancel, discount, export, or any modification actions. No access to Dashboard, Payments, Reports, Lead Management, Referral, Discounts, or Notification Settings.
Access Restrictions:
- CS users have a completely separate login URL from the Pixally owner's Gawd Portal.
- CS accounts are created and managed from the backend (database/admin panel) in Phase 1. There is no UI within the Gawd Portal for the Pixally owner to create or manage CS accounts.
- There is no restriction on the number of CS user accounts that can be created.
- CS users cannot access any module other than the Subscribers listing.
- CS users cannot perform any actions on subscriber records — the interface is strictly read-only.
3. User Flow
3.1 CS Login Flow
3.1.1 The CS user navigates to the dedicated Customer Support portal URL in their browser.
3.1.2 The system displays the CS login page with the Pixally logo, a full-height image on the left panel, and the login form on the right panel titled "Sign in to Gawd Mode — Support."
3.1.3 The CS user enters their email address in the "Email address" field.
3.1.4 The CS user enters their password in the "Password" field (minimum 6 characters).
3.1.5 The CS user may click the eye icon to toggle password visibility.
3.1.6 The CS user clicks the "Sign in" button.
3.1.7 The system validates the credentials and, upon successful authentication, redirects the CS user to the Subscribers listing page.
3.1.8 If the credentials are invalid, the system displays an inline error message.
3.2 CS Subscribers Listing Flow
3.2.1 Upon successful login, the system loads the Subscribers listing page as the only accessible page.
3.2.2 The system displays the page title "Subscribers," three tab filters (All, Active, Inactive), a search bar, a Status filter dropdown, and the subscriber data table with pagination controls.
3.2.3 The CS user clicks the "Active" or "Inactive" tab to filter the listing by subscriber status grouping.
3.2.4 The CS user types a subscriber name, email, or company name in the search bar, and the system filters the table results in real-time.
3.2.5 The CS user selects a status from the Status filter dropdown to narrow results to a specific status.
3.2.6 The CS user clicks any sortable column header to sort the table in ascending or descending order.
3.2.7 The CS user uses the pagination controls at the bottom of the table to navigate through subscriber records.
3.2.8 The CS user reviews subscriber details directly from the listing table without clicking into any profile.
3.3 CS Logout Flow
3.3.1 The CS user clicks the profile avatar in the top-right corner of the header.
3.3.2 The system displays a dropdown with a single option: "Log Out."
3.3.3 The CS user clicks "Log Out," and the system ends the session, clears the session token, and redirects to the CS login page.
4. Functional Logic
4.1 CS Login Page
- The CS login page is hosted on a separate, dedicated URL distinct from the Pixally owner's Gawd Portal URL.
- The page layout is identical to the Pixally owner's login page: a left panel with a full-height editorial image, and a right panel with the Pixally logo and login form.
- The login form title reads "Sign in to Gawd Mode — Support" to differentiate it from the Pixally owner's login ("Sign in to Gawd Mode").
- The login form contains two fields: "Email address" and "Password" (minimum 6 characters, with eye icon toggle for visibility).
- The "Sign in" button is styled identically to the Pixally owner's login (full-width yellow/gold primary button).
- There is no "Forgot Password" or "Sign Up" functionality on this login page. Password resets for CS users are handled from the backend.
- There is no IP whitelisting for CS users (unlike the Pixally owner's login). CS users can log in from any location.
- Upon successful authentication, the system redirects the CS user to the Subscribers listing page.
- CS accounts are pre-provisioned from the backend; no self-registration is possible.
- Multiple CS users can be logged in simultaneously from different devices or browsers.
4.2 CS Portal Shell
4.2.1 Left Sidebar
- The left sidebar displays the Pixally logo at the top, followed by a single navigation item: "Subscribers."
- "Subscribers" is always highlighted as the active module since it is the only accessible page.
- No other navigation items (Dashboard, Payments, Reports, Lead Management, Referral, Discounts) are displayed in the sidebar.
- The sidebar collapse/expand toggle is available and functional, consistent with the Pixally owner's portal experience.
- The "Help Center" link is displayed at the bottom of the sidebar and opens the external Pixally Help page in a new tab.
4.2.2 Top Header Bar
- The header bar contains a simplified set of elements compared to the Pixally owner's portal:
- Dark mode/light mode toggle: Available and functional. Allows the CS user to switch the visual theme. Preference persists across sessions.
- Profile avatar: Displays the CS user's profile picture or a default placeholder. Clicking opens a dropdown with only one option: "Log Out."
- The following elements are NOT displayed in the CS header:
- Global search bar (Cmd+K): Not available. The listing page search is sufficient for CS needs.
- Notification bell: Not available. CS users do not receive in-app notifications.
4.3 CS Subscribers Listing Page
4.3.1 Page Layout
- The page title reads "Subscribers" at the top of the main content area.
- Below the title, three tab filter buttons are displayed: All (selected by default), Active, and Inactive.
- A search bar is positioned to the right of the tabs.
- A Status filter dropdown is positioned next to the search bar.
- Below the tabs and search area, the subscriber data table is displayed with column headers, data rows, and pagination controls at the bottom.
- There is NO "Export Data" button on the CS view.
- There is NO filter icon/panel (the Status dropdown provides the only filter beyond the tabs).
4.3.2 Tab Filtering
- The tab filtering logic is identical to the Pixally owner's Subscribers listing (FRD #2):
- All: Displays all subscribers across all statuses.
- Active: Displays subscribers with Active, Paid, Trial, and Canceling statuses. (Canceling subscribers still have full paid access until their term ends, so they appear under Active.)
- Inactive: Displays subscribers with Expired, Cancelled, and Suspended statuses. (Cancelled subscribers have been downgraded to the Free plan, so their Subscription Plan column shows "Free.")
- Only one tab can be selected at a time.
- Tab switching works in combination with the search query and Status filter.
4.3.3 Table Columns (12 Fields — View-Only)
- The CS subscriber listing table displays the following 12 columns, each with a sort arrow (↓) for ascending/descending sorting:
- Subscriber Name: The agency owner's full name. Displayed as plain text — NOT clickable (no link to profile).
- Email: The subscriber's registered email address.
- Phone Number: The subscriber's phone number (e.g., "+1 (123) 456 7890").
- Company Name: The subscriber's company/agency name.
- Subscription Plan: The plan name and billing cycle (e.g., "Pro Monthly," "Basic Yearly"). For Trial users: "Trial." For cancelled/downgraded subscribers: "Free."
- Subscription Start Date: The date the subscriber started their subscription. Format: MM/DD/YYYY. For Trial users: "N/A."
- Next Billing Date: The date of the subscriber's next scheduled payment. Format: MM/DD/YYYY. For Trial users: "N/A."
- Subscription Status: The subscriber's current status displayed as a color-coded badge: Active (green), Paid (green), Trial (purple), Expired (grey), Cancelled (orange), Suspended (red), Canceling (orange). The "Canceling" status indicates a subscriber who has requested cancellation but whose paid term has not yet ended.
- Most Recent Payment Status: The status of the subscriber's latest payment: "Success," "Failed," "Pending," or "N/A" (for Trial users).
- Payment Method: The masked payment method (e.g., "Visa •••• 4242"). For Trial users without a payment method: "N/A."
- Last Login Date: The date of the subscriber's last login. Format: MM/DD/YYYY or relative time (e.g., "2h ago"). Displays "Never" if the subscriber has never logged in.
- Active Projects: The count of the subscriber's booked projects. A project is counted as booked when at least one of its events is in a stage under the "Booked Stages" group (Proposal Signed, Deposit Paid, Planning, and any custom stages added under Booked Stages) or the "Post-Event Stages" group (Post Production, Completed, and any custom stages under Post-Event Stages) in the pipeline. Projects whose events are only in New Lead stages, archived projects, and deleted projects are not counted. Because a project can contain multiple events, it counts as long as at least one event qualifies. The column header remains labeled "Active Projects," and hovering over it displays a tooltip clarifying that the count reflects booked projects only (from proposal-signed through post-event stages, excluding leads, archived, and deleted projects).
- The table does NOT display the following columns that are visible in the Pixally owner's view: Tickets, Subscription Length, Credit Card Status Icon, Kebab Menu.
- No row in the table is clickable. CS users cannot navigate to subscriber profiles.
- The default sort order is by "Subscriber Name" in ascending alphabetical order.
4.3.4 Search
- The search bar performs a real-time filter on the listing as the CS user types.
- The search matches against three fields: Subscriber Name, Email, and Company Name.
- The search is case-insensitive and supports partial matching.
- If no results match, the table displays: "No subscribers found matching your search."
- Search works in combination with the selected tab and Status filter.
4.3.5 Status Filter
- A Status dropdown is positioned next to the search bar (instead of the full Filters panel available in the Pixally owner's view).
- The dropdown options are: All (default), Active, Paid, Trial, Canceling, Expired, Cancelled, Suspended.
- Selecting a status filters the listing to show only subscribers with that specific status.
- The Status filter works in combination with the selected tab and search query.
- There are no range sliders, plan checkboxes, or other advanced filter options in the CS view.
4.3.6 Pagination
- Pagination controls are displayed at the bottom-right of the table.
- The pagination follows the same pattern as the Pixally owner's view: "Rows per page:" dropdown (default: 10, options: 10, 25, 50, 100), current range indicator, and previous/next page navigation arrows.
4.3.7 No Actions Available
- The CS view does not include any action buttons, kebab menus, credit card icons, or interactive elements on subscriber rows.
- There are no "Apply Discount," "Cancel Subscription," "Delete," "Reset Trial," "Send Reminder," or "Export Data" capabilities.
- The CS user cannot modify any subscriber data or trigger any system actions.
- If a CS user attempts to access any other Gawd Portal module via direct URL (e.g., typing the Dashboard URL), the system redirects them back to the Subscribers listing page.
4.4 Session Management
- CS user sessions are managed via secure session tokens, identical to the Pixally owner's session management.
- Sessions have a defined timeout policy. Upon timeout, the CS user is redirected to the CS login page with a session expiry message.
- Multiple CS users can be logged in simultaneously without affecting each other's sessions.
- CS sessions do not interact with or affect the Pixally owner's session in any way (separate URL, separate authentication).
4.5 Empty State
- If there are no subscribers in the system, the CS view displays the same empty state as the Pixally owner's Subscribers listing:
- An empty state illustration or icon is displayed in the center of the table area.
- Heading: "No subscribers found."
- Description: "You don't have any subscribers yet. Once users subscribe to your plans, they'll appear here along with their status, projects, and billing details."
- The tabs, search bar, and Status filter remain visible and functional.
5. Field Details & Validations
5.1 CS Login Page Fields
Field Name
Field Type
Validation Rules
Email Address
Text Input
Required. Must be a valid email format. Maximum 255 characters.
Password
Text Input (Masked)
Required. Minimum 6 characters. Maximum 128 characters. Eye icon toggle for visibility.
Sign In Button
Button
Always enabled. Triggers client-side validation, then server-side authentication.
5.2 CS Subscriber Listing Table Fields
Field Name
Field Type
Validation / Display Rules
Subscriber Name
Text (Read-only)
Plain text. NOT clickable. No link to profile.
Text (Read-only)
Subscriber's email address.
Phone Number
Text (Read-only)
Formatted phone number. Displays "N/A" if not provided.
Company Name
Text (Read-only)
Company/agency name.
Subscription Plan
Text (Read-only)
Plan name + billing cycle. "Trial" for trial users. "Free" for cancelled/downgraded subscribers.
Subscription Start Date
Date (Read-only)
Format: MM/DD/YYYY. "N/A" for trial users.
Next Billing Date
Date (Read-only)
Format: MM/DD/YYYY. "N/A" for trial users.
Subscription Status
Badge (Read-only)
Color-coded: Active (green), Paid (green), Trial (purple), Expired (grey), Cancelled (orange), Suspended (red), Canceling (orange).
Most Recent Payment Status
Text (Read-only)
Values: "Success," "Failed," "Pending," "N/A."
Payment Method
Text (Read-only)
Masked: "[Card Type] •••• [Last 4]." "N/A" for trial users.
Last Login Date
Date/Text (Read-only)
Format: MM/DD/YYYY or relative time. "Never" if never logged in.
Active Projects
Integer (Read-only)
Whole number count of booked projects only (events in Booked or Post-Event stages; excludes New Lead stages, archived, deleted). Header tooltip explains the booked-projects definition.
5.3 Status Filter
Field Name
Field Type
Validation Rules
Status Dropdown
Single-select Dropdown
Options: All, Active, Paid, Trial, Canceling, Expired, Cancelled, Suspended. Default: All.
6. Success Message Handling
Action
Success Message
Trigger Condition
Post-Success Behavior
CS Login
No explicit toast. CS user is redirected to Subscribers listing.
Valid email and password.
Session created. Subscribers listing loaded.
CS Logout
No explicit toast. CS user is redirected to CS login page.
CS user clicks "Log Out."
Session token cleared. Login page displayed.
Note: The CS view is entirely read-only. There are no create, edit, delete, or modify actions, and therefore no action-triggered success messages beyond login/logout.
7. Error Message Handling
Error Scenario
Error Message
Trigger Condition
Required User Action / System Response
Empty Email Field
"Email address is required."
CS user clicks "Sign in" without entering email.
Inline error below Email field.
Invalid Email Format
"Please enter a valid email address."
CS user enters an invalid email format.
Inline error below Email field.
Empty Password Field
"Password is required."
CS user clicks "Sign in" without entering password.
Inline error below Password field.
Password Too Short
"Password must be at least 6 characters."
CS user enters fewer than 6 characters.
Inline error below Password field.
Invalid Credentials
"Invalid email or password. Please try again."
Email or password does not match stored credentials.
Inline error. Password cleared; email retained.
Account Deactivated
"Your account has been deactivated. Please contact your administrator."
CS user's account has been deactivated from the backend.
Inline error. Login blocked. CS user must contact the Pixally owner or technical team.
Search — No Results
"No subscribers found matching your search."
Search query matches no subscriber name, email, or company.
Message in table body. Headers visible.
Session Expired
"Your session has expired. Please sign in again."
Session timeout due to inactivity.
Redirect to CS login page.
Unauthorized URL Access
No explicit error. Silent redirect.
CS user attempts to access a Gawd Portal URL other than the Subscribers listing (e.g., Dashboard, Payments).
Automatic redirect to the Subscribers listing page.
Network Error
"Unable to connect to the server. Please check your internet connection and try again."
Network failure during page load or search.
Toast or banner error. Last loaded data remains visible.
8. Edge Cases
#
Edge Case
Expected System Behavior
1
CS user attempts to access the Pixally owner's Gawd Portal URL directly.
The system does not authenticate CS credentials on the Pixally owner's portal URL. The CS user must use the dedicated CS URL. If they try to log in, they receive an "Invalid email or password" error since their credentials are scoped to the CS portal.
2
Pixally owner attempts to log in via the CS portal URL.
The system does not authenticate Pixally owner credentials on the CS portal URL. The Pixally owner receives an "Invalid email or password" error. The two portals have completely separate authentication scopes.
3
CS user tries to copy a subscriber's profile URL from the Pixally owner's portal and paste it into their browser.
The system redirects the CS user back to the Subscribers listing page. No profile data is displayed.
4
CS user is logged in when the Pixally owner deletes a subscriber.
The deleted subscriber disappears from the CS listing on the next page refresh or search. No real-time update occurs.
5
CS user searches for a subscriber by partial email (e.g., "@gmail").
The search returns all subscribers with "@gmail" in their email address. Partial matching works across all searchable fields.
6
CS user has the listing open with filters applied and their session expires.
The system redirects to the CS login page with a session expiry message. Upon re-login, the filters are reset to default (All tab, no search, Status: All).
7
10+ CS users are logged in simultaneously and searching for subscribers.
All sessions operate independently. Each CS user's search, filter, and pagination state is isolated to their own session. No performance degradation for normal concurrent usage.
8
A subscriber's status changes (e.g., Active → Suspended) while the CS user is viewing the listing.
The CS user sees the old status until they refresh the page, apply a new filter, or navigate to a different pagination page. No real-time status updates.
9
CS user attempts to right-click a subscriber row to open a context menu.
No custom context menu is displayed. The browser's default right-click menu appears. No "Open in new tab" or profile link is available since rows are not clickable.
10
The Subscribers listing has 10,000+ subscribers.
Data loads in paginated batches. Search and Status filter perform server-side filtering for large datasets. No performance issues on the CS view.
11
CS user's account is deactivated from the backend while they are logged in.
The CS user's current session remains active until their next authentication check (e.g., page refresh or API call). Upon the next authentication check, the session is invalidated and the user is redirected to the login page with the "Account deactivated" message.
12
CS user and Pixally owner are viewing the same subscriber's data at the same time.
Both views operate independently. The Pixally owner's actions (e.g., cancelling the subscriber) are reflected in the CS user's view on the next page refresh. No conflict or data lock occurs.
9. Acceptance Criteria
9.1 CS Login
- The CS login page is accessible on a separate, dedicated URL distinct from the Pixally owner's portal.
- The login form title reads "Sign in to Gawd Mode — Support."
- Login is successful only with valid CS credentials provisioned from the backend.
- Invalid credentials, empty fields, and deactivated accounts display appropriate error messages.
- Successful login redirects to the Subscribers listing page.
- No "Forgot Password" or "Sign Up" options are present.
- No IP whitelisting is enforced for CS logins.
9.2 CS Portal Shell
- The sidebar displays only "Subscribers" as the single navigation item.
- The header displays only the dark mode toggle and profile avatar (with "Log Out" only).
- No global search bar or notification bell is displayed.
- The sidebar collapse/expand toggle works correctly.
- The Help Center link is available and opens the external page.
9.3 Subscribers Listing (View-Only)
- The listing displays all 12 specified columns with correct data.
- No additional columns (Tickets, Subscription Length, CC Icon, Kebab Menu) are displayed.
- No row is clickable — CS users cannot navigate to subscriber profiles.
- No action buttons, kebab menus, or interactive elements are present on subscriber rows.
- No "Export Data" button is visible.
9.4 Search & Filter
- The search bar filters in real-time by Subscriber Name, Email, and Company Name.
- The Status filter dropdown correctly filters by individual status.
- Tab filtering (All/Active/Inactive) works correctly with the same groupings as the Pixally owner's view.
- Search, Status filter, and tabs work in combination.
- Pagination controls work correctly.
9.5 Access Restrictions
- Attempting to access any Gawd Portal URL other than the Subscribers listing redirects to the Subscribers page.
- CS credentials do not work on the Pixally owner's portal URL.
- Pixally owner credentials do not work on the CS portal URL.
- CS users cannot modify any data through any means.
10. Manual Test Cases
Test cases for this module will be generated in a separate phase after all FRDs are finalized.
11. Dependencies
Module/System
Dependency Type
Impact if Unavailable
Authentication Service
Service Dependency
CS users cannot log in. The CS login page displays a generic server error.
Subscribers Module (Gawd Portal — FRD #2)
Data Dependency
The CS listing displays subscriber data from the Subscribers module. If unavailable, the CS listing shows an error or empty state.
Backend Admin Panel
Operational Dependency
CS user accounts are created and managed from the backend in Phase 1. If the backend admin is unavailable, new CS accounts cannot be provisioned or existing ones deactivated.
Agency Portal — User Registration
Data Dependency
New subscriber data originates from the Agency Portal. Without it, the CS listing does not show new subscribers.
12. References
- Figma Link:
Change Log
Gawd Portal FRDs — Phase 2 Change Log
Source: Client meeting transcripts dated July 14, 15, and 16, 2026. Scope: Changes applied to the 9 Gawd Portal FRDs after processing all three transcripts. FRD #5 (Referral) required no changes. Status: Steps 1 (edits), 2 (validation), and a full cross-check verification are complete. All 9 FRDs pass the final validation sweep (12 sections each, 0 fragments in Section 4, tables intact in Sections 5–8, subsection numbering sequential, no stale terms). The cross-check pass — reading each FRD's logic against the transcripts rather than keyword matching — surfaced and fixed 9 additional consistency items (see "Cross-Check Verification Fixes" section at the end). Step 3 (Open Items doc + Ryan email) follows; test cases are deferred per client instruction.
Note on July 15: That meeting was almost entirely Agency Portal (post-production, expense/QuickBooks, media storage). It produced no Gawd Portal FRD changes. Those items (B9–B25) are logged for the Consolidated Open Items doc, not applied here.
FRD #1 — Login & Dashboard
- Churn timing: Churn is now counted on the date a subscriber's paid term actually ends (access lapses), not when they click cancel. A yearly subscriber who cancels in month 9 is counted at month 12. Tooltip updated.
- Active Subscribers: Subscribers with status "Canceling" (clicked cancel, term not ended) remain counted as Active until their paid term ends.
- MRR / ARR rebuilt: Both Actual and Normalized documented for MRR and ARR, with an Actual/Normalized toggle on each card. Full formulas included (monthly-equivalent conversion, Active definition, exclusions/inclusions, ARR = MRR × 12, Free/100%-discount = $0 actual but still counted). Derived discount_burden ("cliff") metric added.
- Revenue by Subscriptions chart: Annual revenue divided by 12 across the term. Tooltip added (includes subscriptions, transaction fees, extra seats) with a link to the Reports breakdown.
- Cancelled Subscribers tab: New Active/Pending toggle (Pending = clicked cancel, term not ended; Lifetime shows a dash under Pending).
- "This Week" → "Last 7 Days" (rolling) on Free Trial, Cancelled, and Paid tabs; comparison is "vs previous 7 days." Subscriber Overview tab unaffected. "Today" stays "vs yesterday."
- Active Users table: "Projects" column now counts Booked Projects (booked + post-event stages; excludes leads, archived, deleted) with a header tooltip.
- Plan rename: Essentials → Pro.
- Field details, edge cases (added 5a/5b/5c), acceptance criteria, and open items updated. Removed resolved open items (Create Invoice; Paid-tab "Today" comparison discrepancy).
FRD #2 — Subscribers
- "Canceling" status (orange) replaces "Active - Cancelling" throughout (one intentional mention remains in an open item explaining the rename).
- Post-cancellation → Free plan: Cancelled subscribers show status "Cancelled" with Plan column "Free" and appear under the Inactive tab.
- Status transitions: Cancel at Cycle End → "Canceling" until term ends → "Cancelled" + Plan "Free." Cancel Now → straight to "Cancelled" + Plan "Free."
- Delete logic rewritten: No Delete for anyone who paid. Delete is only for never-paid leads (via Lead Management, FRD #4). Account self-delete and a Gawd Portal Suspend/Delete capability moved to V2.
- Apply Discount: Applies only to the subscription tier (never extra seats/add-ons). Yearly proration: (annual cost ÷ 12) × discount% × months. Number of Months dropdown extended to 24.
- Booked Projects definition + tooltip on the "Active Projects" column (header unchanged).
- Payment history: Added a Plan column (plan per transaction) for churn/marketing analysis.
- Downgrade-to-Free Impact Box on both Cancel Now and Cancel at Cycle End confirmations; brand/project retention logic summarized (full logic owned by Agency Portal FRD).
- Plan rename: Essentials/Professional → Pro.
- Success/error messages, edge cases, acceptance criteria, and open items updated (added: galleries handling, logic-ownership, V2 suspend/delete, Canceling color).
FRD #3 — Payments
- "+ Create Invoice" button removed (Stripe handles any invoicing).
- Automated Retries section removed entirely (both Max retry attempts and Days between retries → handled globally in Stripe). Sections renumbered (4.4–4.9 now sequential).
- Refund screens combined into one: Single "Refund" popup — type an amount ≤ paid amount; full amount = "Refunded," less = "Partial Refund." Kebab shows "Refund" (Paid status). Flows, logic, field tables (merged to 5.4), success/error messages, and edge case #3 updated.
- Charge Manually kept, scoped to failed/overdue (retry after the subscriber adds funds).
- Payment timeline kept, now shows the failed state + fail count; Deposited noted as days-later for banking reconciliation.
- Credit-card-only subscription note added (no ACH/cash for recurring).
- Open items rewritten (retry-in-Stripe, combined-refund Figma, timeline failed-state).
FRD #4 — Lead Management
- Export Data button added (layout + logic §4.7 + success message + acceptance §9.7 + role permission). Respects active tab/search/filters; intended for manual add to email marketing.
- "This Week Sign-ups" → "Last 7 Days Sign-ups" (rolling). Empty State renumbered to §4.8.
FRD #5 — Referral
No changes. Confirmed unaffected by all three transcripts.
FRD #6 — Discounts
- Subscription-tier-only scope added to business goals and application rules (never extra seats/add-ons).
- Yearly proration logic added: (annual cost ÷ 12) × discount% × months.
- Edge cases 18 (extra-seat exclusion) and 19 (yearly proration) added.
- Open item 5 added: possible 50% first-year → "first 500 members" model (under client consideration).
- Existing strong Duration handling (Duration vs Valid Period, weeks/months) retained — July 16 largely confirmed it.
FRD #7 — Reports
- Revenue Impact meaning reversed: now = total revenue brought in by users of the code (cumulative, continues after the discount ends), shown as a positive value, with a tooltip. (Previously "revenue lost / discount given.")
- Date filter scope → top KPI cards only. Charts and the Discount Code Usage table are not driven by the filter (they follow their own logic). Flows, layout, KPI section, and acceptance criteria updated.
- Revenue by Subscriptions chart: annual ÷12 note added for consistency with FRD #1.
- Plan rename: Essentials → Pro (legend + business goals + acceptance).
- CAC remains a v2 placeholder (unchanged).
FRD #8 — Agency-Side Impact
- Retries handled via Stripe (not portal-configured). Grace-period retry-integration section rewritten; if a Stripe retry succeeds the banner clears.
- Warning banner from day 1 of the failed payment, and also after 3 failed retries (not only near grace-period end).
- Pay-first rule: A suspended subscriber must pay the outstanding balance before they can change plan, cancel, or convert to Free. Self-cancellation disabled during suspension; a suspended subscriber who won't pay can request cancellation via support, and the Pixally owner cancels from the Gawd Portal.
- 28-day suspension confirmed and documented (with the "already received a full period served in advance" rationale).
- Roles table, suspended-state flows, §4.2.5, success message, and acceptance §9.6 updated.
FRD #9 — Customer Support Role
- "Canceling" status (orange) added to the CS status badge list, the Active tab (Canceling subscribers retain paid access, so they appear under Active), and the Status filter dropdown.
- Active Projects → Booked Projects definition + tooltip (header stays "Active Projects").
- Plan rename: Professional → Pro.
"Booked Projects" definition (applied in FRDs #1, #2, #9)
A project counts as booked when at least one of its events is in a stage under the Booked Stages group (Proposal Signed, Deposit Paid, Planning, + any custom stages added under Booked Stages) or the Post-Event Stages group (Post Production, Completed, + any custom stages under Post-Event Stages). Excluded: New Lead stages (New Lead, Follow-up, Proposal Sent, + custom lead stages), Archived, and Deleted. Multi-event projects count if any one event qualifies (e.g., one event Booked + one event Archived = counts as 1). The column header stays "Active Projects"; a tooltip explains the booked-projects meaning.
MRR / ARR formulas (documented in FRD #1, per client spec)
- Per subscription i at date t: list_price_monthly[i], discount_monthlyi, term_months (12 annual / 1 monthly). Annual → monthly_equiv = total_contract_price / term_months.
- Actual MRR[i] = list_price_monthly − discount_monthly(t); actual_MRR = Σ over active subs; actual_ARR = actual_MRR × 12.
- Normalized MRR[i] = list_price_monthly − permanent_discount_monthly (temp discounts ignored, permanent deducted); normalized_ARR = normalized_MRR × 12.
- Rules: Active = paid term not ended (pending-cancel annuals count until access ends); exclude one-time/setup/non-recurring add-ons/sales tax; include recurring add-ons; ARR always MRR × 12; Free/100%-discount = $0 actual MRR but still counted.
- Derived: discount_burden(t) = normalized_MRR − actual_MRR (the "cliff").
Cross-Check Verification Fixes
After completing the edits, a full cross-check pass read each FRD's logic against the transcripts (rather than keyword matching) to catch consistency gaps. The following 9 items were found and fixed, and each affected FRD was re-validated clean.
- FRD #1 — Global Search fields (client request): Global Search now searches by subscriber name, company/agency name, and email address (previously name + company only). Applied across the flow step, logic section, and field detail.
- FRD #2 — "Canceling" missing from tab filtering: The Active tab and All tab did not list the new "Canceling" status. Since Canceling subscribers still have full paid access, they were added to the Active tab (and All) in both the flow step and logic section. Also added a note that Cancelled subscribers show "Free" in the Plan column under the Inactive tab.
- FRD #3 — 28-day suspend default alignment: The "Suspend account after" setting now notes the confirmed 28-day (4-week) default, consistent with FRD #8.
- FRD #4 — Export Data flow step added: Added a dedicated Export Data flow (§3.4) in Section 3 so the action is documented consistently across flow, logic, field details, success message, and acceptance criteria.
- FRD #5 — Confirmed unchanged (verified, not assumed): All three transcripts were searched for referral topics. The only relevant mention (referral discount factored into MRR/ARR) is handled in FRD #1; on July 16 the client explicitly had "no question" on Referral. No changes required.
- FRD #6 — Duration field realigned to months 1–24 (significant): The Phase-1 Duration field still used a "weeks/months" unit dropdown with months capped at 12, which contradicted the July 16 decision ("just months still… 24 months if it's two years") and FRD #2's Apply Discount. Realigned to months, range 1–24 across the flow, listing column, field details, error messages, edge cases, acceptance criteria, and the Duration open item.
- FRD #7 — Churn Rate KPI definition realigned: The Reports Churn Rate card still used the old "number of subscribers who cancelled" definition, contradicting FRD #1. Realigned to "number of subscribers whose paid term ended," consistent with the Dashboard. Also clarified the PDF export scope given the top-cards-only date filter.
- FRD #8 — Verified, no gaps: Pay-first-before-change/cancel/convert, banner timing (day 1 + after 3 retries), retries-via-Stripe, and 28-day suspension all confirmed consistent.
- FRD #9 — Cancelled→Free consistency: Added notes that Cancelled subscribers show "Free" in the Subscription Plan column (Inactive tab definition and the Subscription Plan column/field detail), matching FRD #2.
Most important catches: items 6 (FRD #6) and 7 (FRD #7) were genuine cross-document inconsistencies — the discount Duration units contradicted FRD #2, and the Reports churn definition contradicted FRD #1. Both are now consistent.
Round 3 — Additional Client Changes & Open-Item Answers (post-review)
After reviewing the FRDs, the client provided a batch of additional changes and answered the remaining Gawd Portal open items (including a notification-settings screenshot). All were applied and each affected FRD re-validated clean.
FRD #1 — Login & Dashboard
- Notifications → multi-select: In-App and Email can both be enabled for the same event; selecting "None" clears both. The existing event list already matched the client's screenshot exactly (10 events across 4 groups: New User Activity, Payments & Billing, Account Status & Plan Changes, Security & Account Integrity), so no events were added or removed — only the single-select restriction was replaced. Updated logic, flow, delivery behavior, defaults note, field detail, edge case, and acceptance. Removed the resolved single-select open item.
FRD #2 — Subscribers
- Cancel confirmation simplified: Both Cancel Now and Cancel at Cycle End now show a simple confirmation — "Are you sure? This subscription will be canceled [now / at the end of the cycle on (date)] and the subscriber will be converted to a Free plan user." — with Confirm and Close buttons. The Downgrade-to-Free Impact Box was removed (the retention-logic summary is retained), since this action is performed by the Pixally owner, not the subscriber.
- Credit card expiry threshold: Fixed at 30 days, not configurable. Resolved the related open item.
FRD #3 — Payments
- Refunds tab finalized: Columns are now exactly Invoice Number, Status, Subscriber, Amount, Payment Date, Refund Type, Refund Amount, Refund Date, Notes — with an expandable row revealing Refunded by, Payment Method, and Trace ID. Removed the non-listed Due Date/Reason columns. Updated logic, field details, and acceptance.
FRD #4 — Lead Management
- Filters panel removed entirely (not required) — layout, flow, logic, field details, error message, edge case, acceptance, and open item all updated.
- Pagination added as a confirmed feature (Rows per page + range indicator + navigation; resets to first page on tab/search change).
- Trial reset / auto-reset logic finalized:
- Manual reset: 14 days from the reset date (clock starts immediately); "Next auto" recalculates to 3 months after the new expiry.
- Auto-reset: at the 3-month mark a fresh 14-day trial is made available, but the 14-day clock starts when the user next logs in — not on the auto-reset date. Between the auto-reset date and next login, the user's status stays Expired (no phantom Active). On login, the trial runs 14 days from that login and "Next auto" recalculates to 3 months after the new expiry; the date rolls forward until claimed. The client's worked example (Jan 1–14 → manual reset Jan 10 → expiry Jan 24, auto Apr 24 → return Jun 10 → trial to Jun 24 → next auto Sep 24) is documented, along with new/updated edge cases.
- Leads export: A single Excel (.xlsx) file with three tabs — All, Active, Expired — each with columns matching the listing table (Name, Email, Signed Up, Expires, Last Active, Status, Resets, Next Auto Reset). The stacked "User Details" and "Reset Info" listing cells are split into separate columns for the export; Actions is not exported.
- "Last Active" scope: For leads, tracks the agency owner's activity only. (Confirmed the Dashboard's Active Users definition stays "owner OR team member" — the two are intentionally different, and the Dashboard was not changed.)
FRD #6 — Discounts
- "Upcoming" status (grey) added for future-dated codes (Valid From in the future) — replacing the prior behavior of showing them as "Active." Statuses are now Active (green) / Upcoming (grey) / Expired (red), transitioning automatically as dates are reached. Applied to status logic, listing badge, field detail, edge case, acceptance, and open item.
- Fixed discount floors at $0: A fixed discount larger than the amount it applies to reduces the charge to $0 and never goes negative (no credit/refund/carry-over for the difference). Added as explicit logic and strengthened in the edge case.
FRD #7 — Reports
- Comparison indicator defined: The "% previous period" indicator compares the selected range against the same-length period immediately preceding it (documented in §4.3).
- Discount Code Usage sorting: Confirmed as not required.
- Resolved the Dashboard-consistency open item by pointing to the §4.4 (actual/cash basis) vs §4.5 (÷12) split.
Consolidated Open Items doc
- Rewrote the Gawd Portal sections: all client-decision items are now answered and recorded under "Resolved This Round"; what remains is organized into Figma/design updates (FG-1–FG-13), development-team confirmations (DEV-1–DEV-5), non-blocking client inputs (C-2–C-4), and the one deferred item — the Customer Support role (C-1, next client meeting). The Agency Portal & Cross-Cutting section (B1–B32) is retained.
Follow-up — Ryan's Email Reply (Revenue Chart Split Approved)
Ryan replied to the revenue-chart email approving the two-chart split, with one condition: the tooltips must explain the basis clearly on each chart. Changes made to FRD #7 in response:
- §4.4 Total Revenue Overview: Added an info icon (ⓘ) and tooltip (it previously had none): "Shows actual revenue received each month. Annual payments appear in full in the month they were collected (not spread across 12 months). Includes subscription revenue, extra seat revenue, and transaction fee markup." Added a matching tooltip acceptance criterion (§9.3).
- §4.5 Revenue by Subscriptions: Extended the existing Figma tooltip to also explain the timing basis. Final wording: "Includes both subscription and transaction fee markup revenue. Annual subscriptions are divided by 12 and spread evenly across the subscription term, so this shows a normalized monthly trend rather than the actual cash received each month." A supporting logic bullet was added confirming each plan-type segment includes that plan's subscription revenue plus the transaction fee markup generated by its subscribers, so the tooltip and functional logic agree.
- Open item in FRD #7 updated to note the client's approval and that both tooltips now explain their basis.
No other FRD required changes from this reply. The revenue-chart item is now fully closed.
Still pending
- Customer Support role (FRD #9 scope) — deferred to the next client meeting.
(Test-case workbook updates remain deferred per client instruction — not part of this round.)
Round 4 — Profile, Discount, and Export Refinements
A further batch of client clarifications was applied across FRD #2, #6, and #7. Each affected FRD re-validated clean.
FRD #2 — Subscribers
- Credit card expiry icon on the profile: The same red/green expiry status icon used in the listing now also appears next to Payment Method in the profile's Subscription Details. It is clickable (opens the Credit Card Expiration Reminder popup) and carries the same hover tooltip (reminders sent, last reminder date, 24h cooldown).
- Discount override (behavior change): Re-applying a discount now overrides the existing one rather than stacking. The Apply Discount popup shows an inline warning ("A discount is already applied to this subscriber. Applying a new discount will override the existing one."), the price-breakdown logic was rewritten to compute the new discount on the original plan price (no compounding), and edge cases #4 and #20 were corrected from the previous stacking behavior. (Note: this reverses the Phase 1 stacking model, per client instruction.)
- Free-plan (cancelled) user actions: On the profile, "Apply Discount" and "Cancel Subscription" are now shown disabled (greyed out, not hidden) with explanatory tooltips, since a Free-plan user has no paid subscription to discount or cancel. The profile remains fully viewable. The listing kebab for these users already showed View Profile only.
- Upcoming plan-change indicator on the profile: When a subscriber downgrades or schedules a cancel-at-cycle-end (both initiated on the Agency side), the profile's Subscription Plan field shows the current plan + an "Upcoming" badge + an arrow to the pending plan (→ lower tier, or → Free for a cancellation), with a "Plan Changes On" date equal to the billing cycle end date. This appears only on the profile page; the listing Plan column continues to show the current plan. New edge cases added (#21–#25).
- Discount remaining-months on plan switch (cross-reference): Documented that when a subscriber switches plans mid-discount, only the remaining months carry over at the same percentage (full logic owned by FRD #6).
FRD #6 — Discounts
- Discount duration on a plan switch: Added as owned logic — only the remaining months of an active discount carry over to the new plan at the same percentage; consumed months are not restored; the plan switch itself is an Agency Portal action. New edge case added (#20).
FRD #7 — Reports
- Export changed from PDF to Excel, scoped to one table: The report export is now an Excel (.xlsx) file containing only the Discount Code Usage table (columns: Code, Type, Discount, Usage Count, Revenue Impact, Status; all rows, not limited by on-screen pagination) — not the KPI cards or charts. All PDF references (purpose, business goal, roles, flow, layout, logic §4.8, success/error messages, edge cases, acceptance §9.7, and the dependency) were updated; the button label is now "Export" and the filename convention is "Pixally_Discount_Code_Usage_[Date].xlsx."
Notes on ownership
- Plan switching is an Agency Portal action; the Gawd Portal only displays the pending change (Upcoming badge) and reflects the discount carry-over. No "Change Plan" action was added to the Gawd Portal.
No tickets linked — generate test cases directly from this FRD instead.