Overview
The IPS (Informe Periódico de Seguridad) module, also known as PSUR (Periodic Safety Update Report), automates the creation of periodic safety reports required by regulatory authorities worldwide.
Automated Literature Search Search PubMed, LILACS, and SciELO for safety literature
Case Aggregation Automatically count and aggregate ICSR cases by period
Workflow States Borrador → Validado → Aprobado with QA checkpoints
Multi-Format Export Generate DOCX, PDF, and HTML reports
IPS Report Structure
Each IPS report is linked to a specific pharmaceutical product:
# Product data model (backend/app/models/ips.py:17-39)
class IPSProducto :
- nombre: Product name and presentation
- principio_activo: Active ingredient ( IFA )
- forma_farmaceutica: Pharmaceutical form (tablets, capsules, etc.)
- presentacion: Package presentation
- via: Administration route
- registro_sanitario: Registration number
- fecha_autorizacion: Authorization date
- fabricante: Manufacturer
class IPSReport :
- producto_id: Link to IPSProducto
- periodo_inicio: Report period start date
- periodo_fin: Report period end date
- version: Report version number
- estado: Workflow state (borrador / validado / aprobado)
# Metrics
- unidades_comercializadas: Units sold in period
- lotes_distribuidos: Batches distributed
# Report sections (JSONB fields)
- eventos_resumen: Summary of adverse events
- senales_detectadas: Detected safety signals
- acciones_regulatorias: Regulatory actions taken
- evaluacion_benef_riesgo: Benefit - risk assessment
- conclusiones: Conclusions and recommendations
Creating an IPS Report
From Calendar
VIGIA integrates with a product calendar (calendario_ips) to streamline IPS creation:
Search for product in calendar
GET /api/v1/ips/calendario-search?q=paracetamol & limit = 20
Returns products with their registration numbers and IPS due dates: [
{
"id" : 123 ,
"label" : "PARACETAMOL 500 MG TABLETAS · Reg. AB-1234"
}
]
Get prefilled data from calendar
GET /api/v1/ips/calendario/{cal_id}/prefill
Returns pre-populated product and period data: {
"producto" : {
"nombre" : "PARACETAMOL 500 MG TABLETAS" ,
"principio_activo" : "Paracetamol" ,
"registro_sanitario" : "AB-1234" ,
"fecha_autorizacion" : "2020-01-15"
},
"report" : {
"periodo_inicio" : "2023-01-01" ,
"periodo_fin" : "2023-06-30" ,
"estado" : "borrador"
},
"cal_id" : 123
}
Create IPS from calendar
POST /api/v1/ips/from-calendario?cal_id= 123 & periodo_inicio = 2024-01-01 & periodo_fin = 2024-06-30
Automatically:
Creates or reuses IPSProducto
Creates IPSReport with correct dates
Links to calendar entry for tracking
Manual Creation
For products not in the calendar:
POST /api/v1/ips
Content-Type: application/json
{
"producto_id" : 45,
"periodo_inicio" : "2024-01-01",
"periodo_fin" : "2024-06-30",
"version" : 1,
"estado" : "borrador",
"unidades_comercializadas" : 150000
}
Automatic case counting : When an IPS is created or viewed, VIGIA automatically counts related ICSR cases within the reporting period based on product matching.
Literature Search Integration
Supported Sources
VIGIA searches multiple biomedical databases:
Source Description Coverage PubMed Central (PMC) NIH’s free full-text archive Global, English LILACS Latin American health sciences Latin America, Spanish/Portuguese SciELO Scientific Electronic Library Online Ibero-America, multi-language
Save Literature Results
POST /api/v1/ips/{report_id}/fuentes/bulk
Content-Type: application/json
{
"translate" : true ,
"target_lang" : "es",
"items" : [
{
"source" : "PMC",
"title" : "Hepatotoxicity associated with paracetamol overdose",
"citation" : "Smith J, et al. (2023). J Hepatol. 78(4):234-241.",
"url" : "https://pubmed.ncbi.nlm.nih.gov/12345678",
"year" : 2023,
"journal" : "Journal of Hepatology",
"abstract" : "This study evaluates...",
"detected_total" : 15
},
{
"source" : "LILACS",
"title" : "Reacciones adversas al paracetamol en pacientes pediátricos",
"year" : 2024,
"journal" : "Revista Médica de Chile"
}
]
}
Features:
Auto-translation : Translate titles/abstracts to target language (ES/EN)
Deduplication : Prevents duplicate entries by URL+title+year
Smart upsert : Updates existing entries with better data
Auto KPI calculation : Updates literature counts by source
Response:
{
"saved" : 2 ,
"total_now" : 47 ,
"kpis" : {
"literaturas_detected" : 47 ,
"pmc_detected" : 25 ,
"lilacs_detected" : 12 ,
"scielo_detected" : 10
}
}
Clean Up Literature References
Remove duplicates and normalize citations:
POST /api/v1/ips/{report_id}/fuentes/cleanup
Performs:
Citation normalization
Duplicate removal
Format standardization
IPS Workflow
Workflow States
Estado Permissions Actions Borrador ips:editCreate, Edit, Delete Validado ips:qaCannot edit, can approve/reject Aprobado ips:approveRead-only, can export
State Transitions
QA Validation:
POST /api/v1/ips/{report_id}/qa-validate
Requires: ips:qa permission
Changes: borrador → validado
Approval:
POST /api/v1/ips/{report_id}/approve
Requires: ips:approve permission
Changes: validado → aprobado
Immutability : Once approved, IPS reports cannot be edited. Create a new version if changes are needed.
Case Aggregation
VIGIA automatically aggregates ICSR cases matching the IPS product and period:
# Source: backend/app/services/ips_aggregator.py
def count_cases ( db : Session, producto : IPSProducto, inicio : date, fin : date) -> int :
# Matches by:
# 1. Product registration number
# 2. Product name similarity
# 3. Active ingredient (IFA)
# Within the reporting period
Matching logic:
Exact match on registro_sanitario
Fuzzy match on product name
IFA (active ingredient) matching
Event date within [periodo_inicio, periodo_fin]
Case metrics included:
Total cases in period
Cases by severity (Grave, Moderada, Leve)
Cases by causality (Definitiva, Probable, Posible)
Cases by outcome (Recuperado, Muerte, etc.)
Report Generation
DOCX Export
GET /api/v1/ips/{ips_id}/export/docx
Generates Microsoft Word document using template:
Template location : app/templates/docs/IPS_TEMPLATE.docx
Uses python-docx-template for variable replacement
Includes literature references, case summaries, charts
Template variables:
{{ producto_nombre }}
{{ principio_activo }}
{{ periodo_inicio }} - {{ periodo_fin }}
{{ casos_total }}
{{ literaturas_detected }}
{{ eventos_resumen }}
{{ conclusiones }}
PDF Export
GET /api/v1/ips/{ips_id}/export/pdf
Two methods:
Local conversion (LibreOffice):
GET /api/v1/ips/{ips_id}/export-local/pdf
Requires LibreOffice installed on server
Cloud conversion (via external service):
GET /api/v1/ips/{ips_id}/export/pdf
HTML Export
GET /api/v1/ips/{report_id}/export.html
Generates standalone HTML report for preview/email.
API Endpoints Summary
IPS CRUD
# List all IPS reports
GET /api/v1/ips?limit= 50 & offset = 0 & estado = borrador & producto = 123
# Get single report
GET /api/v1/ips/{report_id}
# Create report
POST /api/v1/ips
# Update report (borrador only)
PUT /api/v1/ips/{report_id}
# Delete report (borrador only, requires password)
DELETE /api/v1/ips/{report_id}
Calendar Integration
# Search calendar
GET /api/v1/ips/calendario-search?q={query} & limit = 20
# Get prefill data
GET /api/v1/ips/calendario/{cal_id}/prefill
# Create from calendar
POST /api/v1/ips/from-calendario?cal_id={id}
# Get report history for calendar item
GET /api/v1/ips/calendario/{cal_id}/reports
Literature
# Get literature sources
GET /api/v1/ips/{report_id}/fuentes
# Save literature (with auto-translate)
POST /api/v1/ips/{report_id}/fuentes/bulk
# Cleanup duplicates
POST /api/v1/ips/{report_id}/fuentes/cleanup
Workflow
# QA validation
POST /api/v1/ips/{report_id}/qa-validate
# Approval
POST /api/v1/ips/{report_id}/approve
# Regenerate (refresh case counts)
POST /api/v1/ips/{report_id}/regen
Export
# DOCX export
GET /api/v1/ips/{ips_id}/export/docx
# PDF export (cloud)
GET /api/v1/ips/{ips_id}/export/pdf
# PDF export (local)
GET /api/v1/ips/{ips_id}/export-local/pdf
# HTML export
GET /api/v1/ips/{report_id}/export.html
Code References
Feature Implementation IPS Models backend/app/models/ips.py:11-89IPS Router backend/app/routers/ips.pyLiterature Sources backend/app/models/ips_fuente.pyCase Aggregation backend/app/services/ips_aggregator.pyDOCX Generation backend/app/services/ips_docx.pyCalendar Integration backend/app/routers/ips.py:260-748
Best Practices
Data Quality
Verify product matching before creating IPS
Review auto-counted cases for accuracy
Include all relevant literature sources
Document benefit-risk assessment thoroughly
Workflow Management
Complete all sections before QA validation
Review literature references for duplicates
Use cleanup tools regularly
Export to PDF only after approval