Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

302 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MicroFinance

A full-stack microfinance management platform built with a namespaced PHP JSON API backend and a React 18 (Vite) single-page application frontend, backed by a MySQL / MariaDB relational schema.

The application supports the day-to-day operations of a microfinance institution: members, committees, loans and loan payments, installments, savings accounts and transactions, branch management, role-based field-officer workflows, an admin dashboard with KPIs, and personal profile / password management.

The React SPA is served from the same Apache document root as the JSON API (/MicroFinance/), sharing PHP session cookies for authentication.


Table of contents


Features

Members

  • Create, view, edit, and deactivate members with full demographic data
  • Search members by name or member code
  • View per-member loans, savings, and recent transactions
  • Bulk filter by branch, status, gender, and join date

Committees

  • Create and edit committees scoped to a branch
  • Assign / remove members from a committee
  • View committee details and member roster

Loans

  • Create loans for members with principal, interest rate, and term
  • Record loan payments and update loan status (active, closed, etc.)
  • Track total disbursed, paid, and outstanding
  • Loan health / repayment-progress indicators on the dashboard

Installments & savings

  • Schedule and record installments
  • Savings accounts with deposit / withdraw flows
  • Per-member savings history and global savings transaction log

Due system

  • List of loans with outstanding balances
  • Overdue-loan view (loans past maturity)
  • Collection reports

Dashboard

  • KPI cards: total members, active members, total loans, total paid, total due, total savings, total collection, overdue loans
  • Loans-vs-collection line chart for the last 6 months
  • Top borrower card
  • Recent transactions and recent members lists

Profile & account

  • View own profile (full name, username, role, branch, avatar)
  • Edit profile (name, phone, email, branch)
  • Change password (with current-password verification and minimum length)
  • Upload / replace avatar (JPEG / PNG / GIF / WebP)
  • Role-gated view: admins and branch managers see the field officers list

Search & notifications (legacy JSON)

  • Global search across members, committees, and officers (Topbar)
  • Role-specific notification feed in the Topbar

Authentication & session

  • PHP-native session cookies (no JWT, no tokens)
  • Server-side session regeneration on login to prevent fixation
  • HTTP-only + SameSite=Lax cookies
  • Tri-state React auth context (loading | unauthenticated | authenticated)
  • 401 responses globally drop the client into the unauthenticated state

Tech stack

Backend

  • PHP 8.x with declare(strict_types=1)
  • mysqli for database access (no PDO, no ORM)
  • password_hash / password_verify (bcrypt) for credentials
  • Native PHP sessions with custom cookie params
  • A PSR-style App\ namespace autoloaded by spl_autoload_register (backend/app/Bootstrap/autoload.php)
  • A small custom JSON front controller (backend/public/index.php) that walks the route manifest in backend/app/Routes/api.php
  • Apache mod_rewrite for clean URLs
  • No Composer dependencies β€” the backend is built entirely on core PHP

Frontend

  • React 18.3 + react-router-dom 6.24 (SPA routing, BrowserRouter basename="/MicroFinance")
  • Vite 5.3 as the dev server and bundler (@vitejs/plugin-react)
  • axios 1.7 with withCredentials: true for cookie-based auth
  • Context API (AuthContext) + a ProtectedRoute wrapper for route gating
  • Plain CSS in frontend/src/styles.css (no CSS-in-JS, no styled-components)
  • CDN-loaded Font Awesome 6, Google Fonts (Inter), and Chart.js at runtime

Tooling

  • Tailwind CSS 4.3 at the project root for the legacy static CSS pipeline
  • A standalone Vite entry point (frontend/installments.html) used as a multi-page-app escape hatch

