This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Start PostgreSQL and Redis (required dependencies)
docker compose up -d
# Run with dev profile (includes Swagger UI)
./mvnw spring-boot:run -Dspring.profiles.active=dev
# Check health endpoint
curl http://localhost:8080/api/v1/actuator/health# Run all tests
./mvnw test
# Build, test with coverage (JaCoCo), and run Checkstyle
./mvnw clean verify
# Run specific test class
./mvnw test -Dtest="AccountServiceTest"
# Run only unit tests (exclude integration tests)
./mvnw test -Dtest="*Test"
# Run only integration tests
./mvnw test -Dtest="*IntegrationTest"# Check code style (Checkstyle)
./mvnw checkstyle:check
# View JaCoCo coverage report (after running verify)
# Linux/Mac: open target/site/jacoco/index.html
# Windows: start target/site/jacoco/index.htmlTrackMoney is a personal finance management system built with Spring Boot 3.4.5 following layered architecture principles.
The codebase enforces strict separation between layers:
-
Controller Layer (
src/main/java/fun/trackmoney/*/controller/)- REST endpoints with
@RestController - Input validation using Bean Validation
- DTOs for request/response (never expose entities directly)
- HTTP status codes and error handling
- REST endpoints with
-
Service Layer (
src/main/java/fun/trackmoney/*/service/)- Business logic and orchestration
- DTO ↔ Entity conversion using MapStruct mappers
- Transaction management with
@Transactional - Custom exceptions for domain errors
-
Repository Layer (
src/main/java/fun/trackmoney/*/repository/)- Spring Data JPA repositories
- Custom queries using
@Queryor query methods - Database abstraction
-
Entity Layer (
src/main/java/fun/trackmoney/*/entity/)- JPA entities mapped to PostgreSQL tables
- All primary keys use UUID (
@Idwith@GeneratedValue(UUID)) - Relationships between domain objects
Each domain module (account, transaction, budget, etc.) follows this structure:
fun.trackmoney.{domain}/
├── entity/ # JPA entities (database model)
├── repository/ # Spring Data JPA repositories
├── service/ # Business logic + DTO conversion
├── controller/ # REST endpoints
├── mappers/ # MapStruct interfaces (DTO ↔ Entity)
└── dto/ # Request/Response DTOs
Important: Always use DTOs for API operations. Never expose entities directly to controllers.
- DTO Strategy: All API operations use DTOs to decouple domain model from API contracts
- MapStruct: Compile-time mapping for performance (type-safe, no reflection overhead)
- Custom Exceptions: Domain-specific exceptions (not generic RuntimeException)
- JWT Dual-Token: Access token (15 min) + Refresh token (7 days) for security
- Flyway Migrations: Versioned database schema in
src/main/resources/db/migration/
- Access Token: Short-lived (15 minutes), used in all authenticated requests
- Refresh Token: Long-lived (7 days), used only to obtain new access tokens
- Tokens are generated/validated in
auth/infra/jwt/JwtService.java
Not just roles, but fine-grained authorities:
USER_ROLES- Authenticated and verified users (most endpoints)USER_UNVERIFIED- Registered but email not verified (limited endpoints)RESET_PASSWORD- Temporary token for password reset flowREFRESH- Token refresh endpoint only
SecurityConfig.javadefines endpoint protection rules- Swagger is blocked in production (only available in dev profile)
- CORS restricted to authorized frontend domain only
- All password hashing uses BCrypt
- Migrations located in
src/main/resources/db/migration/ - Naming convention:
V{number}__description.sql - All tables use
tb_prefix (e.g.,tb_user,tb_transaction) - All primary keys are UUID type
tb_user- User accounts with email verificationtb_account- Financial accounts (bank, wallet, etc.)tb_transaction- Income and expensestb_category- Transaction categoriestb_budget- Monthly budget limits per categorytb_pots- Savings pots for specific goalstb_recurring- Recurring transaction rules
- Used for frequently accessed data (categories, user settings)
- Spring Cache abstraction with Redis backend
- Application-level caching enabled via
@EnableCaching - Cache configuration in
redis/package
- Unit tests:
*Test.java(use Mockito for dependencies) - Integration tests:
*IntegrationTest.javaor*ControllerTest.java(use@SpringBootTestwith MockMvc) - Test utilities in
src/test/java/fun/trackmoney/testutils/(Factories and Builders) - Coverage requirement: >70% (enforced by JaCoCo)
- Entities and Configs excluded from coverage requirements
Use the Factory/Builder classes in testutils/ for creating test data:
AccountEntity account = AccountFactory.createAccount();
TransactionEntity transaction = TransactionBuilder.aTransaction().withAmount(100.0).build();- Never expose entities directly to controllers - always use DTOs
- Never add validation logic to controllers - it belongs in services or DTOs
- Never use reflection for mapping - use MapStruct mappers
- Never add Swagger without checking profile - blocked in production
- Never commit without running tests - CI will fail anyway
- Always create DTOs for new endpoints
- Always create MapStruct mappers for DTO ↔ Entity conversion
- Always add validation to request DTOs (
@NotNull,@NotBlank, etc.) - Always write tests for new services and controllers
- Always create migrations for schema changes
- Main config:
src/main/resources/application.yaml - Environment-specific:
application-dev.yaml,application-prod.yaml - Environment variables required:
API_SECRET_KEY,POSTGRES_*,SPRING_MAIL_*
- API base path:
/api/v1(configurable viaSERVER_CONTEXT_PATH) - All endpoints are prefixed with this path
- Feature development: Create feature branch from
main - Local testing: Run
./mvnw clean verifybefore committing - Commit: Use conventional commits (
feat:,fix:,refactor:, etc.) - PR: Open pull request to
main(CI runs automatically) - Deploy: Merging to
maintriggers automatic deployment to production
- Active branch:
feat/budget(budget-related features in development) - Recent changes: Budget service updates, report entity removal, new dashboard/metrics features
- Production URL: https://trackmoney.fun
- API Base URL: https://api.trackmoney.fun/api/v1