# File Path Storage in Database - How It Works

This document explains how file paths and storage URLs are stored in the database for different storage scenarios (GCS vs Local Storage).

## Database Schema

### Documents Table
- **`file_path`** (VARCHAR(500), NOT NULL): Stores the relative path or GCS path
- **`storage_url`** (VARCHAR(500), NULLABLE): Stores the full URL for accessing the file

### Work Note Attachments Table
- **`file_path`** (VARCHAR(500), NOT NULL): Stores the relative path or GCS path
- **`storage_url`** (VARCHAR(500), NULLABLE): Stores the full URL for accessing the file

## Storage Scenarios

### Scenario 1: File Uploaded to GCS (Successfully)

When GCS is configured and the upload succeeds:

**Database Values:**
```sql
file_path = "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
storage_url = "https://storage.googleapis.com/bucket-name/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
```

**File Location:**
- Physical: Google Cloud Storage bucket
- Path Structure: `requests/{requestNumber}/{fileType}/{fileName}`
- Access: Public URL or signed URL (depending on bucket configuration)

---

### Scenario 2: File Saved to Local Storage (GCS Not Configured or Failed)

When GCS is not configured or upload fails, files are saved to local storage:

**Database Values:**
```sql
file_path = "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
storage_url = "/uploads/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf"
```

**File Location:**
- Physical: Local filesystem at `{UPLOAD_DIR}/requests/{requestNumber}/{fileType}/{fileName}`
- Path Structure: Same as GCS structure for consistency
- Access: Served via Express static middleware at `/uploads/*`

**Example:**
```
uploads/
└── requests/
    └── REQ-2025-12-0001/
        ├── documents/
        │   └── 1701234567890-abc123-proposal.pdf
        └── attachments/
            └── 1701234567890-xyz789-note.pdf
```

---

### Scenario 3: Legacy Files (Before This Implementation)

Older files may have different path formats:

**Possible Database Values:**
```sql
file_path = "/absolute/path/to/uploads/file.pdf"  -- Absolute path
-- OR
file_path = "file.pdf"  -- Simple filename (in root uploads folder)
storage_url = "/uploads/file.pdf"  -- Simple URL
```

**File Location:**
- Physical: Various locations depending on when file was uploaded
- Access: Handled by legacy route logic

---

## How Download/Preview Routes Handle Different Storage Types

### Document Preview Route (`GET /workflows/documents/:documentId/preview`)

1. **Check if GCS URL:**
   ```typescript
   const isGcsUrl = storageUrl && (
     storageUrl.startsWith('https://storage.googleapis.com') || 
     storageUrl.startsWith('gs://')
   );
   ```
   - If yes → Redirect to GCS URL

2. **Check if Local Storage URL:**
   ```typescript
   if (storageUrl && storageUrl.startsWith('/uploads/')) {
     res.redirect(storageUrl);  // Express static serves it
     return;
   }
   ```
   - If yes → Redirect to `/uploads/...` (served by Express static middleware)

3. **Legacy File Handling:**
   ```typescript
   const absolutePath = filePath && !path.isAbsolute(filePath) 
     ? path.join(UPLOAD_DIR, filePath) 
     : filePath;
   ```
   - Resolve relative path to absolute
   - Serve file directly using `res.sendFile()`

### Work Note Attachment Routes

Same logic as document routes:
- Preview: `/workflows/work-notes/attachments/:attachmentId/preview`
- Download: `/workflows/work-notes/attachments/:attachmentId/download`

---

## Key Points

### 1. Consistent Path Structure
- **Both GCS and local storage** use the same path structure: `requests/{requestNumber}/{fileType}/{fileName}`
- This makes migration seamless when moving from local to GCS

### 2. Storage URL Format
- **GCS:** Full HTTPS URL (`https://storage.googleapis.com/...`)
- **Local:** Relative URL (`/uploads/requests/...`)
- **Legacy:** May vary

### 3. File Path Format
- **GCS:** Relative path in bucket (`requests/REQ-.../documents/file.pdf`)
- **Local:** Same relative path format for consistency
- **Legacy:** May be absolute path or simple filename

### 4. Automatic Fallback
- When GCS fails, system automatically saves to local storage
- Same folder structure maintained
- No data loss

### 5. Serving Files
- **GCS files:** Redirect to public/signed URL
- **Local files (new):** Redirect to `/uploads/...` (Express static)
- **Local files (legacy):** Direct file serving with `res.sendFile()`

---

## Migration Path

When migrating from local storage to GCS:

1. **Files already follow same structure** - No path changes needed
2. **Upload new files** - They automatically go to GCS if configured
3. **Existing files** - Can remain in local storage until migrated
4. **Database** - Only `storage_url` field changes (from `/uploads/...` to `https://...`)

---

## Example Database Records

### GCS File (New Upload)
```json
{
  "document_id": "uuid-123",
  "file_path": "requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf",
  "storage_url": "https://storage.googleapis.com/my-bucket/requests/REQ-2025-12-0001/documents/1701234567890-abc123-proposal.pdf",
  "file_name": "1701234567890-abc123-proposal.pdf",
  "original_file_name": "proposal.pdf"
}
```

### Local Storage File (Fallback)
```json
{
  "document_id": "uuid-456",
  "file_path": "requests/REQ-2025-12-0001/documents/1701234567891-def456-report.pdf",
  "storage_url": "/uploads/requests/REQ-2025-12-0001/documents/1701234567891-def456-report.pdf",
  "file_name": "1701234567891-def456-report.pdf",
  "original_file_name": "report.pdf"
}
```

### Legacy File (Old Format)
```json
{
  "document_id": "uuid-789",
  "file_path": "/var/app/uploads/old-file.pdf",
  "storage_url": "/uploads/old-file.pdf",
  "file_name": "old-file.pdf",
  "original_file_name": "old-file.pdf"
}
```

---

## Troubleshooting

### Issue: File not found when downloading

**Check:**
1. Verify `storage_url` format in database
2. Check if file exists at expected location:
   - GCS: Check bucket and path
   - Local: Check `{UPLOAD_DIR}/requests/...` path
3. Verify Express static middleware is mounted at `/uploads`

### Issue: Files not organizing correctly

**Check:**
1. Verify `requestNumber` is being passed correctly to upload functions
2. Check folder structure matches: `requests/{requestNumber}/{fileType}/`
3. Verify `fileType` is either `'documents'` or `'attachments'`

