# Grievance Management API Documentation

## Overview
The Grievance Management system allows tracking and managing public grievances linked to voter IDs and ration card numbers. The system supports multiple status states and provides comprehensive filtering and tracking capabilities.

## Database Schema

```sql
CREATE TABLE grievances (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  voter_id VARCHAR(255) NULL,
  ration_card_number VARCHAR(255) NULL,
  title VARCHAR(160) NOT NULL,
  description TEXT NULL,
  status ENUM('OPEN','IN_PROGRESS','CLOSED','UNRESOLVED','HOLD') DEFAULT 'OPEN',
  meeting_date DATE NULL,
  reported_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  target_resolve_by DATE NULL,
  closed_at DATETIME NULL,
  created_at TIMESTAMP NULL,
  updated_at TIMESTAMP NULL
)
```

**Indexes:**
- `voter_id`, `ration_card_number`, `status`, `target_resolve_by`, `reported_at`

## Status Values

- `OPEN` - Newly reported grievance (default)
- `IN_PROGRESS` - Being actively worked on
- `CLOSED` - Successfully resolved
- `UNRESOLVED` - Could not be resolved
- `HOLD` - Temporarily on hold

## API Endpoints

### Base URL
```
/api/grievance
```

---

### 1. Create Grievance
**POST** `/api/grievance/create`

Creates a new grievance record.

**Request Body:**
```json
{
  "voter_id": "XDQ0110387",           // Optional
  "ration_card_number": "12345678",   // Optional
  "title": "Water supply issue",      // Required, max 160 chars
  "description": "No water supply since last week in our street",  // Optional
  "status": "OPEN",                   // Optional, defaults to OPEN
  "meeting_date": "2025-11-10",       // Optional
  "target_resolve_by": "2025-11-15",  // Optional
  "reported_at": "2025-11-04 10:30:00" // Optional, defaults to now
}
```

**Note:** Both `voter_id` and `ration_card_number` can be null.

**Response:**
```json
{
  "status": 200,
  "message": "Grievance created successfully",
  "data": {
    "id": 1,
    "voter_id": "XDQ0110387",
    "ration_card_number": "12345678",
    "title": "Water supply issue",
    "description": "No water supply since last week in our street",
    "status": "OPEN",
    "meeting_date": "2025-11-10",
    "reported_at": "2025-11-04 10:30:00",
    "target_resolve_by": "2025-11-15",
    "closed_at": null,
    "created_at": "2025-11-04T10:30:00.000000Z",
    "updated_at": "2025-11-04T10:30:00.000000Z"
  }
}
```

---

### 2. Update Grievance
**PUT** `/api/grievance/update/{id}`

Updates an existing grievance. Can be used for the same screen as create.

**Request Body:**
```json
{
  "title": "Updated water supply issue",
  "status": "IN_PROGRESS",
  "meeting_date": "2025-11-12",
  "target_resolve_by": "2025-11-20"
}
```

**Auto-behavior:** When status is changed to `CLOSED`, `closed_at` is automatically set to current timestamp if not provided.

**Response:**
```json
{
  "status": 200,
  "message": "Grievance updated successfully",
  "data": {
    "id": 1,
    "title": "Updated water supply issue",
    "status": "IN_PROGRESS",
    // ... other fields
  }
}
```

---

### 3. Get Grievance by ID
**GET** `/api/grievance/get/{id}`

Retrieves a single grievance with related voter and ration card data.

**Response:**
```json
{
  "status": 200,
  "message": "Grievance retrieved successfully",
  "data": {
    "id": 1,
    "voter_id": "XDQ0110387",
    "ration_card_number": "12345678",
    "title": "Water supply issue",
    "description": "No water supply since last week",
    "status": "OPEN",
    "voter": {
      // Voter details if voter_id is linked
    },
    "ration_card": {
      // Ration card details if ration_card_number is linked
    }
  }
}
```

---

### 4. Get All Grievances by Status (Tab Bar)
**GET** `/api/grievance/getByStatus/{status}`

Retrieves grievances filtered by status, ordered by nearest `target_resolve_by` date.

**Parameters:**
- `status` - One of: `OPEN`, `IN_PROGRESS`, `CLOSED`, `UNRESOLVED`, `HOLD`

**Example:**
```
GET /api/grievance/getByStatus/OPEN
GET /api/grievance/getByStatus/IN_PROGRESS
```

**Sorting Logic:**
1. Grievances with `target_resolve_by` dates (nearest first)
2. Grievances without `target_resolve_by` (at the end)
3. Within each group, sorted by `reported_at` descending

**Response:**
```json
{
  "status": 200,
  "message": "Grievances retrieved successfully",
  "data": {
    "grievances": [
      {
        "id": 1,
        "title": "Water supply issue",
        "status": "OPEN",
        "target_resolve_by": "2025-11-10",
        "reported_at": "2025-11-04 10:30:00",
        // ... other fields
      },
      {
        "id": 2,
        "title": "Road repair needed",
        "status": "OPEN",
        "target_resolve_by": "2025-11-12",
        // ... other fields
      }
    ],
    "count": 2,
    "status": "OPEN"
  }
}
```

---

### 5. Get All Grievances (with optional filter)
**GET** `/api/grievance/getAll?status={status}`

Retrieves all grievances with optional status filter. Includes status counts.

**Query Parameters:**
- `status` (optional) - Filter by status

**Examples:**
```
GET /api/grievance/getAll
GET /api/grievance/getAll?status=OPEN
```

**Response:**
```json
{
  "status": 200,
  "message": "Grievances retrieved successfully",
  "data": {
    "grievances": [ /* array of grievances */ ],
    "count": 15,
    "status_counts": {
      "OPEN": 5,
      "IN_PROGRESS": 3,
      "CLOSED": 6,
      "UNRESOLVED": 1,
      "HOLD": 0
    }
  }
}
```

