move card issuence server side
This commit is contained in:
181
AGENTS.md
181
AGENTS.md
@@ -1,67 +1,36 @@
|
||||
PROJECT CONTEXT / SYSTEM BRIEF
|
||||
|
||||
This is a hotel-grade Property Management System (PMS) being rebuilt from scratch.
|
||||
This AGENTS file captures the product rules + current codebase state.
|
||||
This AGENTS file captures product rules + current codebase state.
|
||||
|
||||
Tech stack
|
||||
- Spring Boot monolith
|
||||
- Kotlin only
|
||||
- JPA / Hibernate
|
||||
- PostgreSQL
|
||||
- No Flyway for now, schema via JPA during development (Flyway deps present but disabled)
|
||||
- Flyway deps present but disabled (no migrations during dev)
|
||||
- Single API domain api.hoteltrisolaris.in
|
||||
- Android app and future website consume the same APIs
|
||||
Server specs (current)
|
||||
- CPU: i5-8400
|
||||
- RAM: 48 GB
|
||||
- GPU: RTX 3060 (used for llama.cpp)
|
||||
|
||||
Legacy note
|
||||
Old Firestore Android app exists only to understand behavior. Do not reuse old models.
|
||||
Core principles
|
||||
- Server is source of truth; clients send intent.
|
||||
- Ledger-based design: never store totals; append rows only.
|
||||
- Occupancy = RoomStay. Billing = Charge. Payments = Payment. Invoices are derived.
|
||||
- Room availability by room number; toAt=null means occupied.
|
||||
- Room change = close old RoomStay + open new one.
|
||||
- Multi-property: every domain object scoped to property_id.
|
||||
- Users belong to org; access granted per property.
|
||||
|
||||
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
|
||||
|
||||
IMMUTABLE RULES
|
||||
- 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.
|
||||
- Canonical staff roles: ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE (other roles may exist but must not be depended on)
|
||||
- Booking is a lifecycle container only. Booking does not own rooms or money. Occupancy via RoomStay. Billing via Charge/Payment ledgers.
|
||||
- Realtime must emit derived events only (no raw entity subscriptions)
|
||||
- Ask before touching auth or payment logic
|
||||
Immutable rules
|
||||
- Use Kotlin only; no microservices.
|
||||
- Flyway must remain disabled until schema stabilizes.
|
||||
- Canonical staff roles: ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE.
|
||||
- Booking does not own rooms or money.
|
||||
- Realtime events must be derived, not raw DB changes.
|
||||
- Ask before touching auth or payment logic.
|
||||
|
||||
===============================================================================
|
||||
CURRENT CODEBASE UNDERSTANDING (TrisolarisServer)
|
||||
@@ -73,72 +42,94 @@ Repository
|
||||
- Scheduling enabled (@EnableScheduling)
|
||||
|
||||
Security/Auth
|
||||
- Firebase Admin auth for every request, Firebase UID required.
|
||||
- Security filter verifies token and maps to MyPrincipal(userId, firebaseUid).
|
||||
- Endpoints: /auth/verify and /auth/me.
|
||||
- Firebase Admin auth for every request; Firebase UID required.
|
||||
- /auth/verify and /auth/me.
|
||||
|
||||
Domain entities
|
||||
- Organization: id, name, emailAliases
|
||||
- Property: org, code, name, addressText, timezone, currency, active, emailAddresses, otaAliases
|
||||
- AppUser: org, firebaseUid, phoneE164, name, disabled
|
||||
- PropertyUser: roles per property
|
||||
- Role enum includes ADMIN, MANAGER, STAFF, HOUSEKEEPING, FINANCE, GUIDE, SUPERVISOR, AGENT (but only canonical roles should be used)
|
||||
- RoomType: code/name/occupancy + otaAliases
|
||||
- Room: roomNumber, floor, hasNfc, active, maintenance, notes
|
||||
- Booking: status, source/sourceBookingId, expected check-in/out, emailAuditPdfUrl
|
||||
- Guest
|
||||
- RoomStay
|
||||
- GuestDocument: files for guest/booking with AI-extracted data
|
||||
- InboundEmail: inbound mail audit (PDF + raw eml), extractedData, status
|
||||
|
||||
Repos
|
||||
- Repos are under com.android.trisolarisserver.repo (note: not db.repo).
|
||||
- Added repos for Booking, Guest, GuestDocument, InboundEmail.
|
||||
- Organization: name, emailAliases, allowedTransportModes.
|
||||
- Property: code, name, addressText, emailAddresses, otaAliases, allowedTransportModes.
|
||||
- AppUser, PropertyUser (roles per property).
|
||||
- RoomType: code/name/occupancy + otaAliases.
|
||||
- Room: roomNumber, floor, hasNfc, active, maintenance, notes.
|
||||
- Booking: status, expected check-in/out, emailAuditPdfUrl, transportMode, transportVehicleNumber.
|
||||
- Guest (org-scoped).
|
||||
- RoomStay.
|
||||
- RoomStayChange (idempotent room move).
|
||||
- IssuedCard (cardId, cardIndex, issuedAt, expiresAt, issuedBy, revokedAt).
|
||||
- PropertyCardCounter (per-property cardIndex counter).
|
||||
- GuestDocument (files + AI-extracted json).
|
||||
- GuestVehicle (org-scoped vehicle numbers).
|
||||
- InboundEmail (audit PDF + raw EML, extracted json, status).
|
||||
- RoomImage (original + thumbnail).
|
||||
|
||||
Key modules
|
||||
|
||||
Rooms / inventory
|
||||
- /properties/{propertyId}/rooms
|
||||
- /properties/{propertyId}/rooms/board
|
||||
- /properties/{propertyId}/rooms/board/stream (SSE)
|
||||
- /properties/{propertyId}/rooms/availability
|
||||
- /properties/{propertyId}/rooms/availability-range?from=YYYY-MM-DD&to=YYYY-MM-DD
|
||||
Availability derived from RoomStay. Date range uses overlap [from, to).
|
||||
|
||||
Room types
|
||||
- CRUD with otaAliases in DTOs.
|
||||
- CRUD with otaAliases.
|
||||
|
||||
Properties/Orgs
|
||||
- Property create/update accept addressText, otaAliases, emailAddresses.
|
||||
- Org create/get returns emailAliases.
|
||||
Properties / Orgs
|
||||
- Property create/update accepts addressText, otaAliases, emailAddresses, allowedTransportModes.
|
||||
- Org create/get returns emailAliases + allowedTransportModes.
|
||||
|
||||
Guest documents (files)
|
||||
- POST /properties/{propertyId}/guests/{guestId}/documents (multipart + bookingId)
|
||||
- GET list
|
||||
- GET file (token or auth)
|
||||
- Files stored under /home/androidlover5842/docs/{propertyId}/{guestId}/{bookingId}/
|
||||
- AI extraction via llama.cpp with strict system prompt
|
||||
Booking flow
|
||||
- /bookings/{id}/check-in (creates RoomStay rows)
|
||||
- /bookings/{id}/check-out (closes RoomStay)
|
||||
- /bookings/{id}/cancel, /no-show
|
||||
- /bookings/{id}/room-stays (pre-assign RoomStay with date range)
|
||||
- /room-stays/{id}/change-room (idempotent via RoomStayChange)
|
||||
|
||||
Card issuing
|
||||
- /room-stays/{id}/cards/prepare -> returns cardIndex + sector0 payload
|
||||
- /room-stays/{id}/cards -> store issued card
|
||||
- /room-stays/{id}/cards (list)
|
||||
- /room-stays/cards/{id}/revoke (ADMIN only)
|
||||
|
||||
Guest APIs
|
||||
- /properties/{propertyId}/guests/search?phone=... or ?vehicleNumber=...
|
||||
- /properties/{propertyId}/guests/{guestId}/vehicles (add vehicle)
|
||||
|
||||
Guest documents
|
||||
- /properties/{propertyId}/guests/{guestId}/documents (upload/list/file)
|
||||
- AI extraction with strict system prompt.
|
||||
|
||||
Room images
|
||||
- /properties/{propertyId}/rooms/{roomId}/images (upload/list/file)
|
||||
- Thumbnails generated (320px).
|
||||
|
||||
Transport modes
|
||||
- /properties/{propertyId}/transport-modes -> returns enabled list (property > org > default all).
|
||||
|
||||
Inbound email ingestion
|
||||
- IMAP poller (1 min) with enable flag.
|
||||
- Saves audit PDF + raw .eml to /home/androidlover5842/docs/emails
|
||||
- Matches property via To/CC email first, then text aliases (name/code/address/otaAliases)
|
||||
- AI extracts booking fields and creates/cancels Booking
|
||||
- Booking gets emailAuditPdfUrl that points to /properties/{propertyId}/inbound-emails/{emailId}/file
|
||||
- Saves audit PDF + raw .eml under /home/androidlover5842/docs/emails.
|
||||
- Property match: To/CC email first; fallback to name/code/address/otaAliases.
|
||||
- AI extracts booking fields; creates/cancels Booking.
|
||||
- Booking emailAuditPdfUrl -> /properties/{propertyId}/inbound-emails/{emailId}/file
|
||||
- Manual upload: POST /properties/{propertyId}/inbound-emails/manual (PDF).
|
||||
|
||||
Realtime
|
||||
- SSE room board events with heartbeat, on room create/update, check-in/out, and room change.
|
||||
|
||||
AI integration
|
||||
- Base URL configured per profile:
|
||||
- dev: https://ai.hoteltrisolaris.in/v1/chat/completions
|
||||
- prod: http://localhost:8089/v1/chat/completions
|
||||
- LlamaClient uses strict system prompt: only visible text, no guessing.
|
||||
- Base URL per profile: dev=https://ai.hoteltrisolaris.in/v1/chat/completions, prod=http://localhost:8089/v1/chat/completions
|
||||
- LlamaClient uses strict system prompt (no guessing).
|
||||
- Read timeout 5 minutes.
|
||||
|
||||
Config
|
||||
- application.properties: flyway disabled, storage paths, IMAP config, token secrets.
|
||||
- storage.documents.publicBaseUrl + token secret/ttl.
|
||||
- storage.emails.publicBaseUrl used for booking audit URL.
|
||||
- mail.imap.enabled=false by default.
|
||||
- storage.documents.root=/home/androidlover5842/docs
|
||||
- storage.emails.root=/home/androidlover5842/docs/emails
|
||||
- storage.rooms.root=/home/androidlover5842/docs/rooms
|
||||
- publicBaseUrl entries for docs/emails/rooms
|
||||
- mail.imap.enabled=false by default
|
||||
|
||||
Notes / constraints
|
||||
- API user creation removed; users are created by app; API only manages roles.
|
||||
- Users are created by app; API only manages roles.
|
||||
- Admin can assign ADMIN/MANAGER/STAFF/AGENT; Manager can assign STAFF/AGENT.
|
||||
- Agents can only see free rooms.
|
||||
|
||||
Reference in New Issue
Block a user