From c360ff627df5d4ecbd813ee6d31eb77ac3a610a7 Mon Sep 17 00:00:00 2001 From: androidlover5842 Date: Sat, 24 Jan 2026 15:10:44 +0530 Subject: [PATCH] vibes --- AGENTS.md | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..82eea27 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,247 @@ +PROJECT CONTEXT / SYSTEM BRIEF + +This is a hotel-grade Property Management System (PMS) being rebuilt from scratch. +This AGENTS file captures both the product rules you gave and my current understanding of +the TrisolarisServer codebase as of the last read, so future sessions can resume accurately. + +Tech stack +- Spring Boot monolith +- Kotlin only +- JPA / Hibernate +- PostgreSQL +- No Flyway for now, schema via JPA during development (Flyway is present in deps but disabled) +- Single API domain api.hoteltrisolaris.in +- Android app and future website consume the same APIs + +This replaces a very old Firestore-based Android app. Old code exists only to understand behaviour. Do not reuse or mirror old models. + +CORE DESIGN PRINCIPLES + +Server is the only source of truth +Clients never calculate state +Clients send intent, server derives facts + +Ledger-based design +Never store totals +Never overwrite money +Append rows and derive views + +Three independent concerns +Occupancy handled by RoomStay +Charges handled by Charge +Payments handled by Payment +Invoices are derived views, not stored state + +Room availability is by room number +Availability is derived from RoomStay +toAt = null means occupied +Category counts are only summaries + +Room changes must never break billing +Changing rooms means closing one RoomStay and opening another +Charges are time-bound and linked to booking, optionally to room_stay + +Multi-property from day one +Every domain object is scoped to property_id +Users belong to organization +Access is granted per property + +Auth and access +User exists once as AppUser +Property access via PropertyUser +Roles are per property +Every API call must enforce property membership + +CURRENT DOMAIN MODEL ALREADY CREATED + +Organization +Property +AppUser +PropertyUser with roles +RoomType +Room +Booking +Guest +RoomStay + +These entities already exist in Kotlin. Do not redesign unless explicitly asked. + +WHAT THE SYSTEM MUST SUPPORT + +Operational behaviour +- Staff sees exact room numbers free, occupied, checkout today +- Different rates for same room type +- Multiple rooms today and fewer tomorrow under the same booking +- Room changes without data loss + +Financial behaviour +- Advance payments, partial payments, refunds +- PayU integration for QR and payment links +- Payment status via webhooks +- Clear source and destination of money +- Staff-wise collection tracking + +Website integration +- Website reads live availability from PMS +- Website creates booking intents +- No inventory sync jobs +- Rate plans like DIRECT, WALKIN, OTA are snapshotted at booking time + +Realtime +- Firestore-like realtime behaviour +- WebSocket or SSE for room board and payment updates +- Push notifications later via FCM + +Infrastructure +- Nginx reverse proxy +- Single domain with multiple paths +- Database is never exposed publicly + +IMPORTANT RULES FOR YOU + +- Use Kotlin only +- Follow existing package structure +- No speculative features +- No premature microservices +- Flyway must remain disabled during development. Do not introduce or modify Flyway migrations unless explicitly instructed after schema stabilization. +- Propose schema or API changes before coding if unsure +- Money logic must be explicit and auditable +- Canonical staff roles for now are ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE. Other roles may exist later but must not be depended on unless asked. +- Booking is a lifecycle container only. Booking does not own rooms or money. Occupancy is only via RoomStay. Billing is only via Charge and Payment ledgers. +- Realtime features must emit derived domain events only. Clients must never subscribe to raw entity state or database changes. + +HOW YOU SHOULD WORK + +- Read the entire repository before making changes +- Work file by file +- Prefer small focused changes +- Ask before touching auth or payment logic +- Assume this will run in real production hotels + +FIRST TASK + +Do nothing until asked. +Likely upcoming tasks include room board API, charge ledger, payment and PayU webhook flow, booking check-in transaction. + +=============================================================================== +CURRENT CODEBASE UNDERSTANDING (TrisolarisServer) +=============================================================================== + +Repository +- Root: /home/androidlover5842/IdeaProjects/TrisolarisServer +- Language: Kotlin only (Spring Boot 4, JPA) +- Entry point: src/main/kotlin/com/android/trisolarisserver/TrisolarisServerApplication.kt +- Active controller layer is minimal (Rooms.kt is stubbed/commented) + +Gradle +- build.gradle.kts uses: + - Spring Boot 4.0.1 + - Kotlin 2.2.21 (kotlin("jvm"), kotlin("plugin.spring"), kotlin("plugin.jpa")) + - Java toolchain 19 + - JPA, WebMVC, Validation, Security, WebSocket, Flyway (dep), Postgres +- Flyway is disabled in application.properties + +Configuration +- src/main/resources/application.properties + - spring.jpa.hibernate.ddl-auto=update + - spring.jpa.open-in-view=false + - flyway.enabled=false +- application-dev.properties -> jdbc:postgresql://192.168.1.53:5432/trisolaris +- application-prod.properties -> jdbc:postgresql://localhost:5432/trisolaris +- DB password via env: DB_PASSWORD + +Current packages and code + +com.android.trisolarisserver.component +- PropertyAccess + - requireMember(propertyId, userId) -> checks PropertyUserRepo + - requireAnyRole(propertyId, userId, roles) -> checks roles + +com.android.trisolarisserver.db.repo +- PropertyUserRepo + - existsByIdPropertyIdAndIdUserId(...) + - hasAnyRole(...) via JPQL joining property_user_role +- RoomRepo + - findFreeRooms(propertyId): active, not maintenance, no open RoomStay + - findOccupiedRooms(propertyId): rooms with active RoomStay + +com.android.trisolarisserver.controller +- Rooms.kt: placeholder, no active endpoints yet + +Entity model (current Kotlin entities) +- Organization + - id (uuid), name, createdAt +- Property + - id (uuid) + - org (Organization) + - code, name, timezone, currency + - active, createdAt +- AppUser + - id (uuid) + - org (Organization) + - firebaseUid, phoneE164, name + - disabled, createdAt +- PropertyUser + - composite key PropertyUserId (propertyId, userId) + - property (Property), user (AppUser) + - roles (ElementCollection of Role) +- Role enum + - ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE, GUIDE, SUPERVISOR, AGENT +- RoomType + - id (uuid) + - property (Property) + - code, name, baseOccupancy, maxOccupancy, createdAt +- Room + - id (uuid) + - property (Property) + - roomType (RoomType) + - roomNumber, floor + - hasNfc, active, maintenance, notes +- Booking + - id (uuid) + - property (Property) + - primaryGuest (Guest) + - status (BookingStatus) + - source, sourceBookingId + - checkinAt, checkoutAt + - expectedCheckinAt, expectedCheckoutAt + - notes + - createdBy (AppUser) + - createdAt, updatedAt +- BookingStatus enum + - OPEN, CHECKED_IN, CHECKED_OUT, CANCELLED, NO_SHOW +- Guest + - id (uuid) + - org (Organization) + - phoneE164, name, nationality + - addressText + - createdAt, updatedAt +- RoomStay + - id (uuid) + - property (Property) + - booking (Booking) + - room (Room) + - fromAt, toAt (null = active occupancy) + - createdBy (AppUser) + - createdAt + +Notes on schema vs migration file +- There is a Flyway migration file at src/main/resources/db/migration/V1__core.sql, + but Flyway is disabled. The SQL file does NOT match current Kotlin entities in + multiple places (columns and tables differ). For now, JPA schema generation is + authoritative during development. + +Gaps relative to target design (do not implement unless asked) +- No Charge entity yet +- No Payment entity yet +- No ledger/derived views +- No API controllers/services for bookings, rooms, payments +- No auth filter or principal model wired (PropertyAccess expects userId) +- No WebSocket/SSE endpoints yet + +Behavioral requirements to keep in mind when coding +- Every domain object must include property scope +- Room availability derived from RoomStay toAt == null +- Room changes are new RoomStay + closing old +- Charges and payments are append-only (never overwrite totals) +- Clients send intent; server derives facts