---

### 6. Get Grievances by Voter ID
**GET** `/api/grievance/getByVoterId/{voterId}`

Retrieves all grievances for a specific voter.

**Example:**
```
GET /api/grievance/getByVoterId/XDQ0110387
```

**Response:**
```json
{
  "status": 200,
  "message": "Grievances retrieved successfully",
  "data": {
    "grievances": [ /* array of grievances */ ],
    "count": 3,
    "voter_id": "XDQ0110387"
  }
}
```

---

### 7. Get Grievances by Ration Card Number
**GET** `/api/grievance/getByRationCard/{rationCardNumber}`

Retrieves all grievances for a specific ration card.

**Example:**
```
GET /api/grievance/getByRationCard/12345678
```

**Response:**
```json
{
  "status": 200,
  "message": "Grievances retrieved successfully",
  "data": {
    "grievances": [ /* array of grievances */ ],
    "count": 2,
    "ration_card_number": "12345678"
  }
}
```

---

### 8. Delete Grievance
**DELETE** `/api/grievance/delete/{id}`

Deletes a grievance record.

**Response:**
```json
{
  "status": 200,
  "message": "Grievance deleted successfully",
  "data": null
}
```

---

### 9. Get Available Statuses
**GET** `/api/grievance/statuses`

Returns list of available status values.

**Response:**
```json
{
  "status": 200,
  "message": "Available statuses",
  "data": {
    "statuses": [
      "OPEN",
      "IN_PROGRESS",
      "CLOSED",
      "UNRESOLVED",
      "HOLD"
    ]
  }
}
```

---

## UI Implementation Guide

### Tab Bar Status Display

Use the `getByStatus/{status}` endpoint for each tab:

```javascript
// Tab configuration
const tabs = [
  { label: 'Open', status: 'OPEN', endpoint: '/api/grievance/getByStatus/OPEN' },
  { label: 'In Progress', status: 'IN_PROGRESS', endpoint: '/api/grievance/getByStatus/IN_PROGRESS' },
  { label: 'Closed', status: 'CLOSED', endpoint: '/api/grievance/getByStatus/CLOSED' },
  { label: 'Unresolved', status: 'UNRESOLVED', endpoint: '/api/grievance/getByStatus/UNRESOLVED' },
  { label: 'On Hold', status: 'HOLD', endpoint: '/api/grievance/getByStatus/HOLD' }
];
```

### Create/Update Form (Same Screen)

```javascript
// Check if editing existing grievance
const isEdit = !!grievanceId;
const endpoint = isEdit 
  ? `/api/grievance/update/${grievanceId}`
  : '/api/grievance/create';
const method = isEdit ? 'PUT' : 'POST';

// Form fields
{
  voter_id: '',              // Optional - autocomplete from voter search
  ration_card_number: '',    // Optional - autocomplete from ration card search
  title: '',                 // Required, max 160 characters
  description: '',           // Optional
  status: 'OPEN',            // Dropdown with available statuses
  meeting_date: null,        // Optional date picker
  target_resolve_by: null,   // Optional date picker
  reported_at: new Date()    // Auto-set to current datetime
}
```

## Error Responses

### Validation Error (422)
```json
{
  "status": 422,
  "message": "Validation error",
  "errors": {
    "title": ["The title field is required."],
    "status": ["The selected status is invalid."]
  }
}
```

### Not Found (404)
```json
{
  "status": 404,
  "message": "Grievance not found"
}
```

### Invalid Status (400)
```json
{
  "status": 400,
  "message": "Invalid status value"
}
```

## Validation Rules

- `voter_id`: Nullable, string, max 255 characters
- `ration_card_number`: Nullable, string, max 255 characters
- `title`: **Required**, string, max 160 characters
- `description`: Nullable, string
- `status`: Must be one of: OPEN, IN_PROGRESS, CLOSED, UNRESOLVED, HOLD
- `meeting_date`: Nullable, valid date
- `reported_at`: Nullable, valid datetime
- `target_resolve_by`: Nullable, valid date
- `closed_at`: Nullable, valid datetime

**Note:** Both `voter_id` and `ration_card_number` can be null/empty when submitting a grievance.

## Architecture

### File Structure
```
app/
├── Http/Controllers/
│   └── GrievanceController.php
├── Models/
│   └── Grievance.php
├── Repositories/
│   └── GrievanceRepository.php
└── Services/
    └── GrievanceService.php

database/migrations/
└── 2025_11_04_000001_create_grievances_table.php

routes/
└── api.php
```

### Service Layer Pattern
The implementation follows the Repository-Service-Controller pattern:
- **Controller**: Handles HTTP requests/responses
- **Service**: Contains business logic and validation
- **Repository**: Handles database operations
- **Model**: Eloquent model with relationships

## Testing Examples

### cURL Examples

**Create Grievance:**
```bash
curl -X POST http://localhost:8000/api/grievance/create \
  -H "Content-Type: application/json" \
  -d '{
    "voter_id": "XDQ0110387",
    "title": "Street light not working",
    "description": "Street light on Main Street has been broken for 3 days",
    "status": "OPEN",
    "target_resolve_by": "2025-11-10"
  }'
```

**Update Grievance:**
```bash
curl -X PUT http://localhost:8000/api/grievance/update/1 \
  -H "Content-Type: application/json" \
  -d '{
    "status": "IN_PROGRESS",
    "meeting_date": "2025-11-08"
  }'
```

**Get by Status:**
```bash
curl http://localhost:8000/api/grievance/getByStatus/OPEN
```

**Get by Voter ID:**
```bash
curl http://localhost:8000/api/grievance/getByVoterId/XDQ0110387
```
