From ee7163980fc6d3d3325fe1202188fb353d1e880c Mon Sep 17 00:00:00 2001 From: Jerry Gu Date: Thu, 4 Dec 2025 18:57:04 -0500 Subject: [PATCH 1/4] Fixed minor logic error in RouteController, improved javadoc comments, enhanced API test collection, updated overall project documentation --- README.md | 183 +- api-testing.md | 1757 ++------ checkstyle.html | 28 +- cpd.html | 127 +- index.html | 2 +- pmd_after.html => old_pmd_after.html | 0 pmd_before.html => old_pmd_before.html | 0 pmd_after_dec.html | 61 + pmd_before_dec.html | 121 + pom.xml | 292 +- postman/postman_collection.json | 1589 ++++++- .../java/dev/ase/teamproject/Application.java | 6 +- .../controller/RouteController.java | 401 +- .../ase/teamproject/filter/LoggerFilter.java | 34 +- .../ase/teamproject/model/Transaction.java | 152 +- .../java/dev/ase/teamproject/model/User.java | 21 +- .../teamproject/service/MockApiService.java | 185 +- src/main/resources/all-java.xml | 17 - src/main/resources/custom-java-rules.xml | 49 + .../MockApiServiceIntegrationTests.java | 839 +++- .../ase/teamproject/MockApiServiceTests.java | 2278 ++++++---- .../RouteControllerIntegrationTests.java | 977 ++++- .../ase/teamproject/RouteControllerTests.java | 3761 +++++++---------- .../ase/teamproject/TransactionUnitTests.java | 910 ++-- .../dev/ase/teamproject/UserUnitTests.java | 411 +- 25 files changed, 8393 insertions(+), 5808 deletions(-) rename pmd_after.html => old_pmd_after.html (100%) rename pmd_before.html => old_pmd_before.html (100%) create mode 100644 pmd_after_dec.html create mode 100644 pmd_before_dec.html delete mode 100644 src/main/resources/all-java.xml create mode 100644 src/main/resources/custom-java-rules.xml diff --git a/README.md b/README.md index 97f8b14..f7155c5 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Repository for Team GLACJ's Fall 2025 Advanced Software Engineering team project This project implements a Ledger Service that allows users to: - Manage users and their transactions - Track budgets and spending summaries - View analytics such as weekly and monthly summaries +- Track budgets and spending summaries +- View analytics such as weekly and monthly summaries It is built with Spring Boot (Java), uses a Cloud SQL database, and exposes RESTful APIs for client interaction. @@ -36,22 +36,30 @@ mvn spring-boot:run Once started, navigate to http://127.0.0.1:8080 or http://localhost:8080/ in your web browser. Alternatively, access GCP-hosted version at https://ase-team-project-141125434285.europe-west1.run.app +## Client Program -## Viewing Log -- Open the GCP project hosting our service [here](https://console.cloud.google.com/welcome?authuser=0&hl=en&project=ageless-answer-474618-u4) -- Navigate to **Monitoring → Logs Explorer** -- Use the time selection tool on the top right to set timeframe of logs you want to view -- In the query textbox, enter the following query: `textPayload:"CLIENT_LOG:"` -Following these instructions will show you a list of all API endpoint calls made as well as their time and the IP address of the client. +View our client repository here: https://github.com/hc8756/ASE-Team-Project-Client -## Client Program -View our client repository here: https://github.com/hc8756/ASE-Team-Project-Client - -This is an example of a client for general users. It allows the user to log in or create an account before viewing their homepage. The homepage contains a list of the user's transactions which can be added to and edited by the viewer. It also shows a user analyitics of their weekly and monthly budgets. +This is an example of a client for general users. It allows the user to log in or create an account before viewing their homepage. The homepage contains a list of the user's transactions which can be added to and edited by the viewer. It also shows a user analytics of their weekly and monthly budgets. Multiple people can build and run the client locally following the instructions on the client repo README. All client instances would automatically make calls to the GCP instance hosting our service. How this was implemented can be seen in [this client script](https://github.com/hc8756/ASE-Team-Project-Client/blob/main/src/main/java/dev/ase/client/service/MockApiService.java). The handling of multiple users at once is done by GCP's Cloud Run and Cloud SQL services. As mentioned in the **Viewing Log** section, GCP's Log Explorer keeps track of the IP addresses of each endpoint call, which is how we differentiate clients. -A hypothetical second client is one for banking institutions. This client would be different in that they would have a view of multiple accounts rather than only one. They could implement this by creating a database of their users. They could then view and manage their users, user transactions, and user analytics through our GET endpoints. However, they would have limited edit access to user information and trasactions. +A hypothetical second client is one for banking institutions. This client would be different in that they would have a view of multiple accounts rather than only one. They could implement this by creating a database of their users. They could then view and manage their users, user transactions, and user analytics through our GET endpoints. However, they would have limited edit access to user information and transactions. + +## Multiple Client Instances + +Multiple clients can connect to the service simultaneously. The service differentiates clients by: + +1. **User-based isolation:** Each client creates/uses their own `userId`. All data (transactions, budgets) is scoped to that user. +2. **IP logging:** GCP's Log Explorer tracks the IP address of each API call for auditing purposes. +3. **Stateless API:** The REST API is stateless - no session is maintained between requests. Clients must include `userId` in each request. + +## Viewing Log +To view client activity: +1. Open [GCP Logs Explorer](https://console.cloud.google.com/welcome?authuser=0&hl=en&project=ageless-answer-474618-u4) +2. Navigate to **Monitoring → Logs Explorer** +3. Query: `textPayload:"CLIENT_LOG:"` + Following these instructions will show you a list of all API endpoint calls made as well as their time and the IP address of the client. ## API Documentation @@ -81,12 +89,12 @@ A hypothetical second client is one for banking institutions. This client would | `/users/{userId}/transactions/create-form` | GET | — → `text/html` | `userId` | `200 OK` HTML form | `404 Not Found` (HTML body) | Browser-only helper | | `/users/{userId}/transactions/{transactionId}` | PUT | `application/json` → `application/json` | `updates: Map` | `200 OK` updated `Transaction` | `404 Not Found` `{"error":"User ... not found"}` or `{"error":"Transaction ... not found for user ..."}` or `{"error":"Transaction ... not found"}` | Partial update keys handled by service | | `/users/{userId}/transactions/{transactionId}` | DELETE | — → `application/json` | `userId,transactionId` | `200 OK` `{"deleted":true,"userId":...,"transactionId":...}` | `404 Not Found` `{"error":"User ... not found"}` or `{"error":"Transaction ... not found for user ..."}` or `{"error":"Transaction ... not found"}` | Deletes transaction | -| `/users/{userId}/deletetransaction/{transactionId}` | GET | — → `text/plain` | `userId,transactionId` | `200 OK` `"Transaction deleted successfully!"` | `200 OK` `"Error: User ... not found"` or `"Error: Transaction ... not found for user ..."` or `"Error: Failed to delete transaction ..."` (plain strings, not HTTP errors) | Browser-friendly delete; returns 200 with error text on failures | +| `/users/{userId}/deletetransaction/{transactionId}` | GET | — → `text/plain` | `userId,transactionId` | `200 OK` `"Transaction deleted successfully!"` | `404 Not Found` `"Error: User ... not found"` or `"Error: Transaction ... not found for user ..."`, `500 Internal Server Error` `"Error: Failed to delete transaction ..."` | Browser-friendly delete | | `/users/{userId}/budget` | GET | — → `text/html` | `userId` | `200 OK` HTML budget dashboard | `404 Not Found` (HTML body) | Renders current budget, remaining, weekly spend, and links | | `/users/{userId}/budget` | PUT | `application/json` → `application/json` | `budgetUpdate: Map` e.g. `{"budget":123.45}` | `200 OK` budget report JSON | `404 Not Found` `{"error":"User ... not found"}` | Persists new budget via service | | `/users/{userId}/update-budget` | POST | `application/x-www-form-urlencoded` → `text/html` | `budget` | `200 OK` HTML confirmation | `404 Not Found` (HTML body) | Browser-friendly budget update | -| `/users/{userId}/weekly-summary` | GET | — → `text/html` | `userId` | `200 OK` HTML with table and total | `404 Not Found` (HTML body) | Renders last 7 days transactions | -| `/users/{userId}/monthly-summary` | GET | — → `text/html` | `userId` | `200 OK` HTML `
` summary | `404 Not Found` (HTML body) | Text summary produced by service |
+| `/users/{userId}/weekly-summary` | GET | — → `application/json` | `userId` | `200 OK` JSON with `username`, `weeklyTotal`, `transactionCount`, `transactions` | `404 Not Found` `{"error":"User ... not found"}` | Returns last 7 days transactions |
+| `/users/{userId}/monthly-summary` | GET | — → `application/json` | `userId` | `200 OK` JSON with `summary` key | `404 Not Found` `{"error":"User ... not found"}` | Text summary produced by service |
 | `/users/{userId}/budget-report` | GET | — → `application/json` | `userId` | `200 OK` budget report JSON `{totalSpent, remaining, ...}` | `404 Not Found` `{"error":"User ... not found"}` | Read-only |
 
 #### Global Error Handling
@@ -104,11 +112,37 @@ To run all unit tests:
 mvn test
 ```
 
