feat: per-operator settings — house rules + card acceptance (multi-tenant)
Chatelet is multi-tenant: any LNbits user can host rooms. What an operator decides for all their rooms now lives in chatelet.operator_settings, keyed by user id and created lazily (m003, which also indexes bookings by guest): check-in/out times, cancellation policy, and accept_fiat. Guests see it: the public room view (both doors) gains house_rules and payment_methods, and the kind:30402 listing carries payment_methods, checkin_time and checkout_time tags so a generic Nostr client can render the right pay buttons and rules without our RPC. The check-in DM reads the room owner's rules instead of the instance row. Card is offered only when the operator opted in, the room is fiat-priced, and LNbits core has a fiat provider for that user — resolved through settings.get_fiat_providers_for_user(owner), the one seam lnbits#67's per-user Stripe credentials will plug into; chatelet never sees creds. Operator endpoints: GET/PUT /api/v1/operator (admin key → wallet user) and RPC twins chatelet_operator_get/update (AUTH_WALLET); saving re-publishes the owner's active listings. Admin UI moves the house-rule inputs into a per-operator card with the card toggle and a provider hint. The old house-rule columns on settings stay for old rows but are no longer read. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
feaaef93e3
commit
9ab52f2c69
17 changed files with 531 additions and 42 deletions
|
|
@ -18,15 +18,30 @@ from .kinds import (
|
|||
)
|
||||
|
||||
|
||||
def build_listing_event(room: Room) -> dict:
|
||||
def build_listing_event(
|
||||
room: Room,
|
||||
*,
|
||||
payment_methods: list[str] | None = None,
|
||||
house_rules: dict | None = None,
|
||||
) -> dict:
|
||||
"""NIP-99 kind:30402 classified listing for a room. Public, signed by
|
||||
the operator's identity. `d` == room.id so re-publishing replaces."""
|
||||
the operator's identity. `d` == room.id so re-publishing replaces.
|
||||
|
||||
`payment_methods` (comma-joined, like events' tickets_payment_methods) and
|
||||
the check-in/out times ride as tags so a generic Nostr client can render
|
||||
the right pay buttons and house rules without speaking our RPC."""
|
||||
tags = [
|
||||
["d", room.id],
|
||||
["title", room.title],
|
||||
["price", str(room.price_amount), room.price_currency, room.price_frequency],
|
||||
["status", "active"],
|
||||
]
|
||||
if payment_methods:
|
||||
tags.append(["payment_methods", ",".join(payment_methods)])
|
||||
if house_rules:
|
||||
for key in ("checkin_time", "checkout_time"):
|
||||
if house_rules.get(key):
|
||||
tags.append([key, str(house_rules[key])])
|
||||
if room.location:
|
||||
tags.append(["location", room.location])
|
||||
if room.geohash:
|
||||
|
|
|
|||
|
|
@ -160,8 +160,17 @@ def _checkin_message(booking, room, settings) -> str:
|
|||
|
||||
|
||||
async def publish_listing(room: Room) -> str | None:
|
||||
"""Publish/refresh a room's NIP-99 kind:30402 listing (public)."""
|
||||
return await _sign_and_publish(events.build_listing_event(room))
|
||||
"""Publish/refresh a room's NIP-99 kind:30402 listing (public), carrying
|
||||
the owner's rails + house rules so the event matches the API view."""
|
||||
owner = await services.room_owner_id(room)
|
||||
ops = await crud.get_or_create_operator_settings(owner)
|
||||
return await _sign_and_publish(
|
||||
events.build_listing_event(
|
||||
room,
|
||||
payment_methods=services.payment_methods_for_room(room, owner, ops),
|
||||
house_rules=services.house_rules_dict(ops),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def publish_reservation(booking: Booking) -> str | None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue