REST API backend only — no frontend application is included or required.
Spring Boot backend for WASAC/REG utility billing. Test using Swagger UI at http://localhost:8081/swagger-ui.html.
Full Swagger guide: see SWAGGER_GUIDE.md — login, authorize, role switching, step-by-step workflow, and sample request bodies.
- Java 17, Spring Boot 4.0.6
- Spring Data JPA, Spring Security (JWT)
- PostgreSQL, JavaMail (Gmail SMTP)
- Swagger/OpenAPI (springdoc)
- Java 17+
- PostgreSQL
CREATE DATABASE utility_billing_db;
- Gmail App Password for sending emails (see Email Setup below)
./mvnw spring-boot:run- API base:
http://localhost:8081/api - Swagger:
http://localhost:8081/swagger-ui.html
| Field | Value |
|---|---|
| iradianah5@gmail.com | |
| Password | Admin@12345 |
- Open Google App Passwords
- Enable 2-Step Verification on your Google account first
- Create an App Password for Mail
- Copy the 16-character password (e.g.
abcd efgh ijkl mnop)
Copy the example file:
cp src/main/resources/application-local.properties.example src/main/resources/application-local.propertiesEdit application-local.properties:
spring.mail.username=iradianah5@gmail.com
spring.mail.password=your16charapppassword
app.mail.from=iradianah5@gmail.com
app.mail.enabled=trueImportant: Remove spaces from the App Password when pasting.
./mvnw spring-boot:run- Call
POST /api/auth/loginwith admin credentials - Copy
data.accessTokenfrom the response - Click Authorize (top right in Swagger)
- Enter:
Bearer <your-token> - Click Authorize → Close
Switch users by logging in again and re-authorizing with the new token.
| Step | Endpoint | Body |
|---|---|---|
| 1 | POST /api/auth/login |
{"email":"iradianah5@gmail.com","password":"Admin@12345"} |
| 2 | Authorize with admin token | — |
| 3 | POST /api/system/email/test |
{"to":"mrshhh39@gmail.com"} |
Expected: emailSent: true and test email in inbox (check spam).
| Step | Endpoint | Role | Body example |
|---|---|---|---|
| 4 | POST /api/tariffs |
Admin | Water FLAT tariff (see below) |
| 5 | POST /api/tariffs |
Admin | Electricity TIERED tariff |
| 6 | POST /api/taxes |
Admin | {"name":"VAT 18%","percentage":18,"effectiveFrom":"2026-01-01"} |
| 7 | POST /api/users |
Admin | Create Finance user |
Water tariff:
{
"name": "Water Flat 2026",
"meterType": "WATER",
"tariffType": "FLAT",
"effectiveFrom": "2026-01-01",
"fixedServiceCharge": 500,
"unitRate": 350
}Create Finance user:
{
"fullNames": "IRANZI Dianah",
"email": "mrshhh39@gmail.com",
"phoneNumber": "+250722500332",
"roles": ["ROLE_FINANCE"]
}Finance user receives credentials email. If not, use POST /api/users/{id}/resend-credentials.
| Step | Endpoint | Notes |
|---|---|---|
| 8 | POST /api/auth/login |
Use email + temp password from email/API |
| 9 | POST /api/auth/change-password |
Required when mustChangePassword: true |
| 10 | POST /api/auth/login |
Login with new password |
| 11 | Re-authorize Swagger | Use Finance token |
Change password body:
{
"currentPassword": "temporary-password-from-email",
"newPassword": "Finance@12345"
}| Step | Endpoint | Body |
|---|---|---|
| 12 | POST /api/customers |
Customer details (nationalId = 16 digits) |
| 13 | POST /api/meters |
Assign meter to customer |
Customer:
{
"fullNames": "Jean Uwimana",
"nationalId": "1199887766554433",
"email": "jean.uwimana@email.com",
"phoneNumber": "+250788123456",
"address": "Kigali, Gasabo District",
"status": "ACTIVE"
}Meter:
{
"meterNumber": "WTR-001",
"meterType": "WATER",
"installationDate": "2026-01-15",
"status": "ACTIVE",
"customerId": 1
}| Step | Endpoint | Notes |
|---|---|---|
| 14 | POST /api/users |
Create Operator (Admin) |
| 15 | POST /api/auth/login |
Login as Operator, authorize |
| 16 | POST /api/meter-readings |
Capture reading |
Meter reading:
{
"meterId": 1,
"previousReading": 100,
"currentReading": 145,
"readingDate": "2026-06-01"
}| Step | Endpoint | Notes |
|---|---|---|
| 17 | POST /api/auth/login |
Login as Finance, authorize |
| 18 | POST /api/bills/generate |
Generate bill for customer + month |
| 19 | PATCH /api/bills/{id}/approve |
Approve bill |
| 20 | POST /api/payments |
Record payment |
Generate bill:
{
"customerId": 1,
"billingMonth": 6,
"billingYear": 2026
}Payment:
{
"billId": 1,
"amountPaid": 5000,
"paymentMethod": "MOBILE_MONEY",
"paymentDate": "2026-06-05"
}| Role | Permissions |
|---|---|
| ROLE_ADMIN | Tariffs, users, taxes, penalties, full CRUD |
| ROLE_FINANCE | Customers, meters, bills, payments |
| ROLE_OPERATOR | Meter readings |
| ROLE_CUSTOMER | View bills, payments, notifications |
| Module | Base Path |
|---|---|
| Auth | /api/auth |
| System | /api/system |
| Users | /api/users |
| Customers | /api/customers |
| Meters | /api/meters |
| Meter Readings | /api/meter-readings |
| Tariffs | /api/tariffs |
| Taxes | /api/taxes |
| Penalties | /api/penalties |
| Bills | /api/bills |
| Payments | /api/payments |
| Notifications | /api/notifications |
| Problem | Fix |
|---|---|
| Email test fails "Authentication failed" | Generate new Gmail App Password, update application-local.properties, restart |
| 401 Unauthorized | Login again, re-authorize in Swagger |
| 403 must change password | Call POST /api/auth/change-password first |
| Bill generation fails | Ensure operator captured reading for that month |
| Inactive customer | Set status to ACTIVE via PATCH /api/customers/{id}/status?status=ACTIVE |