package com.voidsoftware.map02.entities; import com.voidsoftware.map02.models.Gender; import com.voidsoftware.map02.models.MediaEntity; import jakarta.persistence.*; import lombok.Data; import lombok.NoArgsConstructor; import java.time.Instant; import java.time.LocalDate; import java.util.UUID; @Entity @Table(name = "patient", indexes = { @Index(name = "idx_patient_email", columnList = "email", unique = true), @Index(name = "idx_patient_professional_id", columnList = "professional_id"), @Index(name = "idx_patient_user_id", columnList = "user_id"), // Directory pagination order, not case-insensitive substring filtering. @Index(name = "idx_patient_name_id", columnList = "name, id") }) @Data @NoArgsConstructor public class Patient implements MediaEntity { @Id @GeneratedValue(strategy = GenerationType.UUID) @Column(name = "id", nullable = false, updatable = false, columnDefinition = "uuid") private UUID id; /** * Full name of the patient. */ @Column(nullable = false) private String name; /** * Date of birth, used to calculate age and check paediatric dosing rules. */ @Column(name = "date_of_birth") private LocalDate dateOfBirth; /** * IANA timezone (e.g. Europe/Lisbon) used to convert scheduled UTC times to local display times. */ @Column(nullable = false) private String timezone; /** * Soft-delete flag; inactive patients are excluded from dose generation and alerts. */ @Column(nullable = false) private Boolean active = true; /** * Contact e-mail, also used as login identifier if the patient has an app account. */ // Uniqueness is already declared by idx_patient_email on the table. @Column private String email; /** * Mobile number for SMS notification delivery. */ @Column(name = "phone_number") private String phoneNumber; /** * MALE, FEMALE, OTHER */ @Enumerated(EnumType.STRING) @Column(name = "gender") private Gender gender; /** * Residential address, used for home-delivery or home-visit workflows. */ @Column private String address; /** * ABO/Rh blood type (e.g. A+), relevant for clinical decision support. */ @Column(name = "blood_type", length = 5) private String bloodType; /** * Name of the person to contact in a medical emergency. */ @Column(name = "emergency_contact_name") private String emergencyContactName; /** * Phone number of the emergency contact. */ @Column(name = "emergency_contact_phone") private String emergencyContactPhone; /** * Free-text clinical notes visible only to the assigned professional. */ @Column(columnDefinition = "text") private String notes; /** * Professional responsible for this patient's care. */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "professional_id") private Professional professional; @Column(name = "created_at", nullable = false, updatable = false) private Instant createdAt; @Column(name = "updated_at", nullable = false) private Instant updatedAt; @Column(name = "user_id", columnDefinition = "uuid") private UUID userId; @Column(columnDefinition = "uuid") private UUID resourceId; @PrePersist public void prePersist() { Instant now = Instant.now(); this.createdAt = now; this.updatedAt = now; } @PreUpdate public void preUpdate() { this.updatedAt = Instant.now(); } }