ginskill-init 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.wrangler/cache/pages.json +4 -0
  2. package/.wrangler/cache/wrangler-account.json +6 -0
  3. package/DEVELOPMENT.md +510 -0
  4. package/README.md +104 -0
  5. package/agents/developer.md +56 -0
  6. package/agents/frontend-design.md +69 -0
  7. package/agents/mobile-reviewer.md +36 -0
  8. package/agents/review-code.md +49 -0
  9. package/agents/security-scanner.md +50 -0
  10. package/agents/tester.md +72 -0
  11. package/bin/cli.js +461 -0
  12. package/landing/ai-build-ai.png +0 -0
  13. package/landing/index.html +1495 -0
  14. package/landing/logo.png +0 -0
  15. package/package.json +37 -0
  16. package/skills/active-life-dev/SKILL.md +157 -0
  17. package/skills/active-life-dev/docs/auth.md +187 -0
  18. package/skills/active-life-dev/docs/customers.md +216 -0
  19. package/skills/active-life-dev/docs/integrations.md +209 -0
  20. package/skills/active-life-dev/docs/inventory.md +192 -0
  21. package/skills/active-life-dev/docs/modules.md +181 -0
  22. package/skills/active-life-dev/docs/orders.md +180 -0
  23. package/skills/active-life-dev/docs/patterns.md +319 -0
  24. package/skills/active-life-dev/docs/products.md +216 -0
  25. package/skills/active-life-dev/docs/schema.md +502 -0
  26. package/skills/active-life-dev/docs/setup.md +169 -0
  27. package/skills/active-life-dev/docs/vouchers.md +144 -0
  28. package/skills/ai-asset-generator/SKILL.md +247 -0
  29. package/skills/ai-asset-generator/docs/gen-image.md +274 -0
  30. package/skills/ai-asset-generator/docs/genvideo.md +341 -0
  31. package/skills/ai-asset-generator/docs/remove-background.md +19 -0
  32. package/skills/ai-asset-generator/lib/bg-remove.mjs +34 -0
  33. package/skills/ai-asset-generator/lib/env.mjs +48 -0
  34. package/skills/ai-asset-generator/lib/kie-client.mjs +100 -0
  35. package/skills/ai-build-ai/SKILL.md +127 -0
  36. package/skills/ai-build-ai/docs/agent-teams.md +293 -0
  37. package/skills/ai-build-ai/docs/checkpointing.md +161 -0
  38. package/skills/ai-build-ai/docs/create-agent.md +399 -0
  39. package/skills/ai-build-ai/docs/create-mcp.md +395 -0
  40. package/skills/ai-build-ai/docs/create-skill.md +299 -0
  41. package/skills/ai-build-ai/docs/headless-mode.md +614 -0
  42. package/skills/ai-build-ai/docs/hooks.md +578 -0
  43. package/skills/ai-build-ai/docs/memory-claude-md.md +375 -0
  44. package/skills/ai-build-ai/docs/output-styles.md +208 -0
  45. package/skills/ai-build-ai/docs/overview.md +162 -0
  46. package/skills/ai-build-ai/docs/permissions.md +391 -0
  47. package/skills/ai-build-ai/docs/plugins.md +396 -0
  48. package/skills/ai-build-ai/docs/sandbox.md +262 -0
  49. package/skills/ai-build-ai/docs/team-lead-workflow.md +648 -0
  50. package/skills/ant-design/SKILL.md +323 -0
  51. package/skills/ant-design/docs/components.md +160 -0
  52. package/skills/ant-design/docs/data-entry.md +406 -0
  53. package/skills/ant-design/docs/display.md +594 -0
  54. package/skills/ant-design/docs/feedback.md +451 -0
  55. package/skills/ant-design/docs/key-components.md +414 -0
  56. package/skills/ant-design/docs/navigation.md +310 -0
  57. package/skills/ant-design/docs/pro-components.md +543 -0
  58. package/skills/ant-design/docs/setup.md +213 -0
  59. package/skills/ant-design/docs/theme.md +265 -0
  60. package/skills/flutter-performance/SKILL.md +803 -0
  61. package/skills/flutter-performance/references/flutter-patterns.md +595 -0
  62. package/skills/icon-generator/SKILL.md +270 -0
  63. package/skills/mobile-app-review/SKILL.md +321 -0
  64. package/skills/mobile-app-review/references/apple-review.md +132 -0
  65. package/skills/mobile-app-review/references/google-play-review.md +203 -0
  66. package/skills/mongodb/SKILL.md +667 -0
  67. package/skills/mongodb/references/mongoose-patterns.md +368 -0
  68. package/skills/nestjs-architecture/SKILL.md +1086 -0
  69. package/skills/nestjs-architecture/references/advanced-patterns.md +590 -0
  70. package/skills/performance/SKILL.md +509 -0
  71. package/skills/react-fsd-architecture/SKILL.md +693 -0
  72. package/skills/react-fsd-architecture/references/fsd-patterns.md +747 -0
  73. package/skills/react-native-expo/SKILL.md +128 -0
  74. package/skills/react-native-expo/references/data-layer.md +252 -0
  75. package/skills/react-native-expo/references/design-system.md +252 -0
  76. package/skills/react-native-expo/references/navigation.md +199 -0
  77. package/skills/react-native-expo/references/performance.md +229 -0
  78. package/skills/react-native-expo/references/platform-services.md +179 -0
  79. package/skills/react-native-expo/references/state-management.md +209 -0
  80. package/skills/react-native-expo/references/ui-patterns.md +301 -0
  81. package/skills/react-query/SKILL.md +685 -0
  82. package/skills/react-query/references/query-patterns.md +365 -0
  83. package/skills/review-code/SKILL.md +374 -0
  84. package/skills/review-code/references/clean-code-principles.md +395 -0
  85. package/skills/review-code/references/frontend-patterns.md +136 -0
  86. package/skills/review-code/references/nestjs-patterns.md +184 -0
  87. package/skills/security-scanner/SKILL.md +366 -0
  88. package/skills/security-scanner/references/nestjs-security.md +260 -0
  89. package/skills/security-scanner/references/nextjs-security.md +201 -0
  90. package/skills/security-scanner/references/react-native-security.md +199 -0
  91. package/skills/traefik/SKILL.md +105 -0
  92. package/skills/traefik/docs/advanced-routing.md +186 -0
  93. package/skills/traefik/docs/auth-providers.md +137 -0
  94. package/skills/traefik/docs/cicd-devops.md +396 -0
  95. package/skills/traefik/docs/core-config.md +171 -0
  96. package/skills/traefik/docs/distributed-config.md +96 -0
  97. package/skills/traefik/docs/docker-compose.md +182 -0
  98. package/skills/traefik/docs/ha-performance.md +177 -0
  99. package/skills/traefik/docs/kubernetes.md +278 -0
  100. package/skills/traefik/docs/middleware.md +205 -0
  101. package/skills/traefik/docs/monitoring.md +357 -0
  102. package/skills/traefik/docs/security.md +391 -0
  103. package/skills/traefik/docs/tls-acme.md +155 -0
  104. package/skills/ui-ux-pro-max/SKILL.md +377 -0
  105. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  106. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  107. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  108. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  109. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  110. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  111. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  112. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  113. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  114. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  115. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  116. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  117. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  118. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  119. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  120. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  121. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  122. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  123. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  124. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  125. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  126. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  127. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  128. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
