Skip to main content

Overview

The Medical Appointment Management API uses a clear separation between entities (domain models) and DTOs (Data Transfer Objects) to maintain clean boundaries between the API layer and the business logic layer.

Entities vs DTOs

Entities

Purpose: Represent the core business domain
  • Located in Models/Entities/
  • Include all properties, including auto-generated IDs
  • Used internally by the service layer
  • Represent the “truth” of the domain model

DTOs (Data Transfer Objects)

Purpose: Define the API contract
  • Located in Models/Dtos/
  • Used for client-server communication
  • Separate creation DTOs (input) from response DTOs (output)
  • Allow controlled exposure of data to clients
This separation allows you to change internal models without breaking the API contract, and control what clients can send vs. receive.

Core Entities

Paciente (Patient)

Represents a patient in the medical system.
Models/Entities/Paciente.cs
using System;

namespace preliminarServicios.Models.Entities;

public class Paciente
{
    public int Id { get; set; }
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
    public required string Dni { get; set; }
    public required string Email { get; set; }
    public string? Telefono { get; set; }
    public DateOnly FechaNacimiento { get; set; }
}
Properties:
PropertyTypeRequiredDescription
IdintYes (auto)Unique identifier
NombrestringYesPatient’s first name
ApellidostringYesPatient’s last name
DnistringYesNational ID/identification number
EmailstringYesContact email address
Telefonostring?NoContact phone number (optional)
FechaNacimientoDateOnlyYesDate of birth
The required keyword is a C# 11+ feature that ensures these properties must be initialized when creating an instance.

Medico (Doctor)

Represents a medical doctor with a specialty assignment.
Models/Entities/Medico.cs
using System;

namespace preliminarServicios.Models.Entities;

public class Medico
{
    public int Id { get; set; }
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
    public required string NumeroLicencia { get; set; }
    public string? Telefono { get; set; }
    public int EspecialidadId { get; set; }
}
Properties:
PropertyTypeRequiredDescription
IdintYes (auto)Unique identifier
NombrestringYesDoctor’s first name
ApellidostringYesDoctor’s last name
NumeroLicenciastringYesMedical license number
Telefonostring?NoContact phone number (optional)
EspecialidadIdintYesForeign key to Especialidad
Relationships:
  • Each doctor belongs to one specialty (EspecialidadId foreign key)
  • One-to-many: One specialty can have many doctors

Especialidad (Specialty)

Represents a medical specialty.
Models/Entities/Especialidad.cs
using System;

namespace preliminarServicios.Models.Entities;

public class Especialidad
{
    public int Id { get; set; }
    public required string Nombre { get; set; }
}
Properties:
PropertyTypeRequiredDescription
IdintYes (auto)Unique identifier
NombrestringYesSpecialty name (e.g., “Cardiología”)
Common Specialties:
  • Cardiología (Cardiology)
  • Pediatría (Pediatrics)
  • Medicina General (General Medicine)
  • Dermatología (Dermatology)
  • Neurología (Neurology)
  • Traumatología (Traumatology)

Cita (Appointment)

Represents a scheduled medical appointment.
Models/Entities/Cita.cs
using System;
using preliminarServicios.Models.Enums;

namespace preliminarServicios.Models.Entities;

public class Cita
{
    public int Id { get; set; }
    public int PacienteId { get; set; }
    public int MedicoId { get; set; }
    public decimal Costo { get; set; }
    public required string Motivo { get; set; }
    public DateTime FechaInicio { get; set; }
    public DateTime FechaFin { get; set; }
    public string? Observaciones { get; set; }
    public CitaEstado Estado { get; set; }
}
Properties:
PropertyTypeRequiredDescription
IdintYes (auto)Unique identifier
PacienteIdintYesForeign key to patient
MedicoIdintYesForeign key to doctor
CostodecimalYesAppointment cost
MotivostringYesReason for the appointment
FechaInicioDateTimeYesAppointment start time
FechaFinDateTimeYesAppointment end time
Observacionesstring?NoAdditional notes (optional)
EstadoCitaEstadoYesCurrent appointment status
Relationships:
  • Each appointment belongs to one patient (PacienteId foreign key)
  • Each appointment belongs to one doctor (MedicoId foreign key)

Enumerations

CitaEstado (Appointment Status)

Defines the lifecycle states of an appointment.
Models/Enums/CitaEstado.cs
namespace preliminarServicios.Models.Enums;

public enum CitaEstado
{
    Pendiente,    // 0 - Pending
    Confirmada,   // 1 - Confirmed
    Cancelada,    // 2 - Cancelled
    Completada    // 3 - Completed
}
Status Flow:
Pendiente (0) → Confirmada (1) → Completada (3)


  Cancelada (2)
ValueNameDescriptionUse Case
0PendienteNewly created appointmentInitial state when created
1ConfirmadaPatient/doctor confirmedAfter confirmation call/email
2CanceladaAppointment cancelledPatient no-show or cancellation
3CompletadaAppointment completedAfter the visit is finished