Database

  • MySQL / MariaDB (MicroFinance schema)
  • Connection via App\Config\Database (env-driven) and the legacy backend/app/Config/db.php

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       session cookie        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  React SPA (Vite, :5173)   β”‚  ───────────────────────▢   β”‚   PHP JSON API (Apache, /MicroFinance) β”‚
β”‚  axios, withCredentials    β”‚  ◀───────────────────────   β”‚   /MicroFinance/backend/public/api    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      {success, data}         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                                  β”‚
                                                                                  β–Ό
                                                                          MySQL / MariaDB
                                                                          schema: MicroFinance
  • Frontend lives in frontend/. In development it runs on http://localhost:5173 and proxies legacy /MicroFinance/api/*.php and /MicroFinance/uploads calls to Apache on http://localhost.
  • Backend lives in backend/. The JSON API is mounted at /MicroFinance/backend/public/api/* via the project-root .htaccess and backend/public/.htaccess.
  • A single project-root .htaccess rewrites /MicroFinance/ to frontend/dist/index.html (the React SPA shell) and forwards /MicroFinance/backend/public/api/* to the PHP front controller, so the SPA and API share one URL space.
  • Authentication is session-cookie based (PHP native sessions). The React app calls the API with withCredentials: true so cookies are shared between the SPA and the JSON API on the same origin.

Project structure

MicroFinance/
β”œβ”€β”€ .htaccess                       ← Project-root routing: SPA + API under /MicroFinance/*
β”œβ”€β”€ package.json                    ← Tailwind toolchain (project-root dev/build)
β”œβ”€β”€ frontend/                       ← React 18 + Vite SPA
β”‚   β”œβ”€β”€ .env.example                ← VITE_API_BASE_URL
β”‚   β”œβ”€β”€ index.html                  ← SPA entry HTML
β”‚   β”œβ”€β”€ installments.html           ← Standalone Vite entry (multi-page escape hatch)
β”‚   β”œβ”€β”€ package.json
β”‚   β”œβ”€β”€ vite.config.js              ← Dev server :5173, proxy, build inputs
β”‚   └── src/
β”‚       β”œβ”€β”€ main.jsx                ← ReactDOM root, BrowserRouter basename, AuthProvider
β”‚       β”œβ”€β”€ App.jsx                 ← Route table
β”‚       β”œβ”€β”€ styles.css              ← UI styles
β”‚       β”œβ”€β”€ api/                    ← axios clients (auth, members, loans, committees, savings,
β”‚       β”‚                              installments, due-system, profile, branches, field-officers)
β”‚       β”œβ”€β”€ context/AuthContext.jsx ← Session state (loading | unauthenticated | authenticated)
β”‚       β”œβ”€β”€ hooks/useAuth.js
β”‚       β”œβ”€β”€ components/
β”‚       β”‚   β”œβ”€β”€ ProtectedRoute.jsx
β”‚       β”‚   β”œβ”€β”€ LoadingScreen.jsx
β”‚       β”‚   β”œβ”€β”€ layout/             ← AppLayout, Sidebar, Topbar
β”‚       β”‚   β”œβ”€β”€ members/            ← MemberForm, MembersTable, MembersFilters
β”‚       β”‚   β”œβ”€β”€ committees/
β”‚       β”‚   β”œβ”€β”€ loans/
β”‚       β”‚   └── installments/
β”‚       └── pages/                  ← Page components (see "Frontend routes" below)
β”‚
β”œβ”€β”€ backend/                        ← PHP JSON API
β”‚   β”œβ”€β”€ public/
β”‚   β”‚   β”œβ”€β”€ index.php               ← JSON front controller
β”‚   β”‚   └── .htaccess               ← Routes non-files to index.php
β”‚   └── app/
β”‚       β”œβ”€β”€ Bootstrap/
β”‚       β”‚   β”œβ”€β”€ autoload.php        ← spl_autoload_register for App\ namespace
β”‚       β”‚   └── bootstrap.php       ← session, error/exception handlers, CORS
β”‚       β”œβ”€β”€ Config/                 ← app.php, cors.php, Database.php, db.php
β”‚       β”œβ”€β”€ Controllers/JsonApi/    ← 13 namespaced JSON controllers (see "JSON API")
β”‚       β”œβ”€β”€ Middleware/             ← AuthMiddleware, CorsMiddleware
β”‚       β”œβ”€β”€ Helpers/                ← JsonResponse, Request, Logger
β”‚       β”œβ”€β”€ Routes/api.php          ← Full route manifest (single source of truth)
β”‚       β”œβ”€β”€ Views/                  ← Legacy HTML layouts (header, sidebar, topbar, footer)
β”‚       └── Database/
β”‚           β”œβ”€β”€ migrations/         ← (empty, scaffolded)
β”‚           └── seeders/            ← (empty, scaffolded)
β”‚
β”œβ”€β”€ api/                            ← Legacy PHP shims for search/notifications (used by Topbar)
β”œβ”€β”€ assets/                         ← Tailwind-built CSS + legacy JS modules
β”œβ”€β”€ uploads/                        ← User-uploaded files (avatars)
β”œβ”€β”€ backend/tests/                  ← Hand-rolled curl integration tests
β”‚   β”œβ”€β”€ verify_account_api.php
β”‚   └── verify_profile_fixes.php
└── backend/storage/logs/api.log    ← API runtime log

Getting started

Prerequisites

  • XAMPP (Apache + MySQL / MariaDB), with Apache serving this repository at http://localhost/MicroFinance/
  • PHP 8.x with the mysqli extension
  • Node.js 18+ and npm
  • A working MicroFinance MySQL schema (see Database setup)

Backend

No build step. The JSON API is served by Apache directly from backend/public/. The URL surface is:

http://localhost/MicroFinance/backend/public/api

If mod_rewrite is unavailable, the front controller also accepts a ?route= query-string fallback:

http://localhost/MicroFinance/backend/public/index.php?route=/api/dashboard-stats

Frontend (development)

cd frontend
cp .env.example .env       # set VITE_API_BASE_URL if your backend URL differs
npm install
npm run dev

The dev server starts on http://localhost:5173. It proxies /MicroFinance/api/*.php (legacy JSON shims) and /MicroFinance/uploads to Apache, so cookies set by the API are visible to the SPA in development.

Frontend (production build)

cd frontend
npm run build

Static files are emitted to frontend/dist/. Once built, they are served by Apache at http://localhost/MicroFinance/ via the project-root .htaccess.


Database setup

The repository does not ship SQL migrations or seed files yet β€” backend/app/Database/migrations/ and backend/app/Database/seeders/ are scaffolded but empty.

Connection defaults (env-driven) are defined in backend/app/Config/Database.php:

Variable Default
DB_HOST 127.0.0.1
DB_PORT 3306
DB_USER root
DB_PASSWORD (empty)
DB_DATABASE MicroFinance

The legacy procedural controller connection (backend/app/Config/db.php) hardcodes the same defaults and sets the timezone to Asia/Dhaka.

Tables referenced by the application (inferred from queries in the codebase): users, branches, committees, members, loans, loan_payments, loan_installments, savings, savings_transactions. See PROJECT_OVERVIEW.md for the inferred schema.

The users table is expected to contain at least the columns used by the auth controller: user_id, username, password_hash, full_name, role, is_active, avatar.


JSON API

The full route manifest lives in backend/app/Routes/api.php. Controllers are namespaced App\Controllers\JsonApi\* and are PSR-style autoloaded from backend/app/Controllers/JsonApi/.

Endpoints

Method Path Controller Action Auth
POST /api/auth/login AuthController login
POST /api/auth/logout AuthController logout βœ…
GET /api/auth/session AuthController session
GET /api/dashboard-stats DashboardController stats βœ…
GET /api/profile ProfileController show βœ…
PUT /api/profile ProfileController update βœ…
POST /api/profile/avatar ProfileController uploadAvatar βœ…
PUT /api/profile/password ProfileController changePassword βœ…
GET /api/branches BranchesController index βœ…
GET /api/field-officers FieldOfficersController index βœ…
GET /api/field-officers/summary FieldOfficersController summary βœ…
GET /api/search SearchController index βœ…
GET /api/notifications NotificationsController index βœ…
POST /api/notifications/{id}/read NotificationsController markRead βœ…
GET /api/members MembersController index βœ…
POST /api/members MembersController store βœ…
GET /api/members/search MembersController search βœ…
GET /api/members/{id} MembersController show βœ…
PUT /api/members/{id} MembersController update βœ…
DELETE /api/members/{id} MembersController destroy βœ…
GET /api/members/{id}/transactions MembersController transactions βœ…
GET /api/members/{id}/loans MembersController loans βœ…
GET /api/members/{id}/savings MembersController savings βœ…
GET /api/committees CommitteesController index βœ…
POST /api/committees CommitteesController store βœ…
GET /api/committees/{id} CommitteesController show βœ…
PUT /api/committees/{id} CommitteesController update βœ…
DELETE /api/committees/{id} CommitteesController destroy βœ…
GET /api/committees/{id}/members CommitteesController members βœ…
POST /api/committees/{id}/members CommitteesController addMember βœ…
DELETE /api/committees/{id}/members/{memberId} CommitteesController removeMember βœ…
GET /api/loans LoansController index βœ…
POST /api/loans LoansController store βœ…
GET /api/loans/{id} LoansController show βœ…
PUT /api/loans/{id} LoansController update βœ…
DELETE /api/loans/{id} LoansController destroy βœ…
POST /api/loans/{id}/status LoansController updateStatus βœ…
POST /api/loans/{id}/payments LoansController recordPayment βœ…
GET /api/installments InstallmentsController index βœ…
POST /api/installments InstallmentsController store βœ…
GET /api/installments/{id} InstallmentsController show βœ…
PUT /api/installments/{id} InstallmentsController update βœ…
DELETE /api/installments/{id} InstallmentsController destroy βœ…
GET /api/savings SavingsController index βœ…
POST /api/savings SavingsController store βœ…
GET /api/savings/member/{memberId} SavingsController byMember βœ…
POST /api/savings/deposits SavingsController deposit βœ…
POST /api/savings/withdrawals SavingsController withdraw βœ…
GET /api/savings/transactions SavingsController transactions βœ…
GET /api/savings/{id} SavingsController show βœ…
PUT /api/savings/{id} SavingsController update βœ…
DELETE /api/savings/{id} SavingsController destroy βœ…
GET /api/due-system DueSystemController index βœ…
GET /api/due-system/overdue DueSystemController overdue βœ…
GET /api/due-system/report DueSystemController report βœ…
GET /api/due-system/{id} DueSystemController show βœ…
POST /api/due-system/{id}/collect DueSystemController collect βœ…

Static sub-paths (/api/savings/member/{id}, /api/savings/deposits, /api/savings/transactions, /api/due-system/overdue, /api/due-system/report, /api/members/search) are matched before the {id} placeholders so they are not captured as IDs.

Authentication

All endpoints marked with βœ… require an authenticated session. Requests without a valid session cookie receive 401 UNAUTHORIZED. The session cookie is set on POST /api/auth/login and cleared on POST /api/auth/logout.

Legacy JSON shims

The React Topbar also calls two legacy .php shims that bypass the namespaced API:

  • GET /MicroFinance/api/search.php?q=…
  • GET /MicroFinance/api/notifications.php

These are thin wrappers around the controllers in backend/app/Controllers/Api/ and are proxied to Apache by the Vite dev server.


Frontend routes

The full route table lives in frontend/src/App.jsx. All routes except /login are gated by <ProtectedRoute> (which redirects to /login while unauthenticated).

Path Page
/login LoginPage
/ DashboardPage
/installments InstallmentsPage
/members MembersPage
/members/new MemberFormPage (create)
/members/:id MemberProfilePage
/members/:id/edit MemberFormPage (edit)
/committees CommitteesPage
/committees/new CommitteeFormPage (create)
/committees/:id CommitteeViewPage
/committees/:id/edit CommitteeFormPage (edit)
/committees/:id/members CommitteeMembersPage
/loans LoansPage
/loans/new LoanFormPage (create)
/loans/:id LoanViewPage
/loans/:id/edit LoanFormPage (edit)
/loans/:id/payment LoanPaymentPage
/savings SavingsPage
/savings/new SavingsFormPage
/savings/deposit SavingsTransactionPage (deposit)
/savings/withdraw SavingsTransactionPage (withdraw)
/savings/transactions SavingsTransactionsPage
/due-system DueSystemPage
/due-system/overdue DueSystemOverduePage
/due-system/report DueSystemReportPage
/profile ProfilePage
/profile/edit EditProfilePage
/profile/change-password ChangePasswordPage
/field-officers FieldOfficersPage
* NotFoundPage

Because the SPA is served from /MicroFinance/ with BrowserRouter basename="/MicroFinance", all of the above are reachable at http://localhost/MicroFinance/<route>.


JSON envelope

Every API response uses a uniform envelope.

Success:

{
  "success": true,
  "data": { "...": "..." },
  "meta": {}
}

Failure:

{
  "success": false,
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Invalid username or password.",
    "details": {}
  }
}

Standard error codes: UNAUTHORIZED, VALIDATION_ERROR, NOT_FOUND, METHOD_NOT_ALLOWED, INVALID_CREDENTIALS, NOT_IMPLEMENTED, INTERNAL_SERVER_ERROR.

The PHP error and exception handlers in backend/app/Bootstrap/bootstrap.php convert PHP errors into ErrorExceptions and return a 500 INTERNAL_SERVER_ERROR JSON response β€” never raw HTML.


CORS

The API is reachable from the React dev server with credentialed cookies. The allowed-origin list lives in backend/app/Config/cors.php and defaults to:

http://localhost
http://localhost:80
http://localhost:5173
http://localhost:3000
http://127.0.0.1
http://127.0.0.1:80
http://127.0.0.1:5173
http://127.0.0.1:3000

The list can be overridden with the CORS_ALLOWED_ORIGINS environment variable.

CorsMiddleware emits:

Access-Control-Allow-Origin:      <origin>
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers:     Content-Type, X-Requested-With
Access-Control-Allow-Methods:     GET, POST, PUT, PATCH, DELETE, OPTIONS
Vary:                             Origin

OPTIONS preflight is short-circuited with 204 No Content.


Deployment

The intended deployment shape is:

  1. Place the repository under the Apache document root at MicroFinance/ so the URLs match the routes (/MicroFinance/, /MicroFinance/backend/public/api, /MicroFinance/assets/...).
  2. Ensure mod_rewrite is enabled and AllowOverride All is set on the document root.
  3. Build the SPA: cd frontend && npm install && npm run build. The output goes to frontend/dist/.
  4. Configure the MySQL/MariaDB connection (DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE, DB_PORT) via environment variables read by App\Config\Database.
  5. Configure CORS_ALLOWED_ORIGINS if the SPA is hosted on a different origin than the API.
  6. The project-root .htaccess already wires everything together: it serves frontend/dist/index.html for SPA routes, forwards /MicroFinance/backend/public/api/* to the PHP front controller, and serves /MicroFinance/assets/* from frontend/dist/assets/.

A single Apache VirtualHost is sufficient β€” there is no separate reverse proxy or build step required once npm run build has been run.


Testing

The backend/tests/ directory contains two hand-rolled curl-based integration scripts:

  • backend/tests/verify_account_api.php β€” exercises login β†’ session β†’ profile β†’ profile update β†’ password change.
  • backend/tests/verify_profile_fixes.php β€” exercises the profile page, edit profile, avatar upload, field-officers role gating, and branches endpoint.

Both scripts echo a PASS: x, FAIL: y summary on completion. They are invoked from the command line, not through PHPUnit:

php backend/tests/verify_account_api.php
php backend/tests/verify_profile_fixes.php

PHPUnit test scaffolding is not present.


Contributing

  1. Fork the repository.
  2. Create a topic branch: git checkout -b feat/<short-description>.
  3. Make your changes. Keep the JSON envelope and the route-manifest style consistent.
  4. Run the integration scripts in backend/tests/ to verify nothing regressed.
  5. cd frontend && npm run build to confirm the SPA builds cleanly.
  6. Open a pull request describing the change and linking any related issues.

Please do not commit frontend/dist/, frontend/node_modules/, or backend/storage/logs/*.log β€” these are already in .gitignore.


Author

Md Munna Sardar β€” github.com/Mdmunnasardar


License

ISC β€” see the project package.json for the declared license. A standalone LICENSE file is not yet bundled with the repository.

About

A modern MicroFinance Management System built to streamline member, loan, savings, installment, due, committee, and field officer management with secure authentication and financial tracking.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages