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.
- package/.wrangler/cache/pages.json +4 -0
- package/.wrangler/cache/wrangler-account.json +6 -0
- package/DEVELOPMENT.md +510 -0
- package/README.md +104 -0
- package/agents/developer.md +56 -0
- package/agents/frontend-design.md +69 -0
- package/agents/mobile-reviewer.md +36 -0
- package/agents/review-code.md +49 -0
- package/agents/security-scanner.md +50 -0
- package/agents/tester.md +72 -0
- package/bin/cli.js +461 -0
- package/landing/ai-build-ai.png +0 -0
- package/landing/index.html +1495 -0
- package/landing/logo.png +0 -0
- package/package.json +37 -0
- package/skills/active-life-dev/SKILL.md +157 -0
- package/skills/active-life-dev/docs/auth.md +187 -0
- package/skills/active-life-dev/docs/customers.md +216 -0
- package/skills/active-life-dev/docs/integrations.md +209 -0
- package/skills/active-life-dev/docs/inventory.md +192 -0
- package/skills/active-life-dev/docs/modules.md +181 -0
- package/skills/active-life-dev/docs/orders.md +180 -0
- package/skills/active-life-dev/docs/patterns.md +319 -0
- package/skills/active-life-dev/docs/products.md +216 -0
- package/skills/active-life-dev/docs/schema.md +502 -0
- package/skills/active-life-dev/docs/setup.md +169 -0
- package/skills/active-life-dev/docs/vouchers.md +144 -0
- package/skills/ai-asset-generator/SKILL.md +247 -0
- package/skills/ai-asset-generator/docs/gen-image.md +274 -0
- package/skills/ai-asset-generator/docs/genvideo.md +341 -0
- package/skills/ai-asset-generator/docs/remove-background.md +19 -0
- package/skills/ai-asset-generator/lib/bg-remove.mjs +34 -0
- package/skills/ai-asset-generator/lib/env.mjs +48 -0
- package/skills/ai-asset-generator/lib/kie-client.mjs +100 -0
- package/skills/ai-build-ai/SKILL.md +127 -0
- package/skills/ai-build-ai/docs/agent-teams.md +293 -0
- package/skills/ai-build-ai/docs/checkpointing.md +161 -0
- package/skills/ai-build-ai/docs/create-agent.md +399 -0
- package/skills/ai-build-ai/docs/create-mcp.md +395 -0
- package/skills/ai-build-ai/docs/create-skill.md +299 -0
- package/skills/ai-build-ai/docs/headless-mode.md +614 -0
- package/skills/ai-build-ai/docs/hooks.md +578 -0
- package/skills/ai-build-ai/docs/memory-claude-md.md +375 -0
- package/skills/ai-build-ai/docs/output-styles.md +208 -0
- package/skills/ai-build-ai/docs/overview.md +162 -0
- package/skills/ai-build-ai/docs/permissions.md +391 -0
- package/skills/ai-build-ai/docs/plugins.md +396 -0
- package/skills/ai-build-ai/docs/sandbox.md +262 -0
- package/skills/ai-build-ai/docs/team-lead-workflow.md +648 -0
- package/skills/ant-design/SKILL.md +323 -0
- package/skills/ant-design/docs/components.md +160 -0
- package/skills/ant-design/docs/data-entry.md +406 -0
- package/skills/ant-design/docs/display.md +594 -0
- package/skills/ant-design/docs/feedback.md +451 -0
- package/skills/ant-design/docs/key-components.md +414 -0
- package/skills/ant-design/docs/navigation.md +310 -0
- package/skills/ant-design/docs/pro-components.md +543 -0
- package/skills/ant-design/docs/setup.md +213 -0
- package/skills/ant-design/docs/theme.md +265 -0
- package/skills/flutter-performance/SKILL.md +803 -0
- package/skills/flutter-performance/references/flutter-patterns.md +595 -0
- package/skills/icon-generator/SKILL.md +270 -0
- package/skills/mobile-app-review/SKILL.md +321 -0
- package/skills/mobile-app-review/references/apple-review.md +132 -0
- package/skills/mobile-app-review/references/google-play-review.md +203 -0
- package/skills/mongodb/SKILL.md +667 -0
- package/skills/mongodb/references/mongoose-patterns.md +368 -0
- package/skills/nestjs-architecture/SKILL.md +1086 -0
- package/skills/nestjs-architecture/references/advanced-patterns.md +590 -0
- package/skills/performance/SKILL.md +509 -0
- package/skills/react-fsd-architecture/SKILL.md +693 -0
- package/skills/react-fsd-architecture/references/fsd-patterns.md +747 -0
- package/skills/react-native-expo/SKILL.md +128 -0
- package/skills/react-native-expo/references/data-layer.md +252 -0
- package/skills/react-native-expo/references/design-system.md +252 -0
- package/skills/react-native-expo/references/navigation.md +199 -0
- package/skills/react-native-expo/references/performance.md +229 -0
- package/skills/react-native-expo/references/platform-services.md +179 -0
- package/skills/react-native-expo/references/state-management.md +209 -0
- package/skills/react-native-expo/references/ui-patterns.md +301 -0
- package/skills/react-query/SKILL.md +685 -0
- package/skills/react-query/references/query-patterns.md +365 -0
- package/skills/review-code/SKILL.md +374 -0
- package/skills/review-code/references/clean-code-principles.md +395 -0
- package/skills/review-code/references/frontend-patterns.md +136 -0
- package/skills/review-code/references/nestjs-patterns.md +184 -0
- package/skills/security-scanner/SKILL.md +366 -0
- package/skills/security-scanner/references/nestjs-security.md +260 -0
- package/skills/security-scanner/references/nextjs-security.md +201 -0
- package/skills/security-scanner/references/react-native-security.md +199 -0
- package/skills/traefik/SKILL.md +105 -0
- package/skills/traefik/docs/advanced-routing.md +186 -0
- package/skills/traefik/docs/auth-providers.md +137 -0
- package/skills/traefik/docs/cicd-devops.md +396 -0
- package/skills/traefik/docs/core-config.md +171 -0
- package/skills/traefik/docs/distributed-config.md +96 -0
- package/skills/traefik/docs/docker-compose.md +182 -0
- package/skills/traefik/docs/ha-performance.md +177 -0
- package/skills/traefik/docs/kubernetes.md +278 -0
- package/skills/traefik/docs/middleware.md +205 -0
- package/skills/traefik/docs/monitoring.md +357 -0
- package/skills/traefik/docs/security.md +391 -0
- package/skills/traefik/docs/tls-acme.md +155 -0
- package/skills/ui-ux-pro-max/SKILL.md +377 -0
- package/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
package/landing/logo.png
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ginskill-init",
|
|
3
|
+
"version": "2.7.0",
|
|
4
|
+
"description": "Install GinStudio skills and agents for Claude Code",
|
|
5
|
+
"homepage": "https://skills.ginstudio.asia",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://gitlab.com/ginstudio/skills.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"claude-code",
|
|
12
|
+
"claude",
|
|
13
|
+
"skills",
|
|
14
|
+
"agents",
|
|
15
|
+
"ai"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"gen-readme": "node scripts/gen-readme.mjs",
|
|
21
|
+
"check-upstream": "node scripts/check-upstream.mjs",
|
|
22
|
+
"deploy": "npx wrangler pages deploy landing --project-name ginskill --branch main",
|
|
23
|
+
"prepublishOnly": "node scripts/check-upstream.mjs && node scripts/gen-readme.mjs"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"ginskill-init": "bin/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"chalk": "^5.3.0",
|
|
33
|
+
"commander": "^12.1.0",
|
|
34
|
+
"ora": "^8.1.1",
|
|
35
|
+
"prompts": "^2.4.2"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: active-life-dev
|
|
3
|
+
description: |
|
|
4
|
+
**Active Life Backend Dev Guide**: Comprehensive development guide for the Active Life Global Store NestJS backend (be-store-active-life-global). Covers architecture, modules, Prisma schema, DTOs, auth, patterns, integrations, and coding conventions.
|
|
5
|
+
- MANDATORY TRIGGERS: active life, backend, be-store, nestjs, prisma, module, controller, service, dto, guard, interceptor, order, product, inventory, voucher, cart, client, auth, etelecom, category, brand, report, seed, role, user, customer source, customer status, interaction, unit, api endpoint, database schema, migration
|
|
6
|
+
- Use this skill when the user asks about backend architecture, wants to create/modify modules, needs to understand the database schema, wants to follow project conventions, or is working on any feature in the be-store-active-life-global project.
|
|
7
|
+
argument-hint: "[module | schema | auth | patterns | integrations | setup | orders | products | inventory | vouchers | customers | all]"
|
|
8
|
+
user-invocable: true
|
|
9
|
+
disable-model-invocation: false
|
|
10
|
+
allowed-tools: Read, Grep, Glob, Bash, Edit, Write
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Active Life Backend Development Guide
|
|
14
|
+
|
|
15
|
+
You are an expert NestJS developer working on the **Active Life Global Store** backend.
|
|
16
|
+
|
|
17
|
+
## Quick Context Loading
|
|
18
|
+
|
|
19
|
+
Load the relevant documentation based on what you need:
|
|
20
|
+
|
|
21
|
+
!`bash skills/skills/active-life-dev/scripts/load-docs.sh $ARGUMENTS`
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Project Location
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
/Users/nhiensoft/Workspace/ginstudio/active-life/be-store-active-life-global/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Tech Stack
|
|
32
|
+
|
|
33
|
+
| Layer | Technology |
|
|
34
|
+
|-------|-----------|
|
|
35
|
+
| Framework | NestJS 10.x (Express) |
|
|
36
|
+
| Language | TypeScript (ES2022, CommonJS) |
|
|
37
|
+
| Database | PostgreSQL (Supabase) |
|
|
38
|
+
| ORM | Prisma 7.x with @prisma/adapter-pg |
|
|
39
|
+
| Auth | Passport + JWT (dual: User staff + Client customer) |
|
|
40
|
+
| Validation | class-validator + class-transformer |
|
|
41
|
+
| API Docs | Swagger / OpenAPI |
|
|
42
|
+
| Cache | Redis (ioredis) |
|
|
43
|
+
| Email | Nodemailer (@nestjs-modules/mailer) |
|
|
44
|
+
| Notifications | Firebase Admin SDK |
|
|
45
|
+
| Phone | eTelecom SIP integration |
|
|
46
|
+
| Rate Limit | @nestjs/throttler (10 req/60s) |
|
|
47
|
+
| API Versioning | URI-based (v1, v2) |
|
|
48
|
+
|
|
49
|
+
## Architecture Overview
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
src/
|
|
53
|
+
├── app.module.ts # Root module - imports all feature modules
|
|
54
|
+
├── main.ts # Bootstrap: guards, pipes, interceptors, CORS, Swagger
|
|
55
|
+
├── core/ # Global interceptors & guards
|
|
56
|
+
│ ├── transform.interceptor.ts # { statusCode, message, data } response wrapper
|
|
57
|
+
│ ├── logging.interceptor.ts # Request/response logging with timing
|
|
58
|
+
│ ├── roles.guard.ts # Role-based access control
|
|
59
|
+
│ └── query.guard.ts
|
|
60
|
+
├── decorators/ # @Public, @ResponseMessage, @User, @Client, @Roles
|
|
61
|
+
├── interface/ # IUser, IClient, PaginateInfo
|
|
62
|
+
├── generated/prisma/ # Auto-generated Prisma types
|
|
63
|
+
└── [feature-modules]/ # 23 feature modules (see docs/modules.md)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Key Patterns (MUST follow)
|
|
67
|
+
|
|
68
|
+
### 1. Module Structure
|
|
69
|
+
Every module follows: `module.ts` + `controller.ts` + `service.ts` + `dto/` folder.
|
|
70
|
+
|
|
71
|
+
### 2. Response Format
|
|
72
|
+
All responses are wrapped by TransformInterceptor:
|
|
73
|
+
```typescript
|
|
74
|
+
{ statusCode: number, message?: string, data: any }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. Auth - Dual JWT System
|
|
78
|
+
- **User (staff)**: `JwtAuthGuard` (default on all routes) → `@User()` decorator
|
|
79
|
+
- **Client (customer)**: `jwt-client` strategy → `@Client()` decorator
|
|
80
|
+
- **Public routes**: `@Public()` decorator skips auth
|
|
81
|
+
|
|
82
|
+
### 4. DTO Validation
|
|
83
|
+
```typescript
|
|
84
|
+
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
|
|
85
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
86
|
+
|
|
87
|
+
export class CreateXxxDto {
|
|
88
|
+
@ApiProperty()
|
|
89
|
+
@IsString()
|
|
90
|
+
@IsNotEmpty()
|
|
91
|
+
name: string;
|
|
92
|
+
|
|
93
|
+
@ApiProperty({ required: false })
|
|
94
|
+
@IsOptional()
|
|
95
|
+
@IsString()
|
|
96
|
+
description?: string;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 5. Service Pattern
|
|
101
|
+
```typescript
|
|
102
|
+
@Injectable()
|
|
103
|
+
export class XxxService {
|
|
104
|
+
constructor(private prismaService: PrismaService) {}
|
|
105
|
+
|
|
106
|
+
async create(dto: CreateXxxDto) {
|
|
107
|
+
return this.prismaService.xxx.create({ data: dto });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 6. Error Handling
|
|
113
|
+
Use NestJS exceptions: `BadRequestException`, `NotFoundException`, `ForbiddenException`.
|
|
114
|
+
|
|
115
|
+
### 7. Database Commands
|
|
116
|
+
```bash
|
|
117
|
+
yarn db:push # Sync schema (keep data)
|
|
118
|
+
yarn db:migrate # Create & run migrations
|
|
119
|
+
yarn db:seed # Seed database
|
|
120
|
+
yarn db:studio # Prisma Studio GUI
|
|
121
|
+
yarn dev # Dev with hot-reload
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Documentation Files
|
|
127
|
+
|
|
128
|
+
Load specific docs when you need deeper detail:
|
|
129
|
+
|
|
130
|
+
| Doc | Content | When to Read |
|
|
131
|
+
|-----|---------|-------------|
|
|
132
|
+
| `docs/modules.md` | All 23 modules with controllers, services, DTOs | Creating/modifying any module |
|
|
133
|
+
| `docs/schema.md` | Complete Prisma schema (36 models, 7 enums) | Database changes, relations, queries |
|
|
134
|
+
| `docs/auth.md` | JWT strategies, guards, decorators, roles | Auth changes, protected endpoints |
|
|
135
|
+
| `docs/patterns.md` | Coding conventions, service patterns, error handling | Writing new code |
|
|
136
|
+
| `docs/integrations.md` | eTelecom, Firebase, Redis, Email, Mongoose | External service work |
|
|
137
|
+
| `docs/setup.md` | Environment vars, Supabase config, scripts | Setup, deployment, config |
|
|
138
|
+
| `docs/orders.md` | Order lifecycle, statuses, refunds, returns | Order feature work |
|
|
139
|
+
| `docs/products.md` | Products, combos, categories, brands, inventory | Product/catalog work |
|
|
140
|
+
| `docs/inventory.md` | Inventory sessions, transactions, lot tracking | Inventory/warehouse work |
|
|
141
|
+
| `docs/vouchers.md` | Vouchers, rewards, spins, redemptions | Promotion feature work |
|
|
142
|
+
| `docs/customers.md` | Client management, sources, statuses, interactions | CRM feature work |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Creating a New Module Checklist
|
|
147
|
+
|
|
148
|
+
1. Create folder: `src/<module-name>/`
|
|
149
|
+
2. Create files: `<name>.module.ts`, `<name>.controller.ts`, `<name>.service.ts`
|
|
150
|
+
3. Create DTOs in `dto/` subfolder with class-validator decorators
|
|
151
|
+
4. Add Prisma model to `prisma/schema.prisma` if new table needed
|
|
152
|
+
5. Run `yarn db:push` or `yarn db:migrate` to sync schema
|
|
153
|
+
6. Import module in `app.module.ts`
|
|
154
|
+
7. Add `@ApiTags('module-name')` to controller
|
|
155
|
+
8. Add `@ApiBearerAuth()` to protected endpoints
|
|
156
|
+
9. Use `@Public()` for public endpoints
|
|
157
|
+
10. Follow existing service patterns (PrismaService injection, async/await)
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Active Life Backend - Authentication & Authorization
|
|
2
|
+
|
|
3
|
+
## Dual JWT System
|
|
4
|
+
|
|
5
|
+
The app has two separate authentication flows:
|
|
6
|
+
1. **User (Staff)** — Internal employees (Admin, TeleSales, LiveChat, Agency)
|
|
7
|
+
2. **Client (Customer)** — End-users / shoppers
|
|
8
|
+
|
|
9
|
+
Both use JWT Bearer tokens but different strategies and payloads.
|
|
10
|
+
|
|
11
|
+
## JWT Strategies
|
|
12
|
+
|
|
13
|
+
### JwtStrategy (Staff - Default)
|
|
14
|
+
**File**: `src/auth/passport/jwt.strategy.ts`
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// Extracts from: Authorization: Bearer <token>
|
|
18
|
+
// Secret: JWT_CLIENT_ACCESS_TOKEN_SECRET
|
|
19
|
+
// Payload shape:
|
|
20
|
+
interface IJwtPayload {
|
|
21
|
+
id: string;
|
|
22
|
+
phone: string;
|
|
23
|
+
name: string;
|
|
24
|
+
role: { id: string; name: string };
|
|
25
|
+
etelecom?: { extensionNumber: string; extensionPassword: string; tenantId: string; tenantDomain: string };
|
|
26
|
+
}
|
|
27
|
+
// Returns: IUser
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### JwtClientStrategy (Customer)
|
|
31
|
+
**File**: `src/auth/passport/jwt-client.strategy.ts`
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Named strategy: 'jwt-client'
|
|
35
|
+
// Extracts from: Authorization: Bearer <token>
|
|
36
|
+
// Secret: JWT_CLIENT_ACCESS_TOKEN_SECRET (same secret)
|
|
37
|
+
// Payload shape:
|
|
38
|
+
interface IJwtClientPayload {
|
|
39
|
+
id: string;
|
|
40
|
+
phone: string;
|
|
41
|
+
name: string;
|
|
42
|
+
point: number;
|
|
43
|
+
}
|
|
44
|
+
// Returns: IClient with type='client'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Guards
|
|
48
|
+
|
|
49
|
+
### JwtAuthGuard (Global)
|
|
50
|
+
**File**: `src/auth/jwt-auth.guard.ts`
|
|
51
|
+
- Applied globally in `main.ts`
|
|
52
|
+
- Checks `@Public()` metadata — if present, skips auth
|
|
53
|
+
- After validation, checks `user.isBan` — returns 403 if banned
|
|
54
|
+
- Default: all routes require authentication
|
|
55
|
+
|
|
56
|
+
### RolesGuard
|
|
57
|
+
**File**: `src/core/roles.guard.ts`
|
|
58
|
+
- Works with `@Roles()` decorator
|
|
59
|
+
- Checks if authenticated user's role matches required roles
|
|
60
|
+
- Applied per-route, not globally
|
|
61
|
+
|
|
62
|
+
## Custom Decorators
|
|
63
|
+
|
|
64
|
+
**File**: `src/decorators/customize.ts`
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// Skip authentication for a route
|
|
68
|
+
@Public()
|
|
69
|
+
|
|
70
|
+
// Set custom response message (used by TransformInterceptor)
|
|
71
|
+
@ResponseMessage('Custom message here')
|
|
72
|
+
|
|
73
|
+
// Get current authenticated user (staff)
|
|
74
|
+
@User() user: IUser
|
|
75
|
+
|
|
76
|
+
// Get current authenticated client (customer)
|
|
77
|
+
@Client() client: IClient
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**File**: `src/decorators/roles.decorator.ts`
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Require specific roles
|
|
84
|
+
@Roles('Admin', 'TeleSales')
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Interfaces
|
|
88
|
+
|
|
89
|
+
**File**: `src/interface/users.interface.ts`
|
|
90
|
+
```typescript
|
|
91
|
+
interface IUser {
|
|
92
|
+
id: string;
|
|
93
|
+
phone: string;
|
|
94
|
+
name: string;
|
|
95
|
+
email?: string;
|
|
96
|
+
roleName: string;
|
|
97
|
+
role: { id: string; name: string };
|
|
98
|
+
etelecom?: { ... };
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**File**: `src/interface/client.interface.ts`
|
|
103
|
+
```typescript
|
|
104
|
+
interface IClient {
|
|
105
|
+
id: string;
|
|
106
|
+
phone: string;
|
|
107
|
+
name: string;
|
|
108
|
+
point: number;
|
|
109
|
+
type: 'client';
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Auth Controller Endpoints
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
POST /api/v1/auth/login — Staff login (phone + password)
|
|
117
|
+
POST /api/v1/auth/register — Staff register (admin only)
|
|
118
|
+
POST /api/v1/auth/client-login — Client login (phone + password)
|
|
119
|
+
POST /api/v1/auth/client-register — Client register
|
|
120
|
+
POST /api/v1/auth/client-zalo — Client Zalo OAuth login
|
|
121
|
+
GET /api/v1/auth/profile — Get current user profile
|
|
122
|
+
GET /api/v1/auth/client-profile — Get current client profile
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Role-Based Access Patterns
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// Admin only
|
|
129
|
+
@Roles('Admin')
|
|
130
|
+
@UseGuards(RolesGuard)
|
|
131
|
+
|
|
132
|
+
// Multiple roles
|
|
133
|
+
@Roles('Admin', 'TeleSales', 'LiveChat')
|
|
134
|
+
@UseGuards(RolesGuard)
|
|
135
|
+
|
|
136
|
+
// Public endpoint (no auth)
|
|
137
|
+
@Public()
|
|
138
|
+
|
|
139
|
+
// Client endpoint (use jwt-client guard)
|
|
140
|
+
@UseGuards(AuthGuard('jwt-client'))
|
|
141
|
+
|
|
142
|
+
// Staff endpoint (default - no extra decorator needed)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Password Handling
|
|
146
|
+
- Hashing: `bcryptjs` with salt rounds
|
|
147
|
+
- Stored as hashed string in User.password and Client.password
|
|
148
|
+
- Client.password is optional (Zalo login doesn't require it)
|
|
149
|
+
|
|
150
|
+
## Token Configuration
|
|
151
|
+
- Secret: `JWT_CLIENT_ACCESS_TOKEN_SECRET` env var
|
|
152
|
+
- Expiry: `JWT_CLIENT_ACCESS_EXPIRE` env var (default: "15d")
|
|
153
|
+
- Algorithm: Default HS256
|
|
154
|
+
|
|
155
|
+
## Common Auth Patterns
|
|
156
|
+
|
|
157
|
+
### Protecting a staff-only endpoint
|
|
158
|
+
```typescript
|
|
159
|
+
@Controller('admin')
|
|
160
|
+
@ApiTags('admin')
|
|
161
|
+
@ApiBearerAuth()
|
|
162
|
+
export class AdminController {
|
|
163
|
+
@Get('dashboard')
|
|
164
|
+
@Roles('Admin')
|
|
165
|
+
@UseGuards(RolesGuard)
|
|
166
|
+
getDashboard(@User() user: IUser) {
|
|
167
|
+
// user is guaranteed to be authenticated staff with Admin role
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Creating a public + client endpoint
|
|
173
|
+
```typescript
|
|
174
|
+
@Controller('shop')
|
|
175
|
+
@ApiTags('shop')
|
|
176
|
+
export class ShopController {
|
|
177
|
+
@Get('products')
|
|
178
|
+
@Public() // Anyone can browse
|
|
179
|
+
getProducts() { }
|
|
180
|
+
|
|
181
|
+
@Post('checkout')
|
|
182
|
+
@UseGuards(AuthGuard('jwt-client'))
|
|
183
|
+
checkout(@Client() client: IClient) {
|
|
184
|
+
// client is guaranteed to be authenticated customer
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Active Life Backend - Customer Management (CRM)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The CRM system tracks customers through their lifecycle with:
|
|
6
|
+
- Source tracking (where they came from)
|
|
7
|
+
- Status management (lifecycle stage)
|
|
8
|
+
- Staff assignment (who manages them)
|
|
9
|
+
- Interaction tracking (calls, chats, visits)
|
|
10
|
+
- Bank information (for refunds)
|
|
11
|
+
|
|
12
|
+
## Client Model (Customer)
|
|
13
|
+
|
|
14
|
+
```prisma
|
|
15
|
+
model Client {
|
|
16
|
+
id String @id @default(uuid())
|
|
17
|
+
phone String @unique
|
|
18
|
+
email String?
|
|
19
|
+
name String
|
|
20
|
+
password String? // Optional (Zalo login doesn't need it)
|
|
21
|
+
avatar String?
|
|
22
|
+
dob DateTime?
|
|
23
|
+
gender String?
|
|
24
|
+
|
|
25
|
+
// Address
|
|
26
|
+
address String?
|
|
27
|
+
province String?
|
|
28
|
+
district String?
|
|
29
|
+
ward String?
|
|
30
|
+
|
|
31
|
+
// Loyalty
|
|
32
|
+
point Int @default(0)
|
|
33
|
+
|
|
34
|
+
// Status
|
|
35
|
+
isBan Boolean @default(false)
|
|
36
|
+
note String?
|
|
37
|
+
tags String[]
|
|
38
|
+
|
|
39
|
+
// CRM Assignment
|
|
40
|
+
customerSourceId String? // Where they came from
|
|
41
|
+
customerStatusId String? // Lifecycle status
|
|
42
|
+
customerDetailStatusId String? // Detailed status
|
|
43
|
+
livechatStaffId String? // Assigned LiveChat staff
|
|
44
|
+
telesalesStaffId String? // Assigned TeleSales staff
|
|
45
|
+
agencyStaffId String? // Assigned Agency staff
|
|
46
|
+
|
|
47
|
+
// Lifecycle Dates
|
|
48
|
+
firstCallAt DateTime? // First phone call
|
|
49
|
+
lastOrderAt DateTime? // Most recent order
|
|
50
|
+
|
|
51
|
+
// Relations
|
|
52
|
+
orders Order[]
|
|
53
|
+
cart Cart?
|
|
54
|
+
vouchers ClientVoucher[]
|
|
55
|
+
bank ClientBank?
|
|
56
|
+
spinTransactions SpinTransaction[]
|
|
57
|
+
redeemTransactions RedeemTransaction[]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## CRM Lookup Tables
|
|
62
|
+
|
|
63
|
+
### Customer Source
|
|
64
|
+
Where the customer came from:
|
|
65
|
+
```
|
|
66
|
+
Examples: Facebook, Zalo, Website, Walk-in, Referral, Google Ads, TikTok
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Customer Status
|
|
70
|
+
Lifecycle stage:
|
|
71
|
+
```
|
|
72
|
+
Examples: New, Contacted, Active, Inactive, Lost, VIP
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Customer Detail Status
|
|
76
|
+
Granular status within lifecycle:
|
|
77
|
+
```
|
|
78
|
+
Examples: Interested, Following Up, Purchased, Repeat Customer, Churned
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Interaction Status
|
|
82
|
+
Call/chat connection status:
|
|
83
|
+
```
|
|
84
|
+
Examples: Connected, No Answer, Busy, Voicemail, Line Disconnected
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Interaction Result
|
|
88
|
+
Outcome of interaction:
|
|
89
|
+
```
|
|
90
|
+
Examples: Interested, Not Interested, Callback Requested, Order Placed, Info Sent
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Interaction Type
|
|
94
|
+
How the interaction happened:
|
|
95
|
+
```
|
|
96
|
+
Examples: Phone Call, Zalo Message, In-Store Visit, Email, Facebook Message
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
All lookup tables follow the same pattern:
|
|
100
|
+
```prisma
|
|
101
|
+
model CustomerSource {
|
|
102
|
+
id String @id @default(uuid())
|
|
103
|
+
name String @unique
|
|
104
|
+
description String?
|
|
105
|
+
createdAt DateTime @default(now())
|
|
106
|
+
updatedAt DateTime @updatedAt
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Staff Assignment
|
|
111
|
+
|
|
112
|
+
Customers can be assigned to three types of staff:
|
|
113
|
+
- **LiveChat Staff** — Handles online chat support
|
|
114
|
+
- **TeleSales Staff** — Handles phone sales
|
|
115
|
+
- **Agency Staff** — Handles agency/partner relationships
|
|
116
|
+
|
|
117
|
+
Each is a reference to User (staff) by ID.
|
|
118
|
+
|
|
119
|
+
## Bank Information
|
|
120
|
+
|
|
121
|
+
For refund processing:
|
|
122
|
+
```prisma
|
|
123
|
+
model ClientBank {
|
|
124
|
+
id String @id @default(uuid())
|
|
125
|
+
clientId String @unique // 1-to-1
|
|
126
|
+
bankName String
|
|
127
|
+
accountNumber String
|
|
128
|
+
accountHolder String
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Key API Endpoints
|
|
133
|
+
|
|
134
|
+
### Client Management
|
|
135
|
+
```
|
|
136
|
+
GET /api/v1/client — List clients (staff, paginated, filterable)
|
|
137
|
+
GET /api/v1/client/:id — Get client detail (staff)
|
|
138
|
+
POST /api/v1/client — Create client (staff)
|
|
139
|
+
PATCH /api/v1/client/:id — Update client (staff)
|
|
140
|
+
DELETE /api/v1/client/:id — Delete client (staff)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Client Self-Service
|
|
144
|
+
```
|
|
145
|
+
GET /api/v1/client/profile — Get own profile (client auth)
|
|
146
|
+
PATCH /api/v1/client/self-update — Update own profile (client auth)
|
|
147
|
+
PATCH /api/v1/client/bank-info — Update bank info (client auth)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Lookup Tables (all follow same pattern)
|
|
151
|
+
```
|
|
152
|
+
GET /api/v1/customer-source — List sources
|
|
153
|
+
POST /api/v1/customer-source — Create source (staff)
|
|
154
|
+
PATCH /api/v1/customer-source/:id — Update source (staff)
|
|
155
|
+
DELETE /api/v1/customer-source/:id — Delete source (staff)
|
|
156
|
+
|
|
157
|
+
# Same pattern for:
|
|
158
|
+
# /api/v1/customer-status
|
|
159
|
+
# /api/v1/customer-detail-status
|
|
160
|
+
# /api/v1/interaction-status
|
|
161
|
+
# /api/v1/interaction-result
|
|
162
|
+
# /api/v1/interaction-type
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Client Filtering (Staff View)
|
|
166
|
+
|
|
167
|
+
Staff can filter clients by:
|
|
168
|
+
- `customerSourceId` — Filter by source
|
|
169
|
+
- `customerStatusId` — Filter by lifecycle status
|
|
170
|
+
- `customerDetailStatusId` — Filter by detail status
|
|
171
|
+
- `livechatStaffId` — Filter by assigned LiveChat staff
|
|
172
|
+
- `telesalesStaffId` — Filter by assigned TeleSales staff
|
|
173
|
+
- `agencyStaffId` — Filter by assigned agency
|
|
174
|
+
- `search` — Search by name or phone
|
|
175
|
+
- `tags` — Filter by tags
|
|
176
|
+
- `isBan` — Filter banned/active
|
|
177
|
+
|
|
178
|
+
## Ads Source
|
|
179
|
+
|
|
180
|
+
Tracking advertising campaign sources:
|
|
181
|
+
```prisma
|
|
182
|
+
model AdsSource {
|
|
183
|
+
id String @id @default(uuid())
|
|
184
|
+
name String @unique
|
|
185
|
+
description String?
|
|
186
|
+
createdAt DateTime @default(now())
|
|
187
|
+
updatedAt DateTime @updatedAt
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Customer Lifecycle Flow
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
New Customer Registration
|
|
195
|
+
│
|
|
196
|
+
▼
|
|
197
|
+
Source Assigned (Facebook, Zalo, etc.)
|
|
198
|
+
│
|
|
199
|
+
▼
|
|
200
|
+
Status: "New" → Staff Assigned (TeleSales/LiveChat)
|
|
201
|
+
│
|
|
202
|
+
▼
|
|
203
|
+
First Contact (firstCallAt recorded)
|
|
204
|
+
│
|
|
205
|
+
▼
|
|
206
|
+
Interactions Tracked (calls, chats)
|
|
207
|
+
│
|
|
208
|
+
▼
|
|
209
|
+
Status Updates (Interested → Following Up → Active)
|
|
210
|
+
│
|
|
211
|
+
▼
|
|
212
|
+
First Order (lastOrderAt recorded)
|
|
213
|
+
│
|
|
214
|
+
▼
|
|
215
|
+
Repeat Customer → VIP
|
|
216
|
+
```
|