# Service Registry

PSR-4 services in src/RPM/ — accessed via rpm_*_service() factory functions

### Usage Guidance

#### Prefer factory functions over duplicating SQL in pages, API controllers, and cron scripts.

Loading order: Site factories → `includes/site-bootstrap.html`. Booking → `includes/booking-bootstrap.html`. Finance/admin/housekeeping → `includes/functions.html`. Encryption → `includes/rpm-encryption-bootstrap.html`.

### Site Services

#### Bootstrap: `includes/site-bootstrap.html`

Factory | Class | Key Methods | API Usage
--- | --- | --- | ---
`rpm_site_settings_service()` | `RPM\Site\SiteSettingsService` | `settings()`, `siteContent()`, `pages()`, `reviews()`, `sliders()`, `navigation()`, `faqs()`, `events()`, `attractions()` | All `site*` REST controllers
`rpm_site_lead_service()` | `RPM\Site\SiteLeadService` | `submitContactMessage()`, `subscribe()` | `siteContact` controller
`rpm_site_blog_service()` | `RPM\Site\BlogService` | `getPost()`, `listPosts()`, `getCategory()`, `listCategories()` | `networkBlog` controller

### Property Catalog

#### Bootstrap: `includes/site-bootstrap.html`

Factory | Class | Key Methods | API Usage
--- | --- | --- | ---
`rpm_property_catalog_service()` | `RPM\Property\CatalogService` | `getPropertyById()`, `listProperties()`, `getImages()`, `getFeaturedImageUrl()`, `pathId()` | `vrProperties`, `ltrProperties` via `ApiPropertyHelper`

### Booking Services

#### Bootstrap: `includes/booking-bootstrap.html`

Factory | Class | Key Methods | API Usage
--- | --- | --- | ---
`rpm_booking_quote_calculator()` | `RPM\Booking\Quote\QuoteCalculator` | `buildQuote()` | `publicBooking/quote`, `book`
`rpm_booking_reservation_service()` | `RPM\Booking\Reservation\ReservationService` | `createReservation()`, `buildApiQuote()` | `publicBooking/book`
`rpm_booking_post_reservation_service()` | `RPM\Booking\Reservation\PostReservationService` | `finalizeBooking()` | `publicBooking/book` (invoice creation)
`rpm_booking_availability_checker()` | `RPM\Booking\Availability\AvailabilityChecker` | Availability validation | Quote flow
`rpm_booking_date_list_builder()` | `RPM\Booking\Availability\DateListBuilder` | `getReservationRanges()`, `getBlockedRanges()` | `publicBooking/calendar`
`rpm_booking_day_price_calculator()` | `RPM\Booking\Pricing\DayPriceCalculator` | `getDayPrice()`, `getDayPricesForRange()` | `publicBooking/calendar`
`rpm_booking_coupon_validator()` | `RPM\Booking\Quote\CouponValidator` | `checkCoupon()`, `checkCouponCode()` | `publicBooking/validateCoupon`
`rpm_booking_property_service()` | `RPM\Booking\Service\PropertyService` | VR property/service lookups | Booking engine
`rpm_booking_mail_service()` | `RPM\Booking\Notification\MailService` | Booking notification email | Post-reservation

### Finance Services

#### Bootstrap: `includes/functions.html`

Factory | Class | Key Methods
--- | --- | ---
`rpm_finance_invoice_service()` | `RPM\Finance\InvoiceService` | `getSubtotal()`, `getTax()`, `getTotal()`, `getTotalPaid()`, `refreshTotals()`, `syncPaymentState()`, `createInvoice()`, `addInvoiceItem()`
`rpm_finance_expense_service()` | `RPM\Finance\ExpenseService` | `adminListExpenses()`, `adminGetExpenseDetail()`, `adminCreateExpense()`, `adminUpdateExpense()`, `adminCancelExpense()`
`rpm_finance_report_service()` | `RPM\Finance\ReportService` | `incomeSummary()`, `occupancySummary()` — admin REST read-only reports
`rpm_finance_payment_service()` | `RPM\Finance\PaymentService` | `deleteTransaction()`, `addInvoicePayment()`, `addExpensePayment()`
`rpm_finance_lookup_service()` | `RPM\Finance\LookupService` | `getTaxRates()`, `getPaymentGateways()`, `getBankAccounts()`, `getGlCodes()`

