Skip to main content

Data Models & Database Schema

Complete documentation of the Toto ecosystem's data structure, relationships, and business logic with comprehensive seeding system.

πŸ“Š Overview​

The Toto ecosystem uses Firestore as its primary database with a well-structured data model that supports:

  • Case Management - Pet rescue cases with donation tracking
  • User Management - Multi-role user system (users, guardians, admins, investors, partners)
  • Support System - Comprehensive support ticket management
  • Donation System - Fundraising with Stellar wallet integration
  • Audit Logging - Complete system activity tracking
  • Security - Role-based access control and data isolation

πŸ—‚οΈ Collection Structure​

Core Collections​

users/              - User accounts and profiles (all roles)
cases/ - Pet rescue cases and campaigns
donations/ - Donation records with Stellar integration
updates/ - Case updates and progress tracking
follows/ - User subscriptions to cases
support_tickets/ - Support ticket management system
notifications/ - User notification system
audit_logs/ - System audit trail and activity logs

Deprecated Collections (Removed)​

waitlist/           - External waitlist entries (now handled in users collection)
ticket_updates/ - Support ticket updates (now handled in support_tickets)
sharedPosts/ - Social media integration (removed)
pets/ - Pet records (removed)
statusUpdates/ - Status updates (removed)

πŸ‘₯ User Management​

User Roles & Permissions​

User Types​

  • user - Basic platform user, can donate and follow cases
  • guardian - Case owner, can create and manage cases
  • admin - Platform administrator with full access
  • investor - Financial backers and stakeholders
  • partner - Business partners and collaborators

User Status​

  • active - Fully functional user account
  • inactive - Temporarily disabled account
  • pending - Awaiting approval or completion
  • waitlist - On waitlist for platform access

Enhanced User Interface (User)​

interface User {
id: string; // Normalized ID (e.g., "usr_abc123")
email: string; // User's email address
name: string; // Display name
role: UserRole; // 'user' | 'guardian' | 'admin' | 'investor' | 'partner'
status: UserStatus; // 'active' | 'inactive' | 'pending' | 'waitlist'
imageUrl?: string; // Profile picture URL
createdAt: string; // ISO 8601 timestamp
updatedAt: string; // ISO 8601 timestamp
lastLoginAt?: string; // Last login timestamp
firebaseUid?: string; // Firebase Auth UID

// Enhanced profile fields
bio?: string; // User description
location?: string; // Geographic location
phone?: string; // Phone number (Argentina format)
organization?: string; // Organization (guardians/admins)
department?: string; // Department (role-based)
timeSinceJoined?: string; // Time since joining (guardians)

// Activity tracking
activityRate?: number; // User activity score (0-100)

// Permissions (role-based)
permissions?: string[]; // Array of permission strings

// Contact information
contactInfo?: {
phone?: string; // Phone number
website?: string; // Personal/organization website
socialLinks?: {
facebook?: string; // Facebook profile
instagram?: string; // Instagram profile
twitter?: string; // Twitter profile
}
};

// Banking information (for guardians)
bankingAccountAlias?: string; // Primary banking account alias (kept for backward compatibility)
bankingAccountAliases?: string[]; // Multiple banking account aliases for donations

// User preferences
preferences?: {
notifications: boolean; // Push notification preference
emailUpdates: boolean; // Email update preference
caseTypes: string[]; // Preferred case categories
};
}

User Role Types​

type UserRole = 'user' | 'guardian' | 'admin' | 'investor' | 'partner';
type UserStatus = 'active' | 'inactive' | 'pending' | 'waitlist';

Authentication State (AuthState)​

interface AuthState {
user: User | null; // Current authenticated user
isLoading: boolean; // Authentication loading state
error: string | null; // Authentication error message
isAuthenticated: boolean; // Authentication status
}

πŸ†˜ Case Management​

Enhanced Case Interface (Case)​

