190 lines
7.4 KiB
Python
190 lines
7.4 KiB
Python
"""
|
|
Management command to manually fetch patient data from HIS system.
|
|
|
|
Usage:
|
|
python manage.py fetch_his_surveys [--minutes N] [--from-date DATE] [--to-date DATE] [--test]
|
|
|
|
Options:
|
|
--minutes N Fetch patients from the last N minutes (default: 10)
|
|
--from-date DATE Fetch patients from this date (DD-Mon-YYYY HH:MM:SS)
|
|
--to-date DATE Fetch patients until this date (DD-Mon-YYYY HH:MM:SS)
|
|
--test Test connection only, don't fetch data
|
|
--config NAME Configuration name to use (optional)
|
|
|
|
Examples:
|
|
# Relative: last 10 minutes
|
|
python manage.py fetch_his_surveys --minutes 10
|
|
|
|
# Absolute: simulate a date range (for testing against test endpoint)
|
|
python manage.py fetch_his_surveys --config "HIS Test" \
|
|
--from-date "01-Jan-2026 00:00:00" --to-date "01-Jan-2026 02:00:00"
|
|
|
|
# Test connection
|
|
python manage.py fetch_his_surveys --config "HIS Test" --test
|
|
"""
|
|
|
|
from django.core.management.base import BaseCommand
|
|
from django.utils import timezone
|
|
|
|
from apps.integrations.services.his_client import HISClient, HISClientFactory
|
|
from apps.integrations.services.his_adapter import HISAdapter
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Fetch patient data from HIS system"
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
"--minutes",
|
|
type=int,
|
|
default=10,
|
|
help="Fetch patients from the last N minutes (default: 10)",
|
|
)
|
|
parser.add_argument(
|
|
"--from-date",
|
|
type=str,
|
|
default=None,
|
|
help="Fetch patients from this date (DD-Mon-YYYY HH:MM:SS)",
|
|
)
|
|
parser.add_argument(
|
|
"--to-date",
|
|
type=str,
|
|
default=None,
|
|
help="Fetch patients until this date (DD-Mon-YYYY HH:MM:SS)",
|
|
)
|
|
parser.add_argument(
|
|
"--test",
|
|
action="store_true",
|
|
help="Test connection only, don't fetch data",
|
|
)
|
|
parser.add_argument(
|
|
"--config",
|
|
type=str,
|
|
help="Configuration name to use (optional)",
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
minutes = options["minutes"]
|
|
from_date_str = options.get("from_date")
|
|
to_date_str = options.get("to_date")
|
|
test_only = options["test"]
|
|
config_name = options.get("config")
|
|
|
|
self.stdout.write(self.style.MIGRATE_HEADING("=" * 70))
|
|
self.stdout.write(self.style.MIGRATE_HEADING("HIS Patient Data Fetch"))
|
|
self.stdout.write(self.style.MIGRATE_HEADING("=" * 70))
|
|
|
|
if from_date_str and to_date_str:
|
|
self.stdout.write(f"Mode: custom date range")
|
|
self.stdout.write(f" From: {from_date_str}")
|
|
self.stdout.write(f" To: {to_date_str}")
|
|
else:
|
|
self.stdout.write(f"Mode: relative (last {minutes} minutes)")
|
|
|
|
if config_name:
|
|
from apps.integrations.models import IntegrationConfig
|
|
|
|
config = IntegrationConfig.objects.filter(name=config_name).first()
|
|
if not config:
|
|
self.stdout.write(self.style.ERROR(f'Configuration "{config_name}" not found'))
|
|
return
|
|
clients = [HISClient(config)]
|
|
else:
|
|
clients = HISClientFactory.get_all_active_clients()
|
|
|
|
if not clients:
|
|
self.stdout.write(self.style.ERROR("No active HIS configurations found"))
|
|
return
|
|
|
|
self.stdout.write(f"Found {len(clients)} HIS configuration(s)")
|
|
|
|
total_patients = 0
|
|
total_visits_saved = 0
|
|
total_surveys_created = 0
|
|
|
|
for client in clients:
|
|
config_display = client.config.name if client.config else "Default"
|
|
self.stdout.write(self.style.MIGRATE_HEADING(f"\nConfiguration: {config_display}"))
|
|
|
|
self.stdout.write("Testing connection...", ending=" ")
|
|
test_result = client.test_connection()
|
|
|
|
if test_result["success"]:
|
|
self.stdout.write(self.style.SUCCESS("Connected"))
|
|
else:
|
|
self.stdout.write(self.style.ERROR(f"Failed: {test_result['message']}"))
|
|
continue
|
|
|
|
if test_only:
|
|
continue
|
|
|
|
from datetime import timedelta
|
|
from apps.integrations.tasks import _parse_his_date
|
|
|
|
if from_date_str and to_date_str:
|
|
fetch_since = _parse_his_date(from_date_str)
|
|
fetch_until = _parse_his_date(to_date_str)
|
|
if not fetch_since or not fetch_until:
|
|
self.stdout.write(self.style.ERROR("Invalid date format. Use DD-Mon-YYYY HH:MM:SS"))
|
|
return
|
|
time_display = f"{fetch_since.strftime('%Y-%m-%d %H:%M')} to {fetch_until.strftime('%Y-%m-%d %H:%M')}"
|
|
else:
|
|
fetch_since = timezone.now() - timedelta(minutes=minutes)
|
|
fetch_until = None
|
|
time_display = f"{fetch_since.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
|
|
self.stdout.write(f"Fetching patient data: {time_display}")
|
|
|
|
his_data = client.fetch_patient_data(since=fetch_since, until=fetch_until)
|
|
|
|
if not his_data:
|
|
self.stdout.write(self.style.WARNING("No data returned from HIS"))
|
|
continue
|
|
|
|
patient_list = his_data.get("FetchPatientDataTimeStampList", [])
|
|
|
|
if not patient_list:
|
|
self.stdout.write(self.style.WARNING("No patients found"))
|
|
continue
|
|
|
|
self.stdout.write(f"Found {len(patient_list)} patient(s)")
|
|
|
|
process_result = HISAdapter.process_his_response(his_data)
|
|
|
|
total_patients += len(patient_list)
|
|
total_visits_saved += process_result.get("visits_saved", 0)
|
|
total_surveys_created += process_result.get("surveys_created", 0)
|
|
|
|
for detail in process_result.get("details", []):
|
|
name = detail.get("patient_name", "Unknown")
|
|
ptype = detail.get("patient_type", "")
|
|
adm_id = detail.get("admission_id", "")
|
|
|
|
if detail.get("survey_created"):
|
|
self.stdout.write(f" {self.style.SUCCESS('+')} {name} ({ptype}) adm={adm_id} - survey created")
|
|
elif detail.get("error"):
|
|
self.stdout.write(f" {self.style.ERROR('x')} {name} ({ptype}) adm={adm_id} - {detail['error']}")
|
|
else:
|
|
reason = detail.get("reason", "Visit in progress")
|
|
self.stdout.write(f" - {name} ({ptype}) adm={adm_id} - {reason}")
|
|
|
|
if process_result.get("errors"):
|
|
for err in process_result["errors"]:
|
|
self.stdout.write(self.style.WARNING(f" Error: {err}"))
|
|
|
|
if client.config:
|
|
client.config.last_sync_at = timezone.now()
|
|
client.config.save(update_fields=["last_sync_at"])
|
|
|
|
self.stdout.write(self.style.MIGRATE_HEADING("\n" + "=" * 70))
|
|
self.stdout.write(self.style.MIGRATE_HEADING("Summary"))
|
|
self.stdout.write(self.style.MIGRATE_HEADING("=" * 70))
|
|
self.stdout.write(f"Total patients fetched: {total_patients}")
|
|
self.stdout.write(f"Visits saved/updated: {total_visits_saved}")
|
|
self.stdout.write(f"Surveys created: {total_surveys_created}")
|
|
|
|
if test_only:
|
|
self.stdout.write(self.style.SUCCESS("\nConnection test completed successfully!"))
|
|
else:
|
|
self.stdout.write(self.style.SUCCESS("\nFetch completed!"))
|