### Admin Services

Factory | Class | Key Methods
--- | --- | ---
`rpm_admin_tracking_service()` | `RPM\Admin\TrackingService` | `trackPage()`, `updateAdminLastSeen()`, `updateTenantLastSeen()`, `isClockedIn()`, `clockIn()`, `clockOut()`, `hoursWorked()`
`rpm_admin_activity_log_service()` | `RPM\Admin\ActivityLogService` | `log()`
`rpm_admin_tenant_service()` | `RPM\Admin\TenantService` | `listTenants()`, `getTenant()` — admin REST API

Admin REST controllers delegate to catalog, invoice, tenant, reservation, expense, housekeeping, and report services. Authorization: `RPM\Api\AdminAuthGuard` + `RPM\Api\LandlordScope` for landlord read scoping.

### Housekeeping

Factory | Class | Key Methods
--- | --- | ---
`rpm_housekeeping_service()` | `RPM\Housekeeping\Service` | `createRequest()`, `createOwnerRequest()`, `adminListRequests()`, `adminCreateRequest()`, `adminCancelRequest()`

### Security

#### Bootstrap: `includes/rpm-encryption-bootstrap.html`

Factory | Class | Key Methods
--- | --- | ---
`rpm_encryption_service()` | `RPM\Security\EncryptionService` | `encrypt()`, `decrypt()`, `decryptLegacyV1()`, `detectVersion()`, `needsReEncryption()`

### Database & Utilities

Class | Methods | Notes
--- | --- | ---
`RPM\Database\Connection` | `getMysqli()`, `ping()`, `query()`, `prepare()` | Wrapper around mysqli; used by all services
`RPM\Util\ClientHelper` | Static client utilities | —
`RPM\Util\StringHelper` | Static string utilities | —
`RPM\Util\MoneyHelper` | Currency formatting | Use `rpm_money_cmp()` for comparisons

### Legacy Integration Classes

#### Not in PSR-4 registry — located in `includes/`

File | Class | Purpose
--- | --- | ---
`includes/stripe-payment.html` | `StripePaymentService` | PaymentIntent, webhook handling
`includes/stripe-connect.html` | — | Landlord Connect onboarding
`includes/bookingpal/services/*` | BookingPal*Service | Channel manager sync
`includes/quickbooks/services/*` | QuickBooks*Service | Accounting sync
`includes/APIFunctions.html` | — | Outbound calls to external RPM network API

### Coding Standards for API Work

#### From `systemDocuments/myAdmin/coding-standards.md`

Rule | Requirement
--- | ---
Thin controllers | API controllers validate input and delegate to services — no direct SQL
New business logic | Add to `src/RPM/` with factory function in appropriate bootstrap
Database access | Prepared statements for any user input; `rpm_db_fail()` on errors
Output encoding | `htmlspecialchars()` for HTML; `json_encode()` for JSON
Finance invariants | Header totals are denormalized caches; use `rpm_money_cmp()` for currency
CSRF | `rpm_csrf_field()` + `rpm_csrf_require()` on portal POST mutations
REST API CSRF | Not applicable for pure JSON clients without browser cookies. Browser-based API consumers rely on SameSite=Lax session cookies; HTML portal forms use `rpm_csrf` (Stripe uses separate `stripe_csrf`)
HTTPS | Required in production for Secure session cookies. Set `RPM_FORCE_HTTPS=1` in environment for HTTP→HTTPS redirect via root `.htaccess`
Stripe CSRF | Separate namespace via `includes/stripe-csrf.html`
Tenant scoping | `rpm_tenant_page_guard()` and ownership checks before fetch

API gap to fill: There is no OpenAPI/Swagger spec for the main wlRest API yet. This documentation and `website/src/js/api.js` serve as the de-facto contract. Integration guides exist in `systemDocuments/platform/` for Stripe, QuickBooks, and BookingPal.