Data Transfer Objects (DTOs)

CreatePacienteDto

Used when creating a new patient.
Models/Dtos/CreatePacienteDto.cs
public class CreatePacienteDto
{
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
    public required string Dni { get; set; }
    public required string Email { get; set; }
    public string? Telefono { get; set; }
    public DateOnly FechaNacimiento { get; set; }
}
Notice there’s no Id field - IDs are auto-generated by the service layer.

PacienteResumenDto

Lightweight patient representation for nested inclusion in other DTOs.
Models/Dtos/PacienteResumenDto.cs
public class PacienteResumenDto
{
    public int Id { get; set; }
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
}

CreateMedicoDto

Used when creating a new doctor.
Models/Dtos/CreateMedicoDto.cs
public class CreateMedicoDto
{
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
    public required string NumeroLicencia { get; set; }
    public string? Telefono { get; set; }
    public int EspecialidadId { get; set; }
}

MedicoResumenDto

Lightweight doctor representation for nested inclusion.
Models/Dtos/MedicoResumenDto.cs
public class MedicoResumenDto
{
    public int Id { get; set; }
    public required string Nombre { get; set; }
    public required string Apellido { get; set; }
    public required string NumeroLicencia { get; set; }
}

CreateEspecialidadDto

Used when creating a new specialty.
Models/Dtos/CreateEspecialidadDto.cs
public class CreateEspecialidadDto
{
    public required string Nombre { get; set; }
}

CreateCitaDto

Used when scheduling a new appointment.
Models/Dtos/CreateCitaDto.cs
public class CreateCitaDto
{
    public int PacienteId { get; set; }
    public int MedicoId { get; set; }
    public decimal Costo { get; set; }
    public required string Motivo { get; set; }
    public DateTime FechaInicio { get; set; }
    public DateTime FechaFin { get; set; }
    public string? Observaciones { get; set; }
    public CitaEstado Estado { get; set; }
}

CitaDto

Enriched appointment representation with nested patient and doctor information.
Models/Dtos/CitaDto.cs
public class CitaDto
{
    public int Id { get; set; }
    public PacienteResumenDto Paciente { get; set; }
    public MedicoResumenDto Medico { get; set; }
    public decimal Costo { get; set; }
    public required string Motivo { get; set; }
    public DateTime FechaInicio { get; set; }
    public DateTime FechaFin { get; set; }
    public string? Observaciones { get; set; }
    public CitaEstado Estado { get; set; }
}
CitaDto includes full patient and doctor details instead of just IDs, making it more convenient for clients to display appointment information without additional API calls.

Entity Relationships

┌─────────────────┐
│  Especialidad   │
│                 │
│  - Id           │
│  - Nombre       │
└────────┬────────┘
         │ 1

         │ N

┌─────────────────┐      ┌─────────────────┐
│     Medico      │      │    Paciente    │
│                 │      │                 │
│  - Id           │      │  - Id           │
│  - Nombre       │      │  - Nombre       │
│  - Apellido     │      │  - Apellido     │
│  - NumeroLicen. │      │  - Dni          │
│  - EspecialidadI│      │  - Email        │
└────────┬────────┘      └────────┬────────┘
         │ 1                       │ 1
         │                         │
         │                         │
         │         N           N   │
         └────────────┬────────────┘


              ┌─────────────────┐
              │      Cita       │
              │                 │
              │  - Id           │
              │  - PacienteId   │
              │  - MedicoId     │
              │  - FechaInicio  │
              │  - FechaFin     │
              │  - Estado       │
              └─────────────────┘
Relationships:
  • One Especialidad has many Medico
  • One Medico has many Cita
  • One Paciente has many Cita
  • Each Cita belongs to one Medico and one Paciente

Validation Considerations

While the entity models use C#‘s required keyword for compile-time safety, production APIs should add:

Data Annotations

using System.ComponentModel.DataAnnotations;

public class CreatePacienteDto
{
    [Required(ErrorMessage = "El nombre es obligatorio")]
    [StringLength(100)]
    public required string Nombre { get; set; }
    
    [Required]
    [EmailAddress(ErrorMessage = "Email inválido")]
    public required string Email { get; set; }
    
    [Required]
    [RegularExpression(@"^\d{8}[A-Z]$", ErrorMessage = "DNI inválido")]
    public required string Dni { get; set; }
}

Business Rules

Implement in the service layer:
  • Email uniqueness validation
  • DNI format and uniqueness validation
  • Date range validation (appointment end > start)
  • Doctor availability checking
  • Past date validation for appointments

Next Steps

Services

Learn how services work with these models

API Reference

See these models in action in the API

DTOs Documentation

Complete DTO reference with examples

Development Guide

Learn how to extend the data models

Build docs developers (and LLMs) love