-### Endpoint Testing
+### Integration Testing
+- Framework: JUnit 5 with Spring Boot Test
+- Database: Embedded test configuration with JdbcTemplate
 
-Please see `api-testing.md` in the root of this repository for detailed instructions on running tests with `curl`.
+Integration tests verify:
+- **Internal integration:** Controller ↔ Service ↔ Models working together
+- **External integration:** Service ↔ JdbcTemplate ↔ PostgreSQL database
+- **Shared data:** User-Transaction foreign key relationships, budget calculations, cascade deletes
 
-Calls were logged for endpoints. Logging information appears in the terminal that is running the application.
+Test files:
+- `RouteControllerIntegrationTests.java` - Controller-Service integration
+- `MockApiServiceIntegrationTests.java` - Service-Database integration
+
+To run all integration tests:
+```bash
+mvn test
+```
+
+### API Testing (Postman/Newman)
+- Tool: Postman with Newman CLI for CI integration
+
+API tests cover:
+- All REST endpoints with valid and invalid equivalence partitions
+- Boundary value testing (zero, negative, large values)
+- Multiple client simulation
+- Persistent data verification
+
+Our CI configuration automatically run the entire collection of API tests when new pull requests
+are accepted to commit to the main branch
+
+See `api-testing.md` for detailed partition documentation.
 
 ### Test Coverage
 - Tool: JaCoCo
@@ -120,7 +154,7 @@ mvn jacoco:report
 
 The report is accessible at `target/site/jacoco/index.html`.
 
-For the first iteration, we acheived 85% branch coverage. A copy of the report `index.html` is also included in the root of this repository.
+For our service, we have achieved 85% branch coverage. A copy of the report `index.html` is also included in the root of this repository.
 
 
 ## Style Checker
@@ -144,35 +178,105 @@ The report is accessible at `target/site/checkstyle.html`. A copy of a clean rep
 
 ## Static Analysis with PMD
 
-This project uses PMD for static code analysis to enforce consistent quality and style. 
+This project uses PMD for static code analysis to enforce consistent quality and style.
 
 1. Ensure `pom.xml` in the root directory is updated.
-2. Ensure `all-java.xml` is present in `/src/main/resources`
-3. Run PMD:
+2. Ensure `custom-java-rules.xml` is present in `/src/main/resources`
+3. For our project, we chose to use custom, more stringent rule set than the default rules.
+4. Run PMD:
+```bash
+mvn clean pmd:pmd
+``` 
+The report will be available at `/target/reports/pmd.html`
+5. Can also run this command:
 ```bash
 mvn clean site
 ``` 
 The reports will be available at `/target/site/pmd.html` and `/target/site/cpd.html`
 
-A copy of a "before" PMD report and a clean "after" PMD report are available in the root directory. The CPD reports were always clean, and a copy is also included in the root directory.
+Copies of "before" PMD reports and clean "after" PMD reports are available in the root directory.
+The most up-to-date before and after PMD reports in the root directory are `pmd_before_dec.html` and `pmd_after_dec.html`
+The CPD reports were always clean, and a copy is also included in the root directory.
+
+## Continuous Integration
+
+This project uses GitHub Actions for CI. The pipeline runs automatically on pushes and pull requests to `main`.
+
+### CI Pipeline Jobs
 
-In several cases, certain rules were intentionally suppressed because their recommendations conflict with established design decisions, necessary framework patterns, or clarity/readability requirements. Below is a summary of the suppressed warnings and the rationale behind each:
+| Job | Description |
+|-----|-------------|
+| Unit Tests | Runs all unit tests (`*UnitTests`, `*Tests`) |
+| Integration Tests | Runs database integration tests (`*IntegrationTests`) |
+| API Tests | Runs Newman/Postman API tests against live application |
+| Code Coverage | Generates JaCoCo coverage report |
+| Static Analysis | Runs Checkstyle and PMD |
+
+### CI Configuration
+
+The CI workflow is defined in `.github/workflows/maven.yml`.
+
+### Running Tests Locally
+```bash
+# Unit tests
+mvn test -Dtest="*UnitTests,*Tests"
+
+# Integration tests (requires PostgreSQL)
+mvn test -Dtest="*IntegrationTests"
+
+# API tests (requires application running)
+newman run postman/postman_collection.json -e postman/postman_environment.json
+```
+
+## Developing a Third-Party Client
+
+To develop your own client application that uses this service:
+
+### 1. Base URL
+- **Local:** `http://localhost:8080`
+- **Production:** `https://ase-team-project-141125434285.europe-west1.run.app`
+
+### 2. Required Request Flow
+1. **Create a user first** via `POST /users` (JSON) or `POST /users/form` (HTML)
+2. Store the returned `userId` (UUID) for subsequent requests
+3. All `/users/{userId}/...` endpoints require a valid `userId`
+4. Transaction endpoints require the transaction to belong to the specified user
+
+### 3. Content Types
+- **JSON endpoints:** Set `Content-Type: application/json` header
+- **Form endpoints:** Set `Content-Type: application/x-www-form-urlencoded` header
+
+### 4. Example: Creating a User (JSON)
+```bash
+curl -X POST http://localhost:8080/users \
+  -H "Content-Type: application/json" \
+  -d '{"username": "john_doe", "email": "john@example.com", "budget": 1000.00}'
+```
+
+Response:
+```json
+{
+  "userId": "550e8400-e29b-41d4-a716-446655440000",
+  "username": "john_doe",
+  "email": "john@example.com",
+  "budget": 1000.00
+}
+```
+
+### 5. Example: Creating a Transaction
+```bash
+curl -X POST http://localhost:8080/users/{userId}/transactions \
+  -H "Content-Type: application/json" \
+  -d '{"description": "Groceries", "amount": 50.00, "category": "FOOD"}'
+```
 
