Skip to content

Issue #4 — Booking Creation with Payment #601

@yusuftomilola

Description

@yusuftomilola

The core feature of the contract is book_workspace — a member selects a workspace, picks a time slot, pays the computed fee, and the contract records the booking. This issue also adds the three booking query functions.

Task

Building on Issue #3, add:

  1. pub fn book_workspace(env, member, booking_id, workspace_id, start_time, end_time) -> Result<(), Error>

    • Call member.require_auth().
    • Return Error::BookingAlreadyExists if DataKey::Booking(booking_id.clone()) already exists.
    • Validate time range: start_time >= end_time || end_time <= nowError::InvalidTimeRange.
    • Load workspace, return Error::WorkspaceNotFound if absent.
    • Return Error::WorkspaceUnavailable if !workspace.is_available.
    • Call Self::is_slot_available(...) → return Error::BookingConflict if false.
    • Compute cost: hourly_rate × ⌈(end_time - start_time) / 3600⌉ using div_ceil(3600).
    • Transfer payment from member to contract using token::Client::new(&env, &payment_token).transfer(&member, env.current_contract_address(), &amount).
    • Build Booking struct and save to DataKey::Booking(booking_id.clone()) in persistent storage.
    • Append booking_id to DataKey::WorkspaceBookings(workspace_id.clone()) in persistent storage.
    • Append booking_id to DataKey::MemberBookings(member.clone()) in persistent storage.
    • Emit event: topic (symbol_short!("booked"), booking_id), data (member, workspace_id, start_time, end_time, amount).
  2. pub fn get_booking(env: Env, booking_id: String) -> Result<Booking, Error>

    • Read DataKey::Booking(booking_id) from persistent storage, return Error::BookingNotFound if absent.
  3. pub fn get_member_bookings(env: Env, member: Address) -> Vec<String>

    • Read DataKey::MemberBookings(member) from persistent storage, return empty Vec if absent.
  4. pub fn get_workspace_bookings(env: Env, workspace_id: String) -> Vec<String>

    • Read DataKey::WorkspaceBookings(workspace_id) from persistent storage, return empty Vec if absent.

Files to modify

  • contracts/workspace_booking/src/lib.rs

Acceptance criteria

  • cargo check -p workspace_booking and cargo clippy -p workspace_booking -- -D warnings pass.
  • A successful booking transfers tokens from the member to the contract.
  • Cost rounds up to the nearest full hour (e.g., 90-minute booking = 2 hours of payment).
  • Overlapping bookings are rejected with Error(Contract, #6) (BookingConflict).
  • Booking an unavailable workspace returns Error(Contract, #5) (WorkspaceUnavailable).
  • get_member_bookings and get_workspace_bookings return the correct IDs after booking.
  • Duplicate booking_id returns Error(Contract, #8) (BookingAlreadyExists).

Technical notes

  • Use duration_secs.div_ceil(3600) — do not use (duration_secs + 3599) / 3600 (triggers manual_div_ceil clippy lint).
  • Token transfer: from takes &Address, to takes an owned Address (env.current_contract_address() — no &).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions