DeelRx CRM - Data Integrity Invariants
Domain rules that must ALWAYS hold true across all operations📦 Inventory Management
- Stock Quantity:
product.stockQuantity >= 0(never negative) - Adjustment Math:
newQuantity = previousQuantity + adjustmentQuantity(signed) - Adjustment Validation:
previousQuantity + adjustmentQuantity >= 0(before commit) - Concurrent Safety: Stock updates use database transactions with row-level locking
💰 Financial Integrity
- No Overpayment:
totalPaid <= order.totalAmountacross all payments - Money Precision: All monetary values use
Decimal(12,2)- no floating point - Payment Status:
COMPLETEDpayments only count toward order balance - Refund Limits:
refundAmount <= originalPaymentAmount
🏢 Multi-Tenancy
- Data Isolation: ALL queries MUST filter by
teamId(no cross-tenant leaks) - Team Membership: Users can only access data for teams where
TeamMembership.isActive = true - Resource Scoping: SKUs and orderNumbers unique within team, not globally
- Cascade Deletes: Team deletion removes all related business data safely
🛒 Order Processing
- Order Totals:
totalAmount = sum(orderItems.quantity * unitPrice) + taxAmount - discountAmount - Line Item Integrity:
quantity > 0andunitPrice >= 0for all order items - Status Progression: Orders follow business workflow (PENDING → CONFIRMED → PROCESSING → SHIPPED/DELIVERED)
- Number Uniqueness:
orderNumberunique per team (handle concurrency with retry logic)
👥 Customer Data
- Contact Requirements: At least one of
emailorphonemust be provided - Address Validation: JSON addresses validated via Zod schema before persistence
- Referral Logic:
CustomerReferralrequires referrer contact method (email/phone/customerId) - PII Handling: Customer data follows GDPR deletion requirements
🎯 Credit & Receivables
- Balance Accuracy:
outstandingBalance = totalAmount - sum(completedPayments) - Aging Calculation:
daysOutstanding = floor((now - order.createdAt) / 86400000) - Status Consistency: Credit status (NEW/PARTIAL/PAID/PASTDUE) matches payment state
- Risk Assessment: Credit scores based on payment history, not speculation
🔄 System Operations
- Audit Trails: All state changes log
createdAt,updatedAt,createdById - Soft Deletes: Use
isActive = falsefor business entities, hard deletes for system cleanup - Concurrent Updates: Use optimistic locking (
updatedAtchecks) for critical operations - Transaction Boundaries: Multi-table updates use database transactions
🚨 Error Handling
- Server Actions: Always return
{ data: T | null, error: string | null } - Validation: Zod schemas validate input before database operations
- Sentry Integration: All unhandled exceptions captured for observability
- User Feedback: Business rule violations return helpful error messages
🔐 Security Constraints
- Authentication: All operations require valid Clerk session
- Authorization: Team-based permissions enforced at application layer
- Input Sanitization: All user inputs validated/sanitized before persistence
- Rate Limiting: API endpoints protected with @repo/security (Arcjet)