- **Rule** | **Scope (File/Class)** | **Reason for Suppression** |
-|-----------|------------------------|-----------------------------|
-| `OnlyOneReturn` | `RouteController`, `MockApiService`, `Transaction` | Multiple return statements are used intentionally for clearer control flow and early error handling, especially in REST endpoints. Enforcing a single return would reduce readability. |
-| `AvoidCatchingGenericException` | `RouteController`, `MockApiService` | Generic exceptions (e.g., `RuntimeException`) are caught at well-defined boundaries to ensure proper logging and consistent API responses. |
-| `CyclomaticComplexity`, `CognitiveComplexity` | `RouteController`, `MockApiService`, `Transaction` | Some methods inherently require multiple conditional branches for validation or comparison logic. Refactoring would reduce clarity without simplifying logic. |
-| `TooManyMethods` | `RouteController`, `MockApiService` | These classes act as centralized controller/service entry points. Splitting them would fragment logically related functionality. |
-| `CommentSize` | `RouteController`, `Transaction` | Large comments were preserved to provide clear documentation and educational explanations of logic flow. |
-| `DataClass` | `User`, `Transaction` | Both are intentionally implemented as plain data holder classes (POJOs) with standard getters/setters, consistent with Java domain modeling best practices. |
-| `ShortClassName` | `User` | The name `User` is concise, standard, and domain-appropriate. Extending it would reduce clarity. |
-| `ConstructorCallsOverridableMethod` | `Transaction` | The constructor calls `setDescription()` for input normalization. The method has no side effects and is effectively safe to call. |
-| `NullAssignment` | `Transaction` | Null assignments used for optional initialization (e.g., timestamps) are controlled and do not introduce unsafe behavior. |
-| `OnlyOneReturn` (repeated instances) | Multiple classes | Each suppression corresponds to methods where early returns improve clarity and maintainability. |
-| `SystemPrintln` | `LoggerFilter` | Direct `System.out` logging was replaced by a proper logger; suppression documents the historical rule hit. |
+### 6. Some Examples Of Valid Transaction Categories
+`FOOD`, `TRANSPORTATION`, `ENTERTAINMENT`, `UTILITIES`, `HEALTHCARE`, `OTHER`
 
-All PMD suppressions are deliberate, documented, and localized to specific cases where strict compliance would hinder clarity or architectural intent.
+### 7. Error Handling
+- `400 Bad Request`: Invalid input (check `error` field in response)
+- `404 Not Found`: User or transaction not found
+- `500 Internal Server Error`: Server-side error
 
 ## Documentation and Organization
 
@@ -190,6 +294,7 @@ Official documentation and reference materials used throughout the project inclu
 - **Maven Checkstyle Plugin:** https://maven.apache.org/plugins/maven-checkstyle-plugin/
 - **Google Java Style Guide (Checkstyle Rules):** https://google.github.io/styleguide/javaguide.html
 - **Spring Testing (MockMvc):** https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#spring-mvc-test-framework
+- **Postman/Newman (API Testing):** https://learning.postman.com/docs/collections/using-newman-cli/command-line-integration-with-newman/
 
 ChatGPT assisted in referencing documentation, fixing style warnings (long lines, import order), and minor debugging.
 
