Build financial profit and loss reports in Bubble by aggregating income and expense records by time period, displaying them in a formatted report layout with category breakdowns, and enabling PDF export. This tutorial covers the data model for transactions, aggregation formulas, and report visualization.
Overview: Creating P&L Reports in Bubble
A profit and loss report summarizes revenue, costs, and expenses over a period. This tutorial shows how to build a complete P&L reporting system in Bubble — from recording transactions to aggregating by month and category, displaying in a structured layout, and exporting to PDF.
Prerequisites
- A Bubble account with an app ready to edit
- Basic understanding of Data Types and searches
- Familiarity with Repeating Groups and dynamic expressions
Step-by-step guide
Create the transaction data model
Create the transaction data model
Go to the Data tab and create a Data Type called Transaction. Add fields: amount (number), type (Option Set: Income or Expense), category (Option Set with values like Sales, Services, Rent, Salaries, Marketing, Utilities), description (text), transaction_date (date), and created_by (User). Create the two Option Sets: TransactionType (Income, Expense) and TransactionCategory with relevant values.
Expected result: A Transaction data type with Option Sets for type and category.
Build the transaction entry form
Build the transaction entry form
Create a page called transactions. Add a form with inputs for amount (number), type (dropdown with TransactionType), category (dropdown with TransactionCategory), description (text), and date (date picker). Add a Save button with a workflow that creates a new Transaction with all values and created_by set to Current User.
Expected result: Users can record income and expense transactions through the form.
Create the P&L report page
Create the P&L report page
Create a page called pnl-report. Add a date range selector (Month/Year dropdowns or two date pickers). Below it, create a structured layout with three sections: Revenue (searches for Transactions where type is Income and date is within range), Expenses (searches where type is Expense), and Net Profit (Revenue total minus Expense total). Use Text elements with dynamic values showing the aggregated amounts using :each item amount:sum.
Pro tip: Use the :group by operator to break down totals by category within each section.
Expected result: A report page showing total revenue, total expenses, and net profit for the selected period.
Add category breakdowns
Add category breakdowns
Inside the Revenue and Expenses sections, add Repeating Groups with data source: Do a search for Transactions (filtered by type and date range) :group by category. In each cell, display the category name and the sum of amounts for that category. Sort by amount descending to show the largest categories first.
Expected result: Revenue and expenses are broken down by category showing which areas contribute most.
Enable PDF export
Enable PDF export
Install a PDF generation plugin (such as PDF Conjurer or html2pdf). Add an Export PDF button. Create a workflow that captures the report container group and converts it to a PDF file. Alternatively, use a print-friendly CSS approach with a Print button that triggers window.print() via JavaScript, with a print stylesheet that hides navigation and formats the report cleanly.
Expected result: Users can export the P&L report as a PDF document for sharing or record-keeping.
Complete working example
1P&L REPORT — WORKFLOW SUMMARY2==============================34DATA MODEL5 Transaction:6 - amount (number)7 - type (Option Set: Income, Expense)8 - category (Option Set: Sales, Services, Rent, etc.)9 - description (text)10 - transaction_date (date)11 - created_by (User)1213PAGE: pnl-report14 Date Range: Month/Year selector or date pickers1516 REVENUE SECTION17 Total: Search Transactions (type=Income, date in range)18 :each item amount:sum19 Breakdown: Same search :group by category20 Display: category name + sum2122 EXPENSES SECTION23 Total: Search Transactions (type=Expense, date in range)24 :each item amount:sum25 Breakdown: Same search :group by category26 Display: category name + sum2728 NET PROFIT29 = Revenue Total - Expense Total3031 EXPORT32 Button: Export PDF33 Workflow: PDF plugin capture → download34 OR: JavaScript window.print() with print CSSCommon mistakes when building profit and loss reports in Bubble
Why it's a problem: Not filtering transactions by date range
How to avoid: Always apply date constraints to every search: transaction_date >= period start AND transaction_date <= period end.
Why it's a problem: Using :filtered instead of search constraints for aggregation
How to avoid: Put all filters (type, category, date range) in the Do a search for constraints for server-side processing.
Why it's a problem: Hardcoding categories instead of using Option Sets
How to avoid: Use an Option Set for transaction categories so they are consistent and easy to update.
Best practices
- Use Option Sets for transaction types and categories for consistency
- Apply server-side search constraints for all filtering and aggregation
- Display currency with consistent formatting (two decimal places, dollar sign)
- Add Privacy Rules so users can only see their own transactions
- Include a year-over-year comparison option for trend analysis
- Cache expensive calculations in custom states to avoid re-querying on every interaction
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a profit and loss report in Bubble.io that shows monthly revenue and expenses broken down by category, with a net profit calculation and PDF export. What data model and page layout should I use?
Create a P&L report page with month/year selectors. Display total revenue, total expenses, and net profit. Add category breakdowns for both revenue and expenses using Repeating Groups with grouped search results. Add an Export PDF button.
Frequently asked questions
Can I generate reports for multiple months at once?
Yes. Adjust the date range to span multiple months. For a quarterly report, set the range to three months. For annual, set January 1 to December 31.
How do I handle different currencies?
Add a currency field to your Transaction data type. Filter reports by currency or convert to a base currency using exchange rates stored in an Option Set.
Can I automate monthly report generation?
Yes. Create a backend workflow scheduled to run on the first of each month that compiles the previous month data and sends it via email or saves it as a report record.
How accurate are the aggregations?
Bubble number fields support decimal precision. For financial accuracy, store amounts in cents (integers) and divide by 100 for display to avoid floating-point issues.
Can RapidDev help build a complete accounting system?
Yes. RapidDev can build comprehensive financial systems including double-entry bookkeeping, invoicing, tax calculations, multi-currency support, and automated reporting.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation