feat: add advanced analytics and territory management system

- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-26 09:25:10 -06:00
parent d5c3953888
commit aa81eb5adb
438 changed files with 90509 additions and 2787 deletions

View File

@@ -0,0 +1,94 @@
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper functions
function inOrg(orgId) {
return request.auth != null && request.auth.token.orgId == orgId;
}
function canWriteOrg(orgId) {
return inOrg(orgId) && (request.auth.token.role in ['superadmin', 'orgAdmin']);
}
function territoryOK(resOrgId, resTerritoryId) {
return inOrg(resOrgId) && (
request.auth.token.role in ['superadmin', 'orgAdmin'] ||
(request.auth.token.role == 'territoryManager' && (resTerritoryId in request.auth.token.territoryIds)) ||
request.auth.token.role == 'staff' // staff sees entire org; can narrow later
);
}
function canReadTerritory(resOrgId, resTerritoryId) {
return inOrg(resOrgId) && (
request.auth.token.role in ['superadmin', 'orgAdmin'] ||
(request.auth.token.role == 'territoryManager' && (resTerritoryId in request.auth.token.territoryIds)) ||
request.auth.token.role == 'staff'
);
}
// Organizations collection
match /orgs/{orgId} {
allow read, write: if inOrg(orgId);
allow create: if request.auth != null;
}
// Users collection for organization membership tracking
match /users/{userId} {
// Users can read their own document, or admins can read within their org
allow read: if (request.auth != null && request.auth.uid == userId) ||
(request.auth != null && inOrg(resource.data.orgId));
// Only orgAdmins and superadmins can write user documents
allow write: if request.auth != null &&
canWriteOrg(request.resource.data.orgId);
}
// Territories collection
match /territories/{territoryId} {
allow read: if inOrg(resource.data.orgId);
allow write: if canWriteOrg(request.resource.data.orgId);
}
// Events collection with territory scoping
match /events/{eventId} {
allow read: if canReadTerritory(resource.data.orgId, resource.data.territoryId);
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
}
// Ticket types collection with territory inheritance
match /ticket_types/{ticketTypeId} {
allow read: if inOrg(resource.data.orgId);
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
}
// Tickets collection with territory inheritance
match /tickets/{ticketId} {
// Scanning/reporting needs org-wide reads; can narrow if required
allow read: if inOrg(resource.data.orgId);
allow write: if territoryOK(request.resource.data.orgId, request.resource.data.territoryId);
}
// Scans collection - append-only audit trail for ticket scanning
match /scans/{scanId} {
// Staff and above can read scans within their org for reporting/analytics
allow read: if inOrg(resource.data.orgId) &&
request.auth.token.role in ['staff', 'territoryManager', 'orgAdmin', 'superadmin'];
// Only create operations allowed - append-only pattern
// Staff and above can create scan records within their org
allow create: if inOrg(request.resource.data.orgId) &&
request.auth.token.role in ['staff', 'territoryManager', 'orgAdmin', 'superadmin'];
// Explicitly deny updates and deletes to enforce append-only pattern
allow update, delete: if false;
}
// Legacy support for old organization membership model
function isOrgMember(orgId) {
return request.auth != null &&
exists(/databases/$(database)/documents/users/$(request.auth.uid)) &&
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.orgs[orgId] != null;
}
}
}