My Inspiration to Build AdminAssistAI
So I was interning at my Mom's school and I realised that she would spend so much time looking through different excel spreadsheets and payment records to find parents with overdue fees and manually draft reminders ad sent them to the parents one by one so I built AdminAssist to automate this process.
How I built it
AdminAssist is built with Flask and a service-layer architecture that keeps data import, business logic, and AI generation cleanly separated. Routes stay thin — they handle HTTP routing concerns only — while dedicated service modules do the actual work.
Data pipeline: Uploaded Excel files are parsed in-memory with Pandas, validated against required columns, then persisted through SQLAlchemy models (Student and Payment, linked by a one-to-many relationship). Payment status (paid/partial/unpaid) is derived, not stored as a raw admin input — a recalculate_status() method on the Payment model keeps it consistent with the actual amount paid versus the fee owed, called explicitly at every write path (import and manual updates) rather than relying on hidden triggers, so behavior stays predictable and easy to debug.
Dashboard: A server-rendered Flask/Jinja dashboard shows every student's payment status, color-coded, with an at-a-glance count of payments needing follow-up. Admins can update a payment directly from the table when a parent pays, with status recalculating instantly.
AI integration: Using the OpenAI-compatible client with the Featherless AI API, I generated short, personalized fee reminder messages per student — pulling their name, amount owed, and term into a prompt and returning ready-to-send text, rather than requiring admins to write reminders by hand.
Database & deployment: SQLite a lightweight database for fast iteration, PostgreSQL in production via Render, with the same SQLAlchemy models working against both unchanged. Environment-based configuration (no hardcoded secrets) meant the same codebase moved from local development to a live deployment without code changes — only environment variables differed.
What's next: Direct WhatsApp delivery of reminders via Twilio, and an AI-generated summary report giving admins a plain-English overview of the term's fee status across the whole school, not just per-student. For Example : Which grade has the highest amount of overdue fees.
Challenges faced
I faced 2 major challenges in the course of this project which are : 1. When pushing the AI reminder feature to github I took the API Key from Featherless and I created an environment variable in Render but when I redeployed the "Generate Reminder Feature" was not working I tried several times but with no success until after a short break I decided to remove the quotation marks around the key before redeploying and it worked!
2.Challenge: Silent data-persistence failure in the mark-as-paid feature
While building the feature that lets admins record a payment update, we hit a bug where the update route ran successfully (returned the correct HTTP redirect, received the correct form data) but the database value never actually changed. Because there was no error thrown, this was harder to diagnose than a crash — the request "succeeded" at every visible layer while silently doing nothing.
I traced back my steps methodically: confirmed the form was submitting correctly (browser network tab), confirmed the route was receiving the right data (server-side print statement), and confirmed the model logic itself was correct (recalculate_status() tested in isolation). The root cause turned out to be a missing db.session.commit() at the end of the update function — the in-memory Python object was updated correctly, but the change was never actually written to the database.
What I learned
What I learned here is that a fresh set of eyes and a fresh mind beats a tired one every time .Rest is not a waste of time it is part of the debugging process. Even in a limited time hackathon
And Secondly this experience reinforced a habit I now apply everywhere in the codebase — writing to the database must end in an explicit commit, and "the code ran without error" isn't proof that data was saved. This practice of committing at the end make sure that all the data has been written before committing and that there is no inconsistent or partial data in the database.
Log in or sign up for Devpost to join the conversation.