AI Corporate Travel Reimbursement System
The AI Corporate Travel Reimbursement System is a full-stack Spring Boot application for managing employee travel reimbursements.
The AI Corporate Travel Reimbursement System is a full-stack Spring Boot application for managing employee travel reimbursements with JWT security, approval workflows, receipt processing, and AI-powered extraction, summaries, and fraud checks.
Github Repo: https://github.com/sonani-pankaj/AI-Corporate-Travel-Reimbursement-System
This guide explains:
- what the project does
- how the system is structured
- the project architecture
- how to recreate a similar project from scratch
- how to run this repository locally
- how to verify everything is working
Overview
This project is designed as a corporate reimbursement platform where:
- employees submit travel reimbursement requests
- managers review and approve/reject requests
- finance teams perform additional checks
- AI features help extract receipt data, summarize reimbursements, and flag suspicious claims
It uses a layered Spring Boot architecture with PostgreSQL for persistence and Ollama for local AI model inference.
Tech Stack
| Backend | Database | AI | Frontend | DevOps / Tooling |
|---|---|---|---|---|
| Java 21 Spring Boot 3.x Spring Security Spring Data JPA Spring JDBC Flyway | PostgreSQL pgvector | Spring AI Ollama qwen2.5:7b chat modelnomic-embed-text embedding model | Thymeleaf JavaScript Bootstrap | Gradle Kotlin DSL Docker Docker Compose JUnit Mockito Testcontainers |
What the System Does
At a high level, the application supports:
- user registration and login
- JWT-based authentication
- role-based access control
- reimbursement submission
- approval workflows
- receipt handling
- AI-based receipt extraction
- AI summaries
- AI fraud/similarity checks
- Flyway-managed database schema migrations
Architecture
This project follows a standard layered enterprise architecture:
- Controllers receive HTTP requests
- Services implement business logic
- Repositories talk to the database
- Entities represent persisted domain models
- DTOs define API request/response contracts
- Security protects endpoints and roles
- AI services connect the app to Ollama
- Flyway manages schema evolution
Layered Flow
System Diagram
Project Structure
AI-Corporate-Travel-Reimbursement-System/
├── .github/
│ ├── copilot-instructions.md
│ ├── copilot-memory.md
│ └── workflows/
├── gradle/
├── scripts/
├── src/
│ ├── main/
│ │ ├── java/net/aigrama/travel/reimburse/
│ │ │ ├── ai/
│ │ │ ├── config/
│ │ │ ├── controllers/
│ │ │ ├── dto/
│ │ │ ├── entities/
│ │ │ ├── repositories/
│ │ │ ├── security/
│ │ │ ├── services/
│ │ │ ├── utils/
│ │ │ └── TravelReimbursementApplication.java
│ │ └── resources/
│ │ ├── ai/
│ │ │ └── prompts/
│ │ ├── db/
│ │ │ └── migration/
│ │ ├── static/
│ │ ├── templates/
│ │ ├── application.yml
│ │ └── application-docker.yml
├── .dockerignore
├── .gitignore
├── Dockerfile
├── docker-compose.yml
├── build.gradle.kts
├── settings.gradle.kts
├── row-plan.md
└── README.md
Local Development Prerequisites
Before running the project locally, install:
- JDK 21
- Docker Desktop
- Git
Optional but helpful:
- IntelliJ IDEA
- Postman
- psql client
Step 1: Clone the Repository
git clone https://github.com/sonani-pankaj/AI-Corporate-Travel-Reimbursement-System.git
cd AI-Corporate-Travel-Reimbursement-System
Step 2: Understand the Configuration
The application reads its main configuration from src/main/resources/application.yml.
Important environment variables:
DB_URLDB_USERDB_PASSWORDOLLAMA_BASE_URLOLLAMA_CHAT_MODELOLLAMA_EMBEDDING_MODELJWT_SECRETRECEIPT_STORAGE_DIR
Default local values are already defined, including:
- PostgreSQL on
localhost:5432 - Ollama on
localhost:11434 - app on
localhost:8080
Step 3: Choose How You Want to Run It
You have two good local setup options:
-
Full Docker Compose run
Best for first-time setup and easiest reproducibility. -
Hybrid local run
Run PostgreSQL + Ollama in Docker, but run the Spring Boot app from your IDE or terminal.
Option A: Run Everything with Docker Compose
This is the recommended setup.
3A.1 Start Docker Desktop
Make sure Docker is running before continuing.
3A.2 Copy the environment file if available
If the repo contains .env.example, create a local .env file from it.
Windows PowerShell
Copy-Item .env.example .env
macOS / Linux
cp .env.example .env
3A.3 Start the full stack
docker compose up --build
This will start:
- PostgreSQL with pgvector
- Ollama
- an
ollama-inithelper container to preload models - the Spring Boot app
3A.4 Verify the application health
curl http://localhost:8080/api/health
If healthy, the app is ready.
3A.5 Stop the stack
docker compose down
Option B: Run the App Locally, but Keep Services in Docker
This is ideal for active backend development.
3B.1 Start only PostgreSQL and Ollama
docker compose up postgres ollama ollama-init
3B.2 Run the Spring Boot app locally
Windows PowerShell
.\gradlew.bat bootRun
macOS / Linux
./gradlew bootRun
3B.3 Open the application
Open one of the following in your browser:
http://localhost:8080/loginhttp://localhost:8080/register
Or verify the backend directly:
curl http://localhost:8080/api/health
Docker Services Explained
The docker-compose.yml defines four main services.
1. PostgreSQL
- image:
pgvector/pgvector:pg16 - port:
5432 - stores all application data
2. Ollama
- image:
ollama/ollama:latest - port:
11434 - provides local AI inference
3. Ollama Init
- helper service that loads required AI models before app startup
4. App
- builds and runs the Spring Boot application
- exposed on port
8080
Runtime Architecture Diagram
Step 4: Database Migrations
Flyway runs automatically when the app starts.
Migration files are stored in:
src/main/resources/db/migration/
The repo references migrations such as:
V1__baseline.sqlV2__enable_pgvector.sqlV3__core_schema.sqlV4__refresh_tokens.sql
These migrations create and evolve the schema without relying on Hibernate auto-generation.
Step 5: Build the Project
Windows PowerShell
.\gradlew.bat clean build
macOS / Linux
./gradlew clean build
Step 6: Run Tests
Windows PowerShell
.\gradlew.bat clean test
macOS / Linux
./gradlew clean test
The test suite includes:
- auth service unit tests
- AI fallback behavior tests
- pgvector integration tests using Testcontainers
Note: Testcontainers-based tests require Docker to be running.
Step 7: First-Time API Walkthrough
Once the system is running, you can test the backend with curl.
Register a user
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"firstName":"Jane",
"lastName":"Doe",
"department":"Engineering",
"email":"jane@corp.test",
"password":"Password123"
}'
Login
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"jane@corp.test","password":"Password123"}'
Use the returned token as:
Authorization: Bearer <ACCESS_TOKEN>
Create a reimbursement
curl -X POST http://localhost:8080/api/reimbursements \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"title":"Seattle Customer Visit",
"purpose":"Travel for customer architecture workshop",
"tripStartDate":"2026-05-10",
"tripEndDate":"2026-05-12",
"currency":"USD",
"totalAmount":842.50
}'
Get a reimbursement
curl -X GET http://localhost:8080/api/reimbursements/1 \
-H "Authorization: Bearer <ACCESS_TOKEN>"
Approve or reject as manager
curl -X POST http://localhost:8080/api/reimbursements/1/approve \
-H "Authorization: Bearer <MANAGER_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"decision":"APPROVED","comments":"Looks good"}'
Step 8: Test the AI Endpoints
AI Receipt Extraction
curl -X POST http://localhost:8080/api/ai/extract \
-H "Authorization: Bearer <MANAGER_OR_FINANCE_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"receiptText":"Vendor: Contoso Taxi, Date: 2026-05-10, Total: $42.10"}'
AI Summary
curl -X POST http://localhost:8080/api/ai/summarize \
-H "Authorization: Bearer <MANAGER_OR_FINANCE_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"reimbursementDetails":"3 receipts, total 842.50, customer workshop"}'
AI Fraud Check
curl -X POST http://localhost:8080/api/ai/fraud-check \
-H "Authorization: Bearer <FINANCE_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"entityType":"REIMBURSEMENT",
"entityId":1,
"contentText":"Taxi 42.10, Hotel 700.00, Meals 100.40",
"topK":5
}'
Step 9: Use the Frontend
The application includes Thymeleaf-rendered pages such as:
/login/register/employee/dashboard/employee/submit/employee/upload/manager/review/finance/dashboard/ai/summary-panel
These pages provide the web UI for the reimbursement workflow.
How to Recreate This Project from Scratch
If your goal is not only to run this repository, but to build a similar system yourself, follow this blueprint.
1. Generate a Spring Boot project
Start with:
- Java 21
- Spring Boot
- Gradle Kotlin DSL
Include starters for:
- Web
- Security
- Thymeleaf
- Validation
- JPA
- JDBC
- Actuator
2. Add PostgreSQL and Flyway
Configure PostgreSQL as your main database and use Flyway to version the schema.
3. Organize packages by responsibility
Use a layered structure:
controllersservicesrepositoriesentitiesdtosecurityai
4. Add JWT security
Create:
- login and registration endpoints
- JWT token generation
- authorization filters
- role-based endpoint rules
5. Create reimbursement workflows
Add support for:
- submission
- editing
- ownership checks
- manager approvals
- finance review
- status transitions
6. Add receipt and AI features
Integrate:
- receipt text extraction
- reimbursement summaries
- fraud similarity checks
- prompt templates in resource files
7. Add frontend pages
Use Thymeleaf templates for:
- login/register
- dashboards
- reimbursement forms
- manager/finance review panels
8. Containerize the stack
Add:
Dockerfiledocker-compose.yml- PostgreSQL
- Ollama
- app container
- model bootstrap helper
Security Model
Roles in the system:
EMPLOYEEMANAGERFINANCE_ADMINSYSTEM_ADMIN
The system uses JWT-based authentication with:
- access token expiration:
1 hour - refresh token expiration:
7 days
The repository guidance also emphasizes:
- DTOs at API boundaries
- layered architecture
- ownership checks
- role-specific workflow protection
Common Local Issues
Port already in use
If ports 8080, 5432, or 11434 are busy, stop conflicting services or remap ports.
Docker starts but app fails
Check:
- PostgreSQL container health
- Ollama container health
- model preload completion
- environment variable values
AI endpoints are slow the first time
This is normal if Ollama is still downloading or warming the models.
Testcontainers tests fail
Make sure Docker Desktop is running.
Useful Commands
Build
./gradlew clean build
Run tests
./gradlew clean test
Start full stack
docker compose up --build
Validate compose file
docker compose config
Final Notes
This project is a solid example of how to combine:
- enterprise-style Spring Boot architecture
- secure JWT authentication
- PostgreSQL persistence
- Flyway migrations
- AI integration with local models
- server-rendered frontend pages
It’s especially useful if you want to learn how to build a practical Java business platform with AI capabilities while keeping everything runnable on a local machine.
AI Panel Test Exmples
Create one reimbursement (Employee flow)
Go to Employee -> Submit Reimbursement and use:
Title: NYC Client Workshop Trip
Purpose: Onsite workshop and project kickoff with client finance team
Trip Start Date: 2026-05-12
Trip End Date: 2026-05-14
Currency: USD
Total Amount: 642.30
Add 3 daily expense rows:
Row 1:
Expense Date: 2026-05-12
Category: Hotel
Amount: 420.00
Notes: 2 nights corporate rate
Row 2:
Expense Date: 2026-05-13
Category: Meals
Amount: 96.40
Notes: Client dinner and breakfast
Row 3:
Expense Date: 2026-05-14
Category: Taxi
Amount: 125.90
Notes: Airport transfers and local commute
Submit the reimbursement.
AI Panel test 1: Extract Receipt Data
Paste this into Extract Receipt Data:
Merchant: Midtown Business Hotel
Receipt No: MBH-77842
Date: 2026-05-12
Guest: Alex Johnson
Room Charge: 2 x 190.00 USD = 380.00 USD
City Tax: 28.00 USD
Service Fee: 12.00 USD
Total: 420.00 USD
Payment: Visa **** 4242
Purpose: Client workshop trip
Expected result:
extractedJson includes vendor/date/amount/currency/category/confidence
policyAssessment gives compliance guidance
fallbackUsed should be false when model is healthy
AI Panel test 2: Summarize Reimbursement
Paste this into Summarize Reimbursement:
Employee: Alex Johnson
Department: Sales
Trip: NYC client workshop
Dates: 2026-05-12 to 2026-05-14
Expenses:
Hotel: 420.00 USD
Meals: 96.40 USD
Taxi: 125.90 USD
Total Claimed: 642.30 USD
Business Need:
Conducted onboarding workshop, requirements review, and stakeholder meetings. All expenses are itemized and tied to trip dates.
Expected result:
summary is a concise review-ready narrative
fallbackUsed indicates whether normal model or fallback path was used
AI Panel test 3A: Fraud Check low-risk
Set Entity Type to REIMBURSEMENT, then paste:
Employee: Alex Johnson
Trip: NYC workshop
Dates: 2026-05-12 to 2026-05-14
Claim total: 642.30 USD
Receipts are unique and correspond to trip dates.
No reused invoice IDs.
No prior submission of these receipt numbers.
Expected:
likely flagged: false
moderate/low maxSimilarity
reason says no high-similarity anomaly
AI Panel test 3B: Fraud Check high-risk simulation
Set Entity Type to RECEIPT, then paste:
Merchant: Midtown Business Hotel
Receipt No: MBH-77842
Date: 2026-05-12
Total: 420.00 USD
Card: Visa **** 4242
Warning: This same receipt number, amount, date, and merchant were already submitted in another reimbursement.
Expected:
higher maxSimilarity
may return flagged: true (depends on threshold/history)
matches should show close historical content previews
What to verify in 30 seconds
Access control works: only SYSTEM_ADMIN can use AI APIs.
fallbackUsed is visible for reliability monitoring.
Fraud output includes both score (maxSimilarity) and evidence (matches).
Summary and extraction are usable for manager/finance review notes.
Project Prompts
You are an enterprise implementation agent. Build a production-grade Corporate Travel Reimbursement System in this workspace with strict phased governance, security controls, and validation evidence.
Execution governance:
Ask required clarifying questions before coding each phase.
Implement phase-by-phase only.
Hard stop after each phase for explicit approval.
Never skip tests or validation for changed scope.
Provide evidence after each phase:
Scope completed
Files changed
Commands run
Test results
Risks and deferred items
Architecture and code standards:
Layering: Controllers -> Services -> Repositories
DTO-only API contracts; never expose entities directly
Additive Flyway migrations only; avoid destructive changes
Preserve workflow invariants and ownership checks
Maintain backward compatibility unless explicitly approved
Tech baseline:
Java 21
Spring Boot 3.x
Gradle Kotlin DSL
Spring Security JWT with stateless sessions
Spring Data JPA + JDBC helper for vector similarity
PostgreSQL + pgvector
Flyway migrations
Spring AI + Ollama (chat + embedding models)
Thymeleaf + Bootstrap frontend
Docker + Docker Compose
JUnit + Mockito + Testcontainers
Role and authorization policy:
Roles: EMPLOYEE, MANAGER, FINANCE_ADMIN, SYSTEM_ADMIN
Protect all write endpoints with RBAC checks
Employee may modify only own reimbursement and only in allowed statuses
Manager and finance decisions must operate on assigned/queue workflow, not arbitrary free-form target IDs
Record approval actions and audit events transactionally
Receipt storage policy:
Primary storage: PostgreSQL receipts.content_data (BYTEA)
Keep filesystem fallback read support until explicit full backfill confirmation
Support PDF/JPG/PNG uploads and mobile capture path
Mandatory APIs:
POST /api/auth/register
POST /api/auth/login
POST /api/auth/refresh
POST /api/auth/logout
POST /api/reimbursements
GET /api/reimbursements/{id}
POST /api/reimbursements/{id}/approve
POST /api/reimbursements/{id}/finance-validate
POST /api/ai/extract
POST /api/ai/summarize
POST /api/ai/fraud-check
AI implementation requirements:
Prompt templates in resources:
receipt_extraction_prompt.txt
summary_prompt.txt
fraud_detection_prompt.txt
AI service responsibilities:
receipt entity extraction (vendor, date, amount, category)
manager summary generation
fraud analysis using embedding similarity
Embedding lifecycle:
generate embeddings via Spring AI EmbeddingModel
persist vectors in pgvector-capable table
top-k nearest-neighbor search via SQL/JDBC integration
Resilience:
fallback path for model/embedding failures
explicit fallbackUsed flag in response DTOs
deterministic safe response under AI failure
Database migration baseline:
V1 baseline
V2 pgvector enablement
V3 core schema
V4 refresh tokens
V5 receipt blob storage
Include required indexes, FKs, and constraints
UI requirements:
Pages:
login
register
employee dashboard
submit reimbursement
upload receipts
manager review
finance dashboard
ai summary panel
Enforce role-aware UI rendering and client-side guards
Keep server-side authorization as source of truth
Container requirements:
Multi-stage Dockerfile for app image
docker-compose stack with:
postgres + pgvector
ollama
ollama-init sidecar to pre-pull configured models
app service
Provide environment-driven config defaults and override guidance
Test strategy:
Unit tests:
auth service edge cases
reimbursement workflow transitions
AI fallback behavior
Integration tests:
pgvector storage and nearest-neighbor query behavior
use Testcontainers PostgreSQL image with pgvector support
Ensure tests are runnable in CI and locally
Documentation deliverables:
README including:
architecture ASCII diagram
setup steps
local and Docker runbooks
API quickstart examples
AI endpoint test examples
known gaps and operational notes
Phase plan:
Phase 0 scaffold and dependency baseline
Phase 1 data model and migrations
Phase 2 security/authentication
Phase 3 reimbursement workflows
Phase 4 AI services and vector search
Phase 5 UI and role-aware behavior
Phase 6 containerization
Phase 7 tests and hardening
Phase 8 README and runbook finalization
Begin now with Phase 0 only.
First ask clarifying questions.
Then implement only Phase 0.
Then stop and request approval before Phase 1.