Data Models
Complete entity documentation with fields, relationships, and embedded business logic.
Entity Relationship Overview
Core Entities
User
Members and staff of the coworking platform
Key fields:
- name, email (unique)
- organisation_id (FK → Organisation)
- location_id (FK → Location)
- membership_id (FK → Membership)
- space_id (FK → Space)
- status (active/inactive)
- password, pin, card
- wifi_username, wifi_password
- papercut_username
- checked_in, last_checkin
- clay_access_group_ids (array)
- img (avatar with base64 support)
Hooks: Pre-validate ensures unique emails. Pre-save handles base64 image uploads. Post-validate creates audit logs via Log model. Auto-populates Membership and Organisation on queries.
Organisation
Companies/entities renting coworking space
Key fields:
- name (unique), short_name
- status (active/inactive/prospect/pending/offboarded/declined/abandoned)
- user_id (primary member/owner)
- location_id, membership_id
- currency (default ZAR)
- discount, discount_expires
- escalation_percentage, escalation_date
- space_credits_per_month_override
- xero_id, xeroorgaccount_id
- allowed_payments (array → PaymentMethod)
- type (member/gallery/events/partner)
- vat, company_registration_number
Hooks: Pre-save checks ownership permissions. Auto-adds default payment methods. Post-save updates monthly quotas via job queue when primary member changes. getFull() method populates licenses, line items, and adhoc items.
Location
Physical coworking spaces/offices
Key fields:
- name, short_name, urlid
- address, city, suburb
- latitude, longitude
- timezone, timezone_offset
- community_manager_name/email/tel
- contract_template, proposal_template
- xero_tenant_id, xero_tracking_name
- deposit_product_id
- sublocations (array)
- matrix_room
Hooks: Pre-save calculates timezone offset. Validates phone format.
Space Management
Space
Physical areas/sections within locations (collection of rooms)
Key fields: name, spacetype_id, room_id[], claylock_id[], location_id
Computed: total_value, meters_squared, seats — calculated from associated rooms post-query.
Room
Bookable spaces (meeting rooms, offices, desks)
Key fields:
- name, location_id
- type[] (meeting/event/office/hot_desk/dedicated_desk/lobby/circulation/create/vc)
- capacity, number_available
- cost, off_peak_cost
- price_per_day, price_per_room
- half_day_discount, full_day_discount
- private (access control)
- organisation_id[] (allowed orgs)
- external_ical
Booking & Presence
Booking
Room/space reservations
Key fields:
- room_id, start_time, end_time
- title, user_id
- attendee_id[], guest_id[]
- external_attendee[] (emails)
- cost
- public_event, sponsored_event
- is_invoice, invoice_id
- timezone, timezone_offset
Hooks: Pre-save pins times to room slots, checks for conflicts, validates start < end, applies app discount, creates ledger reserve. Post-remove deletes reserve. Static find_available() finds rooms with access control and cost calculation.
Checkin
Presence/access tracking
Key fields: user_id or guest_id, location_id, state (checkin/checkout), timestamp, temperature
Hooks: Pre-validate prevents duplicate state. Post-save updates User with checked_in status.
DeskBooking
Half-day desk reservations
Key fields: location_id, user_id[], date, period (morning/afternoon)
Membership & Licensing
Membership
Membership types/plans available at locations
Key fields:
- name, location_id
- occupancy_type (hotdesk/dedicated_desk/dedicated_office/occasional)
- cost, cost_extra_member
- space_credits_per_month
- stuff_credits_per_month
- print_credits_per_month
- radius_service, papercut_group
- clay_access_group
License
Membership instance binding user to org at a location
Key fields:
- membership_id, organisation_id, user_id
- location_id, space_id
- date_start, date_end
- price, amount
- discount, discount_date_start/end
Virtual: status (pending/current/expired) computed from dates.
Hooks: Post-find auto-applies discounts. Pre-save validates dates, keeps user in sync with license location/membership/space, manages discount CRUD.
Billing & Financial
Invoice
Billing documents for organisations
Key fields:
- invoice_number, status
- sub_total, tax, total
- amount_due, amount_paid
- organisation_id, location_id
- source (ecommerce/subscription/adhoc/bulk)
- xero_invoice_id
- accSyncStatus (pending/syncing/synced/error)
- fulfilled, fulfillment_data[]
- payment_link, payment_result
Hooks: Pre-save normalizes status, auto-fills location from org, validates accounting fields. Post-save triggers fulfillment job when AUTHORISED/PAID.
LineItem
Recurring charges on invoices (from licenses, products, bookings)
Key fields: amount, price, description, date_start/end, product_id, license_id, booking_id, pro_rata, discount
Hooks: Pre-save syncs product properties, manages discounts, detects price customization. Static helpers find bad product/license line items.
Ledger
Financial transaction ledger for wallet/credit tracking
Most complex model in the system
Key fields:
- user_id, organisation_id
- amount (+/- for credit/debit)
- wallet_id[], wallet_split[]
- transaction_type (credit/debit/reserve/quota)
- cred_type (space/stuff/parking)
- reserve, reserve_expires
- source_type, source_id
Business logic (pre-save):
- Auto-derives currency from wallet or cred_type
- Validates organisation is active
- Permission checks: only admins can credit
- Validates sufficient funds with overflow/parking logic
- Builds wallet_split for debits (priority-based deduction)
- For credits, splits into single target wallet
Cron: Converts expired reserves to debits every 60 seconds.
Statics: transfer() (inter-user), confirm_reserve(), report() (analytics)
Wallet
Credit/debit sub-accounts per user per currency type
Key fields: name, user_id[], currency_id, balance, priority, quota_frequency, quota_amount, quota_type (free/post-paid/pre-paid), overflow, overflow_to, parking
Statics: topup_daily(), topup_weekly(), topup_monthly(), topup_annually()
Balance
Cached summary balance per user per credit type
Key fields: user_id, cred_type, balance
Statics: update_balance() recalculates from wallets. get_user_balances() complex aggregation for user lists.
Payment
Payment records for invoices
Key fields: date, amount, reference, status, payment_method, is_reconciled, invoice_id, currency_code
Discount
Discount rules by org, line item, license, or product type
Key fields: discount (0-100%), apply_to[] (product/license/booking/all), date_start/end, organisation_id, lineitem_id, license_id
Sales Pipeline
Lead
Prospective customers
Key fields: name, email, mobile, organisation, location_id, heat (hot/mild/cold), seats, referral_user_id, spam
Hooks: Pre-save validates reCAPTCHA, blocks .ru emails as spam, integrates with Unikey, supports multi-instance federation.
Opportunity
Sales opportunities from leads
Key fields: name, lead_id, track_id, user_id, value, probability, completed, abandoned
Hooks: Pre-save auto-creates task tree from Track template. Post-save updates Lead's opportunity array. Processes referral rewards via Ledger.
Task
Sales follow-up tasks within opportunities
Key fields: name, category (init/call/email/follow_up/meeting/milestone/site_visit), opportunity_id, due_date, due_after_task_id, completed
Hooks: Pre-save calculates due dates from parent tasks (chain support). Post-save cascades updates to child tasks.
Contact
Unified contact record aggregating Users, Guests, and Leads
Key fields: email, name, user_id, guest_id, lead_id[], notes[]
Static: populate() builds Contact records from all three sources.
Supporting Models
| Model | Purpose |
|---|---|
Product | Purchasable goods/services with pricing, frequency, and Xero codes |
ProductType | Product categories |
SpaceType | Space classifications |
Currency | Currency definitions (ZAR, USD, etc.) |
IndustrySector | Industry classifications for organisations |
Log | Audit log (entity changes tracked via deep-diff) |
Tag | User tagging system |
Guest | Visitor records with check-in data |
Contract | Contractual agreements |
Proposal | Sales proposals |
ParkingCenter | Parking facility with bay counts and pricing |
ParkingTenant | Org-level parking bay allocation |
ParkingUser | User parking credentials (Admyt link) |
Notification | Parking entry/exit events with license plates |
Notice / NoticeUser | System notifications to users |
MailTemplate | Email templates (Handlebars) |
InstanceSettings | Dynamic system configuration |
Schedule | Cron schedule records (action, repeat, status) |
ApiKey / Token / RefreshToken | API authentication |
XeroAccount / XeroOrgAccount | Xero account mappings |
ClayLock / ClayAccessGroup / ClayTag | Smart lock access control |
PayFastToken | Stored PayFast payment tokens |
RadAcct | RADIUS accounting (WiFi) |