@@ -0,0 +1,502 @@
1
+ # Active Life Backend - Prisma Database Schema
2
+
3
+ ## Location
4
+ `prisma/schema.prisma`
5
+
6
+ ## Database
7
+ PostgreSQL via Supabase with `@prisma/adapter-pg`
8
+
9
+ ## Enums
10
+
11
+ ```prisma
12
+ enum RewardType { POINT, VOUCHER }
13
+ enum VoucherType { PERCENT, FIXED }
14
+ enum OrderStatus {
15
+ PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED,
16
+ REFUNDED, RETURN_PENDING, RETURN_RECEIVED, RETURN_REJECTED, REFUND_PENDING
17
+ }
18
+ enum PaymentMethod { CASH, TRANSFER }
19
+ enum InventoryTransactionType { IMPORT, EXPORT }
20
+ enum LogOrderType {
21
+ CREATE, PROCESS, SHIP, DELIVER, CANCEL_CLIENT, CANCEL_STAFF,
22
+ RETURN, RETURN_CREATE, RETURN_RECEIVE, RETURN_COMPLETE,
23
+ REFUND, REFUND_CREATE, REFUND_COMPLETE
24
+ }
25
+ enum ProductStatus { HIDDEN, NORMAL, HIGH }
26
+ ```
27
+
28
+ ## Models (36 total)
29
+
30
+ ### Core: Role & User (Staff)
31
+
32
+ ```prisma
33
+ model Role {
34
+ id String @id @default(uuid())
35
+ name String @unique // Admin, TeleSales, LiveChat, Agency
36
+ permissions String[]
37
+ users User[]
38
+ createdAt DateTime @default(now())
39
+ updatedAt DateTime @updatedAt
40
+ }
41
+
42
+ model User {
43
+ id String @id @default(uuid())
44
+ phone String @unique
45
+ email String? @unique
46
+ name String
47
+ password String
48
+ avatar String?
49
+ isBan Boolean @default(false)
50
+ roleId String
51
+ role Role @relation(fields: [roleId], references: [id])
52
+ extension EtelecomExtension? // 1-to-1 SIP extension
53
+ createdAt DateTime @default(now())
54
+ updatedAt DateTime @updatedAt
55
+ }
56
+ ```
57
+
58
+ ### Core: Client (Customer)
59
+
60
+ ```prisma
61
+ model Client {
62
+ id String @id @default(uuid())
63
+ phone String @unique
64
+ email String?
65
+ name String
66
+ password String?
67
+ avatar String?
68
+ dob DateTime?
69
+ gender String?
70
+ address String?
71
+ province String?
72
+ district String?
73
+ ward String?
74
+ point Int @default(0)
75
+ isBan Boolean @default(false)
76
+ note String?
77
+ tags String[]
78
+ // CRM fields
79
+ customerSourceId String?
80
+ customerStatusId String?
81
+ customerDetailStatusId String?
82
+ livechatStaffId String?
83
+ telesalesStaffId String?
84
+ agencyStaffId String?
85
+ firstCallAt DateTime?
86
+ lastOrderAt DateTime?
87
+ // Relations
88
+ orders Order[]
89
+ cart Cart?
90
+ vouchers ClientVoucher[]
91
+ bank ClientBank?
92
+ spinTransactions SpinTransaction[]
93
+ redeemTransactions RedeemTransaction[]
94
+ createdAt DateTime @default(now())
95
+ updatedAt DateTime @updatedAt
96
+ }
97
+ ```
98
+
99
+ ### CRM Lookup Tables
100
+
101
+ ```prisma
102
+ model CustomerSource {
103
+ id String @id @default(uuid())
104
+ name String @unique
105
+ description String?
106
+ createdAt DateTime @default(now())
107
+ updatedAt DateTime @updatedAt
108
+ }
109
+
110
+ model CustomerStatus {
111
+ id String @id @default(uuid())
112
+ name String @unique
113
+ description String?
114
+ createdAt DateTime @default(now())
115
+ updatedAt DateTime @updatedAt
116
+ }
117
+
118
+ model CustomerDetailStatus {
119
+ id String @id @default(uuid())
120
+ name String @unique
121
+ description String?
122
+ createdAt DateTime @default(now())
123
+ updatedAt DateTime @updatedAt
124
+ }
125
+
126
+ model InteractionStatus { /* same shape */ }
127
+ model InteractionResult { /* same shape */ }
128
+ model AdsSource { /* same shape */ }
129
+ ```
130
+
131
+ ### Product Catalog
132
+
133
+ ```prisma
134
+ model Category {
135
+ id String @id @default(uuid())
136
+ name String
137
+ slug String @unique
138
+ image String?
139
+ description String?
140
+ parentId String?
141
+ parent Category? @relation("CategoryTree", fields: [parentId], references: [id])
142
+ children Category[] @relation("CategoryTree")
143
+ brands CategoryBrand[]
144
+ products ProductCategory[]
145
+ createdAt DateTime @default(now())
146
+ updatedAt DateTime @updatedAt
147
+ }
148
+
149
+ model Brand {
150
+ id String @id @default(uuid())
151
+ name String
152
+ slug String @unique
153
+ image String?
154
+ description String?
155
+ categories CategoryBrand[]
156
+ inventoryProducts InventoryProduct[]
157
+ createdAt DateTime @default(now())
158
+ updatedAt DateTime @updatedAt
159
+ }
160
+
161
+ model CategoryBrand {
162
+ id String @id @default(uuid())
163
+ categoryId String
164
+ brandId String
165
+ category Category @relation(fields: [categoryId], references: [id])
166
+ brand Brand @relation(fields: [brandId], references: [id])
167
+ @@unique([categoryId, brandId])
168
+ }
169
+
170
+ model Unit {
171
+ id String @id @default(uuid())
172
+ name String @unique
173
+ abbreviation String?
174
+ createdAt DateTime @default(now())
175
+ updatedAt DateTime @updatedAt
176
+ }
177
+ ```
178
+
179
+ ### Store Products & Combos
180
+
181
+ ```prisma
182
+ model StoreProduct {
183
+ id String @id @default(uuid())
184
+ name String
185
+ slug String @unique
186
+ description String?
187
+ images String[]
188
+ status ProductStatus @default(NORMAL)
189
+ categories ProductCategory[]
190
+ combos StoreProductCombo[]
191
+ cartItems CartItem[]
192
+ orderItems OrderItem[]
193
+ createdAt DateTime @default(now())
194
+ updatedAt DateTime @updatedAt
195
+ }
196
+
197
+ model ProductCategory {
198
+ id String @id @default(uuid())
199
+ productId String
200
+ categoryId String
201
+ product StoreProduct @relation(fields: [productId], references: [id])
202
+ category Category @relation(fields: [categoryId], references: [id])
203
+ @@unique([productId, categoryId])
204
+ }
205
+
206
+ model StoreProductCombo {
207
+ id String @id @default(uuid())
208
+ name String
209
+ price Float
210
+ comparePrice Float?
211
+ productId String
212
+ product StoreProduct @relation(fields: [productId], references: [id])
213
+ items StoreProductComboItem[]
214
+ giftItems StoreProductComboItem[] @relation("GiftItems")
215
+ promotionHistory StoreProductComboPromotionHistory[]
216
+ cartItems CartItem[]
217
+ orderItems OrderItem[]
218
+ createdAt DateTime @default(now())
219
+ updatedAt DateTime @updatedAt
220
+ }
221
+
222
+ model StoreProductComboItem {
223
+ id String @id @default(uuid())
224
+ comboId String?
225
+ giftComboId String?
226
+ inventoryProductId String
227
+ quantity Int
228
+ combo StoreProductCombo? @relation(fields: [comboId], references: [id])
229
+ giftCombo StoreProductCombo? @relation("GiftItems", fields: [giftComboId], references: [id])
230
+ inventoryProduct InventoryProduct @relation(fields: [inventoryProductId], references: [id])
231
+ }
232
+
233
+ model StoreProductComboPromotionHistory {
234
+ id String @id @default(uuid())
235
+ comboId String
236
+ oldPrice Float
237
+ newPrice Float
238
+ reason String?
239
+ combo StoreProductCombo @relation(fields: [comboId], references: [id])
240
+ createdAt DateTime @default(now())
241
+ }
242
+ ```
243
+
244
+ ### Inventory System
245
+
246
+ ```prisma
247
+ model InventoryProduct {
248
+ id String @id @default(uuid())
249
+ name String
250
+ sku String? @unique
251
+ barcode String?
252
+ image String?
253
+ unitId String?
254
+ brandId String?
255
+ unit Unit? @relation(fields: [unitId], references: [id])
256
+ brand Brand? @relation(fields: [brandId], references: [id])
257
+ comboItems StoreProductComboItem[]
258
+ items ProductInventoryItem[]
259
+ transactions InventoryTransaction[]
260
+ createdAt DateTime @default(now())
261
+ updatedAt DateTime @updatedAt
262
+ }
263
+
264
+ model ProductInventoryItem {
265
+ id String @id @default(uuid())
266
+ inventoryProductId String
267
+ quantity Int
268
+ remainingQuantity Int
269
+ expiryDate DateTime?
270
+ lotNumber String?
271
+ inventoryProduct InventoryProduct @relation(fields: [inventoryProductId], references: [id])
272
+ createdAt DateTime @default(now())
273
+ updatedAt DateTime @updatedAt
274
+ }
275
+
276
+ model InventorySession {
277
+ id String @id @default(uuid())
278
+ type InventoryTransactionType
279
+ note String?
280
+ userId String // Staff who created
281
+ transactions InventoryTransaction[]
282
+ createdAt DateTime @default(now())
283
+ }
284
+
285
+ model InventoryTransaction {
286
+ id String @id @default(uuid())
287
+ sessionId String
288
+ inventoryProductId String
289
+ quantity Int
290
+ expiryDate DateTime?
291
+ lotNumber String?
292
+ session InventorySession @relation(fields: [sessionId], references: [id])
293
+ inventoryProduct InventoryProduct @relation(fields: [inventoryProductId], references: [id])
294
+ orderItemId String? // Links to order item when exporting
295
+ createdAt DateTime @default(now())
296
+ }
297
+ ```
298
+
299
+ ### Shopping Cart
300
+
301
+ ```prisma
302
+ model Cart {
303
+ id String @id @default(uuid())
304
+ clientId String @unique
305
+ client Client @relation(fields: [clientId], references: [id])
306
+ items CartItem[]
307
+ createdAt DateTime @default(now())
308
+ updatedAt DateTime @updatedAt
309
+ }
310
+
311
+ model CartItem {
312
+ id String @id @default(uuid())
313
+ cartId String
314
+ productId String
315
+ comboId String
316
+ quantity Int
317
+ cart Cart @relation(fields: [cartId], references: [id])
318
+ product StoreProduct @relation(fields: [productId], references: [id])
319
+ combo StoreProductCombo @relation(fields: [comboId], references: [id])
320
+ createdAt DateTime @default(now())
321
+ updatedAt DateTime @updatedAt
322
+ }
323
+ ```
324
+
325
+ ### Orders
326
+
327
+ ```prisma
328
+ model Order {
329
+ id String @id @default(uuid())
330
+ orderCode String @unique
331
+ clientId String
332
+ status OrderStatus @default(PENDING)
333
+ paymentMethod PaymentMethod
334
+ totalAmount Float
335
+ discountAmount Float @default(0)
336
+ finalAmount Float
337
+ shippingAddress String?
338
+ shippingFee Float @default(0)
339
+ note String?
340
+ voucherId String?
341
+ staffId String? // Staff who processed
342
+ client Client @relation(fields: [clientId], references: [id])
343
+ items OrderItem[]
344
+ logs LogOrder[]
345
+ createdAt DateTime @default(now())
346
+ updatedAt DateTime @updatedAt
347
+ }
348
+
349
+ model OrderItem {
350
+ id String @id @default(uuid())
351
+ orderId String
352
+ productId String
353
+ comboId String
354
+ quantity Int
355
+ price Float
356
+ order Order @relation(fields: [orderId], references: [id])
357
+ product StoreProduct @relation(fields: [productId], references: [id])
358
+ combo StoreProductCombo @relation(fields: [comboId], references: [id])
359
+ createdAt DateTime @default(now())
360
+ }
361
+
362
+ model LogOrder {
363
+ id String @id @default(uuid())
364
+ orderId String
365
+ type LogOrderType
366
+ note String?
367
+ userId String? // Staff who made the change
368
+ order Order @relation(fields: [orderId], references: [id])
369
+ createdAt DateTime @default(now())
370
+ }
371
+ ```
372
+
373
+ ### Vouchers & Rewards
374
+
375
+ ```prisma
376
+ model Voucher {
377
+ id String @id @default(uuid())
378
+ code String @unique
379
+ type VoucherType
380
+ value Float // Percentage or fixed amount
381
+ minOrder Float? // Minimum order to use
382
+ maxDiscount Float? // Max discount (for PERCENT type)
383
+ quantity Int // Total available
384
+ usedCount Int @default(0)
385
+ expiryDate DateTime?
386
+ isActive Boolean @default(true)
387
+ clients ClientVoucher[]
388
+ createdAt DateTime @default(now())
389
+ updatedAt DateTime @updatedAt
390
+ }
391
+
392
+ model ClientVoucher {
393
+ id String @id @default(uuid())
394
+ clientId String
395
+ voucherId String
396
+ isUsed Boolean @default(false)
397
+ usedAt DateTime?
398
+ client Client @relation(fields: [clientId], references: [id])
399
+ voucher Voucher @relation(fields: [voucherId], references: [id])
400
+ @@unique([clientId, voucherId])
401
+ }
402
+
403
+ model SpinReward {
404
+ id String @id @default(uuid())
405
+ name String
406
+ type RewardType
407
+ value Float // Points or voucher value
408
+ probability Float // 0-100 chance
409
+ isActive Boolean @default(true)
410
+ transactions SpinTransaction[]
411
+ createdAt DateTime @default(now())
412
+ updatedAt DateTime @updatedAt
413
+ }
414
+
415
+ model SpinTransaction {
416
+ id String @id @default(uuid())
417
+ clientId String
418
+ rewardId String
419
+ client Client @relation(fields: [clientId], references: [id])
420
+ reward SpinReward @relation(fields: [rewardId], references: [id])
421
+ createdAt DateTime @default(now())
422
+ }
423
+
424
+ model RedeemTransaction {
425
+ id String @id @default(uuid())
426
+ clientId String
427
+ points Int
428
+ description String?
429
+ client Client @relation(fields: [clientId], references: [id])
430
+ createdAt DateTime @default(now())
431
+ }
432
+ ```
433
+
434
+ ### eTelecom Integration
435
+
436
+ ```prisma
437
+ model EtelecomExtension {
438
+ id String @id @default(uuid())
439
+ extensionNumber String @unique
440
+ extensionPassword String
441
+ tenantId String?
442
+ tenantDomain String?
443
+ userId String? @unique // 1-to-1 with User
444
+ user User? @relation(fields: [userId], references: [id])
445
+ createdAt DateTime @default(now())
446
+ updatedAt DateTime @updatedAt
447
+ }
448
+
449
+ model OmiCall {
450
+ id String @id @default(uuid())
451
+ callId String @unique
452
+ direction String // inbound/outbound
453
+ fromNumber String
454
+ toNumber String
455
+ status String // answered, missed, busy
456
+ duration Int? // seconds
457
+ recordingUrl String?
458
+ responseData Json?
459
+ userId String? // Staff who handled
460
+ createdAt DateTime @default(now())
461
+ updatedAt DateTime @updatedAt
462
+ }
463
+ ```
464
+
465
+ ### Other
466
+
467
+ ```prisma
468
+ model ClientBank {
469
+ id String @id @default(uuid())
470
+ clientId String @unique
471
+ bankName String
472
+ accountNumber String
473
+ accountHolder String
474
+ client Client @relation(fields: [clientId], references: [id])
475
+ createdAt DateTime @default(now())
476
+ updatedAt DateTime @updatedAt
477
+ }
478
+ ```
479
+
480
+ ## Key Relationships Diagram
481
+
482
+ ```
483
+ Role ──< User ──? EtelecomExtension
484
+ └──< OmiCall
485
+
486
+ Client ──? Cart ──< CartItem ──> StoreProduct + StoreProductCombo
487
+ ──< Order ──< OrderItem ──> StoreProduct + StoreProductCombo
488
+ │ └──< LogOrder
489
+ ──< ClientVoucher ──> Voucher
490
+ ──? ClientBank
491
+ ──< SpinTransaction ──> SpinReward
492
+ ──< RedeemTransaction
493
+
494
+ Category (self-ref tree) ──< CategoryBrand ──> Brand
495
+ ──< ProductCategory ──> StoreProduct
496
+
497
+ StoreProduct ──< StoreProductCombo ──< StoreProductComboItem ──> InventoryProduct
498
+ ──< StoreProductComboPromotionHistory
499
+
500
+ InventoryProduct ──< ProductInventoryItem (lots with expiry)
501
+ ──< InventoryTransaction ──> InventorySession
502
+ ```
@@ -0,0 +1,169 @@
1
+ # Active Life Backend - Setup & Configuration
2
+
3
+ ## Project Location
4
+ ```
5
+ /Users/nhiensoft/Workspace/ginstudio/active-life/be-store-active-life-global/
6
+ ```
7
+
8
+ ## Prerequisites
9
+ - Node.js (ES2022 compatible)
10
+ - Yarn package manager
11
+ - PostgreSQL (Supabase recommended)
12
+ - Redis (optional, for caching)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ cd be-store-active-life-global
18
+ yarn install
19
+ yarn db:generate # Generate Prisma client
20
+ yarn dev # Start dev server with hot-reload
21
+ ```
22
+
23
+ ## Environment Variables
24
+
25
+ ### Required (.env)
26
+ ```env
27
+ DATABASE_URL="" # Supabase pooler connection (for runtime)
28
+ DIRECT_URL="" # Direct DB connection (for migrations)
29
+ PORT=3000 # Server port
30
+ JWT_CLIENT_ACCESS_TOKEN_SECRET="" # JWT signing secret
31
+ JWT_CLIENT_ACCESS_EXPIRE="15d" # Token expiry duration
32
+ ```
33
+
34
+ ### Supabase Connection Setup
35
+
36
+ **IMPORTANT**: Use the correct connection format for Supabase:
37
+
38
+ **Pooler URL (DATABASE_URL)** — for application runtime:
39
+ ```
40
+ postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres?pgbouncer=true
41
+ ```
42
+
43
+ **Direct URL (DIRECT_URL)** — for migrations only:
44
+ ```
45
+ postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres
46
+ ```
47
+
48
+ **Common Error**: "Tenant or user not found" — Make sure username is `postgres.[project-ref]` NOT just `postgres`.
49
+
50
+ ### Optional Environment Variables
51
+ ```env
52
+ # eTelecom
53
+ ETELECOM_URL= # eTelecom API base URL
54
+ AT_ETELECOM= # eTelecom API token
55
+
56
+ # Email
57
+ MAIL_HOST= # SMTP host
58
+ MAIL_PORT= # SMTP port
59
+ MAIL_USER= # SMTP username
60
+ MAIL_PASS= # SMTP password
61
+ MAIL_FROM= # Default sender
62
+
63
+ # Firebase
64
+ FIREBASE_PROJECT_ID=
65
+ FIREBASE_PRIVATE_KEY=
66
+ FIREBASE_CLIENT_EMAIL=
67
+
68
+ # Redis
69
+ REDIS_URL= # Redis connection URL
70
+
71
+ # MongoDB (if used)
72
+ MONGODB_URI= # MongoDB connection string
73
+ ```
74
+
75
+ ## Database Commands
76
+
77
+ ```bash
78
+ # Sync schema to database (keeps existing data)
79
+ yarn db:push
80
+
81
+ # Create and run a migration (production-ready)
82
+ yarn db:migrate
83
+
84
+ # Seed database with initial data
85
+ yarn db:seed
86
+
87
+ # Open Prisma Studio (GUI for database)
88
+ yarn db:studio
89
+
90
+ # Generate Prisma client (after schema changes)
91
+ yarn db:generate
92
+
93
+ # Reset database (DESTRUCTIVE - drops all data)
94
+ yarn db:reset
95
+ ```
96
+
97
+ ### Migration Workflow
98
+ 1. Edit `prisma/schema.prisma`
99
+ 2. Run `yarn db:push` for development (quick, keeps data)
100
+ 3. Run `yarn db:migrate` for production (creates migration files)
101
+ 4. Commit migration files to git
102
+
103
+ ## All Scripts (package.json)
104
+
105
+ ```bash
106
+ yarn dev # nest start --watch (hot-reload)
107
+ yarn build # nest build
108
+ yarn start # nest start
109
+ yarn start:prod # node dist/main
110
+ yarn start:debug # nest start --debug --watch
111
+ yarn lint # eslint --fix
112
+ yarn format # prettier --write
113
+ yarn test # jest
114
+ yarn test:watch # jest --watch
115
+ yarn test:cov # jest --coverage
116
+ yarn test:e2e # jest --config ./test/jest-e2e.json
117
+ ```
118
+
119
+ ## Configuration Files
120
+
121
+ ### nest-cli.json
122
+ - Builder: TypeScript compiler
123
+ - Assets: `mail/templates` copied to dist
124
+ - Source root: `src/`
125
+
126
+ ### tsconfig.json
127
+ - Target: ES2022
128
+ - Module: CommonJS
129
+ - Path alias: `@prisma/*` → `src/generated/prisma/*`
130
+ - Strict mode: Relaxed (noImplicitAny: false, strictNullChecks: false)
131
+
132
+ ### .prettierrc
133
+ ```json
134
+ {
135
+ "singleQuote": true,
136
+ "trailingComma": "all"
137
+ }
138
+ ```
139
+
140
+ ### .eslintrc.js
141
+ - Parser: @typescript-eslint
142
+ - Relaxed rules for rapid development
143
+
144
+ ## API Documentation
145
+
146
+ Swagger UI available at: `http://localhost:3000/api`
147
+
148
+ ## API Versioning
149
+
150
+ URI-based versioning:
151
+ - v1: `http://localhost:3000/api/v1/...`
152
+ - v2: `http://localhost:3000/api/v2/...`
153
+
154
+ Default version: v1 and v2 (both active)
155
+
156
+ ## CORS Configuration
157
+
158
+ All origins allowed (development mode):
159
+ ```typescript
160
+ app.enableCors({
161
+ origin: true,
162
+ methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
163
+ credentials: true,
164
+ });
165
+ ```
166
+
167
+ ## Rate Limiting
168
+
169
+ Global throttle: 10 requests per 60 seconds per IP.