v1.0.0 - Production-ready cooperative savings and loan management system.
Modern full-stack application for managing cooperative member contributions, loans, dividend distributions, and financial records.
Tech Stack: Express.js + Prisma ORM + Redis + PostgreSQL + Next.js 15 + Tailwind CSS
- β Member Management - Profile management, share tracking, eligibility control
- β Contribution Recording - Multiple payment methods, audit trail, status tracking
- β Loan Management - Application workflow, approval process, payment tracking, co-maker support
- β Dividend Distribution - Bulk payouts, cycle-based eligibility, pro-rata calculation
- β Transaction Ledger - Complete member financial history
- β Admin Dashboard - Comprehensive control panel with filters and analytics
- β Member Portal - Self-service dashboard with loan application
- β Expense Tracking - Profit pool management with Redis caching
- β Archive System - Historical data management
Production Deployment: https://equiyield.sanchez.ph
Demo Credentials:
- Admin:
admin@equiyield.local/Admin@123456 - Members: All use password
Member@123
- apps/server: Express API, Prisma ORM, Redis cache
- apps/web: Next.js App Router admin + member UI
- Node.js 18+
- PostgreSQL
- Redis 6+
- Copy env files and configure values:
cp apps/server/.env.example apps/server/.env
cp apps/web/.env.example apps/web/.env.local- Install dependencies and generate Prisma client:
npm install
npm run prisma:generate- Start PostgreSQL and Redis with Docker:
docker-compose up -d- Initialize database and run migrations:
cd apps/server
npx prisma migrate dev -n init
cd ../..- Start dev servers (Express and Next.js):
npm run dev
**Important security note:** The bootstrap admin user created by `apps/server/create-admin.ts` ships with a default password. Change it immediately after first login and rotate the scriptβs password before committing or sharing the repository.Stop containers:
docker-compose downView logs:
docker-compose logs -fSee DEPLOYMENT.md for complete production setup guide.
Configure a single proxy host with custom location for the API:
1. Main Proxy Host:
- Domain:
equiyield.sanchez.ph(your domain) - Scheme:
http - Forward Hostname:
equiyield-web - Forward Port:
3000 - Cache Assets: β
- Block Common Exploits: β
- Websockets Support: β
- SSL: Request Let's Encrypt certificate, Force SSL
2. Custom Location (same proxy host):
- Go to "Custom Locations" tab
- Location:
/api - Scheme:
http - Forward Hostname:
equiyield-server - Forward Port:
4000
This routes:
yourdomain.com/β Frontend (Next.js web)yourdomain.com/api/*β Backend (Express API)
Cloudflare Users: If using Cloudflare proxy, temporarily set DNS to DNS Only (gray cloud) during initial SSL certificate generation, then re-enable proxy after certificate is issued.
Sensitive admin APIs require x-admin-token header equal to ADMIN_TOKEN from apps/server/.env.
- Admin
- GET /api/admin/system-config β Get system config
- PUT /api/admin/system-config β Update system config
- GET /api/admin/users β List members (paginated)
- POST /api/admin/users β Create member (auto-generates password; returns plaintext)
- POST /api/admin/users/:id/reset-password β Reset one member password
- POST /api/admin/users/bulk-passwords β Bulk reset passwords
- GET /api/admin/users/import/template β Download Excel template
- POST /api/admin/users/import β Upload Excel and create members
- GET /api/admin/users/:id β Member detail
- PUT /api/admin/cycles/:year/:cycle/users/:id/eligibility β Set cycle dividend eligibility (requires reason when ineligible)
- POST /api/admin/contributions β Record contribution (validates FULL vs PARTIAL)
- GET /api/admin/loans β List loans (paginated; supports ?status=PENDING|RELEASED|PAID filter)
- POST /api/admin/loans β Create loan (admin-created loans are RELEASED)
- PUT /api/admin/loans/:id/status β Update loan status (PENDING β RELEASED β PAID)
- GET /api/admin/funds-available β Aggregated funds for loan creation UI
- GET /api/admin/dividends/estimated-per-share β Cached per-share estimate
- PUT /api/admin/profit-pool β Upsert profit pool for current year
- GET /api/admin/dividends/payouts β List dividend payouts (filter by year/userId)
- POST /api/admin/dividends/payouts β Create a payout record for a member
- Auth / Member
- POST /api/auth/login β Member login (email, password)
- POST /api/auth/change-password β Change current user password (requires auth)
- GET /api/member/me β Current member profile (requires auth)
- GET /api/member/loans β Memberβs loans (requires auth)
- POST /api/member/loans β Apply for a loan (creates PENDING)
- Profit pool is fetched from
ProfitPooltable (current year) - Eligible users only (
is_dividend_eligible = true) - Pro-rata share by
share_count - Cached estimated dividend per share in Redis; invalidated when profit pool changes
- Login: http://localhost:3000/member/login
- Dashboard: http://localhost:3000/member/dashboard
- Change password
- Apply for a loan (status PENDING until admin release)
Token is stored in localStorage as eq_member_token and used for authenticated member requests.
-
Admin Page: http://localhost:3000/admin/loans
- Status Filters: Toggle to view by PENDING, RELEASED, or PAID status
- Release Action: PENDING loans can be released to RELEASED status
- Mark as PAID: RELEASED loans can be marked as PAID
- Member-Applied Loans: Created with PENDING status (requires admin release)
- Admin-Created Loans: Automatically created with RELEASED status
-
Member Portal: Apply for loans from dashboard
- Loans appear as PENDING until admin approves them
-
Admin Page: http://localhost:3000/admin/dividends
- Bulk Payout Creation: Distribute dividends to all eligible members for a year with single reference number
- Payout Records: View all distributed payouts with member details, amounts, and deposit info
- Per-Member Recording: Record individual payouts in member detail view (from Members page)
- Audit Logging: Each payout records who created it (admin) and when for reconciliation and compliance
- Reference Tracking: Each payout requires a reference number (transaction ID, receipt, batch ID, etc.) for traceability
-
Payout Fields:
- Year: Fiscal year for the payout
- Per Share Amount: Dividend amount per share (auto-calculated total per member)
- Channel: GCASH or BANK deposit method
- Reference Number (required): Transaction ID, receipt number, or batch reference for reconciliation
- Deposit Date: When the payout was deposited
- Member Visibility: Members can see their payouts on their dashboard with all details
-
Bulk Operations:
POST /api/admin/dividends/payouts/bulkβ Distribute to all eligible members with single parameters- Response includes created count, failed count, and individual member results
- Automatically assigns reference and tracks creator for audit trail
See CHANGELOG.md for detailed release notes.
Current Version: v1.0.0 (January 10, 2026)
- Fork the repository
- Create a feature branch
- Make your changes with descriptive commits
- Submit a pull request
MIT License - See LICENSE file for details
-
Production: https://equiyield.sanchez.ph
-
Documentation: See ADMIN_GUIDE.md for detailed setup instructions
-
Reporting & Audit:
- Payout records include Created By field showing which admin processed the payout
- Year-based filtering for period-end reconciliation
- Total amount summary for each year
- All payouts sortable by date, member, amount, and reference for easy reconciliation with bank/GCash statements
EquiYield is provided free of charge under the EquiYield Free Software License for personal, educational, and non-commercial use.
- β Internal organizational use (non-commercial)
- β Evaluating and testing the Software
- β Educational and learning purposes
- β Contributing to the open-source project
- β Professional implementation or consulting services
- β Software modifications or custom features
- β Use as part of commercial products or SaaS offerings
- β Re-distribution or white-label versions
For Commercial License inquiries or custom arrangements:
π§ Email: [derf@sanchez.ph]
π Website: https://sanchez.ph
See LICENSE and COMMERCIAL_LICENSE.md for complete details.