diff --git a/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.Designer.cs b/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.Designer.cs new file mode 100644 index 0000000..387980a --- /dev/null +++ b/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.Designer.cs @@ -0,0 +1,1466 @@ +// +using System; +using System.Collections.Generic; +using Health.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Health.Infrastructure.Data.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260710052811_AddAppleSignIn")] + partial class AddAppleSignIn + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Health.Domain.Entities.Consultation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DoctorId") + .HasColumnType("uuid"); + + b.Property("Month") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DoctorId"); + + b.HasIndex("UserId"); + + b.ToTable("Consultations"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ConsultationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConsultationId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("SenderName") + .HasColumnType("text"); + + b.Property("SenderType") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ConsultationId", "CreatedAt") + .IsDescending(false, true); + + b.ToTable("ConsultationMessages"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Conversation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AgentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("MessageCount") + .HasColumnType("integer"); + + b.Property("Summary") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "UpdatedAt") + .IsDescending(false, true); + + b.ToTable("Conversations"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ConversationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConversationId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Intent") + .HasColumnType("text"); + + b.Property("MetadataJson") + .HasColumnType("jsonb"); + + b.Property("Role") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ConversationId", "CreatedAt"); + + b.ToTable("ConversationMessages"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DeviceToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Platform") + .IsRequired() + .HasColumnType("text"); + + b.Property("PushToken") + .IsRequired() + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("DeviceTokens"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DietFoodItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Calories") + .HasColumnType("integer"); + + b.Property("CarbsGrams") + .HasColumnType("numeric"); + + b.Property("DietRecordId") + .HasColumnType("uuid"); + + b.Property("FatGrams") + .HasColumnType("numeric"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Portion") + .HasColumnType("text"); + + b.Property("ProteinGrams") + .HasColumnType("numeric"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Warning") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DietRecordId"); + + b.ToTable("DietFoodItems"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DietRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HealthScore") + .HasColumnType("integer"); + + b.Property("MealType") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecordedAt") + .HasColumnType("date"); + + b.Property("TotalCalories") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "RecordedAt") + .IsDescending(false, true); + + b.ToTable("DietRecords"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Doctor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("Introduction") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfessionalDirection") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Doctors"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DoctorProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("DoctorId") + .HasColumnType("uuid"); + + b.Property("Hospital") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsOnline") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DoctorId"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("DoctorProfiles"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ExercisePlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndDate") + .HasColumnType("date"); + + b.Property("ReminderTime") + .HasColumnType("time without time zone"); + + b.Property("StartDate") + .HasColumnType("date"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "StartDate", "EndDate"); + + b.ToTable("ExercisePlans"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ExercisePlanItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DurationMinutes") + .HasColumnType("integer"); + + b.Property("ExerciseType") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsCompleted") + .HasColumnType("boolean"); + + b.Property("IsRestDay") + .HasColumnType("boolean"); + + b.Property("PlanId") + .HasColumnType("uuid"); + + b.Property("ScheduledDate") + .HasColumnType("date"); + + b.HasKey("Id"); + + b.HasIndex("PlanId", "ScheduledDate") + .IsUnique(); + + b.ToTable("ExercisePlanItems"); + }); + + modelBuilder.Entity("Health.Domain.Entities.FollowUp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Department") + .HasColumnType("text"); + + b.Property("DoctorName") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("ScheduledAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("FollowUps"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthArchive", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.PrimitiveCollection>("Allergies") + .IsRequired() + .HasColumnType("text[]"); + + b.PrimitiveCollection>("ChronicDiseases") + .IsRequired() + .HasColumnType("text[]"); + + b.Property("Diagnosis") + .HasColumnType("text"); + + b.PrimitiveCollection>("DietRestrictions") + .IsRequired() + .HasColumnType("text[]"); + + b.Property("FamilyHistory") + .HasColumnType("text"); + + b.Property("SurgeryDate") + .HasColumnType("date"); + + b.Property("SurgeryType") + .HasColumnType("text"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("HealthArchives"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthArchiveSurgery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("HealthArchiveId") + .HasColumnType("uuid"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("HealthArchiveId", "SortOrder"); + + b.ToTable("HealthArchiveSurgeries", (string)null); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Diastolic") + .HasColumnType("integer"); + + b.Property("IsAbnormal") + .HasColumnType("boolean"); + + b.Property("MetricType") + .IsRequired() + .HasColumnType("text"); + + b.Property("RecordedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Source") + .IsRequired() + .HasColumnType("text"); + + b.Property("Systolic") + .HasColumnType("integer"); + + b.Property("Unit") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "MetricType"); + + b.HasIndex("UserId", "RecordedAt") + .IsDescending(false, true); + + b.ToTable("HealthRecords"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Medication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Dosage") + .HasColumnType("text"); + + b.Property("EndDate") + .HasColumnType("date"); + + b.Property("Frequency") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("Source") + .IsRequired() + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("date"); + + b.PrimitiveCollection>("TimeOfDay") + .IsRequired() + .HasColumnType("time[]"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "IsActive"); + + b.ToTable("Medications"); + }); + + modelBuilder.Entity("Health.Domain.Entities.MedicationLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("MedicationId") + .HasColumnType("uuid"); + + b.Property("ScheduledTime") + .HasColumnType("time without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MedicationId", "CreatedAt") + .IsDescending(false, true); + + b.ToTable("MedicationLogs"); + }); + + modelBuilder.Entity("Health.Domain.Entities.NotificationPreference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AbnormalAlert") + .HasColumnType("boolean"); + + b.Property("DoctorReply") + .HasColumnType("boolean"); + + b.Property("FollowUpReminder") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminder") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminderBloodPressure") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminderGlucose") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminderHeartRate") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminderSpO2") + .HasColumnType("boolean"); + + b.Property("HealthRecordReminderWeight") + .HasColumnType("boolean"); + + b.Property("MedicationReminder") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("NotificationPreferences"); + }); + + modelBuilder.Entity("Health.Domain.Entities.RefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsRevoked") + .HasColumnType("boolean"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("RefreshTokens"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Report", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AiIndicators") + .HasColumnType("jsonb"); + + b.Property("AiSummary") + .HasColumnType("text"); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DoctorComment") + .HasColumnType("text"); + + b.Property("DoctorName") + .HasColumnType("text"); + + b.Property("DoctorRecommendation") + .HasColumnType("text"); + + b.Property("FileType") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReviewedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Severity") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Reports"); + }); + + modelBuilder.Entity("Health.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppleUserId") + .HasColumnType("text"); + + b.Property("AvatarUrl") + .HasColumnType("text"); + + b.Property("BirthDate") + .HasColumnType("date"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DoctorId") + .HasColumnType("uuid"); + + b.Property("Gender") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Role") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasDefaultValue("User"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("AppleUserId") + .IsUnique(); + + b.HasIndex("DoctorId"); + + b.HasIndex("Phone") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Health.Domain.Entities.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionTargetId") + .HasColumnType("text"); + + b.Property("ActionType") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Severity") + .IsRequired() + .HasMaxLength(16) + .HasColumnType("character varying(16)"); + + b.Property("SourceId") + .HasColumnType("uuid"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceId") + .IsUnique(); + + b.HasIndex("UserId", "IsDeleted", "IsRead", "CreatedAt"); + + b.ToTable("UserNotifications", (string)null); + }); + + modelBuilder.Entity("Health.Domain.Entities.VerificationCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsUsed") + .HasColumnType("boolean"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Phone", "CreatedAt") + .IsDescending(false, true); + + b.ToTable("VerificationCodes"); + }); + + modelBuilder.Entity("Health.Infrastructure.Data.Records.AiWriteCommandRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Arguments") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("ToolName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "Status", "ExpiresAt"); + + b.ToTable("AiWriteCommands", (string)null); + }); + + modelBuilder.Entity("Health.Infrastructure.Data.Records.DietImageAnalysisTaskRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Attempts") + .HasColumnType("integer"); + + b.Property("AvailableAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FilePaths") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("LastError") + .HasColumnType("text"); + + b.Property("ResultCode") + .HasColumnType("integer"); + + b.Property("ResultData") + .HasColumnType("text"); + + b.Property("ResultMessage") + .HasColumnType("text"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Status", "AvailableAt"); + + b.ToTable("DietImageAnalysisTasks", (string)null); + }); + + modelBuilder.Entity("Health.Infrastructure.Data.Records.MedicationReminderTaskRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Attempts") + .HasColumnType("integer"); + + b.Property("AvailableAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Dosage") + .HasColumnType("text"); + + b.Property("LastError") + .HasColumnType("text"); + + b.Property("MedicationId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ScheduledDate") + .HasColumnType("date"); + + b.Property("ScheduledTime") + .HasColumnType("time without time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Status", "AvailableAt"); + + b.HasIndex("MedicationId", "ScheduledDate", "ScheduledTime") + .IsUnique(); + + b.ToTable("MedicationReminderTasks", (string)null); + }); + + modelBuilder.Entity("Health.Infrastructure.Data.Records.NotificationOutboxRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Attempts") + .HasColumnType("integer"); + + b.Property("AvailableAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LastError") + .HasColumnType("text"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("SourceTaskId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceTaskId") + .IsUnique(); + + b.HasIndex("Status", "AvailableAt"); + + b.ToTable("NotificationOutbox", (string)null); + }); + + modelBuilder.Entity("Health.Infrastructure.Data.Records.ReportAnalysisTaskRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Attempts") + .HasColumnType("integer"); + + b.Property("AvailableAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FilePath") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastError") + .HasColumnType("text"); + + b.Property("ReportId") + .HasColumnType("uuid"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ReportId"); + + b.HasIndex("Status", "AvailableAt"); + + b.ToTable("ReportAnalysisTasks", (string)null); + }); + + modelBuilder.Entity("Health.Domain.Entities.Consultation", b => + { + b.HasOne("Health.Domain.Entities.Doctor", "Doctor") + .WithMany("Consultations") + .HasForeignKey("DoctorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("Consultations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Doctor"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ConsultationMessage", b => + { + b.HasOne("Health.Domain.Entities.Consultation", "Consultation") + .WithMany("Messages") + .HasForeignKey("ConsultationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultation"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Conversation", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("Conversations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ConversationMessage", b => + { + b.HasOne("Health.Domain.Entities.Conversation", "Conversation") + .WithMany("Messages") + .HasForeignKey("ConversationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Conversation"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DeviceToken", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("DeviceTokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DietFoodItem", b => + { + b.HasOne("Health.Domain.Entities.DietRecord", "DietRecord") + .WithMany("FoodItems") + .HasForeignKey("DietRecordId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DietRecord"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DietRecord", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("DietRecords") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DoctorProfile", b => + { + b.HasOne("Health.Domain.Entities.Doctor", "Doctor") + .WithMany() + .HasForeignKey("DoctorId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Health.Domain.Entities.User", "User") + .WithOne("DoctorProfile") + .HasForeignKey("Health.Domain.Entities.DoctorProfile", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Doctor"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ExercisePlan", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("ExercisePlans") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ExercisePlanItem", b => + { + b.HasOne("Health.Domain.Entities.ExercisePlan", "Plan") + .WithMany("Items") + .HasForeignKey("PlanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Plan"); + }); + + modelBuilder.Entity("Health.Domain.Entities.FollowUp", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("FollowUps") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthArchive", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithOne("HealthArchive") + .HasForeignKey("Health.Domain.Entities.HealthArchive", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthArchiveSurgery", b => + { + b.HasOne("Health.Domain.Entities.HealthArchive", "HealthArchive") + .WithMany("Surgeries") + .HasForeignKey("HealthArchiveId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("HealthArchive"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthRecord", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("HealthRecords") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Medication", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("Medications") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.MedicationLog", b => + { + b.HasOne("Health.Domain.Entities.Medication", "Medication") + .WithMany("Logs") + .HasForeignKey("MedicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Medication"); + }); + + modelBuilder.Entity("Health.Domain.Entities.NotificationPreference", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithOne("NotificationPreference") + .HasForeignKey("Health.Domain.Entities.NotificationPreference", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Report", b => + { + b.HasOne("Health.Domain.Entities.User", "User") + .WithMany("Reports") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Health.Domain.Entities.User", b => + { + b.HasOne("Health.Domain.Entities.Doctor", "Doctor") + .WithMany() + .HasForeignKey("DoctorId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Doctor"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Consultation", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Conversation", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("Health.Domain.Entities.DietRecord", b => + { + b.Navigation("FoodItems"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Doctor", b => + { + b.Navigation("Consultations"); + }); + + modelBuilder.Entity("Health.Domain.Entities.ExercisePlan", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Health.Domain.Entities.HealthArchive", b => + { + b.Navigation("Surgeries"); + }); + + modelBuilder.Entity("Health.Domain.Entities.Medication", b => + { + b.Navigation("Logs"); + }); + + modelBuilder.Entity("Health.Domain.Entities.User", b => + { + b.Navigation("Consultations"); + + b.Navigation("Conversations"); + + b.Navigation("DeviceTokens"); + + b.Navigation("DietRecords"); + + b.Navigation("DoctorProfile"); + + b.Navigation("ExercisePlans"); + + b.Navigation("FollowUps"); + + b.Navigation("HealthArchive"); + + b.Navigation("HealthRecords"); + + b.Navigation("Medications"); + + b.Navigation("NotificationPreference"); + + b.Navigation("Reports"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.cs b/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.cs new file mode 100644 index 0000000..d89452a --- /dev/null +++ b/backend/src/Health.Infrastructure/Data/Migrations/20260710052811_AddAppleSignIn.cs @@ -0,0 +1,56 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Health.Infrastructure.Data.Migrations +{ + /// + public partial class AddAppleSignIn : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Phone", + table: "Users", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AddColumn( + name: "AppleUserId", + table: "Users", + type: "text", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_AppleUserId", + table: "Users", + column: "AppleUserId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_Users_AppleUserId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "AppleUserId", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "Phone", + table: "Users", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + } + } +} diff --git a/backend/src/Health.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs b/backend/src/Health.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs index 78975d2..0b05875 100644 --- a/backend/src/Health.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs +++ b/backend/src/Health.Infrastructure/Data/Migrations/AppDbContextModelSnapshot.cs @@ -803,6 +803,9 @@ namespace Health.Infrastructure.Data.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("AppleUserId") + .HasColumnType("text"); + b.Property("AvatarUrl") .HasColumnType("text"); @@ -822,7 +825,6 @@ namespace Health.Infrastructure.Data.Migrations .HasColumnType("text"); b.Property("Phone") - .IsRequired() .HasColumnType("text"); b.Property("Role") @@ -837,6 +839,9 @@ namespace Health.Infrastructure.Data.Migrations b.HasKey("Id"); + b.HasIndex("AppleUserId") + .IsUnique(); + b.HasIndex("DoctorId"); b.HasIndex("Phone") diff --git a/backend/src/Health.WebApi/appsettings.Development.json b/backend/src/Health.WebApi/appsettings.Development.json index 0c208ae..bcdd3fc 100644 --- a/backend/src/Health.WebApi/appsettings.Development.json +++ b/backend/src/Health.WebApi/appsettings.Development.json @@ -1,7 +1,7 @@ { "Logging": { "LogLevel": { - "Default": "Information", + "Default": "Warning", "Microsoft.AspNetCore": "Warning" } }