mirror of
https://github.com/vee1e/bulk-questionnaire-upload.git
synced 2026-09-01 17:57:10 +00:00
139 lines
3.7 KiB
Markdown
139 lines
3.7 KiB
Markdown
# Backend
|
||
|
||
FastAPI service that validates, parses, and stores XLSForm-compatible Excel files. Deployed on Render.
|
||
|
||
## Local Setup
|
||
|
||
```bash
|
||
cd backend/
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||
pip install -r requirements.txt
|
||
uvicorn main:app --reload --port 8000
|
||
```
|
||
|
||
Swagger UI: http://localhost:8000/docs
|
||
|
||
### Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
|----------|---------|-------------|
|
||
| `MONGODB_URL` | — | Full MongoDB connection string |
|
||
| `DATABASE_NAME` | `mform_bulk_upload` | Database name |
|
||
| `FRONTEND_URL` | `*` | Allowed CORS origin(s), comma-separated |
|
||
|
||
## API Reference
|
||
|
||
### POST `/api/validate`
|
||
Validate an Excel file's structure without storing anything.
|
||
|
||
**Request:** `multipart/form-data` — field `file` (.xls / .xlsx)
|
||
|
||
**Response:**
|
||
```json
|
||
{
|
||
"valid": true,
|
||
"message": "File format is valid.",
|
||
"sheets": [{ "name": "Forms", "exists": true, "missing_columns": [] }],
|
||
"form_metadata": { "language": "en", "title": "My Form" },
|
||
"questions_count": 5,
|
||
"options_count": 15,
|
||
"errors": [],
|
||
"warnings": []
|
||
}
|
||
```
|
||
|
||
### POST `/api/forms/parse`
|
||
Parse an Excel file and return the full tempData JSON without saving to the database.
|
||
|
||
**Request:** `multipart/form-data` — field `file`
|
||
|
||
**Response:** Array — `[questionnaireResponse, formDefinition]`
|
||
|
||
### POST `/api/upload`
|
||
Parse and store one or more Excel files concurrently.
|
||
|
||
**Request:** `multipart/form-data` — field `files` (multiple)
|
||
|
||
**Response:** Array of stored form objects in tempData format.
|
||
|
||
### GET `/api/forms`
|
||
List all stored forms.
|
||
```json
|
||
{ "forms": [{ "id": "...", "title": "...", "language": "en", "version": "1.0", "created_at": "..." }], "count": 1 }
|
||
```
|
||
|
||
### GET `/api/forms/{form_id}`
|
||
Retrieve a single form in full tempData format.
|
||
|
||
### PUT `/api/forms/{form_id}/update`
|
||
Replace a form's data with a new Excel file. `multipart/form-data` — field `file`.
|
||
|
||
### DELETE `/api/forms/{form_id}`
|
||
Delete one form and all its questions and options.
|
||
|
||
### DELETE `/api/forms`
|
||
Delete all forms (bulk).
|
||
|
||
## File Format
|
||
|
||
Three sheets are required:
|
||
|
||
### Forms
|
||
| Column | Required | Notes |
|
||
|--------|----------|-------|
|
||
| Language | Yes | ISO 639-1 code (en, fr, es, …) |
|
||
| Title | Yes | ≤ 255 characters |
|
||
| Version | No | Arbitrary string |
|
||
| (others) | No | Extracted dynamically with defaults |
|
||
|
||
### Questions Info
|
||
| Column | Required | Notes |
|
||
|--------|----------|-------|
|
||
| Order | Yes | Positive integer, unique |
|
||
| Title | Yes | ≤ 1000 characters |
|
||
| View Sequence | Yes | Positive integer |
|
||
| Input Type | Yes | 1–10 (see below) |
|
||
|
||
### Answer Options
|
||
| Column | Required | Notes |
|
||
|--------|----------|-------|
|
||
| Order | Yes | References a question Order |
|
||
| Id | Yes | Positive integer, unique per Order |
|
||
| Label | Yes | ≤ 500 characters |
|
||
|
||
### Question Types
|
||
| Code | Type |
|
||
|------|------|
|
||
| 1 | text |
|
||
| 2 | select_one |
|
||
| 3 | select_multiple |
|
||
| 4 | integer |
|
||
| 5 | decimal |
|
||
| 6 | date |
|
||
| 7 | time |
|
||
| 8 | datetime |
|
||
| 9 | note |
|
||
| 10 | calculate |
|
||
|
||
Choice questions (types 2, 3) must have matching Answer Options rows. Orphaned options (no matching question) are a validation error.
|
||
|
||
## Database Schema
|
||
|
||
**forms** `{ _id, title, language, version, created_at }`
|
||
**questions** `{ _id, form_id, order, title, view_sequence, input_type, created_at }`
|
||
**options** `{ _id, form_id, order, option_id, label, created_at }`
|
||
|
||
Indexes: `forms.created_at desc`, `questions.form_id`, `options.{form_id, order}`.
|
||
|
||
## Testing
|
||
|
||
```bash
|
||
# Unit + integration (mocked MongoDB)
|
||
pytest tests/backend -q
|
||
|
||
# Against live deployment (saves perf_results.json)
|
||
BACKEND_URL=https://bulk-questionnaire-upload.onrender.com python scripts/measure_perf.py
|
||
```
|
||
|
||
Test fixtures: `tests/test_xlsforms_valid/` (10 valid files) · `tests/test_xlsforms_incorrect/` (error scenarios).
|