Fees & Payment Management
Last updated August 2, 2026
Classgrid provides a full-cycle fee management system covering fee structure creation, student fee record generation, online payment collection via Razorpay, receipt generation, discounts, and overdue tracking. All fee data uses a dual-database architecture: MongoDB (Mongoose) for fee structures and configurations, and Supabase/Postgres for transactional records.
Fee Structure Setup
Creating a Fee Structure
Org admins create fee structures that define what students must pay.
API: POST /api/fees/structures
Roles: org_admin
Required fields:
name— e.g., "FY BSc Tuition Fee 2026-27"academicYear— e.g., "2026-27"categories— array of fee categories
Each category contains:
categoryName— e.g., "Tuition Fee", "Lab Fee", "Library Fee"components— array of individual line items
Each component contains:
componentName— e.g., "Semester 1 Tuition"amount— the amount in INR (stored as Number)dueDate— when payment is dueisOptional— boolean (defaultfalse)
Models:
FeeStructure— top-level structure documentFeeCategory— embedded category groupingsFeeComponent— individual payable line items
Listing Fee Structures
API: GET /api/fees/structures
Roles: org_admin
Returns all structures for the organization, sorted by createdAt descending.
Student Fee Records
Generating Fee Records
Once a fee structure is created, the admin generates individual fee records for students.
API: POST /api/fees/generate-records
Roles: org_admin
Body:
The system creates one FeeRecord per student per structure, containing:
student— MongoDB ObjectId referencefeeStructure— reference to the structuretotalAmount— sum of all component amountspaidAmount— starts at0balanceAmount—totalAmount - paidAmountstatus—unpaid|partial|paid|overduedueDate— inherited from structure or override
Student Views Their Fees
API: GET /api/fees/student/me
Roles: Any authenticated student
Returns all fee records for the logged-in student with:
- Structure name, academic year
- Component-level breakdown
- Amount paid, balance remaining
- Due date and overdue status
- Payment history (linked transactions)
Admin Views All Fee Records
API: GET /api/fees/records
Roles: org_admin
Query params: structureId, status, search (by student name/PRN)
Returns paginated list of all student fee records with payment summary.
Payment Collection (Razorpay Integration)
Step 1: Student Initiates Payment
API: POST /api/fees/pay/initiate
Roles: Authenticated student
Body:
The system:
- Validates the fee record belongs to the student
- Checks
amount≤balanceAmount - Creates a Razorpay Order via
razorpay.orders.create() - Stores a
PaymentOrderdocument with:razorpayOrderId— from Razorpay responseamount,currency(INR)status—createdfeeRecord— referencestudent— reference
- Returns
{ orderId, amount, currency, key: RAZORPAY_KEY_ID }to frontend
Step 2: Frontend Completes Payment
The frontend opens the Razorpay checkout widget using the orderId and key. Upon success, Razorpay returns razorpay_payment_id, razorpay_order_id, and razorpay_signature.
Step 3: Verify Payment
API: POST /api/fees/pay/verify
Roles: Authenticated student
Body:
The system:
- Verifies the signature using
crypto.createHmac('sha256', RAZORPAY_KEY_SECRET) - Compares
generated_signature === razorpay_signature - If valid:
- Creates a
PaymentTransactionwith statuscaptured - Updates the
FeeRecord: incrementspaidAmount, decrementsbalanceAmount - Updates
FeeRecord.statustopaid(if balance = 0) orpartial - Creates a
PaymentAttemptlog
- Creates a
- If invalid: creates a
PaymentAttemptwith statusfailed
Webhook Handler
API: POST /api/fees/webhook/razorpay
Auth: Verified via x-razorpay-signature header
Handles events:
payment.captured— confirms successful paymentpayment.failed— logs failureorder.paid— marks order as complete
Models involved:
PaymentOrder—razorpayOrderId,amount,currency,status,feeRecord,studentPaymentTransaction—razorpayPaymentId,razorpayOrderId,amount,method,status,feeRecordPaymentAttempt—orderId,paymentId,signature,status,errorCode,errorDescription
Invoices & Receipts
Generate Invoice
API: GET /api/fees/invoice/:feeRecordId
Roles: org_admin, student (own record only)
Returns a structured invoice with:
Invoicedocument:invoiceNumber(auto-generated),issueDate,dueDateInvoiceLineItementries: one per fee component- Organization details (name, address, logo)
- Student details (name, PRN, course)
- Payment status and transaction history
Discounts & Concessions
Apply Discount
API: POST /api/fees/discount
Roles: org_admin
Body:
The system:
- Creates a
Discountdocument - Recalculates the fee record's
totalAmountandbalanceAmount - Logs the discount in
CreditNote
Discount types: percentage, fixed_amount, full_waiver
Student Fee Ledger
API: GET /api/fees/ledger/:studentId
Roles: org_admin
Returns the complete StudentFeeLedger — a chronological record of:
- All fee charges
- All payments received
- All discounts applied
- Running balance
Overdue Tracking
Fee records past their dueDate with balanceAmount > 0 are automatically flagged as overdue. The system:
- Updates
FeeRecord.statustooverdue - Includes overdue records in admin dashboard reports
- Supports filtering by
status=overduein the records list