# Previous NC Module — Backend Deploy Guide

This is **Chunk 1 of 3** for the Previous NC module migration from Laravel.

## What this delivers

A read-only NestJS backend that reads the legacy Laravel NC tables from both `qrs` and `tqs` databases, applies role-based access control, and generates the **Corrective & Preventive Action Request Form PDF** and **Attendance Sheet PDF** using Puppeteer (headless Chrome) — pixel-matched to the existing Laravel DomPDF output.

## File placement

Copy all files from this folder into:

```
/var/www/scheme_certiifcation/backend/src/previous-nc/
```

The final structure should look like:

```
backend/src/previous-nc/
├── controllers/
│   └── previous-nc.controller.ts
├── dto/
│   └── list-previous-ncs.dto.ts
├── entities/
│   ├── previous-nc.entity.ts
│   ├── previous-ncr-entry.entity.ts
│   ├── previous-nc-remark.entity.ts
│   ├── previous-nc-final-closure.entity.ts
│   ├── previous-nc-client.entity.ts
│   ├── previous-nc-surve.entity.ts
│   ├── previous-nc-standard.entity.ts
│   └── previous-nc-user.entity.ts
├── services/
│   ├── previous-nc.service.ts
│   └── previous-nc-pdf.service.ts
├── templates/
│   ├── nc-report.template.html
│   └── nc-attendance.template.html
└── previous-nc.module.ts
```

## Step 1 — Install npm dependencies

```bash
cd /var/www/scheme_certiifcation/backend
npm install puppeteer handlebars
npm install --save-dev @types/handlebars
```

Puppeteer auto-downloads a bundled Chromium (~170 MB) on first install. This may take a few minutes.

If your server lacks the system libs Chromium needs, install them once:

```bash
sudo apt-get update
sudo apt-get install -y \
  libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
  libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 \
  libxfixes3 libxrandr2 libgbm1 libpango-1.0-0 \
  libcairo2 libasound2t64 fonts-liberation
```

## Step 2 — Verify Chromium can launch

```bash
cd /var/www/scheme_certiifcation/backend
node -e "require('puppeteer').launch({args:['--no-sandbox']}).then(b => { console.log('OK'); return b.close(); }).catch(e => { console.error('FAIL:', e.message); process.exit(1); });"
```

If you see `OK` — Puppeteer works. If you see `FAIL` with a missing-library error, install the lib it names and retry.

## Step 3 — Register the module in app.module.ts

Open `/var/www/scheme_certiifcation/backend/src/app.module.ts` and:

1. Add the import at the top:

```typescript
import { PreviousNcModule } from './previous-nc/previous-nc.module';
```

2. Add `PreviousNcModule` to the `imports` array (near the other feature modules like `ClientsModule`).

## Step 4 — Make sure templates are included in the build output

NestJS compiles `.ts` to `.js` but **does not** copy `.html` template files. Open `/var/www/scheme_certiifcation/backend/nest-cli.json` and ensure the `assets` array includes the HTML templates:

```json
{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true,
    "assets": [
      "**/*.html",
      { "include": "previous-nc/templates/**/*.html", "outDir": "dist" }
    ],
    "watchAssets": true
  }
}
```

If `assets` was already there, just add the `previous-nc/templates/**/*.html` glob to it.

## Step 5 — Build and deploy

```bash
cd /var/www/scheme_certiifcation/backend
npm run build
pm2 restart scheme_c-backend
pm2 logs scheme_c-backend --lines 30
```

You should see:

```
[Nest] LOG ... [PreviousNcPdfService] [PREV-NC-PDF] Puppeteer launched, ready
[Nest] LOG ... [RoutesResolver] PreviousNcController {/previous-nc}: +Xms
[Nest] LOG ... [RouterExplorer] Mapped {/previous-nc/paged, GET} route +Xms
```

If Puppeteer fails to launch, the rest of the module still works — only PDF endpoints will error out.

## Step 6 — Test the endpoints

Use the token from earlier:

```bash
export TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImRldmVsb3BlcjFAYWx0YXlhYm9vbi5jb20iLCJzdWIiOjEsInJvbGVJZHMiOlsxLDMsNV0sInJvbGVOYW1lcyI6WyJTdXBlci1hZG1pbiIsInNjaGVtZSIsIkNvb3JkaW5hdG9yIl0sImlhdCI6MTc3OTQyOTY3MiwiZXhwIjoxNzc5NTE2MDcyfQ.nWakXU6aJVL6lCPCXD7dBMRVzcGtpUoseqUtajgIv0g"
```

