Skip to content

Commit db8159b

Browse files
authored
Merge pull request #28 from tusharshah21/feat/database-schema-migration-setup
feat: implement database schema and migration system
2 parents ed60021 + 93d8603 commit db8159b

22 files changed

Lines changed: 3389 additions & 14 deletions

docs/DATABASE_SCHEMA.md

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
# PropChain Database Schema Documentation
2+
3+
## Overview
4+
5+
This document describes the complete PostgreSQL database schema for PropChain, including all entities, relationships, constraints, and indexes.
6+
7+
## Technology Stack
8+
9+
- **Database**: PostgreSQL 15+
10+
- **ORM**: Prisma 5.x
11+
- **Connection Pooling**: Prisma connection pool (configured via DATABASE_URL)
12+
13+
## Entity Relationship Diagram
14+
15+
```
16+
┌─────────────┐ ┌─────────────────┐ ┌───────────────┐
17+
│ User │───────│ Property │───────│ Transaction │
18+
└─────────────┘ └─────────────────┘ └───────────────┘
19+
│ │ │
20+
│ │ │
21+
▼ ▼ ▼
22+
┌─────────────┐ ┌─────────────────┐ ┌───────────────┐
23+
│ Role │ │ Document │◄──────│ Document │
24+
└─────────────┘ └─────────────────┘ └───────────────┘
25+
26+
27+
┌─────────────┐ ┌─────────────────┐
28+
│ Permission │◄──────│ RolePermission │
29+
└─────────────┘ └─────────────────┘
30+
```
31+
32+
## Models
33+
34+
### User
35+
36+
Primary user entity representing all platform participants.
37+
38+
| Field | Type | Constraints | Description |
39+
| ------------- | -------- | ----------------- | ------------------------ |
40+
| id | String | Primary Key, CUID | Unique identifier |
41+
| email | String | Unique, Not Null | User email address |
42+
| walletAddress | String | Unique, Nullable | Ethereum wallet address |
43+
| role | UserRole | Not Null, Default | User role enum |
44+
| roleId | String | Foreign Key | Reference to Role entity |
45+
| createdAt | DateTime | Default: now() | Creation timestamp |
46+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
47+
48+
**Indexes**: `email`, `walletAddress`, `role`, `createdAt`
49+
50+
**Relations**:
51+
52+
- One-to-Many: Properties (as owner)
53+
- One-to-Many: Transactions (as recipient via walletAddress)
54+
- One-to-Many: Documents (as uploader)
55+
- Many-to-One: Role
56+
- One-to-Many: RoleChangeLog
57+
58+
### Property
59+
60+
Real estate property listings.
61+
62+
| Field | Type | Constraints | Description |
63+
| ----------- | -------------- | ----------------- | ------------------------- |
64+
| id | String | Primary Key, CUID | Unique identifier |
65+
| title | String | Not Null | Property title |
66+
| description | String | Nullable | Property description |
67+
| location | String | Not Null | Property address/location |
68+
| price | Decimal | Not Null | Property price |
69+
| status | PropertyStatus | Not Null, Default | Listing status |
70+
| ownerId | String | Foreign Key | Reference to User (owner) |
71+
| createdAt | DateTime | Default: now() | Creation timestamp |
72+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
73+
74+
**Indexes**: `ownerId`, `status`, `createdAt`, `location`
75+
76+
**Relations**:
77+
78+
- Many-to-One: User (owner) - CASCADE delete
79+
- One-to-Many: Transactions
80+
- One-to-Many: Documents
81+
82+
### Transaction
83+
84+
Blockchain transactions for property purchases and transfers.
85+
86+
| Field | Type | Constraints | Description |
87+
| ----------- | ----------------- | --------------------- | --------------------------- |
88+
| id | String | Primary Key, CUID | Unique identifier |
89+
| fromAddress | String | Not Null | Sender wallet address |
90+
| toAddress | String | Not Null | Recipient wallet address |
91+
| amount | Decimal | Not Null | Transaction amount |
92+
| txHash | String | Nullable | Blockchain transaction hash |
93+
| status | TransactionStatus | Not Null, Default | Transaction status |
94+
| type | TransactionType | Not Null | Transaction type |
95+
| propertyId | String | Foreign Key, Nullable | Reference to Property |
96+
| createdAt | DateTime | Default: now() | Creation timestamp |
97+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
98+
99+
**Indexes**: `fromAddress`, `toAddress`, `status`, `createdAt`, `propertyId`
100+
101+
**Relations**:
102+
103+
- Many-to-One: Property - SET NULL on delete
104+
- Many-to-One: User (recipient via walletAddress)
105+
- One-to-Many: Documents
106+
107+
### Document
108+
109+
Document storage for property verification and transactions.
110+
111+
| Field | Type | Constraints | Description |
112+
| ------------- | -------------- | --------------------- | ----------------------------- |
113+
| id | String | Primary Key, CUID | Unique identifier |
114+
| name | String | Not Null | Document name |
115+
| type | DocumentType | Not Null | Document type enum |
116+
| status | DocumentStatus | Not Null, Default | Verification status |
117+
| fileUrl | String | Not Null | Storage URL |
118+
| fileHash | String | Nullable | Content hash for verification |
119+
| mimeType | String | Nullable | File MIME type |
120+
| fileSize | Int | Nullable | File size in bytes |
121+
| description | String | Nullable | Document description |
122+
| propertyId | String | Foreign Key, Nullable | Reference to Property |
123+
| transactionId | String | Foreign Key, Nullable | Reference to Transaction |
124+
| uploadedById | String | Foreign Key | Reference to User (uploader) |
125+
| verifiedAt | DateTime | Nullable | Verification timestamp |
126+
| expiresAt | DateTime | Nullable | Expiration date |
127+
| createdAt | DateTime | Default: now() | Creation timestamp |
128+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
129+
130+
**Indexes**: `propertyId`, `transactionId`, `uploadedById`, `type`, `status`, `createdAt`
131+
132+
**Relations**:
133+
134+
- Many-to-One: Property - SET NULL on delete
135+
- Many-to-One: Transaction - SET NULL on delete
136+
- Many-to-One: User (uploader) - CASCADE delete
137+
138+
### Role
139+
140+
RBAC role definitions.
141+
142+
| Field | Type | Constraints | Description |
143+
| ----------- | -------- | ----------------- | ------------------------ |
144+
| id | String | Primary Key, CUID | Unique identifier |
145+
| name | String | Unique, Not Null | Role name |
146+
| description | String | Nullable | Role description |
147+
| level | Int | Default: 0 | Role hierarchy level |
148+
| isSystem | Boolean | Default: false | System-defined role flag |
149+
| createdAt | DateTime | Default: now() | Creation timestamp |
150+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
151+
152+
**Relations**:
153+
154+
- One-to-Many: Users
155+
- One-to-Many: RolePermissions
156+
- One-to-Many: RoleChangeLog
157+
158+
### Permission
159+
160+
Granular permission definitions.
161+
162+
| Field | Type | Constraints | Description |
163+
| ----------- | -------- | ----------------- | ---------------------- |
164+
| id | String | Primary Key, CUID | Unique identifier |
165+
| resource | String | Not Null | Resource name |
166+
| action | String | Not Null | Action name (CRUD) |
167+
| description | String | Nullable | Permission description |
168+
| createdAt | DateTime | Default: now() | Creation timestamp |
169+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
170+
171+
**Unique Constraint**: `[resource, action]`
172+
173+
**Relations**:
174+
175+
- One-to-Many: RolePermissions
176+
177+
### ApiKey
178+
179+
API key management for external integrations.
180+
181+
| Field | Type | Constraints | Description |
182+
| ------------ | -------- | ----------------- | ----------------------------- |
183+
| id | String | Primary Key, CUID | Unique identifier |
184+
| name | String | Not Null | Key name/description |
185+
| key | String | Unique, Not Null | Hashed API key |
186+
| keyPrefix | String | Not Null | Key prefix for identification |
187+
| scopes | String[] | Not Null | Allowed scopes |
188+
| requestCount | BigInt | Default: 0 | Total request count |
189+
| lastUsedAt | DateTime | Nullable | Last usage timestamp |
190+
| isActive | Boolean | Default: true | Active status |
191+
| rateLimit | Int | Nullable | Requests per minute limit |
192+
| createdAt | DateTime | Default: now() | Creation timestamp |
193+
| updatedAt | DateTime | Auto-updated | Last update timestamp |
194+
195+
**Indexes**: `keyPrefix`, `isActive`, `createdAt`
196+
197+
## Enums
198+
199+
### UserRole
200+
201+
- `ADMIN` - Full system access
202+
- `AGENT` - Property management
203+
- `SELLER` - Can list properties
204+
- `BUYER` - Can purchase properties
205+
- `VIEWER` - Read-only access
206+
- `USER` - Standard user
207+
- `VERIFIED_USER` - Verified standard user
208+
209+
### PropertyStatus
210+
211+
- `DRAFT` - Not yet submitted
212+
- `PENDING` - Awaiting approval
213+
- `APPROVED` - Approved for listing
214+
- `LISTED` - Currently listed
215+
- `SOLD` - Property sold
216+
- `REMOVED` - Removed from listing
217+
218+
### TransactionStatus
219+
220+
- `PENDING` - Awaiting processing
221+
- `PROCESSING` - Currently processing
222+
- `COMPLETED` - Successfully completed
223+
- `FAILED` - Transaction failed
224+
- `CANCELLED` - Transaction cancelled
225+
226+
### TransactionType
227+
228+
- `PURCHASE` - Property purchase
229+
- `TRANSFER` - Property transfer
230+
- `ESCROW` - Escrow deposit
231+
- `REFUND` - Refund transaction
232+
233+
### DocumentType
234+
235+
- `TITLE_DEED` - Property title deed
236+
- `OWNERSHIP_CERTIFICATE` - Ownership certificate
237+
- `INSPECTION_REPORT` - Property inspection
238+
- `APPRAISAL` - Property appraisal
239+
- `INSURANCE` - Insurance documents
240+
- `TAX_DOCUMENT` - Tax-related documents
241+
- `CONTRACT` - Contracts and agreements
242+
- `IDENTITY` - Identity verification
243+
- `OTHER` - Other documents
244+
245+
### DocumentStatus
246+
247+
- `PENDING` - Awaiting verification
248+
- `VERIFIED` - Verified and valid
249+
- `REJECTED` - Rejected/invalid
250+
- `EXPIRED` - Document expired
251+
252+
## Database Configuration
253+
254+
### Connection String Format
255+
256+
```
257+
postgresql://[user]:[password]@[host]:[port]/[database]?connection_limit=10&pool_timeout=30
258+
```
259+
260+
### Connection Pooling Parameters
261+
262+
- `connection_limit` - Maximum number of connections (default: 10)
263+
- `pool_timeout` - Connection pool timeout in seconds (default: 30)
264+
265+
### Recommended Production Settings
266+
267+
```env
268+
DATABASE_URL="postgresql://postgres:password@localhost:5432/propchain?connection_limit=20&pool_timeout=30&statement_cache_size=100"
269+
```
270+
271+
## Migrations
272+
273+
### Running Migrations
274+
275+
```bash
276+
# Development
277+
npm run migrate
278+
279+
# Production
280+
npm run migrate:deploy
281+
282+
# Reset database (development only)
283+
npm run migrate:reset
284+
```
285+
286+
### Creating New Migrations
287+
288+
```bash
289+
npx prisma migrate dev --name <migration_name>
290+
```
291+
292+
## Seeding
293+
294+
### Run Seed Data
295+
296+
```bash
297+
npm run db:seed
298+
```
299+
300+
The seed script creates:
301+
302+
- System roles (Administrator, Agent, User)
303+
- Default permissions for each role
304+
- Sample users (admin, agent, buyer, seller)
305+
- Sample properties
306+
- Sample transactions
307+
- Sample documents
308+
- Development API keys
309+
310+
## Performance Considerations
311+
312+
### Index Strategy
313+
314+
All foreign keys and frequently queried fields are indexed. The following query patterns are optimized:
315+
316+
- User lookup by email/wallet
317+
- Property search by owner, status, location
318+
- Transaction lookup by addresses, status, property
319+
- Document retrieval by property, transaction, uploader
320+
321+
### Query Optimization Tips
322+
323+
1. Use `select` to limit returned fields
324+
2. Use `include` sparingly - prefer explicit joins
325+
3. Use pagination for large result sets
326+
4. Use transactions for related operations

0 commit comments

Comments
 (0)