interface Case {
id: string; // Normalized ID (e.g., "cas_abc123")
name: string; // Case title
description: string; // Detailed case description
imageUrl: string; // Primary case image
additionalImages?: string[]; // Additional case images
status: CaseStatus; // 'active' | 'urgent' | 'completed' | 'draft'
priority: CasePriority; // 'urgent' | 'normal'
category: CaseCategory; // 'rescue' | 'surgery' | 'treatment' | 'transit' | 'foster'
guardianId: string; // Guardian's user ID
guardianName: string; // Guardian's display name

// Financial tracking
donationGoal: number; // Target amount in cents
donationsReceived: number; // Current amount received

// Timestamps (ISO 8601)
createdAt: string; // Case creation timestamp
updatedAt: string; // Last update timestamp

// Analytics (calculated, not seeded)
followersCount?: number; // Number of followers
sharesCount?: number; // Number of shares
viewsCount?: number; // Number of views
commentsCount?: number; // Number of comments
}

Case Types​

type CaseStatus = 'active' | 'urgent' | 'completed' | 'draft';
type CasePriority = 'urgent' | 'normal';
type CaseCategory = 'rescue' | 'surgery' | 'treatment' | 'transit' | 'foster';

Guardian Interface (Guardian)​

interface Guardian {
id: string; // Guardian's user ID
name: string; // Guardian's display name
imageUrl: string; // Guardian's profile image
description?: string; // Guardian's bio/description
}

πŸ’° Donation System (Stellar Integration)​

Enhanced Donation Interface (Donation)​

interface Donation {
id: string; // Normalized ID (e.g., "don_abc123")
caseId: string; // Related case ID
guardianId: string; // Guardian ID (for direct donations)
userId?: string; // Donor's user ID (optional for anonymous)
userName?: string; // Donor's display name
userEmail?: string; // Donor's email

// Financial details
amount: number; // Donation amount in cents
currency: string; // Currency code (ARS, USD)
originalAmount: number; // Original amount before conversion
convertedAmount: number; // Amount after currency conversion

// Payment processing
paymentProvider: string; // Payment provider (MoonPay, etc.)
transactionId: string; // Internal transaction ID
partnerTransactionId: string; // Partner transaction ID

// Status and metadata
status: DonationStatus; // 'pending' | 'completed' | 'failed' | 'refunded'
message?: string; // Optional donor message
isAnonymous: boolean; // Public visibility preference

// Timestamps (ISO 8601)
createdAt: string; // Donation creation timestamp
completedAt?: string; // Payment completion timestamp
}

Donation Types​

type DonationStatus = 'pending' | 'completed' | 'failed' | 'refunded';

πŸ“ Case Updates & Progress​

Case Update Interface (CaseUpdate)​

interface CaseUpdate {
id: string; // Unique update identifier
caseId: string; // Related case ID
type: UpdateType; // 'status_change' | 'note' | 'comment' | 'milestone'
status?: CaseStatus; // New case status
previousStatus?: string; // Previous case status
notes?: string; // Update description
updatedBy: string; // User ID who made the update
updatedByName: string; // User's display name
createdAt: Date; // Update timestamp
metadata?: { // Extended update information
attachmentUrl?: string; // File attachment URL
tags?: string[]; // Update tags
priority?: 'low' | 'medium' | 'high';
}
}

Update Types​

type UpdateType = 'status_change' | 'note' | 'comment' | 'milestone';

🎫 Support System​

Support Ticket Interface (SupportTicket)​

interface SupportTicket {
id: string; // Normalized ID (e.g., "spt_abc123")
ticketNumber: string; // Human-readable ticket number
title: string; // Ticket title
description: string; // Detailed description
status: TicketStatus; // 'open' | 'in_progress' | 'resolved' | 'closed'
priority: TicketPriority; // 'low' | 'medium' | 'high' | 'urgent'
category: string; // Ticket category

// Assignment
assignedTo?: string; // Assigned admin user ID
assignedToName?: string; // Assigned admin name

// Requester information
requesterId?: string; // Requester user ID
requesterEmail: string; // Requester email
requesterName?: string; // Requester name

// Timestamps (ISO 8601)
createdAt: string; // Ticket creation timestamp
updatedAt: string; // Last update timestamp
dueDate: string; // Due date timestamp
resolvedAt?: string; // Resolution timestamp
closedAt?: string; // Closure timestamp

// Additional data
tags: string[]; // Ticket tags
attachments: string[]; // Attachment URLs
internalNotes?: string; // Internal admin notes
}

Support Types​

type TicketStatus = 'open' | 'in_progress' | 'resolved' | 'closed';
type TicketPriority = 'low' | 'medium' | 'high' | 'urgent';

πŸ”” Notification System​

Notification Interface (Notification)​

interface Notification {
id: string; // Normalized ID (e.g., "not_abc123")
userId: string; // Target user ID
userEmail: string; // Target user email
type: NotificationType; // Notification type
category: string; // Notification category
priority: NotificationPriority; // 'low' | 'medium' | 'high' | 'urgent'
title: string; // Notification title
message: string; // Notification message
actionUrl?: string; // Action URL
isRead: boolean; // Read status
createdAt: string; // ISO 8601 timestamp
metadata?: { // Additional data
caseId?: string; // Related case ID
ticketId?: string; // Related ticket ID
[key: string]: any; // Flexible metadata
}
}

Notification Types​

type NotificationType = 'case_update' | 'donation_received' | 'ticket_assigned' | 'system_alert';
type NotificationPriority = 'low' | 'medium' | 'high' | 'urgent';

πŸ” Audit Logging System​

Audit Log Interface (AuditLog)​

interface AuditLog {
id: string; // Normalized ID (e.g., "aud_abc123")
timestamp: string; // ISO 8601 timestamp
userId: string; // User who performed the action
userEmail: string; // User email
userRole: string; // User role
action: string; // Action performed
resource: string; // Resource type
resourceId: string; // Resource ID
details: { // Action details
before?: any; // State before action
after?: any; // State after action
ipAddress?: string; // User IP address
userAgent?: string; // User agent string
reason?: string; // Action reason
[key: string]: any; // Additional details
};
severity: AuditSeverity; // 'low' | 'medium' | 'high' | 'critical'
category: AuditCategory; // Audit category
}

Audit Types​

type AuditSeverity = 'low' | 'medium' | 'high' | 'critical';
type AuditCategory = 'user' | 'case' | 'donation' | 'system' | 'security' | 'support' | 'notification';

πŸ“± Social Media Integration​

Shared Post Interface (SharedPost)​

interface SharedPost {
id: string; // Unique post identifier
caseId: string; // Related case ID
guardianId: string; // Guardian who shared the post
platform: SocialPlatform; // Social media platform
originalPostUrl: string; // Original post URL
embedCode?: string; // Optional embed code
description?: string; // Post description
createdAt: Date; // Sharing timestamp
updatedAt?: Date; // Last update timestamp
approvalStatus?: ApprovalStatus; // 'pending' | 'approved' | 'rejected'
}

Social Platforms​

type SocialPlatform = 'facebook' | 'instagram' | 'twitter' | 'tiktok' | 'other';
type ApprovalStatus = 'pending' | 'approved' | 'rejected';

🌱 Seeding System​

Comprehensive Seeding Script​

The system includes a complete seeding script (/api/init-staging-final) that generates:

  • 27 Users - All roles and statuses including waitlist users
  • 15 Support Tickets - Complete support system with assignments
  • 10 Cases - All categories and priorities
  • 50 Donations - Stellar wallet integration with multiple currencies
  • 30 Follows - User-case relationships
  • 30 Notifications - User-specific notifications
  • 36 Case Updates - Progress tracking
  • 200 Audit Logs - System activity tracking

