Commit a90e14ed authored by ThinhNC's avatar ThinhNC

docs: add memory tracking documentation and update README instructions

parent aea9be81
......@@ -25,10 +25,8 @@ File này chỉ lưu sự thật và quyết định dài hạn giúp các phiê
- Chưa có test script hoặc test suite trong `package.json`.
- `lint` script tồn tại nhưng repository hiện chưa có ESLint config; không coi
lint là verification khả dụng cho tới khi config được bổ sung.
- Port trong tài liệu/cấu hình chưa đồng nhất: README ghi `3000`,
`env.config.ts` mặc định `8888`, `.env.example` dùng `7777`.
- README và một số chuỗi tiếng Việt đang có dấu hiệu sai encoding. Không mở rộng
phạm vi để sửa hàng loạt nếu công việc hiện tại không yêu cầu.
- `env.config.ts` dùng port fallback `8888`, còn `.env.example` dùng `7777`; README
ghi rõ cả hai và dùng `7777` cho hướng dẫn chạy theo file env mẫu.
- Budget chưa được expose qua route. Wallet, Category và Transaction đã có API theo
ownership; Category đồng thời trả các category hệ thống dùng chung.
- Các migration `20260728170000_improve_wallet_management`
......
# FinWise BE - Sổ tay Chi tiêu & Báo cáo Tài chính (Zalo Mini App)
# FinWise Backend
Backend API service for FinWise mini-app. Hiện tại backend cung cấp:
Backend API cho **FinWise - Sổ tay Chi tiêu & Báo cáo Tài chính**, phục vụ Zalo Mini App.
- Xác thực người dùng JWT
- Quản lý tài khoản người dùng
- Health check hệ thống
API hiện hỗ trợ:
## Tech Stack
- Đăng ký, xác thực email, đăng nhập JWT và quản lý phiên đăng nhập.
- Quản lý hồ sơ, mật khẩu và khôi phục mật khẩu qua email.
- Quản trị người dùng theo role.
- Quản lý ví, danh mục thu/chi và giao dịch theo ownership.
- Tự động cập nhật số dư ví khi tạo, sửa hoặc xóa giao dịch.
- Lưu hóa đơn giao dịch dạng JPEG, PNG, WebP hoặc PDF.
- Swagger UI và health check.
- **Node.js** & **Express** with **TypeScript**
- **Prisma ORM** with **PostgreSQL** (Supabase)
- **JWT Authentication** & **Role-Based Access Control**
- **Zod** for schema validation
## Công nghệ
---
- Node.js, Express 4 và TypeScript
- PostgreSQL và Prisma ORM 5
- Zod cho validation
- JWT, cookie và role-based access control
- Helmet, CORS và rate limiting
- Nodemailer cho email xác thực và khôi phục mật khẩu
- pnpm 9
## Core Models
## Yêu cầu
Dựa trên Prisma schema hiện tại, repository chứa các model chính sau:
- Node.js 18 trở lên
- pnpm 9 (`packageManager` của dự án là `pnpm@9.15.0`)
- PostgreSQL
- Docker và Docker Compose nếu muốn chạy database bằng container
- **User**: Email, mật khẩu, tên, trạng thái và role.
- **Wallet**: Ví người dùng.
- **Category**: Danh mục thu/chi.
- **Transaction**: Giao dịch thu/chi.
- **Budget**: Ngân sách theo danh mục.
- **RefreshToken**: Lưu refresh token cho đăng nhập lâu dài.
## Cài đặt
> Lưu ý: hiện tại các route public/active trong project chỉ bao gồm Auth và Users.
### 1. Cài dependency
---
```bash
pnpm install
```
### 2. Tạo file môi trường
Sao chép `.env.example` thành `.env`, sau đó thay các placeholder bằng cấu hình local:
```powershell
Copy-Item .env.example .env
```
Trên macOS/Linux:
## Getting Started
```bash
cp .env.example .env
```
Các biến chính:
| Biến | Mục đích |
| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| `PORT` | Port HTTP; `.env.example` dùng `7777`, fallback của ứng dụng là `8888` |
| `DATABASE_URL` | PostgreSQL connection string dùng bởi Prisma |
| `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` | Thành phần kết nối để các script Prisma dựng `DATABASE_URL` khi biến này chưa có |
| `JWT_ACCESS_SECRET`, `JWT_REFRESH_SECRET` | Khóa ký access token và refresh token |
| `JWT_ACCESS_EXPIRES_IN`, `JWT_REFRESH_EXPIRES_IN` | Thời hạn token |
| `MAIL_HOST`, `MAIL_PORT`, `MAIL_SECURE`, `MAIL_USER`, `MAIL_PASS`, `MAIL_FROM` | Cấu hình SMTP |
| `APP_URL` | Base URL dùng trong email xác thực/khôi phục mật khẩu |
| `ALLOWED_ORIGINS` | Danh sách origin được phép, phân tách bằng dấu phẩy |
| `TRUST_PROXY` | Cấu hình Express `trust proxy` |
| `RECEIPT_UPLOAD_DIR` | Thư mục lưu hóa đơn, mặc định `storage/receipts` |
| `RECEIPT_MAX_FILE_SIZE_MB` | Dung lượng hóa đơn tối đa, mặc định `5`, giới hạn cấu hình là `25` |
### Prerequisites
Không dùng các JWT secret mặc định hoặc thông tin SMTP mẫu ở môi trường thật.
- Node.js (v18+)
- pnpm (recommended) or npm
### 3. Khởi động PostgreSQL
### Installation
Nếu đã có PostgreSQL local, cập nhật thông tin kết nối trong `.env`.
1. Clone the repository.
2. Install dependencies:
```bash
pnpm install
```
3. Set up your environment file:
- Copy `.env.example` to `.env`
- Fill in your connection strings and JWT keys:
```env
DATABASE_URL=your_supabase_pooler_url
DIRECT_URL=your_supabase_direct_url
JWT_ACCESS_SECRET=your_access_secret
JWT_REFRESH_SECRET=your_refresh_secret
```
Hoặc khởi động service PostgreSQL có sẵn trong Docker Compose:
```bash
docker compose up -d postgres
```
### Database Initialization
### 4. Chuẩn bị database
Apply migrations and run the seeding script:
Validate schema, generate Prisma Client, apply migration hiện có và seed dữ liệu:
```bash
# Validate Prisma schema
npx prisma validate
pnpm exec prisma validate
pnpm run prisma:generate
pnpm run db:migrate:deploy
pnpm run db:seed
```
> Migration history hiện đã bao phủ schema khởi tạo và các thay đổi của Wallet,
> Category, Transaction, nhưng chưa phản ánh đầy đủ một số thay đổi Auth và Budget
> đã có trong `schema.prisma`. Khi dựng database hoàn toàn mới, cần bổ sung migration
> còn thiếu trước khi coi schema đã đồng bộ; không dùng `db push` thay cho migration
> ở môi trường chia sẻ/production.
# Run migrations
npx prisma migrate dev --name init_finwise
Khi phát triển schema và cần tạo migration mới:
# Seed initial data
npm run db:seed
```bash
pnpm run db:migrate -- --name ten_migration
```
_Default Admin credentials:_
Không dùng `db:migrate:reset` trên database có dữ liệu cần giữ.
- **Email**: `admin@finwise.local`
- **Password**: `Admin@123456`
### 5. Chạy ứng dụng
### Running the App
Development:
Start the development server:
```bash
pnpm dev
```
Production build:
```bash
npm run dev
pnpm build
pnpm start
```
Với `.env.example`, các địa chỉ local là:
- API base URL: `http://localhost:7777/api/v1`
- Swagger UI: `http://localhost:7777/api/docs`
- Health check: `http://localhost:7777/api/v1/health`
## Xác thực
Các endpoint được bảo vệ nhận access token qua header:
```http
Authorization: Bearer <accessToken>
```
Refresh token cũng được trả qua cookie HTTP-only ở luồng đăng nhập/refresh. Xem Swagger UI để biết request body và response schema chi tiết.
## API hiện có
Tất cả endpoint bên dưới có prefix `/api/v1`.
### System
| Method | Endpoint | Quyền | Mô tả |
| ------ | --------- | ------ | ----------------------- |
| `GET` | `/health` | Public | Kiểm tra trạng thái API |
### Auth
| Method | Endpoint | Quyền | Mô tả |
| -------- | --------------------------- | ------ | --------------------------------- |
| `POST` | `/auth/register` | Public | Đăng ký tài khoản |
| `GET` | `/auth/verify-email` | Public | Xác thực email bằng token |
| `POST` | `/auth/login` | Public | Đăng nhập |
| `GET` | `/auth/me` | Bearer | Lấy thông tin người dùng hiện tại |
| `POST` | `/auth/refresh` | Public | Làm mới cặp token |
| `POST` | `/auth/logout` | Public | Thu hồi refresh token |
| `PUT` | `/auth/profile` | Bearer | Cập nhật hồ sơ |
| `PUT` | `/auth/password` | Bearer | Đổi mật khẩu |
| `POST` | `/auth/forgot-password` | Public | Gửi email khôi phục mật khẩu |
| `POST` | `/auth/reset-password` | Public | Đặt lại mật khẩu bằng token |
| `POST` | `/auth/resend-verification` | Public | Gửi lại email xác thực |
| `GET` | `/auth/sessions` | Bearer | Liệt kê phiên đăng nhập |
| `DELETE` | `/auth/sessions/:id` | Bearer | Thu hồi một phiên |
| `DELETE` | `/auth/sessions` | Bearer | Thu hồi các phiên khác |
### Users
Toàn bộ nhóm này yêu cầu access token và role `ADMIN`.
| Method | Endpoint | Mô tả |
| -------- | ------------ | -------------------------------------------------- |
| `GET` | `/users` | Danh sách người dùng có filter, sort và pagination |
| `GET` | `/users/:id` | Chi tiết người dùng |
| `POST` | `/users` | Tạo người dùng |
| `PUT` | `/users/:id` | Cập nhật trạng thái hoặc role |
| `DELETE` | `/users/:id` | Soft-delete người dùng |
### Wallets
Toàn bộ nhóm này yêu cầu access token và chỉ thao tác trên ví của chính người dùng.
| Method | Endpoint | Mô tả |
| -------- | ---------------------- | ------------------------------------------ |
| `GET` | `/wallets` | Danh sách ví có filter, sort và pagination |
| `POST` | `/wallets` | Tạo ví |
| `GET` | `/wallets/:id` | Chi tiết ví |
| `PUT` | `/wallets/:id` | Cập nhật ví |
| `PATCH` | `/wallets/:id/default` | Đặt ví mặc định |
| `PATCH` | `/wallets/:id/restore` | Khôi phục ví đã archive |
| `DELETE` | `/wallets/:id` | Archive ví |
### Categories
Toàn bộ nhóm này yêu cầu access token. Category hệ thống được dùng chung và chỉ đọc; người dùng chỉ sửa hoặc archive category do mình tạo.
| Method | Endpoint | Mô tả |
| -------- | ------------------------- | ------------------------------------------------------ |
| `GET` | `/categories` | Danh sách category hệ thống và category của người dùng |
| `GET` | `/categories/tree` | Danh sách category dạng cây |
| `POST` | `/categories` | Tạo category |
| `GET` | `/categories/:id` | Chi tiết category |
| `PUT` | `/categories/:id` | Cập nhật category |
| `PATCH` | `/categories/:id/restore` | Khôi phục category đã archive |
| `DELETE` | `/categories/:id` | Archive category và nhánh con thuộc người dùng |
### Transactions
Toàn bộ nhóm này yêu cầu access token và chỉ thao tác trên dữ liệu của chính người dùng.
| Method | Endpoint | Mô tả |
| -------- | --------------------------- | ------------------------------------------------------ |
| `GET` | `/transactions` | Danh sách giao dịch có filter, sort và pagination |
| `POST` | `/transactions` | Tạo giao dịch và cập nhật số dư ví |
| `GET` | `/transactions/:id` | Chi tiết giao dịch |
| `PUT` | `/transactions/:id` | Cập nhật giao dịch và cân chỉnh số dư ví |
| `DELETE` | `/transactions/:id` | Xóa giao dịch và hoàn tác ảnh hưởng lên số dư |
| `PUT` | `/transactions/:id/receipt` | Upload hoặc thay hóa đơn qua field multipart `receipt` |
| `GET` | `/transactions/:id/receipt` | Xem hoặc tải hóa đơn |
| `DELETE` | `/transactions/:id/receipt` | Xóa hóa đơn |
> Model `Budget` đã có trong Prisma schema nhưng chưa được expose qua API.
## Dữ liệu seed
Lệnh `pnpm run db:seed` tạo ba role (`ADMIN`, `MANAGER`, `USER`), các category hệ thống và các tài khoản local:
| Role | Email | Password |
| --------- | ----------------------- | ---------------- |
| `ADMIN` | `admin@finwise.local` | `Admin@123456` |
| `MANAGER` | `manager@finwise.local` | `Manager@123456` |
| `USER` | `user@finwise.local` | `User@123456` |
Các tài khoản này chỉ dành cho development. Hãy đổi hoặc xóa chúng trước khi dùng database ở môi trường chia sẻ/production.
## Cấu trúc dự án
```text
src/
├── common/ # Constant, error, helper, service và type dùng chung
├── config/ # Env, database, JWT, mail và Swagger
├── database/ # Prisma Client
├── middlewares/ # Auth, role, validation, rate limit và error handler
├── modules/
│ ├── auth/
│ ├── users/
│ ├── wallets/
│ ├── categories/
│ └── transactions/
├── routes/ # Mount route dưới /api/v1
├── app.ts # Cấu hình Express
└── server.ts # HTTP entry point
prisma/
├── migrations/ # Lịch sử migration
├── schema.prisma # Database schema
└── seed.ts # Role, tài khoản local và category hệ thống
scripts/
└── prisma-run.js # Wrapper chạy Prisma với env của dự án
```
The server runs on http://localhost:3000 by default.
Luồng xử lý chuẩn của một module:
Swagger UI is available at `http://localhost:3000/api/docs`.
```text
route -> validation -> controller -> service -> repository -> Prisma/PostgreSQL
```
---
## Scripts
## API Endpoints
| Lệnh | Mô tả |
| ---------------------------- | -------------------------------------- |
| `pnpm dev` | Chạy development server với hot reload |
| `pnpm build` | Compile TypeScript vào `dist/` |
| `pnpm start` | Chạy build trong `dist/` |
| `pnpm run prisma:generate` | Generate Prisma Client |
| `pnpm run prisma:studio` | Mở Prisma Studio |
| `pnpm run db:migrate` | Tạo/apply migration trong development |
| `pnpm run db:migrate:deploy` | Apply migration hiện có |
| `pnpm run db:migrate:status` | Xem trạng thái migration |
| `pnpm run db:seed` | Seed dữ liệu development |
| `pnpm format` | Format repository bằng Prettier |
- **System**:
- `GET /api/v1/health`: Health check.
- **Auth** (`/api/v1/auth`):
- `POST /login`: Authenticate user and receive access/refresh tokens.
- `GET /me`: Get current authenticated user details.
- `POST /refresh`: Refresh JWT tokens.
- `POST /logout`: Invalidate refresh token.
- **Users** (`/api/v1/users`) (Admin only):
- `GET /`: Get all users with optional filters, sorting, and pagination.
- `GET /:id`: Get user details by ID.
- `POST /`: Create a new user account.
- `PUT /:id`: Update user status or role.
Repository hiện chưa có test suite. Script `lint` đã được khai báo nhưng chưa có ESLint config, vì vậy verification khả dụng hiện tại là Prisma validation và TypeScript build.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment