Total Income
₹0.00
Credit ledgerTotal Expenses
₹0.00
Debit ledgerPending Reimbursements
₹0.00
Due to staffNet Balance
₹0.00
Net positionThis Month Income
₹0.00
Active monthThis Month Expenses
₹0.00
Active monthIncome by Bank / Account
| Bank / Account | Amount |
|---|
Income by Course / Service
| Course / Service | Amount |
|---|
Expenses by Category
| Category | Amount |
|---|
Reimbursement Summary
| Person | Needed | Paid | Pending |
|---|
Recent Expenses
| Date | Purpose | Paid By | Amount |
|---|---|---|---|
| Loading data... | |||
Recent Income
| Date | Source | Bank | Amount |
|---|---|---|---|
| Loading data... | |||
Add New Expense
Expenses Records
| Date | Project | Category | Paid By / To | Purpose | Reimbursable? | Status | Amount | Actions |
|---|---|---|---|---|---|---|---|---|
| Loading expenses... | ||||||||
Add New Income
Income Records
| Date | Project | Bank / Account | Course / Service | Received From | Purpose | Amount | Actions |
|---|---|---|---|---|---|---|---|
| Loading income logs... | |||||||
Reimbursement Balances
Calculated automatically from all expenses paid by staff with Reimbursement Needed = Yes minus all reimbursements paid to them.
| Person | Total Reimbursement Needed | Total Reimbursement Paid | Balance Pending | Status | Details |
|---|---|---|---|---|---|
| No reimbursable transactions logged yet. | |||||
Mohamed Abdus Salam
Comprehensive Statement and Payment History
Total Reimbursable Needed
₹0.00
0 expenses total
Total Reimbursed Paid
₹0.00
0 payments total
Balance Pending
₹0.00
PendingQuick Actions
Category Breakdown
Included Reimbursable Expenses
| Date | Entry No. | Category | Purpose / Description | Vendor / Paid To | Account / UPI Used | Original Amount | Allocated / Paid | Payment Status | Expense Status | Bill / Proof | Notes |
|---|
Reimbursement Payments History
| Payment Date | Amount Paid | Paid From Account | Notes | Actions |
|---|
Record Reimbursement Payment
Reimbursement Payments History
| Payment Date | Project | Paid To (Staff) | Paid From Bank | Notes | Amount | Actions |
|---|---|---|---|---|---|---|
| Loading payment history... | ||||||
Import Financial Records
Upload Excel (.xlsx, .xls) or CSV files to quickly batch-import your records.
1. Select or Drag Financial File
Click to upload or drag & drop
Supported files: Excel (.xlsx, .xls) and CSV (.csv)
4. Map Spreadsheet Columns
Required fields unmapped| Database Target Field | Requirement | Mapped Excel Column |
|---|
5. Duplicate Protection Policy
6. Parse Review & Preview
First 10 rows previewTotal Rows
0
Valid Rows
0
Invalid Rows
0
Duplicate Rows
0
Parsing Errors found (Invalid rows will be skipped):
Import Job Completed!
Your ledger has been updated successfully with the imported records.
Successfully Imported
0
Skipped Duplicates
0
Failed / Invalid Rows
0
User Management (Owner Only)
Invite new users, assign roles, and toggle user account statuses securely.
Send Invitation
Registered System Users
0 Users| User | Role | Status | Added | Actions |
|---|
Account & Payment Channel Management
Configure physical banks, UPI IDs, Publications, or cash drawers used in transactions.
Add New Account
Configured Payment Accounts
| Account Name | Type | Order | Status | Actions |
|---|
Expense Category Management
Manage physical/operational categories used to organize and track company outlays.
Add New Category
Configured Ledger Categories
| Category Name | Order | Status | Actions |
|---|
Course, Publication & Service Management
Manage active income types, student diplomas, consultation services, or publications.
Add New Item
Active Stream Categories
| Item Name | Type | Order | Status | Actions |
|---|
Configurable Custom Fields Configurator
Add meta-fields (e.g. Student Registration ID, Transaction Slips, Billing ID) dynamically without editing DB structures.
Create Custom Field
Active Metadata Fields
| Field Label | Key | Form | Type | Req? | Status | Actions |
|---|
Global Ledger App Settings
Configure workspace localization, registration defaults, and analytics configurations.
Database Audit Trail Logs
Real-time immutable log tracking deletions, mutations, and role changes across the ledger.
| Timestamp | User Email | Action | Module | Record ID | Details |
|---|
Data Backups, Portability & Bulk Exporters
Export full datasets in XLS format or recover rows that failed Excel validations.
Ledger Backup Summary
Download Structured Data
Export full or partial spreadsheet rows cleanly compiled with all transaction parameters.
Failed Import Rows Recovery
If any spreadsheet rows failed data-type validation or mapping errors, download them here for fast correction.
Audit Log Value Mutation Diff
Previous State
New State
Project Management
Add, rename, activate, deactivate, or reorder projects to track finances separately.
Add New Project
Configured Projects
| Project Name | Order | Status | Actions |
|---|
Confirm Deletion
Are you absolutely sure you want to delete this record? This transaction will be permanently removed from the Supabase database. This action cannot be undone.
Supabase Database Setup Guide
To connect your Personal Office Ledger app, copy and run the following SQL script in your Supabase project's SQL Editor. This will create the required tables and configure standard Row-Level Security (RLS) to keep user accounts isolated.
-- 1. Create Profiles Table (User Roles & Status)
CREATE TABLE IF NOT EXISTS profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'User' CHECK (role IN ('Owner', 'Admin', 'User')),
status TEXT NOT NULL DEFAULT 'Active' CHECK (status IN ('Active', 'Inactive')),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 2. Create Accounts Table
CREATE TABLE IF NOT EXISTS accounts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
type TEXT NOT NULL CHECK (type IN ('Bank', 'UPI', 'Cash', 'Card', 'Publication', 'Other')),
display_order INT NOT NULL DEFAULT 0,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 3. Create Expense Categories Table
CREATE TABLE IF NOT EXISTS expense_categories (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 4. Create Courses and Services Table (Income Stream Types)
CREATE TABLE IF NOT EXISTS courses_services (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
type TEXT NOT NULL CHECK (type IN ('Course', 'Service', 'Publication', 'Other')),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 5. Create Custom Fields Config Table
CREATE TABLE IF NOT EXISTS custom_fields (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
module TEXT NOT NULL CHECK (module IN ('expenses', 'income', 'reimbursements')),
label TEXT NOT NULL,
key TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('Text', 'Number', 'Date', 'Dropdown', 'Yes / No', 'Notes', 'URL')),
required BOOLEAN NOT NULL DEFAULT FALSE,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INT NOT NULL DEFAULT 0,
options TEXT[] DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE (module, key)
);
-- 6. Create App Settings Table
CREATE TABLE IF NOT EXISTS app_settings (
key TEXT PRIMARY KEY,
value JSONB NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- 7. Create Audit Logs Table
CREATE TABLE IF NOT EXISTS audit_logs (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_email TEXT,
user_id UUID,
action TEXT NOT NULL,
module TEXT NOT NULL,
record_id TEXT,
old_value JSONB,
new_value JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 8. Base transaction tables with custom_data support
CREATE TABLE IF NOT EXISTS expenses (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
date DATE NOT NULL,
amount NUMERIC(12, 2) NOT NULL,
paid_by TEXT NOT NULL,
paid_to TEXT NOT NULL,
purpose TEXT NOT NULL,
reimbursement_needed BOOLEAN NOT NULL DEFAULT FALSE,
status TEXT NOT NULL DEFAULT 'Pending',
custom_data JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS income (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
date DATE NOT NULL,
amount NUMERIC(12, 2) NOT NULL,
bank TEXT NOT NULL,
received_from TEXT NOT NULL,
purpose TEXT NOT NULL,
is_reimbursement BOOLEAN NOT NULL DEFAULT FALSE,
reimbursement_for TEXT,
course_service TEXT,
custom_data JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS reimbursements (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
date DATE NOT NULL,
amount NUMERIC(12, 2) NOT NULL,
paid_to TEXT NOT NULL,
paid_from_bank TEXT NOT NULL,
notes TEXT,
custom_data JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Add missing columns safely
ALTER TABLE expenses ADD COLUMN IF NOT EXISTS custom_data JSONB DEFAULT '{}'::jsonb;
ALTER TABLE expenses ADD COLUMN IF NOT EXISTS project TEXT;
ALTER TABLE income ADD COLUMN IF NOT EXISTS custom_data JSONB DEFAULT '{}'::jsonb;
ALTER TABLE income ADD COLUMN IF NOT EXISTS course_service TEXT;
ALTER TABLE income ADD COLUMN IF NOT EXISTS project TEXT;
ALTER TABLE reimbursements ADD COLUMN IF NOT EXISTS custom_data JSONB DEFAULT '{}'::jsonb;
-- Create Projects Table
CREATE TABLE IF NOT EXISTS projects (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Seed default lookup lists
INSERT INTO projects (name, display_order) VALUES
('Shurfi', 0),
('Ilmine', 1),
('Dayarah', 2),
('As-salam Publications', 3)
ON CONFLICT (name) DO NOTHING;
INSERT INTO accounts (name, type, display_order) VALUES
('Saad', 'UPI', 0),
('Ayman', 'UPI', 1),
('Salam Publications', 'Publication', 2)
ON CONFLICT (name) DO NOTHING;
INSERT INTO expense_categories (name, display_order) VALUES
('Office Expenses', 0),
('Office Supplies', 1),
('Internet', 2),
('Furniture & Appliances', 3),
('Maintenance', 4),
('Electricity', 5),
('Marketing', 6),
('Travel', 7),
('Printing', 8),
('Salary', 9),
('Food', 10),
('Rent', 11),
('Utilities', 12),
('Course Material', 13),
('Software / Tools', 14),
('Vendor Payment', 15)
ON CONFLICT (name) DO NOTHING;
INSERT INTO courses_services (name, type, display_order) VALUES
('BA Islamic Studies', 'Course', 0),
('BA Arabic', 'Course', 1),
('BSc Psychology', 'Course', 2),
('BBA', 'Course', 3),
('Diploma in Islamic Studies', 'Course', 4),
('Diploma in Islamic Psychology', 'Course', 5),
('Arabic Diploma', 'Course', 6),
('Marital Life Course', 'Course', 7),
('Webinar', 'Other', 8),
('Books', 'Publication', 9),
('Consultation', 'Service', 10),
('Salam Publication', 'Publication', 11)
ON CONFLICT (name) DO NOTHING;
-- 9. Enable Row Level Security (RLS)
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
ALTER TABLE expense_categories ENABLE ROW LEVEL SECURITY;
ALTER TABLE courses_services ENABLE ROW LEVEL SECURITY;
ALTER TABLE custom_fields ENABLE ROW LEVEL SECURITY;
ALTER TABLE app_settings ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE expenses ENABLE ROW LEVEL SECURITY;
ALTER TABLE income ENABLE ROW LEVEL SECURITY;
ALTER TABLE reimbursements ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
-- Security helper to safely check role without RLS self-recursion
CREATE OR REPLACE FUNCTION get_user_role(u_id UUID)
RETURNS TEXT SECURITY DEFINER AS $$
BEGIN
RETURN (SELECT role FROM profiles WHERE id = u_id LIMIT 1);
END;
$$ LANGUAGE plpgsql;
-- 10. Security Policies
CREATE POLICY "Select Profiles" ON profiles FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Profiles" ON profiles FOR ALL USING (get_user_role(auth.uid()) = 'Owner');
CREATE POLICY "Select Projects" ON projects FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Projects" ON projects FOR ALL USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Select Accounts" ON accounts FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Accounts" ON accounts FOR ALL USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Select Categories" ON expense_categories FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Categories" ON expense_categories FOR ALL USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Select Courses Services" ON courses_services FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Courses Services" ON courses_services FOR ALL USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Select Custom Fields" ON custom_fields FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage Custom Fields" ON custom_fields FOR ALL USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Select App Settings" ON app_settings FOR SELECT USING (auth.uid() IS NOT NULL);
CREATE POLICY "Manage App Settings" ON app_settings FOR ALL USING (get_user_role(auth.uid()) = 'Owner');
CREATE POLICY "Select Audit Logs" ON audit_logs FOR SELECT USING (get_user_role(auth.uid()) IN ('Owner', 'Admin'));
CREATE POLICY "Insert Audit Logs" ON audit_logs FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);
-- Clear old policies
DROP POLICY IF EXISTS "Manage own expenses" ON expenses;
DROP POLICY IF EXISTS "Manage own income" ON income;
DROP POLICY IF EXISTS "Manage own reimbursements" ON reimbursements;
-- Enable role-aware record policies
CREATE POLICY "Access Expenses" ON expenses FOR ALL USING (
get_user_role(auth.uid()) IN ('Owner', 'Admin') OR auth.uid() = user_id
);
CREATE POLICY "Access Income" ON income FOR ALL USING (
get_user_role(auth.uid()) IN ('Owner', 'Admin') OR auth.uid() = user_id
);
CREATE POLICY "Access Reimbursements" ON reimbursements FOR ALL USING (
get_user_role(auth.uid()) IN ('Owner', 'Admin') OR auth.uid() = user_id
);
Next Steps after executing SQL:
- Go to Project Settings > API in your Supabase dashboard.
- Copy your Project URL and anon public API key.
- Paste them into the top of
src/script.tsin this workspace. - Save, let the development server refresh, and sign in or register to track your data!
Record Reimbursement Payment
Staff Member
Mohamed Abdus Salam
Balance Pending
₹0.00