### Test 1 — Paged list (combined QRS + TQS)

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/paged?page=1&limit=3" \
  -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

Expected: JSON with `rows[]`, `total`, `page`, `limit`, `totalPages`. Each row has `id`, `source: 'QRS'|'TQS'`, `company_name`, `audit_type`, `nc_type`, `status`, etc.

### Test 2 — Filter by source

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/paged?page=1&limit=3&source=QRS" \
  -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

### Test 3 — Filter by status and search

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/paged?page=1&limit=5&status=open&search=Belhasa" \
  -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

### Test 4 — Single NC detail

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/QRS/1571" \
  -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
```

Expected: object with `nc`, `entries[]`, `remarks[]`, `final_closures[]`.

### Test 5 — Generate PDF

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/QRS/1571/pdf" \
  -H "Authorization: Bearer $TOKEN" \
  -o /tmp/nc_1571.pdf

# Then open it
ls -lh /tmp/nc_1571.pdf
```

Should be a 30-80 KB PDF. Download it and verify it matches your Laravel PDF layout.

### Test 6 — Generate Attendance PDF

```bash
curl -s "https://web.qrsyst.com/api/previous-nc/QRS/1571/attendance-pdf" \
  -H "Authorization: Bearer $TOKEN" \
  -o /tmp/nc_1571_attendance.pdf

ls -lh /tmp/nc_1571_attendance.pdf
```

## Endpoints summary

| Method | Path | Purpose |
|---|---|---|
| GET | `/previous-nc/paged` | Paginated list with filters (source, status, nc_type, audit_type, search, date_from, date_to) |
| GET | `/previous-nc/:source/:id` | Single NC with all child data (entries, remarks, final closures) |
| GET | `/previous-nc/:source/:id/pdf` | Stream Corrective & Preventive Action Request Form PDF |
| GET | `/previous-nc/:source/:id/attendance-pdf` | Stream Attendance Sheet PDF |

`:source` = `QRS` or `TQS` (case-insensitive). `:id` = the NC id within that DB.

## Access control behavior

- **Super-admin / scheme / coordinator roles** → see ALL NCs from both QRS and TQS
- **Other roles** → see only NCs where `followed_up_by = userId` OR `closed_by = userId`

To change which roles see all, edit the `VIEW_ALL_ROLES` array in `services/previous-nc.service.ts`:

```typescript
const VIEW_ALL_ROLES = ['super-admin', 'scheme', 'coordinator'];
```

## Performance notes

- **Puppeteer** keeps a single Chromium instance alive — uses ~150 MB resident RAM at idle
- Each PDF request opens a new tab, renders, closes — adds ~30 MB during generation
- Cold first PDF: ~1-2 seconds. Subsequent PDFs: ~200-500ms
- Paged list queries hit both qrs and tqs in parallel, so latency is `max(qrs_time, tqs_time)`, not sum

If your server is RAM-constrained (you mentioned 8 GB available), monitor pm2 memory after deployment:

```bash
pm2 monit
```

## Troubleshooting

**Issue: `Error: Could not find Chromium`**
→ Puppeteer didn't finish downloading. Run `npx puppeteer browsers install chrome` inside the backend folder.

**Issue: `Failed to launch the browser process! ... libnss3.so: cannot open shared object`**
→ Install missing system libs from Step 1.

**Issue: `Template not compiled`**
→ The HTML templates weren't copied to `dist/`. Check Step 4 (`nest-cli.json` assets config) and rebuild.

**Issue: PDF works locally but 401 on production**
→ Token expired. Get a fresh one via login.

**Issue: Paged list returns empty for non-admin users**
→ Expected behavior — they only see NCs where they're `followed_up_by` or `closed_by`. Log in as a user with super-admin / scheme / coordinator role to see all.

## Next steps

Once Chunk 1 is deployed and the curl tests pass, ping me for:

- **Chunk 2** — Next.js frontend (NC list page + filters + view detail page + PDF link button)
- **Chunk 3** — Module #53 SQL registration, sidebar entry, permission grants

## Files in this delivery

Total: 13 files (8 entities + 1 DTO + 2 services + 1 controller + 1 module + 2 templates)
