Skip to content

Latest commit

 

History

History
159 lines (115 loc) · 5.89 KB

File metadata and controls

159 lines (115 loc) · 5.89 KB

CLAUDE.md

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

OpenSpec Instructions

These instructions are for AI assistants working in this project.

Always open @/openspec/AGENTS.md when the request:

  • Mentions planning or proposals (words like proposal, spec, change, plan)
  • Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
  • Sounds ambiguous and you need the authoritative spec before coding

Use @/openspec/AGENTS.md to learn:

  • How to create and apply change proposals
  • Spec format and conventions
  • Project structure and guidelines

Keep this managed block so 'openspec update' can refresh the instructions.

Project Overview

Stable Manager (SM) is an equine care management platform for stables. It tracks horses, health events, vaccinations, worm tests, treatments, and sends automated notifications. Multi-tenant support isolates data per stable.

Tech Stack

  • Backend: Jmix 2.7.1, Spring Boot, Java
  • Frontend: Vaadin 24.9.2 Flow UI (Java-based views)
  • Database: PostgreSQL with EclipseLink ORM
  • Build: Gradle 8.x
  • Scheduling: Quartz for automated jobs
  • File Storage: AWS S3 via jmix-awsfs
  • Notifications: Email (SMTP), SMS (GatewayAPI), In-app

Build & Development Commands

# Development
./gradlew bootRun                    # Run dev server (port 7070)
./gradlew build                      # Full build with tests

# Testing
./gradlew test                       # Run all tests
./gradlew test --tests "ClassName"   # Run single test class
./gradlew test --tests "ClassName.methodName"  # Run single test method

# Frontend
npm install                          # Install frontend dependencies
./gradlew vaadinBuildFrontend        # Build frontend bundle

# Docker (user builds manually - do NOT run bootBuildImage automatically)
./gradlew bootBuildImage --imageName=torbenmerrald/stablemanager:<version>

# Deployment (after user builds and pushes image)
docker push torbenmerrald/stablemanager:<version>
kamal deploy --skip-push --version=<version>

Architecture

Package Structure (src/main/java/dk/merrald/sm/)

  • entity/ - JPA entities with Jmix annotations (42 entities)
  • view/ - Vaadin Flow UI views (76 views)
  • service/ - Business logic layer
  • app/ - Scheduled Quartz jobs and application listeners
  • listener/ - Entity event listeners for cascading updates
  • security/ - Roles and user repository

Core Domain Model

Horse is the central entity, linked to:

  • VaccinePlan / EventVaccination - Vaccination tracking
  • WormTestPlan / EventWormTest - Worm test scheduling
  • TreatmentSchedule / PlannedTreatmentTask - Recurring treatments
  • Event (polymorphic) - EventVet, EventFood, EventHealth, etc.
  • Documents - File attachments in S3

Key Patterns

  1. Multi-Tenant Isolation: All entities use @TenantId. Queries automatically filter by tenant.
  2. Soft Deletes: Use Jmix soft delete patterns. Never hard delete.
  3. Event Listeners: listener/*.java handles cascading updates and denormalization.
  4. Scheduled Jobs: app/*Job.java for reminders, task generation, cache refresh.
  5. Notification System: NotificationHistory prevents duplicate notifications.
  6. Denormalization: Horse entity caches computed fields for performance.

Automated Workflows

Job Purpose
VaccinationReminderJob Sends vaccination due/overdue alerts
WormTestReminderJob Sends worm test reminders
TaskGenerationJob Creates PlannedTreatmentTask from schedules
PassportReminderJob Passport expiry notifications

Skills

Detailed guidance for common patterns is available in .claude/skills/:

  • jmix-soft-deletion - Working with soft-deleted entities
  • jmix-data-loaders - Custom data loading with LoadContext hints
  • jmix-help-dialogs - Info icon buttons with help dialogs
  • jmix-dashboard-cards - Dashboard cards with success/warning states
  • jmix-orchestrator-jobs - Global jobs that orchestrate multiple related jobs
  • vaadin-grid-styling - Dynamic row styling with setPartNameGenerator() and ::part() CSS
  • kamal-deployment - Kamal 2 deployment with pre-deploy backups (user builds images manually)

Critical Constraints

Database Migrations

NEVER auto-generate Liquibase changesets. Use Jmix Studio exclusively for schema changes. See src/main/resources/dk/merrald/sm/liquibase/CLAUDE.md for details.

If database changes are needed:

  1. Stop and inform the user
  2. Ask for guidance on proper workflow
  3. Wait for explicit permission

Multi-Tenant Data

All queries must respect tenant isolation. Never bypass with native queries that skip tenant filtering.

Notification History

Always check NotificationHistory before sending notifications to prevent duplicates.

Testing

  • JUnit 5 with @SpringBootTest for integration tests
  • AuthenticatedAsAdmin extension in test_support/ for system authentication
  • Test classes mirror source structure with Test suffix
  • Run ./gradlew test before pushing

Coding Conventions

  • Java: 4-space indentation, Lombok for DTOs
  • Naming: *Service, *Repository, *View, *Job, *Listener
  • Package-by-domain organization
  • Translations in messages_en.properties and messages_da_DK.properties
  • Commits: conventional style (feat:, fix:, chore:)

Configuration Files

  • application.properties - Base configuration
  • application-dev.properties - Local development (port 7070)
  • application-prod.properties - Production (uses env vars)
  • menu.xml - Application menu structure

Key Environment Variables (Production)

SQL_URL, SQL_USERNAME, SQL_PASSWORD     # Database
S3_BUCKET, S3_ACCESSKEY, S3_SECRET_ACCESSKEY, S3_ENDPOINT  # File storage
SMS_GATEWAYAPI_KEY, SMS_GATEWAYAPI_SECRET  # SMS
OPENAI_API_KEY (optional)               # Document summarization