AI Corporate Travel Reimbursement System cover image
AI/ML

AI Corporate Travel Reimbursement System

The AI Corporate Travel Reimbursement System is a full-stack Spring Boot application for managing employee travel reimbursements.

By aigrama / Pankaj Sonani
#project#ai#ollama

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

BackendDatabaseAIFrontendDevOps / Tooling
Java 21
Spring Boot 3.x
Spring Security
Spring Data JPA
Spring JDBC
Flyway
PostgreSQL
pgvector
Spring AI
Ollama
qwen2.5:7b chat model
nomic-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_URL
  • DB_USER
  • DB_PASSWORD
  • OLLAMA_BASE_URL
  • OLLAMA_CHAT_MODEL
  • OLLAMA_EMBEDDING_MODEL
  • JWT_SECRET
  • RECEIPT_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:

  1. Full Docker Compose run
    Best for first-time setup and easiest reproducibility.

  2. 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-init helper 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/login
  • http://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.sql
  • V2__enable_pgvector.sql
  • V3__core_schema.sql
  • V4__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:

  • controllers
  • services
  • repositories
  • entities
  • dto
  • security
  • ai

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:

  • Dockerfile
  • docker-compose.yml
  • PostgreSQL
  • Ollama
  • app container
  • model bootstrap helper

Security Model

Roles in the system:

  • EMPLOYEE
  • MANAGER
  • FINANCE_ADMIN
  • SYSTEM_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.