forked from Dfunder/stellarAid-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.prisma
More file actions
412 lines (361 loc) · 10.6 KB
/
Copy pathschema.prisma
File metadata and controls
412 lines (361 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
// Prisma schema for StellarAid API
// Docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ---------------------------------------------------------------------------
// ENUMS: Define domain-specific enumerations
// ---------------------------------------------------------------------------
enum UserRole {
USER
DONOR
CREATOR
ADMIN
}
enum KycStatus {
UNVERIFIED
PENDING
VERIFIED
REJECTED
}
enum CampaignStatus {
DRAFT
PENDING_APPROVAL
ACTIVE
COMPLETED
CANCELLED
REJECTED
}
enum DonationStatus {
PENDING
CONFIRMED
REFUNDED
FAILED
}
enum TipStatus {
PENDING
CONFIRMED
FAILED
}
enum MilestoneStatus {
PENDING
ACTIVE
COMPLETED
FAILED
UNLOCKED
}
enum FundReleaseStatus {
PENDING
APPROVED
RELEASED
REJECTED
CANCELLED
}
enum NotificationType {
CAMPAIGN_CREATED
CAMPAIGN_UPDATED
DONATION_RECEIVED
MILESTONE_REACHED
CAMPAIGN_COMPLETED
DISPUTE_FILED
DISPUTE_RESOLVED
}
enum DisputeStatus {
OPENED
UNDER_REVIEW
RESOLVED
REJECTED
}
enum AuditActionType {
USER_CREATED
CAMPAIGN_CREATED
CAMPAIGN_UPDATED
DONATION_MADE
MILESTONE_COMPLETED
DISPUTE_FILED
ADMIN_ACTION
}
enum KYCStatus {
PENDING
VERIFIED
REJECTED
}
// ---------------------------------------------------------------------------
// MODELS: Define all database models with relationships and constraints
// ---------------------------------------------------------------------------
/// User model representing donors, creators, and administrators
model User {
id String @id @default(uuid())
walletAddress String @unique
email String? @unique
displayName String?
name String?
role UserRole @default(USER)
kycStatus KycStatus @default(UNVERIFIED)
bio String?
avatarUrl String?
socialLinks Json?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
campaigns Campaign[] @relation("CampaignCreator")
donations Donation[]
updates Update[] @relation("UpdateCreator")
notifications Notification[]
disputes Dispute[] @relation("DisputeFiler")
tips PlatformTip[]
newsLetterSub Newsletter?
auditLogs AuditLog[]
apiKeys ApiKey[]
fundReleases FundRelease[]
@@index([email])
@@index([role])
@@index([isActive])
@@index([kycStatus])
@@map("users")
}
/// ApiKey model for third-party integrations
model ApiKey {
id String @id @default(uuid())
userId String
name String
keyHash String @unique
prefix String
isActive Boolean @default(true)
scope String @default("read")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@map("api_keys")
}
/// Campaign model representing fundraising campaigns
model Campaign {
id String @id @default(uuid())
title String
description String
story String?
goalAmount Decimal @db.Decimal(20, 7)
raisedAmount Decimal @default(0) @db.Decimal(20, 7)
status CampaignStatus @default(DRAFT)
creatorId String
contractId String?
acceptedAssets Json?
isFeatured Boolean @default(false)
startDate DateTime?
endDate DateTime?
imageUrl String?
category String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
creator User @relation("CampaignCreator", fields: [creatorId], references: [id], onDelete: Cascade)
donations Donation[]
milestones Milestone[]
updates Update[]
disputes Dispute[]
fundReleases FundRelease[]
@@index([creatorId])
@@index([status])
@@index([createdAt])
@@index([category])
@@index([isFeatured])
@@map("campaigns")
}
/// Donation model representing individual donations to campaigns
model Donation {
id String @id @default(uuid())
amount Decimal @db.Decimal(20, 7)
assetCode String @default("XLM")
assetIssuer String?
txHash String @unique
isAnonymous Boolean @default(false)
status DonationStatus @default(PENDING)
isAnonymous Boolean @default(false)
donorId String
campaignId String
tipAmount Decimal? @db.Decimal(20, 7)
tipAsset String? @default("XLM")
tipId String?
donatedAt DateTime @default(now())
confirmedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
donor User @relation(fields: [donorId], references: [id], onDelete: Cascade)
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
disputes Dispute[]
tip PlatformTip? @relation(fields: [tipId], references: [id])
@@index([donorId])
@@index([campaignId])
@@index([status])
@@index([createdAt])
@@map("donations")
}
/// PlatformTip model representing platform tips sent with donations
model PlatformTip {
id String @id @default(uuid())
amount Decimal @db.Decimal(20, 7)
assetCode String @default("XLM")
txHash String @unique
status TipStatus @default(PENDING)
donorId String
donationId String? @unique
confirmedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
donor User @relation(fields: [donorId], references: [id], onDelete: Cascade)
donation Donation? @relation(fields: [donationId], references: [id], onDelete: SetNull)
@@index([donorId])
@@index([status])
@@index([createdAt])
@@index([amount])
@@map("platform_tips")
}
/// Milestone model representing campaign milestones
model Milestone {
id String @id @default(uuid())
campaignId String
title String
description String?
targetAmount Decimal @db.Decimal(20, 7)
status MilestoneStatus @default(PENDING)
dueDate DateTime?
completedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
fundReleases FundRelease[]
@@index([campaignId])
@@index([status])
@@map("milestones")
}
/// FundRelease model representing requests to release funds for milestones
model FundRelease {
id String @id @default(uuid())
milestoneId String
campaignId String
creatorId String
amount Decimal @db.Decimal(20, 7)
status FundReleaseStatus @default(PENDING)
signaturePayload String? // JSON stringified signature for on-chain verification
txHash String? @unique
releaseReason String?
approvedBy String? // Admin ID who approved (if applicable)
approvedAt DateTime?
releasedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
milestone Milestone @relation(fields: [milestoneId], references: [id], onDelete: Cascade)
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
@@index([milestoneId])
@@index([campaignId])
@@index([creatorId])
@@index([status])
@@index([createdAt])
@@map("fund_releases")
}
/// Update model representing campaign progress updates
model Update {
id String @id @default(uuid())
campaignId String
creatorId String
title String
content String
imageUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
creator User @relation("UpdateCreator", fields: [creatorId], references: [id], onDelete: Cascade)
@@index([campaignId])
@@index([creatorId])
@@index([createdAt])
@@map("updates")
}
/// Notification model for user notifications
model Notification {
id String @id @default(uuid())
userId String
type NotificationType
title String
message String
relatedId String? // ID of related resource (campaign, donation, etc.)
isRead Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([isRead])
@@index([createdAt])
@@map("notifications")
}
/// Dispute model for handling donation disputes
model Dispute {
id String @id @default(uuid())
donationId String
filerId String
campaignId String
reason String
description String
status DisputeStatus @default(OPENED)
resolution String?
resolvedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
donation Donation @relation(fields: [donationId], references: [id], onDelete: Cascade)
filer User @relation("DisputeFiler", fields: [filerId], references: [id], onDelete: Cascade)
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
@@unique([donationId])
@@index([filerId])
@@index([campaignId])
@@index([status])
@@index([createdAt])
@@map("disputes")
}
/// Newsletter model for newsletter subscriptions
model Newsletter {
id String @id @default(uuid())
userId String @unique
email String @unique
isSubscribed Boolean @default(true)
subscribedAt DateTime @default(now())
unsubscribedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([email])
@@index([isSubscribed])
@@map("newsletters")
}
/// AuditLog model for tracking system actions
model AuditLog {
id String @id @default(uuid())
userId String?
action AuditActionType
resourceType String
resourceId String
details String? // JSON stringified details
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
// Relations
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([userId])
@@index([action])
@@index([resourceType])
@@index([createdAt])
@@map("audit_logs")
}