diff --git a/api-testing.md b/api-testing.md
index 8189014..606e5bf 100644
--- a/api-testing.md
+++ b/api-testing.md
@@ -1,1611 +1,396 @@
-# API Testing with curl
-
-For setup and run instructions, please see `README.md` in the root of this repository.
-
-You can test every endpoint in this application using `curl`. By default, the server runs at `http://127.0.0.1:8080` or `http://localhost:8080`. These examples use `http://localhost:8080`. Some curl commands also in refer to user/transaction IDs placeholder for real values.
-
-Note: For more visually appealing formatting, we use **Lynx**. If you want this too, install these tools.
-
-Mac:
-```
-brew install lynx
-```
-Windows:
-```
-sudo apt install lynx
-```
-
----
-
-## GET `/` or `/index` — homepage
-
-### Typical Valid Input — Normal case with existing users
-```
-# Create a few users if needed
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Alice", "email": "alice@columbia.edu", "budget": 500}' ; echo
-
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Bob", "email": "bob@gmail.com", "budget": 1200}' ; echo
-
-# Access the home page using either / or /index
-curl -isS http://localhost:8080/ ; echo
-curl -isS http://localhost:8080/index ; echo
-
-# Nice formatting
-curl -isS http://localhost:8080/index -o response.html \
-&& echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html \
-&& echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist
-
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html
-Content-Length: 310
-Date: Fri, 24 Oct 2025 00:30:03 GMT
-
-
-                    Welcome to the Personal Finance Tracker
-
-   Existing Users:
-   - Alice | alice@columbia.edu | Budget: $500.00
-   - Bob | bob@gmail.com | Budget: $1200.00
-```
-
-### Atypical Valid Input — No users exist
-```
-# Delete existing users if needed
-# Replace {UUID} with actual IDs from GET /users
-curl -isS http://localhost:8080/deleteuser/{UUID} ; echo
-
-# Acces the home page using either / or /index
-curl -isS http://localhost:8080/ ; echo
-curl -isS http://localhost:8080/index ; echo
-
-# Nice formatting
-curl -isS http://localhost:8080/index -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html
-Content-Length: 96
-Date: Fri, 24 Oct 2025 00:31:11 GMT
-
-
-                    Welcome to the Personal Finance Tracker
-
-   No users found.
-```
-
-### Invalid Input — Wrong path
-```
-# Misspelled endpoint
-curl -isS http://localhost:8080/inde ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Vary: Origin
-Vary: Access-Control-Request-Method
-Vary: Access-Control-Request-Headers
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:31:24 GMT
-
-{"timestamp":"2025-10-24T00:31:24.879+00:00","status":404,"error":"Not Found","path":"/inde"}
-```
+# API Equivalence Partitions Documentation
+
+This document defines the equivalence partitions for each API endpoint in the Personal Finance Tracker service. Each partition represents a class of inputs that should be treated equivalently by the system.
+
+## Table of Contents
+[Index/Home Endpoints](#indexhome-endpoints)  
+[User Management - GET /users](#user-management---get-users)  
+[User Management - POST /users (JSON)](#user-management---post-users-json)  
+[User Management - GET /users/{userId}](#user-management---get-usersuserid)  
+[User Management - PUT /users/{userId}](#user-management---put-usersuserid)  
+[User Management - POST /users/form (HTML)](#user-management---post-usersform-html)  
+[User Management - POST /users/{userId}/update-form (HTML)](#user-management---post-usersuseridupdate-form-html)  
+[User Management - GET Forms](#user-management---get-forms)  
+[User Management - DELETE /users/{userId}](#user-management---delete-usersuserid)  
+[User Management - GET /deleteuser/{userId}](#user-management---get-deleteuseruserid)  
+[Transaction Management - POST](#transaction-management---post-transactions)  
+[Transaction Management - GET List](#transaction-management---get-transactions-list)  
+[Transaction Management - GET Single](#transaction-management---get-single-transaction)  
+[Transaction Management - PUT](#transaction-management---put-transaction)  
+[Transaction Management - DELETE](#transaction-management---delete-transaction)  
+[Transaction Management - GET /deletetransaction](#transaction-management---get-deletetransaction)  
+[Transaction Management - Forms](#transaction-management---forms)  
+[Budget Management - GET Page](#budget-management---get-budget-page)  
+[Budget Management - PUT /budget](#budget-management---put-budget-json)  
+[Budget Management - POST /update-budget](#budget-management---post-update-budget-form)  
+[Analytics - Weekly Summary](#analytics---weekly-summary)  
+[Analytics - Monthly Summary](#analytics---monthly-summary)  
+[Analytics - Budget Report](#analytics---budget-report)
 
 ---
 
-## GET `/users` — Retrieve all users
-
-### Typical Valid Input — Normal case with existing users
-```
-# Create a few users if needed
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Alice", "email": "alice@columbia.edu", "budget": 500}' ; echo
-
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Bob", "email": "bob@gmail.com", "budget": 1200}' ; echo
-
-# Retrieve all users
-curl -isS http://localhost:8080/users -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:33:40 GMT
-
-
-   [{"userId":"31cc9c67-c23c-462b-9a13-a1db18530ee2","username":"Alice","e
-   mail":"alice@columbia.edu","budget":500.0},{"userId":"a031ac86-5c6a-473
-   2-8742-16b6fb83c11a","username":"Bob","email":"bob@gmail.com","budget":
-   1200.0}]
-```
-
-### Atypical Valid Input — No users exist
-```
-# Delete existing users if needed
-# Replace {UUID} with actual IDs from GET /users
-curl -isS http://localhost:8080/deleteuser/{UUID} ; echo
-
-# Retrieve all users again
-curl -isS http://localhost:8080/users -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:31:58 GMT
-
-
-   []
-```
-
-### Invalid Input — Wrong path
-```
-# Misspelled endpoint
-curl -isS http://localhost:8080/user ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Vary: Origin
-Vary: Access-Control-Request-Method
-Vary: Access-Control-Request-Headers
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:34:20 GMT
-
-{"timestamp":"2025-10-24T00:34:20.235+00:00","status":404,"error":"Not Found","path":"/user"}
-```
+## Index/Home Endpoints
 
----
-
-## GET `/users/{userId}` — Retrieve details of a specific user
-
-### Typical Valid Input — Retrieve an existing user by ID
-```
-# Create a user if needed
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Charlie", "email": "charlie@columbia.edu", "budget": 900}' ; echo
-
-curl -isS http://localhost:8080/users/{UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:37:00 GMT
-
-
-   {"userId":"31cc9c67-c23c-462b-9a13-a1db18530ee2","username":"Alice","em
-   ail":"alice@columbia.edu","budget":500.0}
-```
-
-### Atypical Valid Input — UUID format is valid but user does not exist
-```
-# Use a valid UUID that does not correspond to any existing user
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000 -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:37:52 GMT
-
-
-   {"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
-
-### Invalid Input — Invalid UUID
-```
-# Invalid UUID format
-curl -isS http://localhost:8080/users/not-a-valid-uuid ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:38:16 GMT
-Connection: close
-
-{"error":"Invalid UUID string: not-a-valid-uuid"}
-```
----
+### GET / and GET /index
 
-## POST `/users` — Create a new user via JSON
-
-### Typical Valid Input — Normal case with valid JSON data
-```
-# Create a new user
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Ethan", "email": "ethan@gmail.com", "budget": 950}' \
-  -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:39:04 GMT
-
-
-   {"userId":"00df6c5a-9321-4744-b653-3a15be39f085","username":"Ethan","em
-   ail":"ethan@gmail.com","budget":950.0}
-```
-
-### Atypical Valid Input — Missing optional field or empty string
-```
-# Create a user with minimal data or empty name (edge case)
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "", "email": "noname@example.com", "budget": 300}' \
-  -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:39:47 GMT
-
-
-   {"userId":"67a337ac-9034-4b52-a463-6fb3e60572ce","username":"","email":
-   "noname@example.com","budget":300.0}
-```
-
-### Invalid Input — Incomplete JSON
-```
-# Invalid payload
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d 'not-valid-json' ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:40:11 GMT
-Connection: close
-
-{"timestamp":"2025-10-24T00:40:11.717+00:00","status":400,"error":"Bad Request","path":"/users"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid GET request to `/` | 200 OK, HTML with welcome message | `GET / - Home Page (Valid)` |
+| P2 | Valid | Valid GET request to `/index` | 200 OK, HTML with welcome message | `GET /index - Index Page (Valid)` |
+| P3 | Invalid | Invalid path | 404 Not Found | `GET /invalid-path - Invalid Path` |
 
 ---
 
-## POST `/users/form` — Create a new user via HTML form submission
-
-### Typical Valid Input — Normal case with proper form data
-```
-# Submit a new user using form-encoded data
-curl -isS -X POST http://localhost:8080/users/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "username=Grace&email=grace@gmail.com&budget=650" \
-  -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 254
-Date: Fri, 24 Oct 2025 00:40:48 GMT
-
-
-User Created Successfully!
-
-   User ID: 149119d7-dab0-4535-a854-8d2e43f930b5
-
-   Username: Grace
-
-   Email: grace@gmail.com
-
-   Budget: $650.00
-```
-
-### Atypical Valid Input — Zero budget value
-```
-# Submit a user with edge-case budget values
-curl -isS -X POST http://localhost:8080/users/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "username=ZeroBudget&email=zerobudget@test.com&budget=0" \
-  -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+## User Management - GET /users
 
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 261
-Date: Fri, 24 Oct 2025 00:42:04 GMT
+### GET /users
 
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid GET request | 200 OK, JSON array of users | `GET /users - List All Users (Valid)` |
 
-User Created Successfully!
-
-   User ID: bae3e580-f710-43aa-b5d1-343531682c77
-
-   Username: ZeroBudget
-
-   Email: zerobudget@test.com
+---
 
-   Budget: $0.00
-```
+## User Management - POST /users (JSON)
 
-### Invalid Input — Missing required form field(s)
-```
-# Missing budget field
-curl -isS -X POST http://localhost:8080/users/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "username=InvalidUser&email=invalid@test.com" ; echo
-```
+### POST /users
 
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:42:33 GMT
-Connection: close
+**Input Parameters:**
+- `username` (String, required)
+- `email` (String, required)
+- `budget` (Double, required, >= 0)
 
-{"timestamp":"2025-10-24T00:42:33.378+00:00","status":400,"error":"Bad Request","path":"/users/form"
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | All fields valid (username, email, positive budget) | 201 Created with user data | `POST /users - Create Valid User` |
+| P2 | Valid/Boundary | budget = 0 (minimum valid) | 201 Created | `POST /users - Zero Budget` |
+| P3 | Valid/Boundary | budget = 99999999.99 (high value) | 201 Created | `POST /users - Large Budget` |
+| P4 | Invalid | username = null | 400 Bad Request | `POST /users - Missing Username` |
+| P5 | Invalid | email = null | 400 Bad Request | `POST /users - Missing Email` |
+| P6 | Invalid | Malformed JSON | 400 Bad Request | `POST /users - Malformed JSON` |
+| P7 | Invalid | Duplicate username | 400 Bad Request | `POST /users - Duplicate Username` |
+| P8 | Invalid | Duplicate email | 400 Bad Request | `POST /users - Duplicate Email` |
 
 ---
 
-## GET `/users/create-form` — Display HTML form for creating a new user
-
-### Typical Valid Input — Normal request to view the form
-```
-# Access the user creation form
-curl -isS http://localhost:8080/users/create-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 323
-Date: Fri, 24 Oct 2025 00:58:34 GMT
-
-
-Create New User
-
-   Username: ____________________
-   Email: ____________________
-   Budget: ____________________
-   Create User
-```
-
-### Atypical Valid Input — Access form repeatedly
-```
-# Perform multiple requests (user refreshes the form page)
-curl -isS http://localhost:8080/users/create-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 323
-Date: Fri, 24 Oct 2025 00:59:23 GMT
-
-
-Create New User
-
-   Username: ____________________
-   Email: ____________________
-   Budget: ____________________
-   Create User
-```
-
-### Invalid Input — Wrong path/misspelled route
-```
-# Misspelled endpoint path
-curl -isS http://localhost:8080/users/createform ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 00:59:43 GMT
-Connection: close
-
-{"error":"Invalid UUID string: createform"}
-```
+## User Management - GET /users/{userId}
 
----
+### GET /users/{userId}
 
-## GET `/users/{userId}/edit-form` — Display editable form for an existing user
-
-### Typical Valid Input — Retrieve edit form for an existing user
-```
-# Replace {UUID} below with an existing user's ID
-curl -isS http://localhost:8080/users/{UUID}/edit-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 420
-Date: Fri, 24 Oct 2025 01:01:03 GMT
-
-
-Edit User
-
-   Username: Ethan_______________
-   Email: ethan@gmail.com_____
-   Budget: 950.0_______________
-   Update User
-```
-
-### Atypical Valid Input — Access the edit form multiple times (repeated requests)
-```
-# Perform multiple consecutive GET requests to the same edit form
-curl -isS http://localhost:8080/users/{UUID}/edit-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 420
-Date: Fri, 24 Oct 2025 01:01:03 GMT
-
-
-Edit User
-
-   Username: Ethan_______________
-   Email: ethan@gmail.com_____
-   Budget: 950.0_______________
-   Update User
-```
-
-### Invalid Input — Nonexistent user ID
-```
-# Use a UUID that does not exist
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/edit-form ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:02:01 GMT
-
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+**Input Parameters:**
+- `userId` (UUID, path parameter)
 
----
-
-## DELETE `/users/{userId}` — Delete a user by ID (JSON API)
-
-### Typical Valid Input — Delete an existing user
-```
-# Replace {UUID} with an existing user ID
-curl -isS -X DELETE http://localhost:8080/users/{UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:03:22 GMT
-
-
-   {"deleted":true,"userId":"67a337ac-9034-4b52-a463-6fb3e60572ce"}
-```
-
-### Atypical Valid Input — Delete an already deleted user
-```
-# Attempt to delete the same user again
-curl -isS -X DELETE http://localhost:8080/users/{UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:03:47 GMT
-
-
-   {"error":"User 67a337ac-9034-4b52-a463-6fb3e60572ce not found"}
-```
-
-### Invalid Input — Invalid or incorrect UUID
-```
-# Use an invalid UUID string
-curl -isS -X DELETE http://localhost:8080/users/not-a-valid-uuid ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:05:23 GMT
-Connection: close
-
-{"error":"Invalid UUID string: not-a-valid-uuid"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK with user data | `GET /users/{userId} - Existing User` |
+| P2 | Invalid | Non-existent but valid UUID format | 404 Not Found | `GET /users/{userId} - Non-existent UUID` |
+| P3 | Invalid | Invalid UUID format | 400 Bad Request | `GET /users/{userId} - Invalid UUID Format` |
 
 ---
 
-## GET `/deleteuser/{userId}` — Delete a user via GET (HTML Response)
-
-### Typical Valid Input — Delete an existing user
-```
-# Replace {UUID} with the an existin user ID
-curl -isS http://localhost:8080/deleteuser/{UUID} -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 25
-Date: Fri, 24 Oct 2025 01:06:35 GMT
-
-
-   User deleted successfully
-```
-
-### Atypical Valid Input — Attempt to delete an already deleted user
-```
-# Try deleting the same user again
-curl -isS http://localhost:8080/deleteuser/{UUID} -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:07:03 GMT
-
-
-   {"error":"User bae3e580-f710-43aa-b5d1-343531682c77 not found"}
-```
-
-### Invalid Input — Invalid UUID
-```
-# Step 1: Provide an invalid UUID format
-curl -isS http://localhost:8080/deleteuser/not-a-valid-uuid ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:07:37 GMT
-Connection: close
-
-{"error":"Invalid UUID string: not-a-valid-uuid"}
-```
-
----
+## User Management - PUT /users/{userId}
 
-## GET `/users/{userId}/transactions` — Retrieve all transactions for a specific user
-
-### Typical Valid Input — User exists and has transactions
-```
-# Replace {USER_UUID} with the user ID
-# Add two transactions for this user
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Groceries", "amount": 120.5, "category": "FOOD"}' ; echo
-
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "MetroCard Refill", "amount": 40, "category": "TRANSPORTATION"}' ; echo
-
-# Retrieve all transactions for the user
-curl -isS http://localhost:8080/users/{USER_UUID}/transactions -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:09:54 GMT
-
-
-   [{"transactionId":"45ed2ed8-2964-4b56-84cb-2d5832d806c7","userId":"00df
-   6c5a-9321-4744-b653-3a15be39f085","description":"MetroCard
-   Refill","amount":40.0,"category":"TRANSPORTATION","timestamp":"2025-10-
-   23T21:09:34.305769","date":"2025-10-23"},{"transactionId":"c7bb37bf-ab0
-   4-4e8b-a0ac-d348464a9a65","userId":"00df6c5a-9321-4744-b653-3a15be39f08
-   5","description":"Groceries","amount":120.5,"category":"FOOD","timestam
-   p":"2025-10-23T21:09:09.821857","date":"2025-10-23"}]
-```
-
-### Atypical Valid Input — User exists but has no transactions
-```
-# Step 1: Create a new user without adding transactions
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Olivia", "email": "olivia@columbia.edu", "budget": 800}' ; echo
-
-# Step 2: Replace {USER_UUID} with the ID from the response
-
-# Step 3: Retrieve transactions (expect an empty array)
-curl -isS http://localhost:8080/users/{USER_UUID}/transactions -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:10:33 GMT
-
-
-   []
-```
-
-### Invalid Input — Non-existent or invalid user ID
-```
-# Non-existent UUID
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/transactions ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 58
-Date: Fri, 24 Oct 2025 01:11:14 GMT
-
-Error: User 00000000-0000-0000-0000-000000000000 not found
-```
+### PUT /users/{userId}
 
----
+**Input Parameters:**
+- `userId` (UUID, path parameter)
+- `username` (String, body)
+- `email` (String, body)
+- `budget` (Double, body)
 
-## GET `/users/{userId}/transactions/{transactionId}` — Retrieve details of a specific transaction
-
-### Typical Valid Input — Valid user and existing transaction
-```
-# Replace {USER_UUID} with the valid user ID
-# Replace {TRANSACTION_UUID} with existing transaction ID
-curl -isS http://localhost:8080/users/{USER_UUID}/transactions/{TRANSACTION_UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:13:19 GMT
-
-
-   {"transactionId":"45ed2ed8-2964-4b56-84cb-2d5832d806c7","userId":"00df6
-   c5a-9321-4744-b653-3a15be39f085","description":"MetroCard
-   Refill","amount":40.0,"category":"TRANSPORTATION","timestamp":"2025-10-
-   23T21:09:34.305769","date":"2025-10-23"}
-```
-
-### Atypical Valid Input — Valid user but transaction belongs to another user
-```
-# Create a user if needed
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Isabella", "email": "isabella@columbia.edu", "budget": 950}' ; echo
-
-# Create a transaction for the new user
-curl -isS -X POST http://localhost:8080/users/{NEW_USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Dinner", "amount": 80.75, "category": "FOOD"}' ; echo
-
-# Try fetching that transaction under a different valid user
-curl -isS http://localhost:8080/users/{USER_1_UUID}/transactions/{TRANSACTION_NEW_UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:18:23 GMT
-
-
-   {"error":"Transaction 6ce98f89-de4c-4d44-9d3d-d01024bfbf91 not found
-   for user 00df6c5a-9321-4744-b653-3a15be39f085"}
-```
-
-### Invalid Input — Nonexistent/invalid UUIDs
-```
-curl -isS http://localhost:8080/users/{VALID_USER_UUID}/transactions/00000000-0000-0000-0000-000000000000 ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:19:00 GMT
-Connection: close
-
-{"error":"Invalid UUID string: VALID_USER_UUID"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing user, valid update data | 200 OK with updated user | `PUT /users/{userId} - Update All Fields` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `PUT /users/{userId} - Non-existent User` |
+| P3 | Invalid | Duplicate username (conflict with other user) | 400 Bad Request | `PUT /users/{userId} - Duplicate Username` |
+| P4 | Invalid | Duplicate email (conflict with other user) | 400 Bad Request | `PUT /users/{userId} - Duplicate Email` |
+| P5 | Valid/Boundary | budget = 0 | 200 OK | `PUT /users/{userId} - Zero Budget` |
 
 ---
 
-## POST `/users/{userId}/transactions` — Create a new transaction for a user (JSON)
-
-### Typical Valid Input — Valid user with correct JSON payload
-```
-# Create a transaction for a valid user
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Coffee and Bagel", "amount": 8.75, "category": "FOOD"}' -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:20:40 GMT
-
-
-   {"transactionId":"01eb0e59-258e-4828-8ed9-388f534ec498","userId":"00df6
-   c5a-9321-4744-b653-3a15be39f085","description":"Coffee and
-   Bagel","amount":8.75,"category":"FOOD","timestamp":"2025-10-23T21:20:40
-   .313522","date":"2025-10-23"}0
-```
-
-### Atypical Valid Input — Zero transaction amount
-```
-# Create a transaction with a zero amount
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Free coupon coffee", "amount": 0.0, "category": "FOOD"}' -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:21:30 GMT
-
-
-   {"transactionId":"2f67194a-442a-4a00-8771-bd7e334c5fe8","userId":"00df6
-   c5a-9321-4744-b653-3a15be39f085","description":"Free coupon
-   coffee","amount":0.0,"category":"FOOD","timestamp":"2025-10-23T21:21:30
-   .343616","date":"2025-10-23"}
-```
-
-### Invalid Input — Non-existent user or malformed payload
-```
-# Non-existent user
-curl -isS -X POST http://localhost:8080/users/00000000-0000-0000-0000-000000000000/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Lunch", "amount": 12.0, "category": "FOOD"}' ; echo
-
-# Malformed JSON payload
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Invalid JSON", "amount": , "category": "FOOD"}' ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 400 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:22:11 GMT
-Connection: close
-
-{"error":"Invalid UUID string: USER_UUID"}
-```
+## User Management - POST /users/form (HTML)
 
----
+### POST /users/form
 
-## POST `/users/{userId}/transactions/form` — Create a new transaction (HTML form)
+**Input Parameters:**
+- `username` (form field)
+- `email` (form field)
+- `budget` (form field)
 
-### Typical Valid Input — Valid user submitting correct form data
-```
-# Create a new transaction via HTML form submission
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "description=Gym+Membership&amount=50.00&category=HEALTHCARE" -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | All fields valid | 201 Created, HTML success page | `POST /users/form - Valid Form Data` |
+| P2 | Invalid | Duplicate username | 400 Bad Request, HTML error | `POST /users/form - Duplicate Username` |
+| P3 | Invalid | Duplicate email | 400 Bad Request, HTML error | `POST /users/form - Duplicate Email` |
 
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 205
-Date: Fri, 24 Oct 2025 01:23:05 GMT
+---
 
+## User Management - POST /users/{userId}/update-form (HTML)
 
-Transaction Created Successfully!
+### POST /users/{userId}/update-form
 
-   Description: Gym Membership
+**Input Parameters:**
+- `userId` (UUID, path parameter)
+- `username` (form field)
+- `email` (form field)
+- `budget` (form field)
 
-   Amount: $50.00
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing user, valid data | 200 OK, HTML success page | `POST /users/{userId}/update-form - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `POST /users/{userId}/update-form - User Not Found` |
+| P3 | Invalid | Duplicate username | 400 Bad Request | `POST /users/{userId}/update-form - Duplicate Username` |
+| P4 | Invalid | Duplicate email | 400 Bad Request | `POST /users/{userId}/update-form - Duplicate Email` |
 
-   Category: HEALTHCARE
-```
+---
 
-### Atypical Valid Input — Edge case with zero amount
-```
-# Create a transaction with a zero amount
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "description=Free+Trial&amount=0&category=OTHER" -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+## User Management - GET Forms
 
-Sample Output:
-```
-HTTP/1.1 201 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 195
-Date: Fri, 24 Oct 2025 01:24:15 GMT
+### GET /users/create-form
 
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid GET request | 200 OK, HTML form | `GET /users/create-form` |
 
-Transaction Created Successfully!
+### GET /users/{userId}/edit-form
 
-   Description: Free Trial
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, HTML form with user data | `GET /users/{userId}/edit-form - Existing User` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET /users/{userId}/edit-form - Non-existent User` |
 
-   Amount: $0.00
+---
 
-   Category: OTHER
-```
+## Transaction Management - POST Transactions
 
-### Invalid Input — Non-existent user or missing parameters
-```
-# Non-existent user ID
-curl -isS -X POST http://localhost:8080/users/00000000-0000-0000-0000-000000000000/transactions/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "description=Snacks&amount=5.50&category=FOOD" ; echo
+### POST /users/{userId}/transactions
 
-# Missing parameter (no category)
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions/form \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "description=Snacks&amount=5.50" ; echo
-```
+**Input Parameters:**
+- `userId` (UUID, path parameter)
+- `description` (String, required, non-empty)
+- `amount` (Double, required, > 0)
+- `category` (String, required, valid enum value)
 
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 58
-Date: Fri, 24 Oct 2025 01:24:47 GMT
+**Valid Categories:** FOOD, TRANSPORTATION, ENTERTAINMENT, UTILITIES, SHOPPING, HEALTHCARE, TRAVEL, EDUCATION, OTHER
 
-Error: User 00000000-0000-0000-0000-000000000000 not found
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | All fields valid | 201 Created with transaction data | `POST Transaction - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `POST Transaction - Non-existent User` |
+| P3 | Invalid | Invalid category | 400/500 Error | `POST Transaction - Invalid Category` |
+| P4 | Invalid/Boundary | amount < 0 (negative) | 400/500 Error | `POST Transaction - Negative Amount` |
+| P5 | Invalid/Boundary | amount = 0 | 400/500 Error | `POST Transaction - Zero Amount` |
+| P6 | Invalid | description = "" (empty) | 400/500 Error | `POST Transaction - Empty Description` |
+| P7 | Valid | Large amount (boundary high) | 201 Created | `POST Transaction - Large Amount` |
 
 ---
 
-## GET `/users/{userId}/transactions/create-form` — Display the HTML form for creating a new transaction
-
-### Typical Valid Input — Display form for an existing user
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/transactions/create-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 793
-Date: Fri, 24 Oct 2025 01:49:41 GMT
-
-
-Create New Transaction
-
-   Description: ____________________
-   Amount: ____________________
-   Category: [Food__________]
-   Create Transaction
-```
-
-### Atypical Valid Input — User exists but has no prior transactions
-```
-# Access the form for a user who has no transactions yet
-curl -isS http://localhost:8080/users/{USER_UUID}/transactions/create-form -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 793
-Date: Fri, 24 Oct 2025 01:52:00 GMT
-
-
-Create New Transaction
-
-   Description: ____________________
-   Amount: ____________________
-   Category: [Food__________]
-   Create Transaction
-```
-
-### Invalid Input — Nonexistent user ID
-```
-# Case 1: Non-existent user UUID
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/transactions/create-form ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:52:49 GMT
-
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+## Transaction Management - GET Transactions List
 
----
+### GET /users/{userId}/transactions
 
-## DELETE `/users/{userId}/transactions/{transactionId}` — Delete a transaction (JSON)
-
-### Typical Valid Input — Delete an existing transaction for a valid user
-```
-curl -isS -X DELETE http://localhost:8080/users/{USER_UUID}/transactions/{TRANSACTION_UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:54:27 GMT
-
-
-   {"deleted":true,"transactionId":"62e35ca8-dc11-403d-ad2d-4e7d538e046c",
-   "userId":"00df6c5a-9321-4744-b653-3a15be39f085"}
-```
-
-### Atypical Valid Input — Try deleting the same transaction twice
-```
-# Attempt to delete the same transaction again
-curl -isS -X DELETE http://localhost:8080/users/{USER_UUID}/transactions/{TRANSACTION_UUID} -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:54:39 GMT
-
-
-   {"error":"Transaction 62e35ca8-dc11-403d-ad2d-4e7d538e046c not found
-   for user 00df6c5a-9321-4744-b653-3a15be39f085"}
-```
-
-### Invalid Input — Transaction belongs to another user
-```
-# Transaction belongs to another user
-curl -isS -X DELETE http://localhost:8080/users/{DIFFERENT_USER_UUID}/transactions/{TRANSACTION_UUID} ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 01:55:32 GMT
-
-{"error":"Transaction 135dd178-9e17-4f30-a6f2-84b6d035fb31 not found for user 149119d7-dab0-4535-a854-8d2e43f930b5"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, JSON array | `GET Transactions - Valid User` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET Transactions - Non-existent User` |
 
 ---
 
-## GET `/users/{userId}/deletetransaction/{transactionId}` — Delete a transaction via GET (plain text)
-
-### Typical Valid Input — Delete an existing transaction
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/deletetransaction/{TRANSACTION_UUID} -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 33
-Date: Fri, 24 Oct 2025 01:57:01 GMT
-
+## Transaction Management - GET Single Transaction
 
-   Transaction deleted successfully!
-```
+### GET /users/{userId}/transactions/{transactionId}
 
-### Atypical Valid Input — Attempt to delete the same transaction twice
-```
-# Attempt to delete again using the same UUIDs
-curl -isS http://localhost:8080/users/{USER_UUID}/deletetransaction/{TRANSACTION_UUID} -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output (Nice Format):
-```
-HTTP/1.1 200 
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 111
-Date: Fri, 24 Oct 2025 01:57:10 GMT
-
-
-   Error: Transaction 2f67194a-442a-4a00-8771-bd7e334c5fe8 not found for
-   user 00df6c5a-9321-4744-b653-3a15be39f085
-```
-
-### Invalid Input — Nonexistent user/transaction ID
-```
-# Non-existent user UUID
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/deletetransaction/{TRANSACTION_UUID} ; echo
-
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 58
-Date: Fri, 24 Oct 2025 01:57:54 GMT
-
-Error: User 00000000-0000-0000-0000-000000000000 not found
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid userId and transactionId | 200 OK with transaction | `GET Single Transaction - Valid` |
+| P2 | Invalid | Transaction belongs to different user | 404 Not Found | `GET Single Transaction - Wrong User` |
+| P3 | Invalid | Non-existent transactionId | 404 Not Found | `GET Single Transaction - Non-existent Transaction` |
 
 ---
 
-## GET `/users/{userId}/budget` — Display the budget management page for a user
-
-### Typical Valid Input — Display budget dashboard for an existing user
-```
-# Step 1: Create a user
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Sophia", "email": "sophia@columbia.edu", "budget": 1000}' ; echo
-
-# Step 2: Replace {USER_UUID} with the user ID from the response
-
-# Step 3: Add a few transactions for realism
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "Lunch", "amount": 25.75, "category": "FOOD"}' ; echo
-
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/transactions \
-  -H "Content-Type: application/json" \
-  -d '{"description": "MetroCard Refill", "amount": 33.00, "category": "TRANSPORTATION"}' ; echo
-
-# Step 4: View the budget management dashboard
-curl -isS http://localhost:8080/users/{USER_UUID}/budget -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 835
-Date: Fri, 24 Oct 2025 01:58:35 GMT
-
-
-                           Budget Management - Ethan
-
-Current Budget
-
-   Total Budget: $950.00
-
-   Total Spent: $219.25
-
-   Remaining: $730.75
+## Transaction Management - PUT Transaction
 
-   Weekly Spending: $0.00
+### PUT /users/{userId}/transactions/{transactionId}
 
-Update Budget
+**Input Parameters:**
+- `userId` (UUID, path parameter)
+- `transactionId` (UUID, path parameter)
+- `amount` (Double, optional)
+- `description` (String, optional)
+- `category` (String, optional)
 
-   New Budget: 950.0_______________
-   Update Budget
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid userId, transactionId, update data | 200 OK with updated transaction | `PUT Transaction - Update Amount` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `PUT Transaction - Non-existent User` |
+| P3 | Invalid | Transaction belongs to different user | 404 Not Found | `PUT Transaction - Wrong User` |
+| P4 | Invalid | Non-existent transactionId | 404 Not Found | `PUT Transaction - Non-existent Transaction` |
+| P5 | Invalid | Invalid category in update | 400 Bad Request | `PUT Transaction - Invalid Category` |
 
-Quick Reports
-
-     * Weekly Summary
-     * Monthly Summary
-     * Budget Report (JSON)
-```
-
-### Atypical Valid Input — User exists but has no transactions
-```
-# Create a new user with no transactions if needed
-curl -isS -X POST http://localhost:8080/users \
-  -H "Content-Type: application/json" \
-  -d '{"username": "Liam", "email": "liam@columbia.edu", "budget": 500}' ; echo
-
-# Access the budget dashboard
-curl -isS http://localhost:8080/users/{USER_UUID}/budget -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 830
-Date: Fri, 24 Oct 2025 02:00:00 GMT
+---
 
+## Transaction Management - Forms
 
-                            Budget Management - Liam
+### GET /users/{userId}/transactions/create-form
 
-Current Budget
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, HTML form | `GET /transactions/create-form - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET /transactions/create-form - User Not Found` |
 
-   Total Budget: $500.00
+### POST /users/{userId}/transactions/form
 
-   Total Spent: $0.0
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid form data | 201 Created, HTML success | `POST /transactions/form - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `POST /transactions/form - User Not Found` |
+| P3 | Invalid | Invalid category | 500 Error | `POST /transactions/form - Invalid Category` |
 
-   Remaining: $500.0
+---
 
-   Weekly Spending: $0.00
+## Budget Management - GET Budget Page
 
-Update Budget
+### GET /users/{userId}/budget
 
-   New Budget: 500.0_______________
-   Update Budget
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, HTML budget page | `GET Budget Page - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET Budget Page - Non-existent User` |
 
-Quick Reports
+---
 
-     * Weekly Summary
-     * Monthly Summary
-     * Budget Report (JSON)
-```
+## Budget Management - PUT /budget (JSON)
 
-### Invalid Input — Nonexistent user ID
-```
-# Non-existent user
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/budget ; echo
-```
+### PUT /users/{userId}/budget
 
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:00:23 GMT
+**Input Parameters:**
+- `userId` (UUID, path parameter)
+- `budget` (Double, body, >= 0)
 
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing user, valid budget | 200 OK with budget report | `PUT Budget - Update` |
+| P2 | Valid/Boundary | budget = 0 | 200 OK | `PUT Budget - Zero Budget` |
+| P3 | Invalid/Boundary | budget < 0 (negative) | 400/500 Error | `PUT Budget - Negative` |
+| P4 | Invalid | Non-existent userId | 404 Not Found | `PUT Budget - Non-existent User` |
 
 ---
 
-## PUT `/users/{userId}/budget` — Update a user's budget (JSON)
-
-### Typical Valid Input — Update budget for an existing user
-```
-curl -isS -X PUT http://localhost:8080/users/{USER_UUID}/budget \
-  -H "Content-Type: application/json" \
-  -d '{"budget": 1200}' -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:01:13 GMT
-
-
-   {"userId":"00df6c5a-9321-4744-b653-3a15be39f085","warnings":"","remaini
-   ng":980.75,"isOverBudget":false,"totalSpent":219.25,"hasWarnings":false
-   ,"categories":{"HEALTHCARE":50.0,"TRANSPORTATION":40.0,"FOOD":129.25},"
-   totalBudget":1200.0,"username":"Ethan"}
-```
-
-### Atypical Valid Input — Budget updated with same value (no effective change)
-```
-curl -isS -X PUT http://localhost:8080/users/{USER_UUID}/budget \
-  -H "Content-Type: application/json" \
-  -d '{"budget": 1200}' -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:02:15 GMT
-
-
-   {"userId":"00df6c5a-9321-4744-b653-3a15be39f085","warnings":"","remaini
-   ng":980.75,"isOverBudget":false,"totalSpent":219.25,"hasWarnings":false
-   ,"categories":{"HEALTHCARE":50.0,"TRANSPORTATION":40.0,"FOOD":129.25},"
-   totalBudget":1200.0,"username":"Ethan"}
-```
-
-### Invalid Input — Nonexistent user
-```
-# Non-existent user
-curl -isS -X PUT http://localhost:8080/users/00000000-0000-0000-0000-000000000000/budget \
-  -H "Content-Type: application/json" \
-  -d '{"budget": 1500}' ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:02:45 GMT
-
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+## Budget Management - POST /update-budget (Form)
 
----
+### POST /users/{userId}/update-budget
 
-## POST `/users/{userId}/update-budget` — Update a user’s budget via HTML form
-
-### Typical Valid Input — Update budget for existing user
-```
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/update-budget \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "budget=950" -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 106
-Date: Fri, 24 Oct 2025 02:03:47 GMT
-
-
-Budget Updated Successfully!
-
-   New Budget: $950.00
-```
-
-### Atypical Valid Input — Submit same budget amount (no change)
-```
-# Submit the same budget value again
-curl -isS -X POST http://localhost:8080/users/{USER_UUID}/update-budget \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "budget=950" -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 106
-Date: Fri, 24 Oct 2025 02:04:03 GMT
-
-
-Budget Updated Successfully!
-
-   New Budget: $950.00
-```
-
-### Invalid Input — Nonexistent user
-```
-curl -isS -X POST http://localhost:8080/users/00000000-0000-0000-0000-000000000000/update-budget \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "budget=1200" ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:04:26 GMT
-
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing user, valid budget | 200 OK, HTML success | `POST Update Budget Form - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `POST Update Budget Form - User Not Found` |
 
 ---
 
-## GET `/users/{userId}/weekly-summary` — Display the user’s weekly spending summary
-
-### Typical Valid Input — User with transactions in the past week
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/weekly-summary -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+## Analytics - Weekly Summary
 
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 693
-Date: Fri, 24 Oct 2025 02:05:22 GMT
+### GET /users/{userId}/weekly-summary
 
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, JSON summary | `GET Weekly Summary - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET Weekly Summary - Non-existent User` |
 
-                             Weekly Summary - Ethan
-
-   Total Spent Last 7 Days: $0.00
-
-Recent Transactions
+---
 
-     Description    Amount     Category       Date
-   Free Trial       $0.00   OTHER          2025-10-23
-   Gym Membership   $50.00  HEALTHCARE     2025-10-23
-   Coffee and Bagel $8.75   FOOD           2025-10-23
-   MetroCard Refill $40.00  TRANSPORTATION 2025-10-23
-   Groceries        $120.50 FOOD           2025-10-23
-```
+## Analytics - Monthly Summary
 
-### Atypical Valid Input — User exists but has no transactions in the past week
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/weekly-summary -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+### GET /users/{userId}/monthly-summary
 
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 180
-Date: Fri, 24 Oct 2025 02:05:59 GMT
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, JSON with summary | `GET Monthly Summary - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET Monthly Summary - Non-existent User` |
 
+---
 
-                             Weekly Summary - Liam
+## Analytics - Budget Report
 
-   Total Spent Last 7 Days: $0.00
+### GET /users/{userId}/budget-report
 
-Recent Transactions
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, JSON report | `GET Budget Report - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET Budget Report - Non-existent User` |
 
-   No transactions in the last 7 days.
-```
+---
 
-### Invalid Input — Nonexistent user ID
-```
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/weekly-summary ; echo
-```
+## Transaction Management - DELETE Transaction
 
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:06:31 GMT
+### DELETE /users/{userId}/transactions/{transactionId}
 
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid userId and transactionId | 200 OK, deletion confirmed | `DELETE Transaction - Valid` |
+| P2 | Invalid | Already deleted transaction | 404 Not Found | `DELETE Transaction - Already Deleted` |
+| P3 | Invalid | Transaction belongs to different user | 404 Not Found | `DELETE Transaction - Wrong User` |
 
 ---
 
-## GET `/users/{userId}/monthly-summary` — Display the user’s monthly spending summary
+## Transaction Management - GET /deletetransaction
 
-### Typical Valid Input — User with transactions this month
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/monthly-summary -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+### GET /users/{userId}/deletetransaction/{transactionId}
 
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 251
-Date: Fri, 24 Oct 2025 02:07:15 GMT
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Valid userId and transactionId | 200 OK, success message | `GET /deletetransaction - Valid` |
+| P2 | Invalid | Non-existent or wrong user | Error message | `GET /deletetransaction - Invalid` |
 
+## User Management - DELETE /users/{userId}
 
-                                Monthly Summary
+### DELETE /users/{userId}
 
-Monthly Summary for Ethan (OCTOBER 2025)
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, deletion confirmed | `DELETE /users/{userId} - Valid` |
+| P2 | Invalid | Already deleted user | 404 Not Found | `DELETE /users/{userId} - Already Deleted` |
+| P3 | Invalid | Non-existent UUID | 404 Not Found | `DELETE /users/{userId} - Non-existent UUID` |
+| P4 | Invalid | Invalid UUID format | 400 Bad Request | `DELETE /users/{userId} - Invalid UUID Format` |
 
-Total Budget: $1200.00
-Total Spent: $219.25
-Remaining: $980.75
+---
 
-Spending by Category:
-- FOOD: $129.25
-- HEALTHCARE: $50.00
-- TRANSPORTATION: $40.00
-```
+## User Management - GET /deleteuser/{userId}
 
-### Atypical Valid Input — User exists but has no transactions this month
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/monthly-summary -o response.html ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.html ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.html | lynx -dump -stdin -nolist ; echo
-```
+### GET /deleteuser/{userId}
 
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: text/html;charset=UTF-8
-Content-Length: 185
-Date: Fri, 24 Oct 2025 02:07:53 GMT
+| Partition | Type | Input | Expected Output | Test Coverage |
+|-----------|------|-------|-----------------|---------------|
+| P1 | Valid | Existing userId | 200 OK, success message | `GET /deleteuser/{userId} - Valid` |
+| P2 | Invalid | Non-existent userId | 404 Not Found | `GET /deleteuser/{userId} - Not Found` |
 
+---
 
-                                Monthly Summary
+## Boundary Value Analysis Summary
 
-Monthly Summary for Liam (OCTOBER 2025)
+| Input | Lower Boundary | Upper Boundary |
+|-------|----------------|----------------|
+| User budget | 0 (valid) | 99999999.99 (valid) |
+| Transaction amount | 0 (invalid), 0.01 (valid) | Large value (valid) |
+| UUID format | Valid UUID | Invalid string |
+| String fields | Empty string (invalid) | Non-empty (valid) |
 
-Total Budget: $950.00
-Total Spent: $0.00
-Remaining: $950.00
+---
 
-Spending by Category:
-```
+## Multiple Clients Testing
 
-### Invalid Input — Nonexistent user ID
-```
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/monthly-summary ; echo
-```
+The test suite exercises multiple clients through:
+- Creating two test users (`testUserId` and `testUserId2`)
+- Testing transaction ownership validation (accessing another user's transactions)
+- Testing concurrent data isolation
 
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:08:19 GMT
+## Persistent Data Testing
 
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
+The test suite verifies data persistence through:
+- Create → Retrieve sequences
+- Update → Retrieve sequences
+- Delete → Verify deletion sequences
+- Cascade delete verification (user deletion removes transactions)
 
----
+## CI Integration
 
-## GET `/users/{userId}/budget-report` — Retrieve a user’s budget report in JSON
-
-### Typical Valid Input — Retrieve JSON report for existing user
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/budget-report -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:09:10 GMT
-
-
-   {"userId":"00df6c5a-9321-4744-b653-3a15be39f085","warnings":"","remaini
-   ng":980.75,"isOverBudget":false,"totalSpent":219.25,"hasWarnings":false
-   ,"categories":{"HEALTHCARE":50.0,"TRANSPORTATION":40.0,"FOOD":129.25},"
-   totalBudget":1200.0,"username":"Ethan"}
-```
-
-### Atypical Valid Input — No transactions yet
-```
-curl -isS http://localhost:8080/users/{USER_UUID}/budget-report -o response.json ; echo \
-&& awk '/^\r?$/{print; exit} {print}' response.json ; echo \
-&& awk 'f; /^\r?$/{f=1}' response.json | lynx -dump -stdin -nolist ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 200 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:09:47 GMT
-
-
-   {"userId":"5a3c181f-39ee-42e0-a1ff-88cfc5a301d1","warnings":"","remaini
-   ng":950.0,"isOverBudget":false,"totalSpent":0.0,"hasWarnings":false,"ca
-   tegories":{},"totalBudget":950.0,"username":"Liam"}
-```
-
-### Invalid Input — Nonexistent user ID
-```
-curl -isS http://localhost:8080/users/00000000-0000-0000-0000-000000000000/budget-report ; echo
-```
-
-Sample Output:
-```
-HTTP/1.1 404 
-Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Fri, 24 Oct 2025 02:10:19 GMT
-
-{"error":"User 00000000-0000-0000-0000-000000000000 not found"}
-```
\ No newline at end of file
+These tests run automatically via Newman in the CI pipeline (./github/workflows/maven.yml).
\ No newline at end of file
diff --git a/checkstyle.html b/checkstyle.html
index 929485f..bc06855 100644
--- a/checkstyle.html
+++ b/checkstyle.html
@@ -1,6 +1,6 @@
 
 
@@ -10,10 +10,10 @@
     
     
     ledger – Checkstyle Results
-    
-    
-    
-    
+    
+    
+    
+