# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Build
./mvnw clean package

# Run tests (uses H2 in-memory DB via test profile)
./mvnw test

# Run a single test class
./mvnw test -Dtest=ChargebeeServiceTest

# Local development (requires Java 21; loads dev profile + AWS credentials from aws-config/aws-credentials files)
./run.sh

# Local MySQL via Docker (port 3310 → 3306, DB name: billing)
docker-compose up

# OWASP dependency vulnerability scan
./mvnw verify -Pdependency_check

# SonarCloud analysis
./sonar.sh
```

The app runs on port **8094** under the package `io.netfoundry.billing`.

## Architecture

**Stack:** Spring Boot 3.4.5 · Java 21 · Spring Data JDBC (not JPA) · Spring WebFlux (reactive HTTP client only) · MySQL 8.0 · Flyway migrations

### Layer structure

| Layer | Package | Notes |
|-------|---------|-------|
| REST controllers | `controller/` | Inheritance hierarchy: `SubscriptionControllerBase` → `EnterpriseSubscriptionController`, `ChargebeeSubscriptionController`, etc. |
| Domain models | `domain/` | Grouped by sub-domain: `account`, `subscription`, `contract`, `usage`, `overage`, `paymentprofile`, `accounthierarchy`, `rules` |
| Business processes | `process/`, `processor/` | Long-running async processes via NetFoundry process-framework (RabbitMQ executor + Redis tracker + ShedLock distributed locks) |
| External integrations | `external/` | `netsuite/`, `s3/` — each has its own domain models, clients, and process classes |
| Configuration | `config/` | One class per concern: S3, DataSource, RabbitMQ, Elasticsearch, ShedLock, Auth, Secrets Manager |

### Key integrations

- **AWS S3** — stores generated PDF billing reports. `S3Config` builds the client; `S3ReportStorageService` handles uploads. Key format: `billing-reports/{accountId}/{contractId}/{year}/{month}/{fileName}`.
- **AWS Secrets Manager** — runtime credentials for DB, Elasticsearch, Chargebee, email. Secret name: `billing` (region: `us-east-1`).
- **NetSuite** — ERP sync for subscriptions and invoice submission. Controllers: `NetsuiteSubscriptionController`, `NetSuiteUsageReportController`.
- **Chargebee** — SaaS billing provider. Plans: Freemium, Freemium PAYG, Basic, Enterprise, Trial. Toggle: `io.netfoundry.billing.chargebee.active`.
- **Elasticsearch** — usage event source; queried on a 60-minute schedule to aggregate metered usage.
- **RabbitMQ** — process execution backbone (concurrency: 10–50 consumers, prefetch: 1).
- **Redis (Redisson)** — distributed cache + process tracking.

### Report generation

JasperReports 6.20.0 renders JRXML templates to PDF. Reports are stored to S3. The routing between storage backends goes through `ReportStorageRouter` → `ReportStorageService`. New S3 files flow through `UsageReportService` / `UsageReportRepository`.

### Database

Flyway manages schema under `src/main/resources/database/migration/`. Current baseline version: `1.5.5`. C3P0 connection pool. Tests use H2 in-memory with `@ActiveProfiles("test")`.

### Environment profiles

`development`, `staging`, `sandbox`, `production`, `test` — selected via `SPRING_PROFILES_ACTIVE`. The `run.sh` script targets `development` and expects `aws-config` and `aws-credentials` files in the project root.

### Process framework pattern

Long-running work (invoice generation, onboarding, usage submission) is modeled as named processes registered with the internal `process-framework` library. Each process: declares its type, is submitted to RabbitMQ, tracked in Redis, and guarded by a ShedLock to prevent duplicate execution across instances.

## Testing

- Base class: `BaseServiceTest` — full `@SpringBootTest` context with `@ActiveProfiles("test")`, H2 database, embedded Redis, WireMock for HTTP stubs.
- Integration test naming: `*IntegrationTest.java`; unit test naming: `*Test.java`.
- JaCoCo coverage report lands in `target/jacoco-ut/`. Coverage exclusions: `config/`, `external/netsuite/client/`, `CommonExceptionHandler`.