Seeding Features​

  • Normalized IDs - Consistent ID format across all entities
  • ISO 8601 Timestamps - Standardized time format
  • Realistic Data - Argentina phone numbers, realistic names
  • Role-based Data - Appropriate fields based on user roles
  • Conditional Fields - No undefined values in Firestore
  • Modular Design - Separate modules for each entity type

ID Generation System​

// ID prefixes
const ENTITY_PREFIXES = {
USER: 'usr',
CASE: 'cas',
DONATION: 'don',
FOLLOW: 'flw',
NOTIFICATION: 'not',
AUDIT_LOG: 'aud',
SUPPORT_TICKET: 'spt',
UPDATE: 'upd'
};

// Example IDs
// usr_abc123def456
// cas_xyz789ghi012
// don_mno345pqr678

πŸ” Security & Access Control​

Firestore Security Rules​

User Data Isolation​

// Users can only access their own data
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}

Case Access Control​

// Public read access, guardian/admin write access
match /cases/{caseId} {
allow read: if true;
allow create: if request.auth != null &&
request.auth.uid == request.resource.data.guardianId;
allow update, delete: if request.auth != null &&
(request.auth.uid == resource.data.guardianId ||
request.auth.token.admin == true);
}

Donation Privacy​

// Donors can see their own donations, guardians see case donations
match /donations/{donationId} {
allow read: if request.auth != null && (
request.auth.uid == resource.data.donorId ||
// Guardian of related case
get(/databases/$(database)/documents/cases/$(resource.data.caseId))
.data.guardianId == request.auth.uid
);
}

πŸ”— Data Relationships​

Primary Relationships​

User (1) ←→ (Many) Cases (as guardian)
User (1) ←→ (Many) Donations (as donor)
User (1) ←→ (Many) Follows (as follower)
User (1) ←→ (Many) Notifications (as recipient)
User (1) ←→ (Many) AuditLogs (as actor)
Case (1) ←→ (Many) Donations
Case (1) ←→ (Many) Updates
Case (1) ←→ (Many) Follows
SupportTicket (1) ←→ (Many) AuditLogs

Collection Dependencies​

  • Cases depend on Users (guardian relationship)
  • Donations depend on Cases and optionally Users
  • Updates depend on Cases and Users
  • Notifications depend on Users
  • AuditLogs depend on Users and various resources

πŸ“ˆ Performance Considerations​

Indexing Strategy​

  • User queries: Index on role, status, createdAt
  • Case queries: Index on status, priority, category, guardianId
  • Donation queries: Index on caseId, status, createdAt
  • Support queries: Index on status, priority, assignedTo
  • Audit queries: Index on userId, category, timestamp

Query Optimization​

  • Use compound indexes for complex queries
  • Limit result sets with pagination
  • Cache frequently accessed data
  • Use subcollection queries for related data

πŸš€ Migration & Versioning​

Schema Evolution​

  • All fields are optional where possible for backward compatibility
  • Use metadata fields for future extensibility
  • Version control through Firestore document versions
  • Gradual migration strategies for breaking changes

Data Validation​

  • Client-side validation for immediate feedback
  • Server-side validation for data integrity
  • Firestore rules for access control validation
  • TypeScript interfaces for compile-time checking

πŸ“š API Integration​

Data Flow​

  1. Client β†’ API β†’ Firestore (Create/Update)
  2. Firestore β†’ API β†’ Client (Read)
  3. Real-time updates via Firestore listeners
  4. Offline support with local caching

CRUD Operations​

  • Create: New cases, users, donations
  • Read: Public case data, user-specific data
  • Update: Case progress, user profiles
  • Delete: Soft deletes preferred over hard deletes

πŸ” Monitoring & Analytics​

Key Metrics​

  • Case completion rates by category and urgency
  • Donation patterns and fundraising success
  • User engagement and retention
  • System performance and response times

Data Export​

  • CSV exports for guardian reports
  • Analytics dashboards for admins
  • API endpoints for external integrations
  • Backup strategies for data preservation

This documentation covers the complete data model for the Toto ecosystem. For implementation details, see the API Reference and Development Setup.