📄 System Overview Document

TIP TOP - System Architecture & Technical Overview

Version: 2026-05-19

Purpose: Reference document for safe, accurate, and fast future development

Status: Production system — read this before touching anything


1. System Purpose

What the Platform Does

TIP TOP is an event management platform for an Israeli event management company ("TIP TOP - ניהול אירועים"). It manages the full lifecycle of an event: from first client inquiry → quotation → signing → payment → event preparation → supplier management → post-event receipts and client portal access.

Main Business Goals

  • Allow staff to create and manage quotations, events, clients, ushers, and receipts
  • Give clients a secure self-service portal to sign contracts, complete tasks, view documents, and track their event
  • Manage deputy managers (field staff) who handle event files and collect supplier signatures
  • Automate event-related reminders, calendar invites, and SMS notifications
  • Main User Types

    RoleAccessKey Pages
    AdminFull system accessDashboard, Events, Quotations, Clients, Receipts, SystemSettings, UserManagement
    StaffRole-based page permissionsDashboard, Events, Quotations (limited)
    ClientClient portal onlyClientDashboard, ViewQuotation, DepositPayment
    Deputy ManagerField-only pageDeputyManager (event file packages)
    SupplierNo login requiredDirect link to sign supplementary quotations via /SignSupplementaryQuotation

    Authentication Architecture

  • NOT base44 native auth. Uses a custom localStorage-based auth system.
  • Login via /AccessLogin — phone + password for staff, phone-based OTP for clients.
  • userRole, staffMember, clientPhone, clientName, quotationId stored in localStorage.
  • layout.jsx checks currentPageName === 'AccessLogin' to suppress the inactivity logout component.
  • InactivityLogout component auto-logs out inactive staff sessions.

  • 2. Main Modules

    2.1 Client Portal (/ClientDashboard)

    Purpose: Self-service portal for clients to track their event, sign quotations, complete tasks, view receipts and documents.

    Main Files:

  • pages/ClientDashboard.jsx — monolithic, ~1000 lines — DO NOT REBUILD
  • components/client/MoreServicesTab.jsx
  • components/client/SupplierReceiptsTab.jsx
  • components/client/TermsReacceptanceDialog.jsx
  • components/ProgressStepper.jsx
  • Entities Involved: Quotation, ClientTask, ClientFile, ClientActivity, Receipt, SupplementaryQuotation, Event, Client, CompanySettings, Service

    Critical Flows:

  • Client authenticates via SMS OTP → clientPhone in localStorage
  • Quotations fetched by client_phone
  • If no approved quotation → shows unsigned quotation with "sign" CTA
  • If approved quotation → full dashboard with tabs
  • If event has passed → shows post-event view (thank you, event summary, receipts, review link)
  • Real-time subscriptions on Quotation, ClientTask, Receipt, Event, DeletedEvent
  • Auto-kicks client from portal if quotation or event is deleted (redirects to login)
  • Risks if Modified:

  • Any change to subscription logic or clientPhone normalization can break real-time updates
  • The phone normalization .replace(/[-\s]/g, '') is used throughout — must be consistent
  • The needsTermsReacceptance = false is **intentionally hardcoded** — do not restore the logic without testing
  • The isEventPassed flag gates many tabs — breaking it breaks the whole post-event flow

  • 2.2 Quotation System

    Purpose: Create, send, and manage price quotations for clients. Clients sign them; admin approves them.

    Main Files:

  • pages/Quotations.jsx
  • components/quotations/QuotationForm.jsx
  • components/quotations/QuotationCard.jsx
  • components/quotations/QuotationPDF.jsx
  • pages/ViewQuotation.jsx — client-facing signing page
  • pages/AdminViewQuotation.jsx — admin view
  • Entities: Quotation, Service, Client, Event, CompanySettings

    Critical Fields on Quotation:

  • approved (boolean) — set by admin; gates full client dashboard access
  • signed_date — set when client signs; triggers notifyAdminQuotationSigned
  • calendar_invite_sent + google_calendar_event_id — deduplication for Google Calendar
  • legacy_terms (boolean) — marks old contracts; shows special legacy message in TermsTab
  • access_code — one-time code for client to access their quotation
  • Flow:

  • Admin creates quotation → sets access_code → sends link to client
  • Client opens /ViewQuotation?id=... → views terms → signs → signed_date set
  • Automation triggers notifyAdminQuotationSigned → SMS to admin
  • Admin approves in Dashboard → approved = true
  • Automation triggers createQuotationCalendarInvite → Google Calendar event created
  • Client now has full dashboard access
  • Risks if Modified:

  • approved field is the master gate for the client portal — changing its name/type will break everything
  • calendar_invite_sent is checked BEFORE creating a Calendar event to prevent duplicates
  • Changing quotation signing flow will affect ClientActivity logging

  • 2.3 Receipts Module

    Purpose: Issue numbered receipts for payments (deposit, balance, supplementary, credit invoice).

    Main Files:

  • pages/Receipts.jsx
  • components/receipts/ReceiptForm.jsx
  • components/receipts/ReceiptPDF.jsx — generates downloadable PDF client-side using html2canvas + jsPDF
  • components/receipts/SplitReceiptDialog.jsx
  • components/receipts/CreditInvoicePDF.jsx
  • functions/reindexReceipts.js — corrects sequential numbering
  • functions/splitReceipt.js
  • Critical Logic:

  • Receipt numbering uses CompanySettings.last_receipt_number — auto-incremented on each receipt creation
  • receipt_start_number in CompanySettings defines starting offset
  • is_credit_invoice field distinguishes credit invoices from regular receipts
  • split_from_receipt_id tracks which receipt was split
  • auto_generated marks system-generated receipts
  • Risks if Modified:

  • last_receipt_number in CompanySettings must NEVER be manually edited — always use the reindex function
  • ReceiptPDF depends on the DOM structure of the receipt — if layout changes, PDF output breaks
  • Do not rename receipt_number field — used in display, PDF, and client portal

  • 2.4 Supplier Receipts & Deputy Manager

    Purpose: Field staff (deputy managers) collect payment confirmations from suppliers AT THE EVENT by capturing their signature on a tablet.

    Flow:

  • Admin prepares event file package (EventFilePackage) and uploads files (EventFile) for the event
  • Deputy manager opens /DeputyManager → sees complete packages (is_complete: true)
  • At event: deputy manager opens event file viewer → can add supplier signatures
  • Supplier signs on-screen → signature saved as private file → SupplierPaymentReceipt created
  • Admin publishes receipts → publishReceiptsToClientPortal creates PublishedEventDocument records
  • Client sees these in their portal under "Supplier Receipts" tab (only visible after event)
  • Risks if Modified:

  • SupplierPaymentReceipt.supplier_signature_url stores a **private file URI** (not a public URL)
  • publishReceiptsToClientPortal uses supplier_signature_url as the file_url for PublishedEventDocument
  • getEventFileSignedUrl creates temporary signed URLs for private files

  • 2.5 SMS System

    Architecture:

    Business Event → calls sendSystemSms(trigger_key, dynamic_data) → looks up SmsTemplate by trigger_key → replaces {{placeholders}} with dynamic_data → sends via Active Trail API → logs to SmsLog entity

    Key Functions:

  • functions/sendSms.js — raw SMS sender (phone + message → Active Trail API)
  • functions/sendSystemSms.js — template-based SMS system
  • functions/requestSmsVerificationCode.js — client OTP login
  • functions/verifySmsCode.js — verifies OTP code
  • Provider: Active Trail (webapi.mymarketing.co.il) using ACTIVE_TRAIL_TOKEN secret.

    Sender Name: TIPTOP (hardcoded in both sendSms.js and sendSystemSms.js)

    SMS Trigger Keys:

  • admin_quotation_signed — when client signs quotation
  • admin_quotation_viewed — when client clicks "view quotation" button
  • admin_task_completed — when client completes a task
  • event_prep_72_hour_notification — 72h before event with external manager
  • event_prep_24_hour_notification — 24h before event with external manager
  • client_sms_verification — OTP code for client login
  • Rate Limiting on requestSmsVerificationCode:

  • 60-second cooldown between requests
  • 10-minute code expiry
  • 5 resend maximum before lockout
  • Lockout stored in Client.verification_locked_until

  • 2.6 Automations

    Automation NameTypeTriggerFunctionNotes
    בדיקת תאריך אירועEntityEvent create/updatecheckEventDateAndNotifyOnly fires for events with מנהל אירוע חיצוני service
    התראה 24 שעותScheduledDaily 03:00create24HourEventPrepNotificationCurrently FAILING
    התראה 72 שעותScheduledDaily 03:00create72HourEventPrepNotificationCurrently FAILING
    מחיקת משימות לקוחEntityClient deletecleanupClientTasksDeletes all ClientTask by phone
    התראה לאדמין - לקוח צפה בהצעהEntityClientActivity createnotifyAdminQuotationViewedCondition: action_type=view_quotation
    Event Deleted - Delete Google CalendarEntityEvent deletesyncEventCalendarInviteRemoves event from Google Calendar
    Event Date Changed - Sync CalendarEntityEvent updatesyncEventCalendarInviteCondition: changed_fields contains event_date
    Quotation Approved - Send Calendar InviteEntityQuotation updatecreateQuotationCalendarInviteCondition: approved=true AND calendar_invite_sent != true
    Quotation Signed - Notify AdminEntityQuotation updatenotifyAdminQuotationSignedCondition: signed_date was just set

    2.7 Calendar Integration

    Provider: Google Calendar via authorized shared connector.

    Functions:

  • createQuotationCalendarInvite — creates event when quotation is approved
  • syncEventCalendarInvite — updates/deletes event when event date changes or event is deleted
  • addEventToStaffCalendars — adds to staff members' calendars
  • sendInterviewCalendarInvite — sends calendar invite for client interview
  • Deduplication:

  • Quotation.calendar_invite_sent (boolean) — checked before creating
  • Quotation.google_calendar_event_id (string) — stored after creation; used for updates/deletes

  • 3. Entity Architecture

    Critical Entities

    Client

  • client_phone — primary identifier used everywhere. Format varies: must always use .replace(/[-\s]/g, '') for comparison.
  • verified_email / is_email_verified — email verification state
  • verified_phone / is_phone_verified — SMS verification state
  • verification_locked_until — lockout field; set to "" (empty string) to unlock
  • accepted_general_terms_version — ISO datetime; compared against CompanySettings.general_terms_version
  • accepted_service_terms — array of {service_name, accepted_version} objects
  • NEVER DELETE without running cleanupClientTasks first.
  • Event

  • contract_id — links to the parent Quotation.id — MASTER JOIN FIELD
  • client_phone — must match quotation's phone (normalized)
  • service_type — array of service names; drives many conditional features
  • assigned_ushers — array of usher IDs
  • event_summary — nested object {actual_guest_count, summary_notes, completed_at, completed_by}
  • Relationships: Event.contract_id → Quotation.id; Event.id → EventFile.event_id
  • Quotation

  • approved (boolean) — MASTER GATE for client portal access
  • signed_date — triggers admin SMS notification
  • calendar_invite_sent + google_calendar_event_id — deduplication for Google Calendar
  • access_code — client login key
  • legacy_terms — marks pre-system contracts
  • deposit_status — not_paid / paid
  • CompanySettings

  • general_terms — displayed to all clients in TermsTab
  • general_terms_version — ISO datetime; auto-updated every time general_terms is saved
  • last_receipt_number — auto-incremented counter; NEVER manually edit
  • renovation_mode — if true, redirects all client portal users to /RenovationMode
  • admin_notification_phone — phone number for admin SMS alerts
  • CRITICAL: There is always exactly ONE record. Always access via .list()[0]
  • Service

  • terms_and_limitations — shown to clients in TermsTab
  • terms_version — ISO datetime; auto-updated when terms_and_limitations changes
  • is_active — gates display in MoreServicesTab and TermsTab
  • predefined_items — default line items for quotation creation
  • Receipt

  • receipt_number — sequential; driven by CompanySettings.last_receipt_number
  • is_credit_invoice — boolean; separate PDF template if true
  • split_from_receipt_id — tracks split origin
  • auto_generated — system-created flag
  • SupplierPaymentReceipt

  • supplier_signature_url — PRIVATE file URI (not a public URL) — used to generate signed download URLs
  • event_id — links to Event

  • 4. Financial Logic

    Receipt Numbering

    CompanySettings.receipt_start_number = N (one-time setup)

    CompanySettings.last_receipt_number = increments with each new receipt

    New receipt number = receipt_start_number + last_receipt_number offset

    Payment Flow

  • Client signs quotation (deposit amount set on quotation)
  • Admin creates Receipt for deposit → payment_for = 'מקדמה'
  • Admin creates Receipt for balance → payment_for = 'יתרה'
  • Supplementary services → payment_for = 'שירותים נוספים'
  • Credit invoices → is_credit_invoice = true, original_receipt_number set

  • 5. Dangerous Areas / Do-Not-Break List

    AreaRiskFiles
    Quotation.approved logicGates entire client portalClientDashboard, ViewQuotation, Dashboard
    Receipt numbering (last_receipt_number)Financial integrityCompanySettings, Receipts.jsx
    Phone normalizationAuth, portal, all lookupsAccessLogin, requestSmsVerificationCode, ClientDashboard
    clientPhone in localStorageAll client portal dataClientDashboard (every query key)
    Google Calendar deduplicationDouble-booking preventioncreateQuotationCalendarInvite, syncEventCalendarInvite
    Real-time subscriptions + verificationInProgress guardPortal stability, rate limitsClientDashboard
    SupplierPaymentReceipt.supplier_signature_urlPrivate URI, not public URLsaveSupplierPaymentReceipt, getClientEventDocuments
    needsTermsReacceptance = falseIntentionally disabledClientDashboard
    CompanySettings single-record assumptionAll settings queriesEverywhere that calls .list()[0]

    6. Current Known Issues & Technical Debt

    Intentionally Disabled

  • Terms re-acceptance dialog — needsTermsReacceptance = false hardcoded in ClientDashboard. Disabled to avoid forcing all production clients to re-sign terms.
  • Scheduled Automation Failures

  • create24HourEventPrepNotification and create72HourEventPrepNotification are FAILING (as of 2026-05-19). Both scheduled at 03:00 daily.
  • Email Largely Replaced by SMS

  • The sendSystemEmail / EmailTemplate system exists but most notifications have been migrated to SMS.
  • SEND_REAL_EMAILS_ENABLED secret controls email sending — check this before any email testing.
  • ClientDashboard Sensitivity

  • ClientDashboard.jsx is ~1000 lines with many interconnected states, queries, subscriptions, and conditional rendering. It is EXTREMELY fragile.
  • Rule: minimal, surgical fixes only. Never refactor the whole file at once.
  • Always use find_replace for changes here, never write_file.

  • 7. Recommended Development Rules

    Before Any Change

  • Read the relevant file first — never assume content
  • Check if an automation watches the entity being modified
  • Check if a subscription in ClientDashboard depends on this entity
  • Ask: will this change trigger any SMS/email/notification?
  • Making Changes

  • Use find_replace for existing files — never use write_file on large existing files
  • One thing at a time — change one logical thing per session
  • Test backend functions with test_backend_function before wiring to UI
  • Phone numbers — always normalize with .replace(/[-\s]/g, '') when comparing
  • Financial Data

  • Never manually edit CompanySettings.last_receipt_number
  • Never modify ReceiptPDF structure without testing the download output
  • Credit invoices — always check is_credit_invoice flag before processing
  • Production Safety

  • No notification/SMS testing in production without disabling the relevant SmsTemplate (is_active = false)
  • No bulk entity operations without confirming no automations are watching that entity
  • Terms changes — currently SAFE (no automated notifications)
  • Quotation approval — TRIGGERS Google Calendar invite (one-time, deduplicated)
  • Quotation signing — TRIGGERS admin SMS notification
  • Architecture Rules

  • Client portal authentication is localStorage-based — not base44 auth
  • CompanySettings — always one record, always access via .list()[0]
  • Event-Quotation link is Event.contract_id = Quotation.id — this is the master join
  • Private files (supplier signatures, event files) use signed URLs — never embed raw private URIs in client-facing HTML

  • *Document generated: 2026-05-19. Update whenever significant architectural changes are made.*