from datetime import time, date, timedelta from . import db from .models import ( User, ProfessionalProfile, Service, WorkingHour, Leave, Appointment, Specialty, Patient, ObraSocialCatalog, Prescription, FrontendBlock, ClinicalRecord, ClinicalEntry, ContactInquiry, AccountingEntry, ) from .utils import generate_public_token, set_setting, generate_legal_number, generate_prescription_group, build_cuir, resolve_jurisdiction_code, ensure_clinical_record def seed_demo_data(): set_setting('sisa_enabled', '0') set_setting('sisa_wsdl', 'https://sisa.msal.gov.ar/sisa/services/profesionalService?wsdl') set_setting('sisa_user', '') set_setting('sisa_password', '') set_setting('sisa_operation', 'profesionalNominal') set_setting('site_title', 'Book Appointments Pro Salud') set_setting('site_phone', '11-5555-0000') set_setting('site_email', 'contacto@demo.com') set_setting('site_url', 'http://127.0.0.1:5000') set_setting('site_country', 'Argentina') set_setting('site_province', 'Buenos Aires') set_setting('site_municipality', 'Berazategui') set_setting('site_city', 'Sourigues') set_setting('site_platform_number', '1025') set_setting('site_repository_number', '0042') set_setting('site_tagline', 'Psiquiatría clínica • historia clínica digital • receta electrónica') set_setting('site_contact_address', 'Calle 14 N° 1450, Sourigues, Buenos Aires') set_setting('site_copyright', '© 2026 Book Appointments Pro Salud. Todos los derechos reservados.') admin = User(full_name='Administrador Demo', email='admin@demo.com', role='admin') admin.set_password('admin1234') recep = User(full_name='Recepción Demo', email='recepcion@demo.com', role='receptionist') recep.set_password('recepcion1234') accounting = User(full_name='Contabilidad Demo', email='contable@demo.com', role='accounting') accounting.set_password('contable1234') prof_user_1 = User(full_name='Dra. Laura Gómez', email='laura@demo.com', role='professional') prof_user_1.set_password('profesional1234') prof_user_2 = User(full_name='Lic. Martín Pérez', email='martin@demo.com', role='professional') prof_user_2.set_password('profesional1234') db.session.add_all([admin, recep, accounting, prof_user_1, prof_user_2]) db.session.flush() esp1 = Specialty(name='Clínica Médica', active=True) esp2 = Specialty(name='Psicología', active=True) esp3 = Specialty(name='Cardiología', active=True) db.session.add_all([esp1, esp2, esp3]) db.session.flush() obra1 = ObraSocialCatalog( tipo=4, categoria_oficial='Agentes del Seguro con Regimen de Adherentes', rnas='1-1950-0', denominacion='OBRA SOCIAL DEL PERSONAL DE LA SANIDAD ARGENTINA', domicilio='DEAN FUNES 1242', localidad='CAPITAL FEDERAL', telefono='0800-000-0000', linea_gratuita='0800-111-2222', habilitada_opciones='SI', vigente=True, ) obra2 = ObraSocialCatalog( tipo=1, categoria_oficial='Agentes del Seguro que aceptan Personal de Servicio Doméstico', rnas='1-2570-7', denominacion='OBRA SOCIAL UNION PERSONAL DE LA UNION DEL PERSONAL CIVIL DE LA NACION', domicilio='TUCUMAN 949', localidad='CAPITAL FEDERAL', telefono='(011) 0000-0000', linea_gratuita='sin línea gratuita', habilitada_opciones='SI', vigente=True, ) db.session.add_all([obra1, obra2]) db.session.flush() patient1 = Patient( nombre='Andrea', apellido='Torres', documento='30111222', tipo_documento='DNI', fecha_nacimiento='1988-05-17', genero='Femenino', telefono='11-5555-2001', email='andrea@example.com', calle='Mitre', numero='123', provincia='Buenos Aires', municipio='Berazategui', localidad='Sourigues', obra_social_id=obra1.id, afiliado_nro='A-778899', estado='Activo', nombre_contacto='Carlos Torres', telefono_contacto='11-4444-9999' ) patient2 = Patient( nombre='Lucía', apellido='Ferrer', documento='28999111', tipo_documento='DNI', fecha_nacimiento='1990-10-01', genero='Femenino', telefono='11-5555-2003', email='lucia@example.com', calle='Belgrano', numero='550', provincia='Buenos Aires', municipio='Quilmes', localidad='Quilmes', obra_social_id=obra2.id, afiliado_nro='B-445566', estado='Activo' ) db.session.add_all([patient1, patient2]) db.session.flush() ensure_clinical_record(patient1, retention_years=10) ensure_clinical_record(patient2, retention_years=10) db.session.flush() prof1 = ProfessionalProfile( user_id=prof_user_1.id, display_name='Dra. Laura Gómez', specialty='Clínica Médica', specialty_id=esp1.id, profession_name='Médica', matricula='MN 123456', jurisdiction_name='Buenos Aires', state_name='Activa', bio='Atención clínica general, presencial y videollamada.', location='Sede Centro', phone='11-5555-1001', contact_email='laura.profesional@demo.com', province='Buenos Aires', municipality='Berazategui', city='Sourigues', address='Calle 14', address_number='1450', color='#0d6efd', source_mode='manual', ) prof2 = ProfessionalProfile( user_id=prof_user_2.id, display_name='Lic. Martín Pérez', specialty='Psicología', specialty_id=esp2.id, profession_name='Psicólogo', matricula='MN 654321', jurisdiction_name='Buenos Aires', state_name='Activa', bio='Entrevista inicial, seguimiento y evaluación breve.', location='Sede Norte', phone='11-5555-1002', contact_email='martin.profesional@demo.com', province='Buenos Aires', municipality='Quilmes', city='Quilmes', address='Alsina', address_number='230', color='#198754', source_mode='manual', ) db.session.add_all([prof1, prof2]) db.session.flush() s1 = Service( name='Primera consulta', description='Entrevista inicial para admisión o evaluación.', duration_minutes=45, buffer_before_minutes=0, buffer_after_minutes=15, price=25000, mode='Presencial / Virtual', min_notice_hours=6, cancel_notice_hours=12, ) s2 = Service( name='Seguimiento profesional', description='Control o seguimiento de un caso ya iniciado.', duration_minutes=30, buffer_before_minutes=0, buffer_after_minutes=10, price=18000, mode='Presencial / Virtual', min_notice_hours=4, cancel_notice_hours=8, ) s3 = Service( name='Reunión administrativa', description='Espacio de coordinación con recepción o administración.', duration_minutes=20, price=0, mode='Telefónica / Virtual', min_notice_hours=2, cancel_notice_hours=4, ) s1.professionals.extend([prof1, prof2]) s2.professionals.extend([prof1, prof2]) s3.professionals.extend([prof1]) db.session.add_all([s1, s2, s3]) db.session.flush() for weekday in [0, 1, 2, 3, 4]: db.session.add(WorkingHour(professional_id=prof1.id, weekday=weekday, start_time=time(9, 0), end_time=time(13, 0))) db.session.add(WorkingHour(professional_id=prof1.id, weekday=weekday, start_time=time(14, 0), end_time=time(18, 0))) db.session.add(WorkingHour(professional_id=prof2.id, weekday=weekday, start_time=time(10, 0), end_time=time(14, 0))) if weekday in [1, 3]: db.session.add(WorkingHour(professional_id=prof2.id, weekday=weekday, start_time=time(15, 0), end_time=time(19, 0))) db.session.add(Leave(professional_id=prof2.id, start_date=date.today() + timedelta(days=7), end_date=date.today() + timedelta(days=9), reason='Capacitación')) sample_appointments = [ Appointment( service_id=s1.id, professional_id=prof1.id, patient_id=patient1.id, client_name=patient1.nombre_completo, client_email=patient1.email, client_phone=patient1.telefono, notes='Turno generado como ejemplo.', appointment_date=date.today() + timedelta(days=1), start_time=time(10, 0), end_time=time(10, 45), status='confirmed', public_token=generate_public_token(), ), Appointment( service_id=s2.id, professional_id=prof2.id, patient_id=patient1.id, client_name=patient1.nombre_completo, client_email=patient1.email, client_phone=patient1.telefono, appointment_date=date.today() + timedelta(days=1), start_time=time(11, 0), end_time=time(11, 30), status='pending', public_token=generate_public_token(), ), Appointment( service_id=s2.id, professional_id=prof1.id, patient_id=patient2.id, client_name=patient2.nombre_completo, client_email=patient2.email, client_phone=patient2.telefono, appointment_date=date.today() + timedelta(days=2), start_time=time(9, 30), end_time=time(10, 0), status='confirmed', public_token=generate_public_token(), ), Appointment( service_id=s1.id, professional_id=prof2.id, patient_id=patient2.id, client_name=patient2.nombre_completo, client_email=patient2.email, client_phone=patient2.telefono, appointment_date=date.today() + timedelta(days=3), start_time=time(15, 0), end_time=time(15, 45), status='confirmed', public_token=generate_public_token(), ), ] db.session.add_all(sample_appointments) db.session.flush() group = generate_prescription_group() legal_number = generate_legal_number() jurisdiction_code = resolve_jurisdiction_code(prof1.jurisdiction_name) sample_prescription = Prescription( patient_id=patient1.id, professional_id=prof1.id, issued_by_user_id=admin.id, prescription_date=date.today(), expires_at=date.today() + timedelta(days=30), status='Activa', legal_number=legal_number, cuir=build_cuir('1025', '0042', jurisdiction_code, '01', '02', group, '01'), platform_number='1025', repository_number='0042', jurisdiction_code=jurisdiction_code, prescription_type='01', prescription_subtype='02', prescription_group=group, item_number='01', patient_full_name=patient1.nombre_completo, patient_document=patient1.documento, patient_birth_date=patient1.fecha_nacimiento, patient_gender=patient1.genero, patient_obra_social=patient1.obra_social.denominacion if patient1.obra_social else 'Particular', patient_plan=patient1.afiliado_nro, professional_display_name=prof1.display_name, professional_profession_name=prof1.profession_name, professional_specialty=prof1.specialty, professional_matricula=prof1.matricula, professional_jurisdiction_name=prof1.jurisdiction_name, professional_address=prof1.full_address, medication_generic_name='Losartán', medication_presentation='Caja x 30 comprimidos de 50 mg', pharmaceutical_form='Comprimidos', quantity_units='1 caja', diagnosis='Hipertensión arterial', dosage_instructions='1 comprimido por día por la mañana', barcode_value='', platform_registry_legend='Receta electrónica registrada por plataforma 1025 / repositorio 0042', ) db.session.add(sample_prescription) frontend_blocks = [ FrontendBlock(section='navbar_menu', key='inicio', title='Inicio', link_url='#hero', sort_order=1), FrontendBlock(section='navbar_menu', key='nosotros', title='Nosotros', link_url='#about', sort_order=2), FrontendBlock(section='navbar_menu', key='servicios', title='Servicios', link_url='#services', sort_order=3), FrontendBlock(section='navbar_menu', key='turnos', title='Turnos', link_url='#appointment', sort_order=4), FrontendBlock(section='navbar_menu', key='departamentos', title='Departamentos', link_url='#departments', sort_order=5), FrontendBlock(section='navbar_menu', key='faq', title='Preguntas frecuentes', link_url='#faq', sort_order=6), FrontendBlock(section='navbar_menu', key='contacto', title='Contacto', link_url='#contact', sort_order=7), FrontendBlock(section='about_items', title='Abordaje longitudinal', body='Seguimiento clínico con foco en diagnóstico, evolución y adherencia terapéutica.', icon='fa-solid fa-vial-circle-check', sort_order=1), FrontendBlock(section='about_items', title='Seguridad documental', body='Historia clínica digital y receta electrónica con eventos auditables.', icon='fa-solid fa-pump-medical', sort_order=2), FrontendBlock(section='about_items', title='Visión integral', body='Antecedentes y registros accesibles para profesionales autorizados.', icon='fa-solid fa-heart-circle-xmark', sort_order=3), FrontendBlock(section='stats_items', title='Profesionales', subtitle='8', body='Equipo interdisciplinario', icon='fa-solid fa-user-doctor', sort_order=1), FrontendBlock(section='stats_items', title='Departamentos', subtitle='6', body='Áreas clínicas y administrativas', icon='fa-regular fa-hospital', sort_order=2), FrontendBlock(section='stats_items', title='Recetas mensuales', subtitle='120', body='Prescripciones con trazabilidad', icon='fas fa-flask', sort_order=3), FrontendBlock(section='stats_items', title='Años de retención', subtitle='3', body='Backups y conservación digital', icon='fas fa-award', sort_order=4), FrontendBlock(section='service_cards', title='Evaluación psiquiátrica', body='Consulta inicial, evaluación diagnóstica y plan terapéutico.', icon='bi bi-heart-pulse', sort_order=1), FrontendBlock(section='service_cards', title='Seguimiento clínico', body='Control evolutivo, adherencia y ajuste farmacológico.', icon='bi bi-clipboard2-pulse', sort_order=2), FrontendBlock(section='department_cards', title='Psiquiatría clínica', subtitle='Atención ambulatoria y seguimiento', body='Consultas diagnósticas, interconsultas, seguimiento y documentación clínica centralizada.', image_path='medilab/assets/img/departments-1.jpg', sort_order=1), FrontendBlock(section='department_cards', title='Receta electrónica', subtitle='Prescripción legal y verificable', body='Emisión con CUIR, número legal, PDF y consulta pública de validez.', image_path='medilab/assets/img/departments-2.jpg', sort_order=2), FrontendBlock(section='department_cards', title='Historia clínica digital', subtitle='Registro único por paciente', body='Legajo electrónico cronológico, foliado y auditable para atención multiespecialidad.', image_path='medilab/assets/img/departments-3.jpg', sort_order=3), FrontendBlock(section='faq_items', title='¿Cómo solicito un turno?', body='Podés reservar online desde la sección Turnos con disponibilidad real por profesional.', sort_order=1), FrontendBlock(section='faq_items', title='¿Cómo verifico una receta?', body='Ingresando el CUIR o número legal en la sección Verificar receta.', sort_order=2), FrontendBlock(section='gallery_items', title='Sala 1', image_path='medilab/assets/img/gallery/gallery-1.jpg', sort_order=1), FrontendBlock(section='gallery_items', title='Sala 2', image_path='medilab/assets/img/gallery/gallery-2.jpg', sort_order=2), FrontendBlock(section='gallery_items', title='Sala 3', image_path='medilab/assets/img/gallery/gallery-3.jpg', sort_order=3), FrontendBlock(section='contact_items', title='Dirección', body='Calle 14 N° 1450, Sourigues, Buenos Aires', icon='bi bi-geo-alt', sort_order=1), FrontendBlock(section='contact_items', title='Teléfono', body='11-5555-0000', icon='bi bi-telephone', sort_order=2), FrontendBlock(section='contact_items', title='Email', body='contacto@demo.com', icon='bi bi-envelope', sort_order=3), FrontendBlock(section='footer_columns', title='Institución', body='Psiquiatría clínica, historia clínica digital y receta electrónica.', sort_order=1), FrontendBlock(section='footer_columns', title='Servicios', body='Turnos, recetas, historia clínica y verificación pública.', sort_order=2), FrontendBlock(section='footer_columns', title='Datos legales', body='Plataforma 1025 · Repositorio 0042', sort_order=3), FrontendBlock(section='footer_columns', title='Accesos rápidos', body='Reservar turno · Verificar receta · Área administrativa', sort_order=4), ] db.session.add_all(frontend_blocks) record1 = patient1.clinical_record db.session.add(ClinicalEntry(record_id=record1.id, patient_id=patient1.id, professional_id=prof1.id, created_by_user_id=admin.id, folio_number=1, specialty_name=prof1.specialty, diagnosis_text='Trastorno de ansiedad', cie10_code='F41.1', subjective='Refiere insomnio y ansiedad anticipatoria.', objective='Se observa discurso coherente, sin ideación autolesiva.', assessment='Ansiedad generalizada compensada parcialmente.', plan='Continuar seguimiento clínico y psicoeducación.', treatment='Medicación según criterio profesional.', study_results='Sin estudios complementarios relevantes.', signed_name=prof1.display_name, signed_hash='seed-entry-1')) db.session.add(ContactInquiry(name='María López', email='maria@example.com', phone='11-4444-1234', detail='Quisiera consultar disponibilidad para primera entrevista.', status='No Leido')) db.session.add_all([ AccountingEntry(entry_date=date.today(), entry_type='ingreso', category='Consultas', description='Cobro de consulta particular', amount=25000, receipt_type='Recibo', receipt_number='R-0001', counterparty_name='Andrea Torres', payment_method='Transferencia', status='Registrado', created_by_user_id=admin.id), AccountingEntry(entry_date=date.today(), entry_type='egreso', category='Servicios', description='Pago servicio de internet', amount=18000, receipt_type='Factura B', receipt_number='FB-1138', counterparty_name='Proveedor de Internet', counterparty_cuit='30-12345678-9', payment_method='Débito', status='Registrado', created_by_user_id=admin.id), ]) db.session.commit()