mi-proyecto/app/seed.py

349 lines
18 KiB
Python

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()