# Week 7: Paper Export Module - Implementation Guide

## Overview

This document provides comprehensive documentation for the Week 7 Paper Export Module implementation, including all features developed across Days 1-5.

## Table of Contents

1. [Day 1-2: DOCX Export](#day-1-2-docx-export)
2. [Day 3: Test Series Assignment to Groups](#day-3-test-series-assignment-to-groups)
3. [Day 4: Standalone Answer Key Export](#day-4-standalone-answer-key-export)
4. [Day 5: Unified PDF Service](#day-5-unified-pdf-service)
5. [Architecture](#architecture)
6. [Testing](#testing)

---

## Day 1-2: DOCX Export

### Implementation Summary

Created a fully-featured DOCX export service using PhpOffice/PhpWord library to export test series with questions, options, and optional answer keys.

### Files Created/Modified

- **Service**: `/app/Services/DocxExportService.php`
- **Controller**: `/app/Http/Controllers/Api/V2/TutorController.php` (added `exportTestSeriesToDocx` method)
- **Routes**: `/routes/api.php` (added Week 7 routes)

### Features

✅ School logo/header integration
✅ Test title, duration, and marks display
✅ Questions numbered sequentially (1, 2, 3...)
✅ Options formatted as a) b) c) d)
✅ CKEditor HTML formatting preserved
✅ Image embedding support (base64 and remote URLs)
✅ Answer key on separate page (optional)
✅ LaTeX formula handling (converted to plain text)
✅ Two-column layout for compact options
✅ Professional document styling

### API Endpoint

**POST** `/api/v2/tutor/test-series/{id}/export-docx`

### Request Parameters

```json
{
  "include_answers": false,      // Optional: Include answer key
  "include_solutions": false,    // Optional: Include detailed solutions
  "watermark": false            // Optional: Add watermark (future feature)
}
```

### cURL Example

```bash
# Export test series to DOCX without answers
curl -X POST "https://your-domain.com/api/v2/tutor/test-series/1674/export-docx" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "include_answers": false,
    "include_solutions": false
  }'
```

```bash
# Export test series to DOCX with answers and solutions
curl -X POST "https://your-domain.com/api/v2/tutor/test-series/1674/export-docx" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "include_answers": true,
    "include_solutions": true
  }'
```

### Response Example

```json
{
  "status": true,
  "message": "DOCX file generated successfully",
  "file_path": "https://your-domain.com/testseries_docx/testseries_abc123_1699999999.docx",
  "file_name": "testseries_abc123_1699999999.docx"
}
```

### Document Structure

```
┌─────────────────────────────────┐
│     School Logo (if exists)     │
│        School Name              │
│      School Address             │
│                                 │
│      Question Paper             │
├─────────────────────────────────┤
│ Test Title: Mathematics Test    │
│ Date: _______________           │
│ Total Marks: 100                │
│ Duration: 180 minutes           │
│ Student Name: _______________   │
│ Roll Number: ________________   │
├─────────────────────────────────┤
│ Section: Physics                │
│                                 │
│ 1. Question text here?  [2 Marks]│
│    a) Option 1    b) Option 2   │
│    c) Option 3    d) Option 4   │
│                                 │
│ 2. Another question...  [1 Mark]│
│    ...                          │
└─────────────────────────────────┘
```

---

## Day 3: Test Series Assignment to Groups

### Implementation Summary

Enhanced the variant generation system to properly handle group assignments, allowing test series and their variants (A/B/C) to be assigned to different groups/batches.

### Features

✅ Assign test series to multiple groups
✅ Automatic variant distribution across groups
✅ Parent-child relationship maintenance
✅ Support for A/B/C variants
✅ Random or sequential variant assignment
✅ Track which groups have which variants
✅ Student count per group

### API Endpoints

#### 1. Assign Test Series to Groups

**POST** `/api/v2/tutor/test-series/{id}/assign-to-groups`

##### Request Body

```json
{
  "group_ids": [1, 2, 3, 4, 5],     // Required: Array of group IDs
  "distribute_variants": true        // Optional: Distribute A/B/C variants across groups
}
```

##### cURL Example

```bash
# Assign test to groups with variant distribution
curl -X POST "https://your-domain.com/api/v2/tutor/test-series/1674/assign-to-groups" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "group_ids": [1, 2, 3, 4, 5],
    "distribute_variants": true
  }'
```

##### Response

```json
{
  "status": true,
  "message": "Test series assigned to groups successfully",
  "assignments": [
    {
      "group_id": 1,
      "test_series_id": 1674,
      "variant": "original"
    },
    {
      "group_id": 2,
      "test_series_id": 1675,
      "variant": "A"
    },
    {
      "group_id": 3,
      "test_series_id": 1676,
      "variant": "B"
    },
    {
      "group_id": 4,
      "test_series_id": 1677,
      "variant": "C"
    },
    {
      "group_id": 5,
      "test_series_id": 1674,
      "variant": "original"
    }
  ]
}
```

#### 2. Get Assigned Groups

**GET** `/api/v2/tutor/test-series/{id}/groups`

##### cURL Example

```bash
# Get all groups assigned to a test series
curl -X GET "https://your-domain.com/api/v2/tutor/test-series/1674/groups" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN"
```

##### Response

```json
{
  "status": true,
  "message": "Groups retrieved successfully",
  "test_series_name": "Mathematics Final Exam",
  "total_groups": 5,
  "assignments": [
    {
      "group_id": 1,
      "group_name": "Batch A - Class 10",
      "school_id": 4,
      "test_series_id": 1674,
      "variant": "original",
      "student_count": 35,
      "assigned_at": "2025-01-13 10:30:00"
    },
    {
      "group_id": 2,
      "group_name": "Batch B - Class 10",
      "school_id": 4,
      "test_series_id": 1675,
      "variant": "A",
      "student_count": 32,
      "assigned_at": "2025-01-13 10:30:00"
    }
  ]
}
```

### How Variant Distribution Works

When `distribute_variants` is set to `true`:

1. System checks if test has variants (A/B/C)
2. If variants exist, distributes them across groups in round-robin fashion:
   - Group 1 → Original
   - Group 2 → Variant A
   - Group 3 → Variant B
   - Group 4 → Variant C
   - Group 5 → Original (cycles back)
3. Each group gets a different variant to prevent cheating

---

## Day 4: Standalone Answer Key Export

### Implementation Summary

Created a dedicated service for generating standalone answer keys in both PDF and DOCX formats, with optional detailed solutions.

### Files Created

- **Service**: `/app/Services/AnswerKeyService.php`
- **Controller**: Added `exportAnswerKey` method to TutorController

### Features

✅ Generate answer key in PDF or DOCX format
✅ Compact two-column layout
✅ Question number → Correct answer mapping
✅ Optional detailed solutions
✅ Set variant identification (A/B/C)
✅ School branding
✅ Section-wise organization

### API Endpoint

**POST** `/api/v2/tutor/test-series/{id}/export-answer-key`

### Request Parameters

```json
{
  "format": "pdf",              // Required: "pdf" or "docx"
  "include_solutions": false    // Optional: Include detailed solutions
}
```

### cURL Examples

```bash
# Generate PDF answer key (no solutions)
curl -X POST "https://your-domain.com/api/v2/tutor/test-series/1674/export-answer-key" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "pdf",
    "include_solutions": false
  }'
```

```bash
# Generate DOCX answer key with solutions
curl -X POST "https://your-domain.com/api/v2/tutor/test-series/1674/export-answer-key" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "docx",
    "include_solutions": true
  }'
```

### Response

```json
{
  "status": true,
  "message": "Pdf answer key generated successfully",
  "file_path": "https://your-domain.com/testseries_answerkey/answerkey_abc123_1699999999.pdf",
  "file_name": "answerkey_abc123_1699999999.pdf"
}
```

### Answer Key Format

```
┌─────────────────────────────────────┐
│         Answer Key                  │
│  Mathematics Final Exam - Set A     │
│      Pathshalaa School              │
└─────────────────────────────────────┘

Section: Physics
┌──────────┬──────────┬──────────┐
│ Q1: B    │ Q11: A   │ Q21: C   │
│ Q2: A    │ Q12: D   │ Q22: B   │
│ Q3: C    │ Q13: B   │ Q23: A   │
│ Q4: D    │ Q14: C   │ Q24: D   │
│ Q5: B    │ Q15: A   │ Q25: B   │
│ Q6: A    │ Q16: D   │ Q26: A   │
│ Q7: C    │ Q17: B   │ Q27: C   │
│ Q8: D    │ Q18: A   │ Q28: D   │
│ Q9: B    │ Q19: C   │ Q29: B   │
│ Q10: A   │ Q20: D   │ Q30: A   │
└──────────┴──────────┴──────────┘

Section: Chemistry
...
```

---

## Day 5: Unified PDF Service

### Implementation Summary

Consolidated all 6 PDF generation methods from PDFController into a single, maintainable service with configurable options.

### Files Created

- **Service**: `/app/Services/UnifiedPdfService.php`

### Features

✅ Multiple PDF generation methods (Browsershot, Snappy)
✅ Configurable options for all scenarios
✅ Watermark support with FPDI
✅ Answer highlighting (optional)
✅ Solution inclusion (optional)
✅ Image processing and embedding
✅ Custom margins and formatting
✅ Set variant support

### Usage Examples

```php
use App\Services\UnifiedPdfService;

// Basic PDF generation
$pdfService = new UnifiedPdfService();
$result = $pdfService->generate(1674);

// PDF with answers highlighted
$result = $pdfService->generate(1674, [
    'include_answers' => true,
    'watermark' => true
]);

// PDF with Snappy instead of Browsershot
$result = $pdfService->generate(1674, [
    'method' => UnifiedPdfService::METHOD_SNAPPY,
    'include_answers' => false,
    'watermark' => true
]);

// Custom margins and format
$result = $pdfService->generate(1674, [
    'format' => 'A4',
    'orientation' => 'portrait',
    'margins' => [
        'top' => 20,
        'bottom' => 20,
        'left' => 15,
        'right' => 15
    ]
]);
```

### Available Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `method` | string | `'browsershot'` | PDF generation method: `'browsershot'` or `'snappy'` |
| `include_answers` | boolean | `false` | Highlight correct answers in green |
| `include_solutions` | boolean | `false` | Include detailed solutions |
| `watermark` | boolean | `true` | Apply watermark to PDF |
| `set_variant` | string | `null` | Set variant (A/B/C) identifier |
| `with_images` | boolean | `true` | Process and embed images |
| `format` | string | `'A4'` | Paper format |
| `orientation` | string | `'portrait'` | Page orientation |
| `margins` | array | See below | Page margins in mm |

Default margins:
```php
'margins' => [
    'top' => 15,
    'bottom' => 15,
    'left' => 15,
    'right' => 15
]
```

### Previous PDFController Methods Audit

The PDFController had 6 different PDF generation methods:

1. **DownloadTestseries_PDF_BrowserShot** (lines 31-141)
   - Uses Browsershot with Chrome headless
   - Applies watermark with FPDI
   - Saves to database

2. **DownloadTestseries_PDF_snappyTest** (lines 142-230)
   - Uses Browsershot with custom Chrome path
   - Streams to browser

3. **DownloadTestseries_PDF** (lines 700-897)
   - Uses mPDF library
   - Basic PDF generation

4. **DownloadTestseries_PDF_snappy222** (lines 1276-1576)
   - Uses Snappy/wkhtmltopdf
   - Streams to browser

5. **DownloadTestseries_PDF_v1** (lines 1581-1790)
   - Uses DomPDF
   - Custom font support

6. **DownloadTestseries_PDF_Five** (lines 1242-1274)
   - Uses Snappy
   - Devanagari font support

**All consolidated into UnifiedPdfService!**

---

## Architecture

### Service Layer

```
app/Services/
├── DocxExportService.php      # DOCX generation
├── AnswerKeyService.php        # Answer key generation (PDF/DOCX)
└── UnifiedPdfService.php       # Unified PDF generation
```

### Controller Layer

```
app/Http/Controllers/Api/V2/TutorController.php
├── exportTestSeriesToDocx()    # DOCX export endpoint
├── exportAnswerKey()           # Answer key export endpoint
├── assignToGroups()            # Assign test to groups
└── getAssignedGroups()         # Get group assignments
```

### Models

```
app/Models/
├── TestSeries.php              # Test series model (with variants)
├── TestSeriesQuestion.php      # Question relationship
├── GroupTestSeries.php         # Group assignment pivot
└── Group.php                   # Group/batch model
```

### Database Schema

#### testseries table
```sql
- id
- name
- user_id
- parent_test_id        # Parent test for variants
- set_variant           # A, B, C, or null
- per_ques_mark
- total_time
- child                 # Comma-separated child section IDs
- sequence
- ...
```

#### group_test_series table
```sql
- id
- group_id              # Foreign key to groups
- test_series_id        # Foreign key to testseries
- created_at
- updated_at
```

#### groups table
```sql
- id
- name
- school_id
- class_id
- subject_ids           # JSON array
- status
- enrollment_code
- expires_at
- ...
```

---

## Testing

### Test Scenarios

#### DOCX Export

```bash
# Test 1: Basic DOCX export
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/export-docx" \
  -H "Authorization: Bearer TOKEN"

# Test 2: DOCX with answers
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/export-docx" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"include_answers": true}'

# Test 3: DOCX with solutions
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/export-docx" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"include_answers": true, "include_solutions": true}'
```

#### Group Assignment

```bash
# Test 4: Assign to single group
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/assign-to-groups" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"group_ids": [1]}'

# Test 5: Assign with variant distribution
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/assign-to-groups" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"group_ids": [1, 2, 3], "distribute_variants": true}'

# Test 6: Get assigned groups
curl -X GET "http://localhost:8000/api/v2/tutor/test-series/1674/groups" \
  -H "Authorization: Bearer TOKEN"
```

#### Answer Key Export

```bash
# Test 7: PDF answer key
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/export-answer-key" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"format": "pdf"}'

# Test 8: DOCX answer key with solutions
curl -X POST "http://localhost:8000/api/v2/tutor/test-series/1674/export-answer-key" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"format": "docx", "include_solutions": true}'
```

### Error Handling

All endpoints include comprehensive error handling:

- **404**: Test series not found or access denied
- **422**: Validation errors (invalid parameters)
- **500**: Server errors (logged for debugging)

Example error response:
```json
{
  "status": false,
  "message": "Test series not found or access denied",
  "error": "Detailed error message"
}
```

---

## File Structure Summary

```
pathshalaa_api/
├── app/
│   ├── Http/Controllers/Api/V2/
│   │   └── TutorController.php         (Modified - added 4 methods)
│   ├── Models/
│   │   ├── TestSeries.php              (Uses existing variants relationship)
│   │   ├── GroupTestSeries.php         (Existing)
│   │   └── Group.php                   (Existing)
│   └── Services/
│       ├── DocxExportService.php       (New - 800+ lines)
│       ├── AnswerKeyService.php        (New - 450+ lines)
│       └── UnifiedPdfService.php       (New - 700+ lines)
├── routes/
│   └── api.php                         (Modified - added 4 routes)
├── public/
│   ├── testseries_docx/                (Auto-created - DOCX files)
│   ├── testseries_answerkey/          (Auto-created - Answer keys)
│   └── testseries_pdf/                 (Existing - PDF files)
└── WEEK_7_IMPLEMENTATION.md           (This file)
```

---

## Next Steps & Recommendations

### Immediate Actions

1. **Test all endpoints** with Postman or cURL
2. **Verify file permissions** on public folders
3. **Check PhpWord installation**: `composer show phpoffice/phpword`
4. **Test with actual test series data** to ensure formatting is correct

### Future Enhancements

1. **Background Job Processing**: Use Laravel queues for large exports
2. **Email Delivery**: Send exported files via email
3. **Cloud Storage**: Upload to S3/Google Cloud Storage
4. **Version Control**: Track document versions
5. **Custom Templates**: Allow schools to customize document templates
6. **Bulk Export**: Export multiple test series at once
7. **LaTeX Rendering**: Better LaTeX to image conversion
8. **Accessibility**: PDF/A compliance for archiving

### Performance Optimization

- Cache test series data for repeated exports
- Optimize image processing pipeline
- Implement CDN for generated files
- Add file cleanup cron job (delete old exports)

---

## Support & Documentation

- **Service Classes**: All services include comprehensive inline documentation
- **OpenAPI Specs**: Swagger annotations included in controller methods
- **Error Logging**: All errors logged to `storage/logs/laravel.log`
- **Debug Mode**: Set `APP_DEBUG=true` in `.env` for detailed errors

---

## Version History

| Version | Date | Changes |
|---------|------|---------|
| 1.0.0 | 2025-01-13 | Initial implementation - Days 1-5 complete |

---

**Implementation completed by:** Claude (AI Assistant)
**Date:** January 13, 2025
**Branch:** `claude/implement-docx-export-011CV5yhF5ABHgT9pxm94626`
