From 96e866fce5c607cc9644dbe5618efa0ad8ed77e5 Mon Sep 17 00:00:00 2001 From: CIS Guru Date: Mon, 29 Dec 2025 16:17:03 -0600 Subject: [PATCH 1/5] SendGrid and Twilio setup --- .../Services/EmailSettingsService.cs | 164 + .../Services/NotificationService.cs | 226 + .../Application/Services/SMSSettingService.cs | 127 + Aquiis.SimpleStart/Aquiis.SimpleStart.csproj | 2 + .../Core/Constants/NotificationConstants.cs | 62 + .../Core/Entities/Notification.cs | 66 + .../Core/Entities/NotificationPreferences.cs | 52 + .../Core/Entities/OperationResult.cs | 24 + .../Entities/OrganizationEmailSettings.cs | 64 + .../Core/Entities/OrganizationSMSSettings.cs | 65 + .../Core/Interfaces/Services/IEmailService.cs | 11 + .../Core/Interfaces/Services/ISMSService.cs | 9 + .../Settings/Pages/EmailSettings.razor | 443 ++ .../Settings/Pages/SMSSettings.razor | 445 ++ .../Data/ApplicationDbContext.cs | 89 + ..._AddNotificationInfrastructure.Designer.cs | 4123 +++++++++++++++++ ...229144549_AddNotificationInfrastructure.cs | 666 +++ .../ApplicationDbContextModelSnapshot.cs | 278 +- .../Infrastructure/Services/EmailService.cs | 43 + .../Infrastructure/Services/SMSService.cs | 29 + .../Services/SendGridEmailService.cs | 275 ++ .../Services/TwilioSMSService.cs | 222 + Aquiis.SimpleStart/Program.cs | 9 + Aquiis.SimpleStart/appsettings.json | 17 +- 24 files changed, 7471 insertions(+), 40 deletions(-) create mode 100644 Aquiis.SimpleStart/Application/Services/EmailSettingsService.cs create mode 100644 Aquiis.SimpleStart/Application/Services/NotificationService.cs create mode 100644 Aquiis.SimpleStart/Application/Services/SMSSettingService.cs create mode 100644 Aquiis.SimpleStart/Core/Constants/NotificationConstants.cs create mode 100644 Aquiis.SimpleStart/Core/Entities/Notification.cs create mode 100644 Aquiis.SimpleStart/Core/Entities/NotificationPreferences.cs create mode 100644 Aquiis.SimpleStart/Core/Entities/OperationResult.cs create mode 100644 Aquiis.SimpleStart/Core/Entities/OrganizationEmailSettings.cs create mode 100644 Aquiis.SimpleStart/Core/Entities/OrganizationSMSSettings.cs create mode 100644 Aquiis.SimpleStart/Core/Interfaces/Services/IEmailService.cs create mode 100644 Aquiis.SimpleStart/Core/Interfaces/Services/ISMSService.cs create mode 100644 Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor create mode 100644 Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor create mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Services/TwilioSMSService.cs diff --git a/Aquiis.SimpleStart/Application/Services/EmailSettingsService.cs b/Aquiis.SimpleStart/Application/Services/EmailSettingsService.cs new file mode 100644 index 0000000..c6c559b --- /dev/null +++ b/Aquiis.SimpleStart/Application/Services/EmailSettingsService.cs @@ -0,0 +1,164 @@ +using System; +using System.Threading.Tasks; +using Aquiis.SimpleStart.Core.Constants; +using Aquiis.SimpleStart.Core.Entities; +using Aquiis.SimpleStart.Core.Interfaces.Services; +using Aquiis.SimpleStart.Core.Services; +using Aquiis.SimpleStart.Infrastructure.Data; +using Aquiis.SimpleStart.Infrastructure.Services; +using Aquiis.SimpleStart.Shared.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using SendGrid; +using SendGrid.Helpers.Mail; + +namespace Aquiis.SimpleStart.Application.Services +{ + public class EmailSettingsService : BaseService + { + private readonly SendGridEmailService _emailService; + + public EmailSettingsService( + ApplicationDbContext context, + ILogger logger, + UserContextService userContext, + IOptions settings, + SendGridEmailService emailService) + : base(context, logger, userContext, settings) + { + _emailService = emailService; + } + + /// + /// Get email settings for current organization or create default disabled settings + /// + public async Task GetOrCreateSettingsAsync() + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + if (orgId == null) + { + throw new UnauthorizedAccessException("No active organization"); + } + + var settings = await _dbSet + .FirstOrDefaultAsync(s => s.OrganizationId == orgId && !s.IsDeleted); + + if (settings == null) + { + settings = new OrganizationEmailSettings + { + Id = Guid.NewGuid(), + OrganizationId = orgId.Value, + IsEmailEnabled = false, + DailyLimit = 100, // SendGrid free tier default + MonthlyLimit = 40000, + CreatedBy = await _userContext.GetUserIdAsync() ?? string.Empty, + CreatedOn = DateTime.UtcNow + }; + await CreateAsync(settings); + } + + return settings; + } + + /// + /// Configure SendGrid API key and enable email functionality + /// + public async Task UpdateSendGridConfigAsync( + string apiKey, + string fromEmail, + string fromName) + { + // Verify the API key works before saving + if (!await _emailService.VerifyApiKeyAsync(apiKey)) + { + return OperationResult.FailureResult( + "Invalid SendGrid API key. Please verify the key has Mail Send permissions."); + } + + var settings = await GetOrCreateSettingsAsync(); + + settings.SendGridApiKeyEncrypted = _emailService.EncryptApiKey(apiKey); + settings.FromEmail = fromEmail; + settings.FromName = fromName; + settings.IsEmailEnabled = true; + settings.IsVerified = true; + settings.LastVerifiedOn = DateTime.UtcNow; + settings.LastError = null; + + await UpdateAsync(settings); + + return OperationResult.SuccessResult("SendGrid configuration saved successfully"); + } + + /// + /// Disable email functionality for organization + /// + public async Task DisableEmailAsync() + { + var settings = await GetOrCreateSettingsAsync(); + settings.IsEmailEnabled = false; + await UpdateAsync(settings); + + return OperationResult.SuccessResult("Email notifications disabled"); + } + + /// + /// Re-enable email functionality + /// + public async Task EnableEmailAsync() + { + var settings = await GetOrCreateSettingsAsync(); + + if (string.IsNullOrEmpty(settings.SendGridApiKeyEncrypted)) + { + return OperationResult.FailureResult( + "SendGrid API key not configured. Please configure SendGrid first."); + } + + settings.IsEmailEnabled = true; + await UpdateAsync(settings); + + return OperationResult.SuccessResult("Email notifications enabled"); + } + + /// + /// Send a test email to verify configuration + /// + public async Task TestEmailConfigurationAsync(string testEmail) + { + try + { + await _emailService.SendEmailAsync( + testEmail, + "Aquiis Email Configuration Test", + "

Configuration Test Successful!

" + + "

This is a test email to verify your SendGrid configuration is working correctly.

" + + "

If you received this email, your email integration is properly configured.

"); + + return OperationResult.SuccessResult("Test email sent successfully! Check your inbox."); + } + catch (Exception ex) + { + _logger.LogError(ex, "Test email failed"); + return OperationResult.FailureResult($"Failed to send test email: {ex.Message}"); + } + } + + /// + /// Update email sender information + /// + public async Task UpdateSenderInfoAsync(string fromEmail, string fromName) + { + var settings = await GetOrCreateSettingsAsync(); + + settings.FromEmail = fromEmail; + settings.FromName = fromName; + + await UpdateAsync(settings); + + return OperationResult.SuccessResult("Sender information updated"); + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Application/Services/NotificationService.cs b/Aquiis.SimpleStart/Application/Services/NotificationService.cs new file mode 100644 index 0000000..6cdc423 --- /dev/null +++ b/Aquiis.SimpleStart/Application/Services/NotificationService.cs @@ -0,0 +1,226 @@ + +using Aquiis.SimpleStart.Core.Constants; +using Aquiis.SimpleStart.Core.Entities; +using Aquiis.SimpleStart.Core.Interfaces.Services; +using Aquiis.SimpleStart.Core.Services; +using Aquiis.SimpleStart.Infrastructure.Data; +using Aquiis.SimpleStart.Shared.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; + +namespace Aquiis.SimpleStart.Application.Services +{ + public class NotificationService : BaseService + { + private readonly IEmailService _emailService; + private readonly ISMSService _smsService; + private new readonly ILogger _logger; + + public NotificationService( + ApplicationDbContext context, + ILogger logger, + UserContextService userContext, + IOptions settings, + IEmailService emailService, + ISMSService smsService) + : base(context, logger, userContext, settings) + { + _emailService = emailService; + _smsService = smsService; + _logger = logger; + } + + /// + /// Create and send a notification to a user + /// + public async Task SendNotificationAsync( + string recipientUserId, + string title, + string message, + string type, + string category, + Guid? relatedEntityId = null, + string? relatedEntityType = null) + { + var organizationId = await _userContext.GetActiveOrganizationIdAsync(); + + // Get user preferences + var preferences = await GetNotificationPreferencesAsync(recipientUserId); + + var notification = new Notification + { + Id = Guid.NewGuid(), + OrganizationId = organizationId!.Value, + RecipientUserId = recipientUserId, + Title = title, + Message = message, + Type = type, + Category = category, + RelatedEntityId = relatedEntityId, + RelatedEntityType = relatedEntityType, + SentOn = DateTime.UtcNow, + IsRead = false, + SendInApp = preferences.EnableInAppNotifications, + SendEmail = preferences.EnableEmailNotifications && ShouldSendEmail(category, preferences), + SendSMS = preferences.EnableSMSNotifications && ShouldSendSMS(category, preferences) + }; + + // Save in-app notification + await CreateAsync(notification); + + // Send email if enabled + if (notification.SendEmail && !string.IsNullOrEmpty(preferences.EmailAddress)) + { + try + { + await _emailService.SendEmailAsync( + preferences.EmailAddress, + title, + message); + + notification.EmailSent = true; + notification.EmailSentOn = DateTime.UtcNow; + } + catch (Exception ex) + { + _logger.LogError(ex, $"Failed to send email notification to {recipientUserId}"); + notification.EmailError = ex.Message; + } + } + + // Send SMS if enabled + if (notification.SendSMS && !string.IsNullOrEmpty(preferences.PhoneNumber)) + { + try + { + await _smsService.SendSMSAsync( + preferences.PhoneNumber, + $"{title}: {message}"); + + notification.SMSSent = true; + notification.SMSSentOn = DateTime.UtcNow; + } + catch (Exception ex) + { + _logger.LogError(ex, $"Failed to send SMS notification to {recipientUserId}"); + notification.SMSError = ex.Message; + } + } + + await UpdateAsync(notification); + + return notification; + } + + /// + /// Mark notification as read + /// + public async Task MarkAsReadAsync(Guid notificationId) + { + var notification = await GetByIdAsync(notificationId); + if (notification == null) return; + + notification.IsRead = true; + notification.ReadOn = DateTime.UtcNow; + + await UpdateAsync(notification); + } + + /// + /// Get unread notifications for current user + /// + public async Task> GetUnreadNotificationsAsync() + { + var userId = await _userContext.GetUserIdAsync(); + var organizationId = await _userContext.GetActiveOrganizationIdAsync(); + + return await _context.Notifications + .Where(n => n.OrganizationId == organizationId + && n.RecipientUserId == userId + && !n.IsRead + && !n.IsDeleted) + .OrderByDescending(n => n.SentOn) + .Take(50) + .ToListAsync(); + } + + /// + /// Get notification history for current user + /// + public async Task> GetNotificationHistoryAsync(int count = 100) + { + var userId = await _userContext.GetUserIdAsync(); + var organizationId = await _userContext.GetActiveOrganizationIdAsync(); + + return await _context.Notifications + .Where(n => n.OrganizationId == organizationId + && n.RecipientUserId == userId + && !n.IsDeleted) + .OrderByDescending(n => n.SentOn) + .Take(count) + .ToListAsync(); + } + + /// + /// Get or create notification preferences for user + /// + private async Task GetNotificationPreferencesAsync(string userId) + { + var organizationId = await _userContext.GetActiveOrganizationIdAsync(); + + var preferences = await _context.NotificationPreferences + .FirstOrDefaultAsync(p => p.OrganizationId == organizationId + && p.UserId == userId + && !p.IsDeleted); + + if (preferences == null) + { + // Create default preferences + preferences = new NotificationPreferences + { + Id = Guid.NewGuid(), + OrganizationId = organizationId!.Value, + UserId = userId, + EnableInAppNotifications = true, + EnableEmailNotifications = true, + EnableSMSNotifications = false, + EmailLeaseExpiring = true, + EmailPaymentDue = true, + EmailPaymentReceived = true, + EmailApplicationStatusChange = true, + EmailMaintenanceUpdate = true, + EmailInspectionScheduled = true + }; + + _context.NotificationPreferences.Add(preferences); + await _context.SaveChangesAsync(); + } + + return preferences; + } + + private bool ShouldSendEmail(string category, NotificationPreferences prefs) + { + return category switch + { + NotificationConstants.Categories.Lease => prefs.EmailLeaseExpiring, + NotificationConstants.Categories.Payment => prefs.EmailPaymentDue, + NotificationConstants.Categories.Application => prefs.EmailApplicationStatusChange, + NotificationConstants.Categories.Maintenance => prefs.EmailMaintenanceUpdate, + NotificationConstants.Categories.Inspection => prefs.EmailInspectionScheduled, + _ => true + }; + } + + private bool ShouldSendSMS(string category, NotificationPreferences prefs) + { + return category switch + { + NotificationConstants.Categories.Payment => prefs.SMSPaymentDue, + NotificationConstants.Categories.Maintenance => prefs.SMSMaintenanceEmergency, + NotificationConstants.Categories.Lease => prefs.SMSLeaseExpiringUrgent, + _ => false + }; + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Application/Services/SMSSettingService.cs b/Aquiis.SimpleStart/Application/Services/SMSSettingService.cs new file mode 100644 index 0000000..b3efc6d --- /dev/null +++ b/Aquiis.SimpleStart/Application/Services/SMSSettingService.cs @@ -0,0 +1,127 @@ +using System; +using System.Threading.Tasks; +using Aquiis.SimpleStart.Core.Constants; +using Aquiis.SimpleStart.Core.Entities; +using Aquiis.SimpleStart.Core.Services; +using Aquiis.SimpleStart.Infrastructure.Data; +using Aquiis.SimpleStart.Infrastructure.Services; +using Aquiis.SimpleStart.Shared.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Aquiis.SimpleStart.Application.Services +{ + public class SMSSettingsService : BaseService + { + private readonly TwilioSMSService _smsService; + + public SMSSettingsService( + ApplicationDbContext context, + ILogger logger, + UserContextService userContext, + IOptions settings, + TwilioSMSService smsService) + : base(context, logger, userContext, settings) + { + _smsService = smsService; + } + + public async Task GetOrCreateSettingsAsync() + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + if (orgId == null) + { + throw new UnauthorizedAccessException("No active organization"); + } + + var settings = await _dbSet + .FirstOrDefaultAsync(s => s.OrganizationId == orgId && !s.IsDeleted); + + if (settings == null) + { + settings = new OrganizationSMSSettings + { + Id = Guid.NewGuid(), + OrganizationId = orgId.Value, + IsSMSEnabled = false, + CostPerSMS = 0.0075m, // Approximate US cost + CreatedBy = await _userContext.GetUserIdAsync() ?? string.Empty, + CreatedOn = DateTime.UtcNow + }; + await CreateAsync(settings); + } + + return settings; + } + + public async Task UpdateTwilioConfigAsync( + string accountSid, + string authToken, + string phoneNumber) + { + // Verify credentials work before saving + if (!await _smsService.VerifyTwilioCredentialsAsync(accountSid, authToken, phoneNumber)) + { + return OperationResult.FailureResult( + "Invalid Twilio credentials or phone number. Please verify your Account SID, Auth Token, and phone number."); + } + + var settings = await GetOrCreateSettingsAsync(); + + settings.TwilioAccountSidEncrypted = _smsService.EncryptAccountSid(accountSid); + settings.TwilioAuthTokenEncrypted = _smsService.EncryptAuthToken(authToken); + settings.TwilioPhoneNumber = phoneNumber; + settings.IsSMSEnabled = true; + settings.IsVerified = true; + settings.LastVerifiedOn = DateTime.UtcNow; + settings.LastError = null; + + await UpdateAsync(settings); + + return OperationResult.SuccessResult("Twilio configuration saved successfully"); + } + + public async Task DisableSMSAsync() + { + var settings = await GetOrCreateSettingsAsync(); + settings.IsSMSEnabled = false; + await UpdateAsync(settings); + + return OperationResult.SuccessResult("SMS notifications disabled"); + } + + public async Task EnableSMSAsync() + { + var settings = await GetOrCreateSettingsAsync(); + + if (string.IsNullOrEmpty(settings.TwilioAccountSidEncrypted)) + { + return OperationResult.FailureResult( + "Twilio credentials not configured. Please configure Twilio first."); + } + + settings.IsSMSEnabled = true; + await UpdateAsync(settings); + + return OperationResult.SuccessResult("SMS notifications enabled"); + } + + public async Task TestSMSConfigurationAsync(string testPhoneNumber) + { + try + { + await _smsService.SendSMSAsync( + testPhoneNumber, + "Aquiis SMS Configuration Test: This message confirms your Twilio integration is working correctly."); + + return OperationResult.SuccessResult("Test SMS sent successfully! Check your phone."); + } + catch (Exception ex) + { + _logger.LogError(ex, "Test SMS failed"); + return OperationResult.FailureResult($"Failed to send test SMS: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Aquiis.SimpleStart.csproj b/Aquiis.SimpleStart/Aquiis.SimpleStart.csproj index d9a846c..4657822 100644 --- a/Aquiis.SimpleStart/Aquiis.SimpleStart.csproj +++ b/Aquiis.SimpleStart/Aquiis.SimpleStart.csproj @@ -40,9 +40,11 @@ all + + diff --git a/Aquiis.SimpleStart/Core/Constants/NotificationConstants.cs b/Aquiis.SimpleStart/Core/Constants/NotificationConstants.cs new file mode 100644 index 0000000..79b5727 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Constants/NotificationConstants.cs @@ -0,0 +1,62 @@ + +namespace Aquiis.SimpleStart.Core.Constants +{ + public static class NotificationConstants + { + public static class Types + { + public const string Info = "Info"; + public const string Warning = "Warning"; + public const string Error = "Error"; + public const string Success = "Success"; + } + + public static class Categories + { + public const string Lease = "Lease"; + public const string Payment = "Payment"; + public const string Maintenance = "Maintenance"; + public const string Application = "Application"; + public const string Property = "Property"; + public const string Inspection = "Inspection"; + public const string Document = "Document"; + public const string System = "System"; + } + + public static class Templates + { + // Lease notifications + public const string LeaseExpiring90Days = "lease_expiring_90"; + public const string LeaseExpiring60Days = "lease_expiring_60"; + public const string LeaseExpiring30Days = "lease_expiring_30"; + public const string LeaseActivated = "lease_activated"; + public const string LeaseTerminated = "lease_terminated"; + + // Payment notifications + public const string PaymentDueReminder = "payment_due_reminder"; + public const string PaymentReceived = "payment_received"; + public const string PaymentLate = "payment_late"; + public const string LateFeeApplied = "late_fee_applied"; + + // Maintenance notifications + public const string MaintenanceRequestCreated = "maintenance_created"; + public const string MaintenanceRequestAssigned = "maintenance_assigned"; + public const string MaintenanceRequestStarted = "maintenance_started"; + public const string MaintenanceRequestCompleted = "maintenance_completed"; + + // Application notifications + public const string ApplicationSubmitted = "application_submitted"; + public const string ApplicationUnderReview = "application_under_review"; + public const string ApplicationApproved = "application_approved"; + public const string ApplicationRejected = "application_rejected"; + + // Inspection notifications + public const string InspectionScheduled = "inspection_scheduled"; + public const string InspectionCompleted = "inspection_completed"; + + // Document notifications + public const string DocumentUploaded = "document_uploaded"; + public const string DocumentExpiring = "document_expiring"; + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Entities/Notification.cs b/Aquiis.SimpleStart/Core/Entities/Notification.cs new file mode 100644 index 0000000..3fe75d8 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Entities/Notification.cs @@ -0,0 +1,66 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Aquiis.SimpleStart.Core.Validation; + +namespace Aquiis.SimpleStart.Core.Entities +{ + public class Notification : BaseModel + { + [RequiredGuid] + public Guid OrganizationId { get; set; } + + [Required] + [StringLength(200)] + public string Title { get; set; } = string.Empty; + + [Required] + [StringLength(2000)] + public string Message { get; set; } = string.Empty; + + [Required] + [StringLength(50)] + public string Type { get; set; } = string.Empty; // Info, Warning, Error, Success + + [Required] + [StringLength(50)] + public string Category { get; set; } = string.Empty; // Lease, Payment, Maintenance, Application + + [Required] + public string RecipientUserId { get; set; } = string.Empty; + + [Required] + public DateTime SentOn { get; set; } + + public DateTime? ReadOn { get; set; } + + public bool IsRead { get; set; } + + // Optional entity reference for "view details" link + public Guid? RelatedEntityId { get; set; } + + [StringLength(50)] + public string? RelatedEntityType { get; set; } + + // Delivery channels + public bool SendInApp { get; set; } = true; + public bool SendEmail { get; set; } + public bool SendSMS { get; set; } + + // Delivery status + public bool EmailSent { get; set; } + public DateTime? EmailSentOn { get; set; } + + public bool SMSSent { get; set; } + public DateTime? SMSSentOn { get; set; } + + [StringLength(500)] + public string? EmailError { get; set; } + + [StringLength(500)] + public string? SMSError { get; set; } + + // Navigation + [ForeignKey(nameof(OrganizationId))] + public virtual Organization? Organization { get; set; } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Entities/NotificationPreferences.cs b/Aquiis.SimpleStart/Core/Entities/NotificationPreferences.cs new file mode 100644 index 0000000..12409d6 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Entities/NotificationPreferences.cs @@ -0,0 +1,52 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Aquiis.SimpleStart.Core.Validation; + +namespace Aquiis.SimpleStart.Core.Entities +{ + public class NotificationPreferences : BaseModel + { + [RequiredGuid] + public Guid OrganizationId { get; set; } + + [Required] + public string UserId { get; set; } = string.Empty; + + // In-App Notification Preferences + public bool EnableInAppNotifications { get; set; } = true; + + // Email Preferences + public bool EnableEmailNotifications { get; set; } = true; + + [StringLength(200)] + public string? EmailAddress { get; set; } + + public bool EmailLeaseExpiring { get; set; } = true; + public bool EmailPaymentDue { get; set; } = true; + public bool EmailPaymentReceived { get; set; } = true; + public bool EmailApplicationStatusChange { get; set; } = true; + public bool EmailMaintenanceUpdate { get; set; } = true; + public bool EmailInspectionScheduled { get; set; } = true; + + // SMS Preferences + public bool EnableSMSNotifications { get; set; } = false; + + [StringLength(20)] + public string? PhoneNumber { get; set; } + + public bool SMSPaymentDue { get; set; } = false; + public bool SMSMaintenanceEmergency { get; set; } = true; + public bool SMSLeaseExpiringUrgent { get; set; } = false; // 30 days or less + + // Digest Preferences + public bool EnableDailyDigest { get; set; } = false; + public TimeSpan DailyDigestTime { get; set; } = new TimeSpan(9, 0, 0); // 9 AM + + public bool EnableWeeklyDigest { get; set; } = false; + public DayOfWeek WeeklyDigestDay { get; set; } = DayOfWeek.Monday; + + // Navigation + [ForeignKey(nameof(OrganizationId))] + public virtual Organization? Organization { get; set; } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Entities/OperationResult.cs b/Aquiis.SimpleStart/Core/Entities/OperationResult.cs new file mode 100644 index 0000000..7ef7375 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Entities/OperationResult.cs @@ -0,0 +1,24 @@ +namespace Aquiis.SimpleStart.Core.Entities +{ + public class OperationResult + { + public bool Success { get; set; } + public string Message { get; set; } = string.Empty; + public List Errors { get; set; } = new(); + + public static OperationResult SuccessResult(string message = "Operation completed successfully") + { + return new OperationResult { Success = true, Message = message }; + } + + public static OperationResult FailureResult(string message, List? errors = null) + { + return new OperationResult + { + Success = false, + Message = message, + Errors = errors ?? new List() + }; + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Entities/OrganizationEmailSettings.cs b/Aquiis.SimpleStart/Core/Entities/OrganizationEmailSettings.cs new file mode 100644 index 0000000..0db7d2b --- /dev/null +++ b/Aquiis.SimpleStart/Core/Entities/OrganizationEmailSettings.cs @@ -0,0 +1,64 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Aquiis.SimpleStart.Core.Validation; + +namespace Aquiis.SimpleStart.Core.Entities +{ + /// + /// Stores SendGrid email configuration per organization. + /// Each organization manages their own SendGrid account. + /// + public class OrganizationEmailSettings : BaseModel + { + [RequiredGuid] + public Guid OrganizationId { get; set; } + + // SendGrid Configuration + public bool IsEmailEnabled { get; set; } + + /// + /// Encrypted SendGrid API key using Data Protection API + /// + [StringLength(1000)] + public string? SendGridApiKeyEncrypted { get; set; } + + [StringLength(200)] + [EmailAddress] + public string? FromEmail { get; set; } + + [StringLength(200)] + public string? FromName { get; set; } + + // Email Usage Tracking (local cache) + public int EmailsSentToday { get; set; } + public int EmailsSentThisMonth { get; set; } + public DateTime? LastEmailSentOn { get; set; } + public DateTime? StatsLastUpdatedOn { get; set; } + public DateTime? DailyCountResetOn { get; set; } + public DateTime? MonthlyCountResetOn { get; set; } + + // SendGrid Account Info (cached from API) + public int? DailyLimit { get; set; } + public int? MonthlyLimit { get; set; } + + [StringLength(100)] + public string? PlanType { get; set; } // Free, Essentials, Pro, etc. + + // Verification Status + public bool IsVerified { get; set; } + public DateTime? LastVerifiedOn { get; set; } + + /// + /// Last error encountered when sending email or verifying API key + /// + [StringLength(1000)] + public string? LastError { get; set; } + + public DateTime? LastErrorOn { get; set; } + + // Navigation + [ForeignKey(nameof(OrganizationId))] + public virtual Organization? Organization { get; set; } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Entities/OrganizationSMSSettings.cs b/Aquiis.SimpleStart/Core/Entities/OrganizationSMSSettings.cs new file mode 100644 index 0000000..bc71944 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Entities/OrganizationSMSSettings.cs @@ -0,0 +1,65 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Aquiis.SimpleStart.Core.Validation; + +namespace Aquiis.SimpleStart.Core.Entities +{ + /// + /// Stores Twilio SMS configuration per organization. + /// Each organization manages their own Twilio account. + /// + public class OrganizationSMSSettings : BaseModel + { + [RequiredGuid] + public Guid OrganizationId { get; set; } + + // Twilio Configuration + public bool IsSMSEnabled { get; set; } + + /// + /// Encrypted Twilio Account SID using Data Protection API + /// + [StringLength(1000)] + public string? TwilioAccountSidEncrypted { get; set; } + + /// + /// Encrypted Twilio Auth Token using Data Protection API + /// + [StringLength(1000)] + public string? TwilioAuthTokenEncrypted { get; set; } + + [StringLength(20)] + [Phone] + public string? TwilioPhoneNumber { get; set; } + + // SMS Usage Tracking (local cache) + public int SMSSentToday { get; set; } + public int SMSSentThisMonth { get; set; } + public DateTime? LastSMSSentOn { get; set; } + public DateTime? StatsLastUpdatedOn { get; set; } + public DateTime? DailyCountResetOn { get; set; } + public DateTime? MonthlyCountResetOn { get; set; } + + // Twilio Account Info (cached from API) + public decimal? AccountBalance { get; set; } + public decimal? CostPerSMS { get; set; } // Approximate cost + + [StringLength(100)] + public string? AccountType { get; set; } // Trial, Paid + + // Verification Status + public bool IsVerified { get; set; } + public DateTime? LastVerifiedOn { get; set; } + + /// + /// Last error encountered when sending SMS or verifying credentials + /// + [StringLength(1000)] + public string? LastError { get; set; } + + // Navigation + [ForeignKey(nameof(OrganizationId))] + public virtual Organization? Organization { get; set; } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Interfaces/Services/IEmailService.cs b/Aquiis.SimpleStart/Core/Interfaces/Services/IEmailService.cs new file mode 100644 index 0000000..44e5ab6 --- /dev/null +++ b/Aquiis.SimpleStart/Core/Interfaces/Services/IEmailService.cs @@ -0,0 +1,11 @@ + +namespace Aquiis.SimpleStart.Core.Interfaces.Services +{ + public interface IEmailService + { + Task SendEmailAsync(string to, string subject, string body); + Task SendEmailAsync(string to, string subject, string body, string? fromName = null); + Task SendTemplateEmailAsync(string to, string templateId, Dictionary templateData); + Task ValidateEmailAddressAsync(string email); + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Core/Interfaces/Services/ISMSService.cs b/Aquiis.SimpleStart/Core/Interfaces/Services/ISMSService.cs new file mode 100644 index 0000000..bb49f1c --- /dev/null +++ b/Aquiis.SimpleStart/Core/Interfaces/Services/ISMSService.cs @@ -0,0 +1,9 @@ + +namespace Aquiis.SimpleStart.Core.Interfaces.Services +{ + public interface ISMSService + { + Task SendSMSAsync(string phoneNumber, string message); + Task ValidatePhoneNumberAsync(string phoneNumber); + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor new file mode 100644 index 0000000..3696623 --- /dev/null +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor @@ -0,0 +1,443 @@ +@page "/settings/email" +@using Aquiis.SimpleStart.Application.Services +@using Aquiis.SimpleStart.Infrastructure.Services +@using SocketIOClient.Messages +@using System.ComponentModel.DataAnnotations +@inject EmailSettingsService EmailSettingsService +@inject SendGridEmailService EmailService +@inject ToastService ToastService +@inject IJSRuntime JSRuntime + +@inject UserContextService _userContext + +Email Settings - Aquiis + +
+
+
+

+ Email Configuration +

+

+ Configure SendGrid integration for automated email notifications +

+
+
+ + @if (settings == null) + { +
+
+ Loading... +
+
+ } + else if (!settings.IsEmailEnabled) + { +
+
+
+

Email Integration Not Configured

+

Enable automated email notifications by connecting your SendGrid account.

+ +
Why Use SendGrid?
+
    +
  • Free tier: 100 emails per day forever (perfect for getting started)
  • +
  • Reliable delivery: Industry-leading email infrastructure
  • +
  • Analytics: Track opens, clicks, and bounces
  • +
  • Your account: You manage billing and usage directly
  • +
+ +
Setup Steps:
+
    +
  1. + + Create a free SendGrid account + +
  2. +
  3. Generate an API key with "Mail Send" permissions
  4. +
  5. Click the button below to configure your API key
  6. +
+ + +
+
+
+
+
+
Need Help?
+
+
+
Common Questions
+

+ Do I need a paid account?
+ No! The free tier (100 emails/day) is usually sufficient. +

+

+ What happens without email?
+ The app works fine. Notifications appear in-app only. +

+

+ Is my API key secure?
+ Yes, it's encrypted and never shared. +

+
+ + API Key Guide + +
+
+
+
+ } + else + { +
+
+
+
+ Email Integration Active +
+
+
+
+
Configuration
+

+ From Email:
+ @settings.FromEmail +

+

+ From Name:
+ @settings.FromName +

+

+ + Verified @settings.LastVerifiedOn?.ToString("g") +

+
+
+ @if (stats != null && stats.IsConfigured) + { +
Usage Statistics
+
+
+ Today: + @stats.EmailsSentToday / @stats.DailyLimit +
+
+
+ @(stats.DailyPercentUsed)% +
+
+
+
+
+ This Month: + @stats.EmailsSentThisMonth / @stats.MonthlyLimit +
+
+
+ @(stats.MonthlyPercentUsed)% +
+
+
+

+ + Plan: @stats.PlanType + @if (stats.LastEmailSentOn.HasValue) + { +
Last sent: @stats.LastEmailSentOn?.ToString("g") + } +

+ } +
+
+ + @if (!string.IsNullOrEmpty(settings.LastError)) + { +
+ + Recent Error: @settings.LastError +
+ Try updating your API key or contact SendGrid support +
+ } + +
+ + + + +
+
+
+ +
+
+ Email Activity +
+
+

+ View detailed email statistics in your + + SendGrid Dashboard + +

+
+
+
+ +
+
+
+
Tips
+
+
+
Optimize Email Usage
+
    +
  • Enable daily/weekly digest mode to batch notifications
  • +
  • Let users configure their notification preferences
  • +
  • Monitor your usage to avoid hitting limits
  • +
  • Consider upgrading if you consistently hit daily limits
  • +
+ +
SendGrid Features
+
    +
  • Templates: Create branded email templates
  • +
  • Analytics: Track opens and clicks
  • +
  • Webhooks: Get delivery notifications
  • +
  • Lists: Manage recipient groups
  • +
+
+
+
+
+ } +
+ +@* Configuration Modal *@ +@if (showConfigModal) +{ + +} + +@code { + private OrganizationEmailSettings? settings; + private SendGridStats? stats; + private bool showConfigModal; + private bool isSaving; + private bool isRefreshing; + private ConfigurationModel configModel = new(); + + protected override async Task OnInitializedAsync() + { + await LoadSettings(); + } + + private async Task LoadSettings() + { + settings = await EmailSettingsService.GetOrCreateSettingsAsync(); + if (settings.IsEmailEnabled) + { + stats = await EmailService.GetSendGridStatsAsync(); + } + } + + private async Task SaveConfiguration() + { + isSaving = true; + + var result = await EmailSettingsService.UpdateSendGridConfigAsync( + configModel.ApiKey!, + configModel.FromEmail!, + configModel.FromName!); + + if (result.Success) + { + ToastService.ShowSuccess(result.Message); + showConfigModal = false; + configModel = new(); // Clear sensitive data + await LoadSettings(); + } + else + { + ToastService.ShowError(result.Message); + } + + isSaving = false; + } + + private async Task SendTestEmail() + { + var userEmail = await _userContext.GetUserEmailAsync(); + var testEmail = await JSRuntime.InvokeAsync("prompt", + "Enter email address to send test email:", + userEmail ?? settings?.FromEmail ?? ""); + + if (!string.IsNullOrEmpty(testEmail)) + { + var result = await EmailSettingsService.TestEmailConfigurationAsync(testEmail); + if (result.Success) + ToastService.ShowSuccess(result.Message); + else + ToastService.ShowError(result.Message); + } + } + + private async Task DisableEmail() + { + var confirmed = await JSRuntime.InvokeAsync("confirm", + "Are you sure you want to disable email notifications?\n\n" + + "Notifications will only appear in-app until you re-enable email."); + + if (confirmed) + { + var result = await EmailSettingsService.DisableEmailAsync(); + ToastService.ShowInfo(result.Message); + await LoadSettings(); + } + } + + private async Task RefreshStats() + { + isRefreshing = true; + await LoadSettings(); + isRefreshing = false; + ToastService.ShowSuccess("Statistics refreshed"); + } + + private void CloseModal() + { + showConfigModal = false; + configModel = new(); // Clear sensitive data + } + + private string GetProgressBarClass(int percent) + { + return percent switch + { + < 50 => "bg-success", + < 75 => "bg-info", + < 90 => "bg-warning", + _ => "bg-danger" + }; + } + + public class ConfigurationModel + { + [Required(ErrorMessage = "SendGrid API key is required")] + [StringLength(100, MinimumLength = 32, ErrorMessage = "API key must be at least 32 characters")] + public string? ApiKey { get; set; } + + [Required(ErrorMessage = "From email address is required")] + [EmailAddress(ErrorMessage = "Invalid email address")] + public string? FromEmail { get; set; } + + [Required(ErrorMessage = "From name is required")] + [StringLength(200, MinimumLength = 2, ErrorMessage = "From name must be 2-200 characters")] + public string? FromName { get; set; } + } +} + + \ No newline at end of file diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor new file mode 100644 index 0000000..e62f4da --- /dev/null +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor @@ -0,0 +1,445 @@ +@page "/settings/sms" +@using Aquiis.SimpleStart.Application.Services +@using Aquiis.SimpleStart.Infrastructure.Services +@using SocketIOClient.Messages +@using System.ComponentModel.DataAnnotations +@inject EmailSettingsService EmailSettingsService +@inject SMSSettingsService SMSSettingsService + +@inject TwilioSMSService TwilioSMSService + +@inject ToastService ToastService +@inject IJSRuntime JSRuntime + +@inject UserContextService _userContext + +SMS Settings - Aquiis +
+
+
+

+ SMS Configuration +

+

+ Configure Twilio integration for automated SMS notifications +

+
+
+ + @if (settings == null) + { +
+
+ Loading... +
+
+ } + else if (!settings.IsEmailEnabled) + { +
+
+
+

SMS Integration Not Configured

+

Enable automated SMS notifications by connecting your Twilio account.

+ +
Why Use Twilio?
+
    +
  • Free tier: 100 messages per day forever (perfect for getting started)
  • +
  • Reliable delivery: Industry-leading SMS infrastructure
  • +
  • Analytics: Track delivery, opens, and clicks
  • +
  • Your account: You manage billing and usage directly
  • +
+ +
Setup Steps:
+
    +
  1. + + Create a free Twilio account + +
  2. +
  3. Generate an API key with "Messaging" permissions
  4. +
  5. Click the button below to configure your API key
  6. +
+ + +
+
+
+
+
+
Need Help?
+
+
+
Common Questions
+

+ Do I need a paid account?
+ No! The free tier (100 emails/day) is usually sufficient. +

+

+ What happens without email?
+ The app works fine. Notifications appear in-app only. +

+

+ Is my API key secure?
+ Yes, it's encrypted and never shared. +

+
+ + API Key Guide + +
+
+
+
+ } + else + { +
+
+
+
+ SMS Integration Active +
+
+
+
+
Configuration
+

+ From Email:
+ @settings.FromEmail +

+

+ From Name:
+ @settings.FromName +

+

+ + Verified @settings.LastVerifiedOn?.ToString("g") +

+
+
+ @if (stats != null && stats.IsConfigured) + { +
Usage Statistics
+
+
+ Today: + @stats.EmailsSentToday / @stats.DailyLimit +
+
+
+ @(stats.DailyPercentUsed)% +
+
+
+
+
+ This Month: + @stats.EmailsSentThisMonth / @stats.MonthlyLimit +
+
+
+ @(stats.MonthlyPercentUsed)% +
+
+
+

+ + Plan: @stats.PlanType + @if (stats.LastEmailSentOn.HasValue) + { +
Last sent: @stats.LastEmailSentOn?.ToString("g") + } +

+ } +
+
+ + @if (!string.IsNullOrEmpty(settings.LastError)) + { +
+ + Recent Error: @settings.LastError +
+ Try updating your API key or contact SendGrid support +
+ } + +
+ + + + +
+
+
+ +
+
+ Email Activity +
+
+

+ View detailed SMS statistics in your + + Twilio Dashboard + +

+
+
+
+ +
+
+
+
Tips
+
+
+
Optimize SMS Usage
+
    +
  • Enable daily/weekly digest mode to batch notifications
  • +
  • Let users configure their notification preferences
  • +
  • Monitor your usage to avoid hitting limits
  • +
  • Consider upgrading if you consistently hit daily limits
  • +
+ +
Twilio Features
+
    +
  • Templates: Create branded SMS templates
  • +
  • Analytics: Track opens and clicks
  • +
  • Webhooks: Get delivery notifications
  • +
  • Lists: Manage recipient groups
  • +
+
+
+
+
+ } +
+ +@* Configuration Modal *@ +@if (showConfigModal) +{ + +} + +@code { + private OrganizationEmailSettings? settings; + private SendGridStats? stats; + private bool showConfigModal; + private bool isSaving; + private bool isRefreshing; + private ConfigurationModel configModel = new(); + + protected override async Task OnInitializedAsync() + { + await LoadSettings(); + } + + private async Task LoadSettings() + { + settings = await EmailSettingsService.GetOrCreateSettingsAsync(); + if (settings.IsEmailEnabled) + { + stats = await EmailService.GetSendGridStatsAsync(); + } + } + + private async Task SaveConfiguration() + { + isSaving = true; + + var result = await SMSSettingsService.UpdateTwilioConfigAsync( + configModel.ApiKey!, + configModel.FromPhoneNumber!, + configModel.FromName!); + + if (result.Success) + { + ToastService.ShowSuccess(result.Message); + showConfigModal = false; + configModel = new(); // Clear sensitive data + await LoadSettings(); + } + else + { + ToastService.ShowError(result.Message); + } + + isSaving = false; + } + + private async Task SendTestEmail() + { + var userEmail = await _userContext.GetUserEmailAsync(); + var testEmail = await JSRuntime.InvokeAsync("prompt", + "Enter email address to send test email:", + userEmail ?? settings?.FromEmail ?? ""); + + if (!string.IsNullOrEmpty(testEmail)) + { + var result = await EmailSettingsService.TestEmailConfigurationAsync(testEmail); + if (result.Success) + ToastService.ShowSuccess(result.Message); + else + ToastService.ShowError(result.Message); + } + } + + private async Task DisableEmail() + { + var confirmed = await JSRuntime.InvokeAsync("confirm", + "Are you sure you want to disable email notifications?\n\n" + + "Notifications will only appear in-app until you re-enable email."); + + if (confirmed) + { + var result = await EmailSettingsService.DisableEmailAsync(); + ToastService.ShowInfo(result.Message); + await LoadSettings(); + } + } + + private async Task RefreshStats() + { + isRefreshing = true; + await LoadSettings(); + isRefreshing = false; + ToastService.ShowSuccess("Statistics refreshed"); + } + + private void CloseModal() + { + showConfigModal = false; + configModel = new(); // Clear sensitive data + } + + private string GetProgressBarClass(int percent) + { + return percent switch + { + < 50 => "bg-success", + < 75 => "bg-info", + < 90 => "bg-warning", + _ => "bg-danger" + }; + } + + public class ConfigurationModel + { + [Required(ErrorMessage = "SendGrid API key is required")] + [StringLength(100, MinimumLength = 32, ErrorMessage = "API key must be at least 32 characters")] + public string? ApiKey { get; set; } + + [Required(ErrorMessage = "From phone number is required")] + [Phone(ErrorMessage = "Invalid phone number")] + public string? FromPhoneNumber { get; set; } + + [Required(ErrorMessage = "From name is required")] + [StringLength(200, MinimumLength = 2, ErrorMessage = "From name must be 2-200 characters")] + public string? FromName { get; set; } + } +} + + \ No newline at end of file diff --git a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs index 5bc265c..c85afcc 100644 --- a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs +++ b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs @@ -56,6 +56,16 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) // Workflow audit logging public DbSet WorkflowAuditLogs { get; set; } + // Notification system + public DbSet Notifications { get; set; } + public DbSet NotificationPreferences { get; set; } + + // Organization email settings + public DbSet OrganizationEmailSettings { get; set; } + + // Organization SMS settings + public DbSet OrganizationSMSSettings { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); @@ -531,6 +541,85 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.HasIndex(e => e.PerformedBy); }); + // Configure Notification entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.RecipientUserId); + entity.HasIndex(e => e.OrganizationId); + entity.HasIndex(e => e.SentOn); + entity.HasIndex(e => e.IsRead); + entity.HasIndex(e => e.Category); + + // Organization relationship + entity.HasOne(n => n.Organization) + .WithMany() + .HasForeignKey(n => n.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + + // User relationship (RecipientUserId) + entity.HasOne() + .WithMany() + .HasForeignKey(n => n.RecipientUserId) + .OnDelete(DeleteBehavior.Cascade); + }); + + // Configure NotificationPreferences entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.UserId); + entity.HasIndex(e => e.OrganizationId); + + // Unique constraint: one preference record per user per organization + entity.HasIndex(e => new { e.UserId, e.OrganizationId }) + .IsUnique(); + + // Organization relationship + entity.HasOne(np => np.Organization) + .WithMany() + .HasForeignKey(np => np.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + + // User relationship + entity.HasOne() + .WithMany() + .HasForeignKey(np => np.UserId) + .OnDelete(DeleteBehavior.Cascade); + }); + + // Configure OrganizationEmailSettings entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.OrganizationId).IsUnique(); + entity.HasIndex(e => e.IsEmailEnabled); + + // One email settings per organization + entity.HasOne(e => e.Organization) + .WithOne() + .HasForeignKey(e => e.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + }); + + // Configure OrganizationSMSSettings entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.OrganizationId).IsUnique(); + entity.HasIndex(e => e.IsSMSEnabled); + + // One SMS settings per organization + entity.HasOne(e => e.Organization) + .WithOne() + .HasForeignKey(e => e.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + }); + // Seed System Checklist Templates SeedChecklistTemplates(modelBuilder); } diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs new file mode 100644 index 0000000..a4b0c16 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs @@ -0,0 +1,4123 @@ +// +using System; +using Aquiis.SimpleStart.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aquiis.SimpleStart.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251229144549_AddNotificationInfrastructure")] + partial class AddNotificationInfrastructure + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.11"); + + modelBuilder.Entity("Aquiis.SimpleStart.Application.Services.Workflows.WorkflowAuditLog", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasColumnType("TEXT"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FromStatus") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Metadata") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PerformedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PerformedOn") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("ToStatus") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Action"); + + b.HasIndex("EntityId"); + + b.HasIndex("EntityType"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PerformedBy"); + + b.HasIndex("PerformedOn"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("WorkflowAuditLogs"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckCompletedOn") + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckPassed") + .HasColumnType("INTEGER"); + + b.Property("BackgroundCheckRequested") + .HasColumnType("INTEGER"); + + b.Property("BackgroundCheckRequestedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("CreditCheckCompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreditCheckNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("CreditCheckPassed") + .HasColumnType("INTEGER"); + + b.Property("CreditCheckRequested") + .HasColumnType("INTEGER"); + + b.Property("CreditCheckRequestedOn") + .HasColumnType("TEXT"); + + b.Property("CreditScore") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OverallResult") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RentalApplicationId") + .HasColumnType("TEXT"); + + b.Property("ResultNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("OverallResult"); + + b.HasIndex("RentalApplicationId") + .IsUnique(); + + b.ToTable("ApplicationScreenings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Color") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("DurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("EndOn") + .HasColumnType("TEXT"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Location") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("SourceEntityId") + .HasColumnType("TEXT"); + + b.Property("SourceEntityType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("StartOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventType"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("SourceEntityId"); + + b.HasIndex("StartOn"); + + b.HasIndex("SourceEntityType", "SourceEntityId"); + + b.ToTable("CalendarEvents"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AutoCreateEvents") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DefaultColor") + .HasColumnType("TEXT"); + + b.Property("DefaultIcon") + .HasColumnType("TEXT"); + + b.Property("DisplayOrder") + .HasColumnType("INTEGER"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ShowOnCalendar") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("OrganizationId", "EntityType") + .IsUnique(); + + b.ToTable("CalendarSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ChecklistTemplateId") + .HasColumnType("TEXT"); + + b.Property("ChecklistType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CompletedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("GeneralNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistTemplateId"); + + b.HasIndex("ChecklistType"); + + b.HasIndex("CompletedOn"); + + b.HasIndex("DocumentId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("Status"); + + b.ToTable("Checklists"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CategorySection") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ChecklistId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("IsChecked") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemOrder") + .HasColumnType("INTEGER"); + + b.Property("ItemText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhotoUrl") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("RequiresValue") + .HasColumnType("INTEGER"); + + b.Property("SectionOrder") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistId"); + + b.ToTable("ChecklistItems"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsSystemTemplate") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Category"); + + b.HasIndex("OrganizationId"); + + b.ToTable("ChecklistTemplates"); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0001-000000000001"), + Category = "Tour", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Standard property showing checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Property Tour", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000002"), + Category = "MoveIn", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Move-in inspection checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Move-In", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000003"), + Category = "MoveOut", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Move-out inspection checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Move-Out", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000004"), + Category = "Tour", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Open house event checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Open House", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllowsNotes") + .HasColumnType("INTEGER"); + + b.Property("CategorySection") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ChecklistTemplateId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsRequired") + .HasColumnType("INTEGER"); + + b.Property("ItemOrder") + .HasColumnType("INTEGER"); + + b.Property("ItemText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RequiresValue") + .HasColumnType("INTEGER"); + + b.Property("SectionOrder") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistTemplateId"); + + b.ToTable("ChecklistTemplateItems"); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0002-000000000001"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Greeted prospect and verified appointment", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000002"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Reviewed property exterior and curb appeal", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000003"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Showed parking area/garage", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000004"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 4, + ItemText = "Toured living room/common areas", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000005"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 5, + ItemText = "Showed all bedrooms", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000006"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 6, + ItemText = "Showed all bathrooms", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000007"), + AllowsNotes = true, + CategorySection = "Kitchen & Appliances", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 7, + ItemText = "Toured kitchen and demonstrated appliances", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 3 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000008"), + AllowsNotes = true, + CategorySection = "Kitchen & Appliances", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 8, + ItemText = "Explained which appliances are included", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 3 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000009"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 9, + ItemText = "Explained HVAC system and thermostat controls", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000010"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 10, + ItemText = "Reviewed utility responsibilities (tenant vs landlord)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000011"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 11, + ItemText = "Showed water heater location", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000012"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 12, + ItemText = "Showed storage areas (closets, attic, basement)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000013"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 13, + ItemText = "Showed laundry facilities", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000014"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 14, + ItemText = "Showed outdoor space (yard, patio, balcony)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000015"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 15, + ItemText = "Discussed monthly rent amount", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000016"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 16, + ItemText = "Explained security deposit and move-in costs", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000017"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 17, + ItemText = "Reviewed lease term length and start date", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000018"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 18, + ItemText = "Explained pet policy", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000019"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 19, + ItemText = "Explained application process and requirements", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000020"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 20, + ItemText = "Reviewed screening process (background, credit check)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000021"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 21, + ItemText = "Answered all prospect questions", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000022"), + AllowsNotes = true, + CategorySection = "Assessment", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 22, + ItemText = "Prospect Interest Level", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = true, + SectionOrder = 8 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000023"), + AllowsNotes = true, + CategorySection = "Assessment", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 23, + ItemText = "Overall showing feedback and notes", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 8 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000024"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Document property condition", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000025"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Collect keys and access codes", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000026"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Review lease terms with tenant", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000027"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Inspect property condition", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000028"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Collect all keys and access devices", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000029"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Document damages and needed repairs", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000030"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Set up signage and directional markers", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000031"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Prepare information packets", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000032"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Set up visitor sign-in sheet", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DocumentType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("FileData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("FileExtension") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("FileType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("InvoiceId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("TenantId"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActionItemsRequired") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("BathroomSinkGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomSinkNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomToiletGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomToiletNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomTubShowerGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomTubShowerNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomVentilationGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomVentilationNotes") + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("CarbonMonoxideDetectorsGood") + .HasColumnType("INTEGER"); + + b.Property("CarbonMonoxideDetectorsNotes") + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("ElectricalSystemGood") + .HasColumnType("INTEGER"); + + b.Property("ElectricalSystemNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorDoorsGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorDoorsNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorFoundationGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorFoundationNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorGuttersGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorGuttersNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorRoofGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorRoofNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorSidingGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorSidingNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorWindowsGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorWindowsNotes") + .HasColumnType("TEXT"); + + b.Property("GeneralNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("HvacSystemGood") + .HasColumnType("INTEGER"); + + b.Property("HvacSystemNotes") + .HasColumnType("TEXT"); + + b.Property("InspectedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("InspectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("InteriorCeilingsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorCeilingsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorDoorsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorDoorsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorFloorsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorFloorsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorWallsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorWallsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorWindowsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorWindowsNotes") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("KitchenAppliancesGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenAppliancesNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenCabinetsGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenCabinetsNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenCountersGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenCountersNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenSinkPlumbingGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenSinkPlumbingNotes") + .HasColumnType("TEXT"); + + b.Property("LandscapingGood") + .HasColumnType("INTEGER"); + + b.Property("LandscapingNotes") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OverallCondition") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("PlumbingSystemGood") + .HasColumnType("INTEGER"); + + b.Property("PlumbingSystemNotes") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("SmokeDetectorsGood") + .HasColumnType("INTEGER"); + + b.Property("SmokeDetectorsNotes") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CompletedOn"); + + b.HasIndex("DocumentId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("PropertyId"); + + b.ToTable("Inspections"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("AmountPaid") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("DueOn") + .HasColumnType("TEXT"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("InvoicedOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LateFeeAmount") + .HasColumnType("decimal(18,2)"); + + b.Property("LateFeeApplied") + .HasColumnType("INTEGER"); + + b.Property("LateFeeAppliedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaidOn") + .HasColumnType("TEXT"); + + b.Property("ReminderSent") + .HasColumnType("INTEGER"); + + b.Property("ReminderSentOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("InvoiceNumber") + .IsUnique(); + + b.HasIndex("LeaseId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Invoices"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActualMoveOutDate") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DeclinedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("ExpectedMoveOutDate") + .HasColumnType("TEXT"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseOfferId") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OfferedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PreviousLeaseId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProposedRenewalRent") + .HasColumnType("decimal(18,2)"); + + b.Property("RenewalNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("RenewalNotificationSent") + .HasColumnType("INTEGER"); + + b.Property("RenewalNotificationSentOn") + .HasColumnType("TEXT"); + + b.Property("RenewalNumber") + .HasColumnType("INTEGER"); + + b.Property("RenewalOfferedOn") + .HasColumnType("TEXT"); + + b.Property("RenewalReminderSentOn") + .HasColumnType("TEXT"); + + b.Property("RenewalResponseOn") + .HasColumnType("TEXT"); + + b.Property("RenewalStatus") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("SecurityDeposit") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("SignedOn") + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("TerminationNoticedOn") + .HasColumnType("TEXT"); + + b.Property("TerminationReason") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("Terms") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("TenantId"); + + b.ToTable("Leases"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConvertedLeaseId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasColumnType("decimal(18,2)"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OfferedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("RentalApplicationId") + .HasColumnType("TEXT"); + + b.Property("RespondedOn") + .HasColumnType("TEXT"); + + b.Property("ResponseNotes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SecurityDeposit") + .HasColumnType("decimal(18,2)"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Terms") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("RentalApplicationId"); + + b.ToTable("LeaseOffers"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActualCost") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("AssignedTo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EstimatedCost") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RequestedBy") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("RequestedByEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("RequestedByPhone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("RequestedOn") + .HasColumnType("TEXT"); + + b.Property("ResolutionNotes") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ScheduledOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LeaseId"); + + b.HasIndex("Priority"); + + b.HasIndex("PropertyId"); + + b.HasIndex("RequestedOn"); + + b.HasIndex("Status"); + + b.ToTable("MaintenanceRequests"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(5000) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasColumnType("TEXT"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("UserFullName") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Notes"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EmailError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("EmailSent") + .HasColumnType("INTEGER"); + + b.Property("EmailSentOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsRead") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ReadOn") + .HasColumnType("TEXT"); + + b.Property("RecipientUserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RelatedEntityId") + .HasColumnType("TEXT"); + + b.Property("RelatedEntityType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("SMSError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SMSSent") + .HasColumnType("INTEGER"); + + b.Property("SMSSentOn") + .HasColumnType("TEXT"); + + b.Property("SendEmail") + .HasColumnType("INTEGER"); + + b.Property("SendInApp") + .HasColumnType("INTEGER"); + + b.Property("SendSMS") + .HasColumnType("INTEGER"); + + b.Property("SentOn") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Category"); + + b.HasIndex("IsRead"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("RecipientUserId"); + + b.HasIndex("SentOn"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DailyDigestTime") + .HasColumnType("TEXT"); + + b.Property("EmailAddress") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmailApplicationStatusChange") + .HasColumnType("INTEGER"); + + b.Property("EmailInspectionScheduled") + .HasColumnType("INTEGER"); + + b.Property("EmailLeaseExpiring") + .HasColumnType("INTEGER"); + + b.Property("EmailMaintenanceUpdate") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentReceived") + .HasColumnType("INTEGER"); + + b.Property("EnableDailyDigest") + .HasColumnType("INTEGER"); + + b.Property("EnableEmailNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableInAppNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableSMSNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableWeeklyDigest") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("SMSLeaseExpiringUrgent") + .HasColumnType("INTEGER"); + + b.Property("SMSMaintenanceEmergency") + .HasColumnType("INTEGER"); + + b.Property("SMSPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WeeklyDigestDay") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "OrganizationId") + .IsUnique(); + + b.ToTable("NotificationPreferences"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IsActive"); + + b.HasIndex("OwnerId"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllowTenantDividendChoice") + .HasColumnType("INTEGER"); + + b.Property("ApplicationExpirationDays") + .HasColumnType("INTEGER"); + + b.Property("ApplicationFeeEnabled") + .HasColumnType("INTEGER"); + + b.Property("AutoCalculateSecurityDeposit") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DefaultApplicationFee") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("DefaultDividendPaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("DividendDistributionMonth") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LateFeeAutoApply") + .HasColumnType("INTEGER"); + + b.Property("LateFeeEnabled") + .HasColumnType("INTEGER"); + + b.Property("LateFeeGracePeriodDays") + .HasColumnType("INTEGER"); + + b.Property("LateFeePercentage") + .HasPrecision(5, 4) + .HasColumnType("TEXT"); + + b.Property("MaxLateFeeAmount") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationSharePercentage") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("PaymentReminderDaysBefore") + .HasColumnType("INTEGER"); + + b.Property("PaymentReminderEnabled") + .HasColumnType("INTEGER"); + + b.Property("RefundProcessingDays") + .HasColumnType("INTEGER"); + + b.Property("SecurityDepositInvestmentEnabled") + .HasColumnType("INTEGER"); + + b.Property("SecurityDepositMultiplier") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("TourNoShowGracePeriodHours") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("InvoiceId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaidOn") + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Bathrooms") + .HasMaxLength(3) + .HasColumnType("decimal(3,1)"); + + b.Property("Bedrooms") + .HasMaxLength(3) + .HasColumnType("INTEGER"); + + b.Property("City") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("IsAvailable") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastRoutineInspectionDate") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("NextRoutineInspectionDueDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RoutineInspectionIntervalMonths") + .HasColumnType("INTEGER"); + + b.Property("SquareFeet") + .HasMaxLength(7) + .HasColumnType("INTEGER"); + + b.Property("State") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("UnitNumber") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Address"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Properties"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateOfBirth") + .HasColumnType("TEXT"); + + b.Property("DesiredMoveInDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("FirstContactedOn") + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationNumber") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationState") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("InterestedPropertyId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Source") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("InterestedPropertyId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Status"); + + b.ToTable("ProspectiveTenants"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ApplicationFee") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationFeePaid") + .HasColumnType("INTEGER"); + + b.Property("ApplicationFeePaidOn") + .HasColumnType("TEXT"); + + b.Property("ApplicationFeePaymentMethod") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("AppliedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("CurrentAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("CurrentCity") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CurrentRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CurrentState") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("CurrentZipCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("DecidedOn") + .HasColumnType("TEXT"); + + b.Property("DecisionBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DenialReason") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("EmployerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmploymentLengthMonths") + .HasColumnType("INTEGER"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("JobTitle") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LandlordName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("LandlordPhone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyIncome") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("Reference1Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Reference1Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Reference1Relationship") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Reference2Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Reference2Phone") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Reference2Relationship") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AppliedOn"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("Status"); + + b.ToTable("RentalApplications"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SchemaVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AppliedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SchemaVersions"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateReceived") + .HasColumnType("TEXT"); + + b.Property("DeductionsAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("DeductionsReason") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("InInvestmentPool") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PoolEntryDate") + .HasColumnType("TEXT"); + + b.Property("PoolExitDate") + .HasColumnType("TEXT"); + + b.Property("RefundAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("RefundMethod") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RefundProcessedDate") + .HasColumnType("TEXT"); + + b.Property("RefundReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("TransactionReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("InInvestmentPool"); + + b.HasIndex("LeaseId") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("TenantId"); + + b.ToTable("SecurityDeposits"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BaseDividendAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ChoiceMadeOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("InvestmentPoolId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("MailingAddress") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("MonthsInPool") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PaymentProcessedOn") + .HasColumnType("TEXT"); + + b.Property("PaymentReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ProrationFactor") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("SecurityDepositId") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("InvestmentPoolId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("SecurityDepositId"); + + b.HasIndex("Status"); + + b.HasIndex("TenantId"); + + b.HasIndex("Year"); + + b.ToTable("SecurityDepositDividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActiveLeaseCount") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendPerLease") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("DividendsCalculatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendsDistributedOn") + .HasColumnType("TEXT"); + + b.Property("EndingBalance") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OrganizationShare") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("OrganizationSharePercentage") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("ReturnRate") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("StartingBalance") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantShareTotal") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("TotalEarnings") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Status"); + + b.HasIndex("Year") + .IsUnique(); + + b.ToTable("SecurityDepositInvestmentPools"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateOfBirth") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("EmergencyContactName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationNumber") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("IdentificationNumber") + .IsUnique(); + + b.HasIndex("OrganizationId"); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("ChecklistId") + .HasColumnType("TEXT"); + + b.Property("ConductedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("Feedback") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("InterestLevel") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("ScheduledOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("ScheduledOn"); + + b.HasIndex("Status"); + + b.ToTable("Tours"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GrantedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("GrantedOn") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevokedOn") + .HasColumnType("TEXT"); + + b.Property("Role") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrantedBy"); + + b.HasIndex("IsActive"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Role"); + + b.HasIndex("UserId", "OrganizationId") + .IsUnique(); + + b.ToTable("UserOrganizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ActiveOrganizationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginIP") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("LoginCount") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("PreviousLoginDate") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") + .WithOne("Screening") + .HasForeignKey("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", "RentalApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RentalApplication"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") + .WithMany("Checklists") + .HasForeignKey("ChecklistTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ChecklistTemplate"); + + b.Navigation("Document"); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") + .WithMany("Items") + .HasForeignKey("ChecklistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Checklist"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") + .WithMany("Items") + .HasForeignKey("ChecklistTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChecklistTemplate"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") + .WithMany() + .HasForeignKey("InvoiceId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany("Documents") + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Payment", "Payment") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany("Documents") + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Invoice"); + + b.Navigation("Lease"); + + b.Navigation("Payment"); + + b.Navigation("Property"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany("Invoices") + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Lease"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Leases") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany("Leases") + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany("Leases") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Property"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany() + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") + .WithMany() + .HasForeignKey("RentalApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + + b.Navigation("RentalApplication"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", "User") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("RecipientUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Properties") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "InterestedProperty") + .WithMany() + .HasForeignKey("InterestedPropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("InterestedProperty"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany("Applications") + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Lease"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", "InvestmentPool") + .WithMany("Dividends") + .HasForeignKey("InvestmentPoolId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", "SecurityDeposit") + .WithMany("Dividends") + .HasForeignKey("SecurityDepositId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("InvestmentPool"); + + b.Navigation("Lease"); + + b.Navigation("SecurityDeposit"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Tenants") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") + .WithMany() + .HasForeignKey("ChecklistId"); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany("Tours") + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Checklist"); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("GrantedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany("UserOrganizations") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => + { + b.Navigation("Checklists"); + + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.Navigation("Documents"); + + b.Navigation("Invoices"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.Navigation("Leases"); + + b.Navigation("Properties"); + + b.Navigation("Tenants"); + + b.Navigation("UserOrganizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.Navigation("Documents"); + + b.Navigation("Leases"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.Navigation("Applications"); + + b.Navigation("Tours"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.Navigation("Screening"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.Navigation("Dividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => + { + b.Navigation("Dividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.Navigation("Leases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs new file mode 100644 index 0000000..5a84a1e --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs @@ -0,0 +1,666 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aquiis.SimpleStart.Migrations +{ + /// + public partial class AddNotificationInfrastructure : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "NotificationPreferences", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + UserId = table.Column(type: "TEXT", nullable: false), + EnableInAppNotifications = table.Column(type: "INTEGER", nullable: false), + EnableEmailNotifications = table.Column(type: "INTEGER", nullable: false), + EmailAddress = table.Column(type: "TEXT", maxLength: 200, nullable: true), + EmailLeaseExpiring = table.Column(type: "INTEGER", nullable: false), + EmailPaymentDue = table.Column(type: "INTEGER", nullable: false), + EmailPaymentReceived = table.Column(type: "INTEGER", nullable: false), + EmailApplicationStatusChange = table.Column(type: "INTEGER", nullable: false), + EmailMaintenanceUpdate = table.Column(type: "INTEGER", nullable: false), + EmailInspectionScheduled = table.Column(type: "INTEGER", nullable: false), + EnableSMSNotifications = table.Column(type: "INTEGER", nullable: false), + PhoneNumber = table.Column(type: "TEXT", maxLength: 20, nullable: true), + SMSPaymentDue = table.Column(type: "INTEGER", nullable: false), + SMSMaintenanceEmergency = table.Column(type: "INTEGER", nullable: false), + SMSLeaseExpiringUrgent = table.Column(type: "INTEGER", nullable: false), + EnableDailyDigest = table.Column(type: "INTEGER", nullable: false), + DailyDigestTime = table.Column(type: "TEXT", nullable: false), + EnableWeeklyDigest = table.Column(type: "INTEGER", nullable: false), + WeeklyDigestDay = table.Column(type: "INTEGER", nullable: false), + CreatedOn = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), + LastModifiedOn = table.Column(type: "TEXT", nullable: true), + LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsDeleted = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_NotificationPreferences", x => x.Id); + table.ForeignKey( + name: "FK_NotificationPreferences_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_NotificationPreferences_Organizations_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organizations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Notifications", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", maxLength: 200, nullable: false), + Message = table.Column(type: "TEXT", maxLength: 2000, nullable: false), + Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), + Category = table.Column(type: "TEXT", maxLength: 50, nullable: false), + RecipientUserId = table.Column(type: "TEXT", nullable: false), + SentOn = table.Column(type: "TEXT", nullable: false), + ReadOn = table.Column(type: "TEXT", nullable: true), + IsRead = table.Column(type: "INTEGER", nullable: false), + RelatedEntityId = table.Column(type: "TEXT", nullable: true), + RelatedEntityType = table.Column(type: "TEXT", maxLength: 50, nullable: true), + SendInApp = table.Column(type: "INTEGER", nullable: false), + SendEmail = table.Column(type: "INTEGER", nullable: false), + SendSMS = table.Column(type: "INTEGER", nullable: false), + EmailSent = table.Column(type: "INTEGER", nullable: false), + EmailSentOn = table.Column(type: "TEXT", nullable: true), + SMSSent = table.Column(type: "INTEGER", nullable: false), + SMSSentOn = table.Column(type: "TEXT", nullable: true), + EmailError = table.Column(type: "TEXT", maxLength: 500, nullable: true), + SMSError = table.Column(type: "TEXT", maxLength: 500, nullable: true), + CreatedOn = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), + LastModifiedOn = table.Column(type: "TEXT", nullable: true), + LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsDeleted = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Notifications", x => x.Id); + table.ForeignKey( + name: "FK_Notifications_AspNetUsers_RecipientUserId", + column: x => x.RecipientUserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Notifications_Organizations_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organizations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000001"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000002"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000003"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000004"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000005"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000006"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000007"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000008"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000009"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000010"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000011"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000012"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000013"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000014"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000015"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000016"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000017"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000018"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000019"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000020"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000021"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000022"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000023"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000024"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000025"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000026"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000027"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000028"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000029"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000030"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000031"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000032"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000001"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000002"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000003"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000004"), + column: "LastModifiedBy", + value: null); + + migrationBuilder.CreateIndex( + name: "IX_NotificationPreferences_OrganizationId", + table: "NotificationPreferences", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_NotificationPreferences_UserId", + table: "NotificationPreferences", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_NotificationPreferences_UserId_OrganizationId", + table: "NotificationPreferences", + columns: new[] { "UserId", "OrganizationId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Notifications_Category", + table: "Notifications", + column: "Category"); + + migrationBuilder.CreateIndex( + name: "IX_Notifications_IsRead", + table: "Notifications", + column: "IsRead"); + + migrationBuilder.CreateIndex( + name: "IX_Notifications_OrganizationId", + table: "Notifications", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Notifications_RecipientUserId", + table: "Notifications", + column: "RecipientUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Notifications_SentOn", + table: "Notifications", + column: "SentOn"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "NotificationPreferences"); + + migrationBuilder.DropTable( + name: "Notifications"); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000001"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000002"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000003"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000004"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000005"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000006"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000007"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000008"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000009"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000010"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000011"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000012"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000013"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000014"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000015"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000016"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000017"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000018"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000019"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000020"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000021"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000022"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000023"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000024"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000025"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000026"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000027"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000028"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000029"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000030"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000031"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplateItems", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0002-000000000032"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000001"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000002"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000003"), + column: "LastModifiedBy", + value: ""); + + migrationBuilder.UpdateData( + table: "ChecklistTemplates", + keyColumn: "Id", + keyValue: new Guid("00000000-0000-0000-0001-000000000004"), + column: "LastModifiedBy", + value: ""); + } + } +} diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 2c59203..47a604a 100644 --- a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -541,7 +541,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) Description = "Standard property showing checklist", IsDeleted = false, IsSystemTemplate = true, - LastModifiedBy = "", Name = "Property Tour", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") }, @@ -554,7 +553,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) Description = "Move-in inspection checklist", IsDeleted = false, IsSystemTemplate = true, - LastModifiedBy = "", Name = "Move-In", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") }, @@ -567,7 +565,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) Description = "Move-out inspection checklist", IsDeleted = false, IsSystemTemplate = true, - LastModifiedBy = "", Name = "Move-Out", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") }, @@ -580,7 +577,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) Description = "Open house event checklist", IsDeleted = false, IsSystemTemplate = true, - LastModifiedBy = "", Name = "Open House", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") }); @@ -658,7 +654,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 1, ItemText = "Greeted prospect and verified appointment", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -675,7 +670,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 2, ItemText = "Reviewed property exterior and curb appeal", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -692,7 +686,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 3, ItemText = "Showed parking area/garage", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -709,7 +702,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 4, ItemText = "Toured living room/common areas", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 2 @@ -726,7 +718,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 5, ItemText = "Showed all bedrooms", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 2 @@ -743,7 +734,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 6, ItemText = "Showed all bathrooms", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 2 @@ -760,7 +750,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 7, ItemText = "Toured kitchen and demonstrated appliances", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 3 @@ -777,7 +766,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 8, ItemText = "Explained which appliances are included", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 3 @@ -794,7 +782,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 9, ItemText = "Explained HVAC system and thermostat controls", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 4 @@ -811,7 +798,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 10, ItemText = "Reviewed utility responsibilities (tenant vs landlord)", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 4 @@ -828,7 +814,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 11, ItemText = "Showed water heater location", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 4 @@ -845,7 +830,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 12, ItemText = "Showed storage areas (closets, attic, basement)", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 5 @@ -862,7 +846,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 13, ItemText = "Showed laundry facilities", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 5 @@ -879,7 +862,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 14, ItemText = "Showed outdoor space (yard, patio, balcony)", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 5 @@ -896,7 +878,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 15, ItemText = "Discussed monthly rent amount", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 6 @@ -913,7 +894,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 16, ItemText = "Explained security deposit and move-in costs", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 6 @@ -930,7 +910,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 17, ItemText = "Reviewed lease term length and start date", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 6 @@ -947,7 +926,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 18, ItemText = "Explained pet policy", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 6 @@ -964,7 +942,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 19, ItemText = "Explained application process and requirements", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 7 @@ -981,7 +958,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 20, ItemText = "Reviewed screening process (background, credit check)", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 7 @@ -998,7 +974,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 21, ItemText = "Answered all prospect questions", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 7 @@ -1015,7 +990,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 22, ItemText = "Prospect Interest Level", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = true, SectionOrder = 8 @@ -1032,7 +1006,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 23, ItemText = "Overall showing feedback and notes", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 8 @@ -1049,7 +1022,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 1, ItemText = "Document property condition", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1066,7 +1038,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 2, ItemText = "Collect keys and access codes", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1083,7 +1054,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 3, ItemText = "Review lease terms with tenant", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1100,7 +1070,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 1, ItemText = "Inspect property condition", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1117,7 +1086,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 2, ItemText = "Collect all keys and access devices", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1134,7 +1102,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 3, ItemText = "Document damages and needed repairs", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1151,7 +1118,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 1, ItemText = "Set up signage and directional markers", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1168,7 +1134,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 2, ItemText = "Prepare information packets", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -1185,7 +1150,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) IsRequired = true, ItemOrder = 3, ItemText = "Set up visitor sign-in sheet", - LastModifiedBy = "", OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), RequiresValue = false, SectionOrder = 1 @@ -2014,6 +1978,214 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Notes"); }); + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EmailError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("EmailSent") + .HasColumnType("INTEGER"); + + b.Property("EmailSentOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsRead") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ReadOn") + .HasColumnType("TEXT"); + + b.Property("RecipientUserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RelatedEntityId") + .HasColumnType("TEXT"); + + b.Property("RelatedEntityType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("SMSError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SMSSent") + .HasColumnType("INTEGER"); + + b.Property("SMSSentOn") + .HasColumnType("TEXT"); + + b.Property("SendEmail") + .HasColumnType("INTEGER"); + + b.Property("SendInApp") + .HasColumnType("INTEGER"); + + b.Property("SendSMS") + .HasColumnType("INTEGER"); + + b.Property("SentOn") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Category"); + + b.HasIndex("IsRead"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("RecipientUserId"); + + b.HasIndex("SentOn"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DailyDigestTime") + .HasColumnType("TEXT"); + + b.Property("EmailAddress") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmailApplicationStatusChange") + .HasColumnType("INTEGER"); + + b.Property("EmailInspectionScheduled") + .HasColumnType("INTEGER"); + + b.Property("EmailLeaseExpiring") + .HasColumnType("INTEGER"); + + b.Property("EmailMaintenanceUpdate") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentReceived") + .HasColumnType("INTEGER"); + + b.Property("EnableDailyDigest") + .HasColumnType("INTEGER"); + + b.Property("EnableEmailNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableInAppNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableSMSNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableWeeklyDigest") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("SMSLeaseExpiringUrgent") + .HasColumnType("INTEGER"); + + b.Property("SMSMaintenanceEmergency") + .HasColumnType("INTEGER"); + + b.Property("SMSPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WeeklyDigestDay") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "OrganizationId") + .IsUnique(); + + b.ToTable("NotificationPreferences"); + }); + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => { b.Property("Id") @@ -3607,6 +3779,40 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("RecipientUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => { b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) diff --git a/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs b/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs new file mode 100644 index 0000000..0f35db1 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs @@ -0,0 +1,43 @@ + +using Aquiis.SimpleStart.Application.Services; +using Aquiis.SimpleStart.Core.Interfaces.Services; + +namespace Aquiis.SimpleStart.Infrastructure.Services +{ + public class EmailService : IEmailService + { + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + + public EmailService(ILogger logger, IConfiguration configuration) + { + _logger = logger; + _configuration = configuration; + } + + public async Task SendEmailAsync(string to, string subject, string body) + { + // TODO: Implement with SendGrid/Mailgun in Task 2.5 + _logger.LogInformation($"[EMAIL] To: {to}, Subject: {subject}, Body: {body}"); + await Task.CompletedTask; + } + + public async Task SendEmailAsync(string to, string subject, string body, string? fromName = null) + { + _logger.LogInformation($"[EMAIL] From: {fromName}, To: {to}, Subject: {subject}"); + await Task.CompletedTask; + } + + public async Task SendTemplateEmailAsync(string to, string templateId, Dictionary templateData) + { + _logger.LogInformation($"[EMAIL TEMPLATE] To: {to}, Template: {templateId}"); + await Task.CompletedTask; + } + + public async Task ValidateEmailAddressAsync(string email) + { + // Basic validation + return await Task.FromResult(!string.IsNullOrWhiteSpace(email) && email.Contains("@")); + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs new file mode 100644 index 0000000..6156802 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs @@ -0,0 +1,29 @@ + +using Aquiis.SimpleStart.Core.Interfaces.Services; + +namespace Aquiis.SimpleStart.Infrastructure.Services +{ + public class SMSService : ISMSService + { + private readonly ILogger _logger; + + public SMSService(ILogger logger) + { + _logger = logger; + } + + public async Task SendSMSAsync(string phoneNumber, string message) + { + // TODO: Implement with Twilio in Task 2.5 + _logger.LogInformation($"[SMS] To: {phoneNumber}, Message: {message}"); + await Task.CompletedTask; + } + + public async Task ValidatePhoneNumberAsync(string phoneNumber) + { + // Basic validation + var digits = new string(phoneNumber.Where(char.IsDigit).ToArray()); + return await Task.FromResult(digits.Length >= 10); + } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs b/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs new file mode 100644 index 0000000..822f88b --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs @@ -0,0 +1,275 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Aquiis.SimpleStart.Core.Entities; +using Aquiis.SimpleStart.Core.Interfaces.Services; +using Aquiis.SimpleStart.Infrastructure.Data; +using Aquiis.SimpleStart.Shared.Services; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using SendGrid; +using SendGrid.Helpers.Mail; + +namespace Aquiis.SimpleStart.Infrastructure.Services +{ + public class SendGridEmailService : IEmailService + { + private readonly ApplicationDbContext _context; + private readonly UserContextService _userContext; + private readonly ILogger _logger; + private readonly IDataProtectionProvider _dataProtection; + + private const string PROTECTION_PURPOSE = "SendGridApiKey"; + + public SendGridEmailService( + ApplicationDbContext context, + UserContextService userContext, + ILogger logger, + IDataProtectionProvider dataProtection) + { + _context = context; + _userContext = userContext; + _logger = logger; + _dataProtection = dataProtection; + } + + public async Task SendEmailAsync(string to, string subject, string body) + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + if (orgId == null) + { + _logger.LogWarning("Cannot send email - no active organization"); + return; + } + + var settings = await GetEmailSettingsAsync(orgId.Value); + + if (!settings.IsEmailEnabled || string.IsNullOrEmpty(settings.SendGridApiKeyEncrypted)) + { + _logger.LogInformation("Email disabled for organization {OrgId}", orgId); + return; // Graceful degradation - don't throw + } + + try + { + var apiKey = DecryptApiKey(settings.SendGridApiKeyEncrypted); + var client = new SendGridClient(apiKey); + + var from = new EmailAddress(settings.FromEmail, settings.FromName); + var toAddress = new EmailAddress(to); + var msg = MailHelper.CreateSingleEmail(from, toAddress, subject, body, body); + + var response = await client.SendEmailAsync(msg); + + if (response.IsSuccessStatusCode) + { + _logger.LogInformation("Email sent successfully to {To}", to); + await UpdateUsageStatsAsync(settings); + } + else + { + var error = await response.Body.ReadAsStringAsync(); + _logger.LogError("SendGrid error {StatusCode}: {Error}", response.StatusCode, error); + settings.LastError = $"HTTP {response.StatusCode}: {error}"; + await _context.SaveChangesAsync(); + throw new Exception($"SendGrid returned {response.StatusCode}"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to send email via SendGrid for org {OrgId}", orgId); + settings.LastError = ex.Message; + settings.LastErrorOn = DateTime.UtcNow; + await _context.SaveChangesAsync(); + throw; + } + } + + public async Task SendEmailAsync(string to, string subject, string body, string? fromName = null) + { + // Override from name if provided + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + var settings = await GetEmailSettingsAsync(orgId!.Value); + + var originalFromName = settings.FromName; + if (!string.IsNullOrEmpty(fromName)) + { + settings.FromName = fromName; + } + + await SendEmailAsync(to, subject, body); + + settings.FromName = originalFromName; + } + + public async Task SendTemplateEmailAsync(string to, string templateId, Dictionary templateData) + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + var settings = await GetEmailSettingsAsync(orgId!.Value); + + if (!settings.IsEmailEnabled) + { + _logger.LogInformation("Email disabled for organization {OrgId}", orgId); + return; + } + + try + { + var apiKey = DecryptApiKey(settings.SendGridApiKeyEncrypted!); + var client = new SendGridClient(apiKey); + + var msg = new SendGridMessage(); + msg.SetFrom(new EmailAddress(settings.FromEmail, settings.FromName)); + msg.AddTo(new EmailAddress(to)); + msg.SetTemplateId(templateId); + msg.SetTemplateData(templateData); + + var response = await client.SendEmailAsync(msg); + + if (response.IsSuccessStatusCode) + { + await UpdateUsageStatsAsync(settings); + } + else + { + var error = await response.Body.ReadAsStringAsync(); + _logger.LogError("SendGrid template error: {Error}", error); + throw new Exception(error); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to send template email via SendGrid"); + throw; + } + } + + public async Task ValidateEmailAddressAsync(string email) + { + return !string.IsNullOrWhiteSpace(email) && + email.Contains("@") && + email.Contains("."); + } + + public async Task VerifyApiKeyAsync(string apiKey) + { + try + { + var client = new SendGridClient(apiKey); + + // Test API key by fetching user profile + var response = await client.RequestAsync( + method: SendGridClient.Method.GET, + urlPath: "user/profile"); + + return response.IsSuccessStatusCode; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "SendGrid API key verification failed"); + return false; + } + } + + public async Task GetSendGridStatsAsync() + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + var settings = await GetEmailSettingsAsync(orgId!.Value); + + if (!settings.IsEmailEnabled) + { + return new SendGridStats { IsConfigured = false }; + } + + // Optionally refresh stats from SendGrid API + // await RefreshStatsFromSendGridAsync(settings); + + return new SendGridStats + { + IsConfigured = true, + EmailsSentToday = settings.EmailsSentToday, + EmailsSentThisMonth = settings.EmailsSentThisMonth, + DailyLimit = settings.DailyLimit ?? 100, + MonthlyLimit = settings.MonthlyLimit ?? 40000, + LastEmailSentOn = settings.LastEmailSentOn, + LastVerifiedOn = settings.LastVerifiedOn, + PlanType = settings.PlanType ?? "Free", + DailyPercentUsed = settings.DailyLimit.HasValue + ? (int)((settings.EmailsSentToday / (double)settings.DailyLimit.Value) * 100) + : 0, + MonthlyPercentUsed = settings.MonthlyLimit.HasValue + ? (int)((settings.EmailsSentThisMonth / (double)settings.MonthlyLimit.Value) * 100) + : 0 + }; + } + + private async Task GetEmailSettingsAsync(Guid organizationId) + { + var settings = await _context.OrganizationEmailSettings + .FirstOrDefaultAsync(s => s.OrganizationId == organizationId && !s.IsDeleted); + + if (settings == null) + { + throw new InvalidOperationException( + $"Email settings not found for organization {organizationId}"); + } + + return settings; + } + + private async Task UpdateUsageStatsAsync(OrganizationEmailSettings settings) + { + var now = DateTime.UtcNow; + var today = now.Date; + + // Reset daily counter if needed + if (settings.DailyCountResetOn?.Date != today) + { + settings.EmailsSentToday = 0; + settings.DailyCountResetOn = today; + } + + // Reset monthly counter if needed (first of month) + if (settings.MonthlyCountResetOn?.Month != now.Month || + settings.MonthlyCountResetOn?.Year != now.Year) + { + settings.EmailsSentThisMonth = 0; + settings.MonthlyCountResetOn = new DateTime(now.Year, now.Month, 1); + } + + settings.EmailsSentToday++; + settings.EmailsSentThisMonth++; + settings.LastEmailSentOn = now; + settings.StatsLastUpdatedOn = now; + + await _context.SaveChangesAsync(); + } + + private string DecryptApiKey(string encrypted) + { + var protector = _dataProtection.CreateProtector(PROTECTION_PURPOSE); + return protector.Unprotect(encrypted); + } + + public string EncryptApiKey(string apiKey) + { + var protector = _dataProtection.CreateProtector(PROTECTION_PURPOSE); + return protector.Protect(apiKey); + } + } + + public class SendGridStats + { + public bool IsConfigured { get; set; } + public int EmailsSentToday { get; set; } + public int EmailsSentThisMonth { get; set; } + public int DailyLimit { get; set; } + public int MonthlyLimit { get; set; } + public int DailyPercentUsed { get; set; } + public int MonthlyPercentUsed { get; set; } + public DateTime? LastEmailSentOn { get; set; } + public DateTime? LastVerifiedOn { get; set; } + public string? PlanType { get; set; } + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Infrastructure/Services/TwilioSMSService.cs b/Aquiis.SimpleStart/Infrastructure/Services/TwilioSMSService.cs new file mode 100644 index 0000000..881d7b6 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Services/TwilioSMSService.cs @@ -0,0 +1,222 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Aquiis.SimpleStart.Core.Entities; +using Aquiis.SimpleStart.Core.Interfaces.Services; +using Aquiis.SimpleStart.Infrastructure.Data; +using Aquiis.SimpleStart.Shared.Services; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Twilio; +using Twilio.Rest.Api.V2010.Account; +using Twilio.Types; + +namespace Aquiis.SimpleStart.Infrastructure.Services +{ + public class TwilioSMSService : ISMSService + { + private readonly ApplicationDbContext _context; + private readonly UserContextService _userContext; + private readonly ILogger _logger; + private readonly IDataProtectionProvider _dataProtection; + + private const string ACCOUNT_SID_PURPOSE = "TwilioAccountSid"; + private const string AUTH_TOKEN_PURPOSE = "TwilioAuthToken"; + + public TwilioSMSService( + ApplicationDbContext context, + UserContextService userContext, + ILogger logger, + IDataProtectionProvider dataProtection) + { + _context = context; + _userContext = userContext; + _logger = logger; + _dataProtection = dataProtection; + } + + public async Task SendSMSAsync(string phoneNumber, string message) + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + if (orgId == null) + { + _logger.LogWarning("Cannot send SMS - no active organization"); + return; + } + + var settings = await GetSMSSettingsAsync(orgId.Value); + + if (!settings.IsSMSEnabled || + string.IsNullOrEmpty(settings.TwilioAccountSidEncrypted) || + string.IsNullOrEmpty(settings.TwilioAuthTokenEncrypted)) + { + _logger.LogInformation("SMS disabled for organization {OrgId}", orgId); + return; // Graceful degradation + } + + try + { + var accountSid = DecryptAccountSid(settings.TwilioAccountSidEncrypted); + var authToken = DecryptAuthToken(settings.TwilioAuthTokenEncrypted); + + TwilioClient.Init(accountSid, authToken); + + var messageResource = await MessageResource.CreateAsync( + body: message, + from: new PhoneNumber(settings.TwilioPhoneNumber), + to: new PhoneNumber(phoneNumber)); + + if (messageResource.Status == MessageResource.StatusEnum.Queued || + messageResource.Status == MessageResource.StatusEnum.Sent) + { + _logger.LogInformation("SMS sent successfully to {PhoneNumber}", phoneNumber); + await UpdateUsageStatsAsync(settings); + } + else + { + _logger.LogError("Twilio SMS status: {Status}", messageResource.Status); + settings.LastError = $"Status: {messageResource.Status}"; + await _context.SaveChangesAsync(); + throw new Exception($"SMS send failed with status: {messageResource.Status}"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to send SMS via Twilio for org {OrgId}", orgId); + settings.LastError = ex.Message; + await _context.SaveChangesAsync(); + throw; + } + } + + public async Task ValidatePhoneNumberAsync(string phoneNumber) + { + // Basic validation + var digits = new string(phoneNumber.Where(char.IsDigit).ToArray()); + return await Task.FromResult(digits.Length >= 10); + } + + public async Task VerifyTwilioCredentialsAsync(string accountSid, string authToken, string phoneNumber) + { + try + { + TwilioClient.Init(accountSid, authToken); + + // Verify by fetching the incoming phone number + var incomingPhoneNumber = await IncomingPhoneNumberResource.ReadAsync( + phoneNumber: new PhoneNumber(phoneNumber)); + + return incomingPhoneNumber.Any(); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Twilio credentials verification failed"); + return false; + } + } + + public async Task GetTwilioStatsAsync() + { + var orgId = await _userContext.GetActiveOrganizationIdAsync(); + var settings = await GetSMSSettingsAsync(orgId!.Value); + + if (!settings.IsSMSEnabled) + { + return new TwilioStats { IsConfigured = false }; + } + + return new TwilioStats + { + IsConfigured = true, + SMSSentToday = settings.SMSSentToday, + SMSSentThisMonth = settings.SMSSentThisMonth, + AccountBalance = settings.AccountBalance ?? 0, + CostPerSMS = settings.CostPerSMS ?? 0.0075m, + EstimatedMonthlyCost = settings.SMSSentThisMonth * (settings.CostPerSMS ?? 0.0075m), + LastSMSSentOn = settings.LastSMSSentOn, + LastVerifiedOn = settings.LastVerifiedOn, + AccountType = settings.AccountType ?? "Unknown" + }; + } + + private async Task GetSMSSettingsAsync(Guid organizationId) + { + var settings = await _context.OrganizationSMSSettings + .FirstOrDefaultAsync(s => s.OrganizationId == organizationId && !s.IsDeleted); + + if (settings == null) + { + throw new InvalidOperationException( + $"SMS settings not found for organization {organizationId}"); + } + + return settings; + } + + private async Task UpdateUsageStatsAsync(OrganizationSMSSettings settings) + { + var now = DateTime.UtcNow; + var today = now.Date; + + // Reset daily counter if needed + if (settings.DailyCountResetOn?.Date != today) + { + settings.SMSSentToday = 0; + settings.DailyCountResetOn = today; + } + + // Reset monthly counter if needed + if (settings.MonthlyCountResetOn?.Month != now.Month || + settings.MonthlyCountResetOn?.Year != now.Year) + { + settings.SMSSentThisMonth = 0; + settings.MonthlyCountResetOn = new DateTime(now.Year, now.Month, 1); + } + + settings.SMSSentToday++; + settings.SMSSentThisMonth++; + settings.LastSMSSentOn = now; + settings.StatsLastUpdatedOn = now; + + await _context.SaveChangesAsync(); + } + + private string DecryptAccountSid(string encrypted) + { + var protector = _dataProtection.CreateProtector(ACCOUNT_SID_PURPOSE); + return protector.Unprotect(encrypted); + } + + private string DecryptAuthToken(string encrypted) + { + var protector = _dataProtection.CreateProtector(AUTH_TOKEN_PURPOSE); + return protector.Unprotect(encrypted); + } + + public string EncryptAccountSid(string accountSid) + { + var protector = _dataProtection.CreateProtector(ACCOUNT_SID_PURPOSE); + return protector.Protect(accountSid); + } + + public string EncryptAuthToken(string authToken) + { + var protector = _dataProtection.CreateProtector(AUTH_TOKEN_PURPOSE); + return protector.Protect(authToken); + } + } + + public class TwilioStats + { + public bool IsConfigured { get; set; } + public int SMSSentToday { get; set; } + public int SMSSentThisMonth { get; set; } + public decimal AccountBalance { get; set; } + public decimal CostPerSMS { get; set; } + public decimal EstimatedMonthlyCost { get; set; } + public DateTime? LastSMSSentOn { get; set; } + public DateTime? LastVerifiedOn { get; set; } + public string AccountType { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Aquiis.SimpleStart/Program.cs b/Aquiis.SimpleStart/Program.cs index 0f7ec17..cabb7b1 100644 --- a/Aquiis.SimpleStart/Program.cs +++ b/Aquiis.SimpleStart/Program.cs @@ -14,6 +14,8 @@ using ElectronNET.API; using Microsoft.Extensions.Options; using Aquiis.SimpleStart.Application.Services.Workflows; +using Aquiis.SimpleStart.Core.Interfaces.Services; +using Aquiis.SimpleStart.Infrastructure.Services; var builder = WebApplication.CreateBuilder(args); @@ -163,6 +165,13 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); // Phase 2.4.8 - Notifications & Alerts +builder.Services.AddScoped(); // Phase 2.4.8 - Notifications & Alerts +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); // Workflow services builder.Services.AddScoped(); diff --git a/Aquiis.SimpleStart/appsettings.json b/Aquiis.SimpleStart/appsettings.json index fdb5a1b..2d52ade 100644 --- a/Aquiis.SimpleStart/appsettings.json +++ b/Aquiis.SimpleStart/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "DataSource=Infrastructure/Data/app_v0.0.0.db;Cache=Shared" + "DefaultConnection": "DataSource=Infrastructure/Data/app_v0.3.0.db;Cache=Shared" }, "Logging": { "LogLevel": { @@ -13,18 +13,27 @@ "AllowedHosts": "*", "ApplicationSettings": { "AppName": "Aquiis", - "Version": "0.2.0", + "Version": "0.3.0", "Author": "CIS Guru", "Email": "cisguru@outlook.com", "Repository": "https://github.com/xnodeoncode/Aquiis", "SoftDeleteEnabled": true, - "DatabaseFileName": "app_v0.0.0.db", + "DatabaseFileName": "app_v0.3.0.db", "PreviousDatabaseFileName": "app_v0.0.0.db", - "SchemaVersion": "0.0.0" + "SchemaVersion": "0.3.0" }, "SessionTimeout": { "InactivityTimeoutMinutes": 18, "WarningDurationMinutes": 3, "Enabled": true + }, + "DataProtection": { + "ApplicationName": "Aquiis" + }, + "Notifications": { + "EnableInApp": true, + "EnableEmail": true, + "EnableSMS": true, + "GracefulDegradation": true } } From fc6ca4e44571f7a2cbd25f685bc48950eb4ec65f Mon Sep 17 00:00:00 2001 From: CIS Guru Date: Mon, 29 Dec 2025 19:24:35 -0600 Subject: [PATCH 2/5] Final merge from Phase 2.4 Notifications Infrastructure --- .../Infrastructure/Services/SMSService.cs | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs index 6650606..a248656 100644 --- a/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs +++ b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs @@ -1,32 +1,6 @@ using Aquiis.SimpleStart.Core.Interfaces.Services; -<<<<<<< HEAD -namespace Aquiis.SimpleStart.Infrastructure.Services -{ - public class SMSService : ISMSService - { - private readonly ILogger _logger; - - public SMSService(ILogger logger) - { - _logger = logger; - } - - public async Task SendSMSAsync(string phoneNumber, string message) - { - // TODO: Implement with Twilio in Task 2.5 - _logger.LogInformation($"[SMS] To: {phoneNumber}, Message: {message}"); - await Task.CompletedTask; - } - - public async Task ValidatePhoneNumberAsync(string phoneNumber) - { - // Basic validation - var digits = new string(phoneNumber.Where(char.IsDigit).ToArray()); - return await Task.FromResult(digits.Length >= 10); - } -======= namespace Aquiis.SimpleStart.Infrastructure.Services; public class SMSService : ISMSService @@ -50,6 +24,5 @@ public async Task ValidatePhoneNumberAsync(string phoneNumber) // Basic validation var digits = new string(phoneNumber.Where(char.IsDigit).ToArray()); return await Task.FromResult(digits.Length >= 10); ->>>>>>> phase-2.4-notification-infrastructure } } \ No newline at end of file From 52bc29f32a63343b1efe07702b663c6c04eae3e4 Mon Sep 17 00:00:00 2001 From: CIS Guru Date: Mon, 29 Dec 2025 19:25:08 -0600 Subject: [PATCH 3/5] Final merge from Phase 2.4 Notifications Infrastructure --- .../Infrastructure/Services/EmailService.cs | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs b/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs index a7a8468..b340828 100644 --- a/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs +++ b/Aquiis.SimpleStart/Infrastructure/Services/EmailService.cs @@ -1,46 +1,4 @@ -<<<<<<< HEAD -using Aquiis.SimpleStart.Application.Services; -using Aquiis.SimpleStart.Core.Interfaces.Services; - -namespace Aquiis.SimpleStart.Infrastructure.Services -{ - public class EmailService : IEmailService - { - private readonly ILogger _logger; - private readonly IConfiguration _configuration; - - public EmailService(ILogger logger, IConfiguration configuration) - { - _logger = logger; - _configuration = configuration; - } - - public async Task SendEmailAsync(string to, string subject, string body) - { - // TODO: Implement with SendGrid/Mailgun in Task 2.5 - _logger.LogInformation($"[EMAIL] To: {to}, Subject: {subject}, Body: {body}"); - await Task.CompletedTask; - } - - public async Task SendEmailAsync(string to, string subject, string body, string? fromName = null) - { - _logger.LogInformation($"[EMAIL] From: {fromName}, To: {to}, Subject: {subject}"); - await Task.CompletedTask; - } - - public async Task SendTemplateEmailAsync(string to, string templateId, Dictionary templateData) - { - _logger.LogInformation($"[EMAIL TEMPLATE] To: {to}, Template: {templateId}"); - await Task.CompletedTask; - } - - public async Task ValidateEmailAddressAsync(string email) - { - // Basic validation - return await Task.FromResult(!string.IsNullOrWhiteSpace(email) && email.Contains("@")); - } -======= using Aquiis.SimpleStart.Core.Interfaces.Services; namespace Aquiis.SimpleStart.Infrastructure.Services; @@ -79,6 +37,5 @@ public async Task ValidateEmailAddressAsync(string email) { // Basic validation return await Task.FromResult(!string.IsNullOrWhiteSpace(email) && email.Contains("@")); ->>>>>>> phase-2.4-notification-infrastructure } } \ No newline at end of file From df883a068dac43b49e66811d1edb17deb64300c5 Mon Sep 17 00:00:00 2001 From: CIS Guru Date: Mon, 29 Dec 2025 20:11:41 -0600 Subject: [PATCH 4/5] Post Phase 2.4 merge clean up. --- ...ettingService.cs => SMSSettingsService.cs} | 0 .../Settings/Pages/EmailSettings.razor | 15 +- .../Settings/Pages/SMSSettings.razor | 191 +- .../Data/ApplicationDbContext.cs | 2 + ..._AddNotificationInfrastructure.Designer.cs | 4123 ----------------- ...229144549_AddNotificationInfrastructure.cs | 666 --- .../Infrastructure/Services/SMSService.cs | 1 + .../Services/SendGridEmailService.cs | 1 + Aquiis.SimpleStart/Program.cs | 6 + 9 files changed, 95 insertions(+), 4910 deletions(-) rename Aquiis.SimpleStart/Application/Services/{SMSSettingService.cs => SMSSettingsService.cs} (100%) delete mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs delete mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs diff --git a/Aquiis.SimpleStart/Application/Services/SMSSettingService.cs b/Aquiis.SimpleStart/Application/Services/SMSSettingsService.cs similarity index 100% rename from Aquiis.SimpleStart/Application/Services/SMSSettingService.cs rename to Aquiis.SimpleStart/Application/Services/SMSSettingsService.cs diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor index 3696623..d90317a 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor @@ -329,10 +329,11 @@ private async Task LoadSettings() { settings = await EmailSettingsService.GetOrCreateSettingsAsync(); - if (settings.IsEmailEnabled) - { - stats = await EmailService.GetSendGridStatsAsync(); - } + // TODO Phase 2.5: Uncomment when GetSendGridStatsAsync is implemented + // if (settings.IsEmailEnabled) + // { + // stats = await EmailService.GetSendGridStatsAsync(); + // } } private async Task SaveConfiguration() @@ -408,9 +409,9 @@ { return percent switch { - < 50 => "bg-success", - < 75 => "bg-info", - < 90 => "bg-warning", + ( < 50) => "bg-success", + ( < 75) => "bg-info", + ( < 90) => "bg-warning", _ => "bg-danger" }; } diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor index e62f4da..4f226a3 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor @@ -3,9 +3,7 @@ @using Aquiis.SimpleStart.Infrastructure.Services @using SocketIOClient.Messages @using System.ComponentModel.DataAnnotations -@inject EmailSettingsService EmailSettingsService @inject SMSSettingsService SMSSettingsService - @inject TwilioSMSService TwilioSMSService @inject ToastService ToastService @@ -18,7 +16,7 @@

- SMS Configuration + SMS Configuration

Configure Twilio integration for automated SMS notifications @@ -34,7 +32,7 @@

} - else if (!settings.IsEmailEnabled) + else if (!settings.IsSMSEnabled) {
@@ -44,9 +42,9 @@
Why Use Twilio?
    -
  • Free tier: 100 messages per day forever (perfect for getting started)
  • +
  • Free trial: $15 credit for testing (perfect for getting started)
  • Reliable delivery: Industry-leading SMS infrastructure
  • -
  • Analytics: Track delivery, opens, and clicks
  • +
  • Analytics: Track message delivery and status
  • Your account: You manage billing and usage directly
@@ -62,7 +60,7 @@
@@ -75,10 +73,10 @@
Common Questions

Do I need a paid account?
- No! The free tier (100 emails/day) is usually sufficient. + You get $15 free trial credit. Pay-as-you-go after that.

- What happens without email?
+ What happens without SMS?
The app works fine. Notifications appear in-app only.

@@ -86,7 +84,7 @@ Yes, it's encrypted and never shared.


- API Key Guide @@ -109,12 +107,8 @@
Configuration

- From Email:
- @settings.FromEmail -

-

- From Name:
- @settings.FromName + Twilio Phone Number:
+ @settings.TwilioPhoneNumber

@@ -122,44 +116,12 @@

- @if (stats != null && stats.IsConfigured) - { -
Usage Statistics
-
-
- Today: - @stats.EmailsSentToday / @stats.DailyLimit -
-
-
- @(stats.DailyPercentUsed)% -
-
-
-
-
- This Month: - @stats.EmailsSentThisMonth / @stats.MonthlyLimit -
-
-
- @(stats.MonthlyPercentUsed)% -
-
-
-

- - Plan: @stats.PlanType - @if (stats.LastEmailSentOn.HasValue) - { -
Last sent: @stats.LastEmailSentOn?.ToString("g") - } -

- } + @* TODO Phase 2.5: Implement SMS usage statistics display *@ +
Usage Statistics
+

+ + SMS usage statistics will be available after Twilio integration (Phase 2.5) +

@@ -169,7 +131,7 @@ Recent Error: @settings.LastError
- Try updating your API key or contact SendGrid support + Try updating your API key or contact Twilio support } @@ -177,15 +139,15 @@ - - @@ -193,7 +155,7 @@
- Email Activity + SMS Activity

@@ -222,10 +184,10 @@

Twilio Features
    -
  • Templates: Create branded SMS templates
  • -
  • Analytics: Track opens and clicks
  • +
  • Templates: Use message templates and variables
  • +
  • Analytics: Track delivery and status
  • Webhooks: Get delivery notifications
  • -
  • Lists: Manage recipient groups
  • +
  • Phone Numbers: Purchase dedicated numbers
@@ -242,7 +204,7 @@
@@ -316,8 +279,8 @@ } @code { - private OrganizationEmailSettings? settings; - private SendGridStats? stats; + private OrganizationSMSSettings? settings; + private TwilioStats? stats; private bool showConfigModal; private bool isSaving; private bool isRefreshing; @@ -330,11 +293,12 @@ private async Task LoadSettings() { - settings = await EmailSettingsService.GetOrCreateSettingsAsync(); - if (settings.IsEmailEnabled) - { - stats = await EmailService.GetSendGridStatsAsync(); - } + settings = await SMSSettingsService.GetOrCreateSettingsAsync(); + // TODO Phase 2.5: Uncomment when GetTwilioStatsAsync is implemented + // if (settings.IsSMSEnabled) + // { + // stats = await SMSService.GetTwilioStatsAsync(); + // } } private async Task SaveConfiguration() @@ -342,9 +306,9 @@ isSaving = true; var result = await SMSSettingsService.UpdateTwilioConfigAsync( - configModel.ApiKey!, - configModel.FromPhoneNumber!, - configModel.FromName!); + configModel.AccountSid!, + configModel.AuthToken!, + configModel.PhoneNumber!); if (result.Success) { @@ -361,16 +325,15 @@ isSaving = false; } - private async Task SendTestEmail() + private async Task SendTestSMS() { - var userEmail = await _userContext.GetUserEmailAsync(); - var testEmail = await JSRuntime.InvokeAsync("prompt", - "Enter email address to send test email:", - userEmail ?? settings?.FromEmail ?? ""); + var testPhone = await JSRuntime.InvokeAsync("prompt", + "Enter phone number to send test SMS (E.164 format, e.g., +1234567890):", + ""); - if (!string.IsNullOrEmpty(testEmail)) + if (!string.IsNullOrEmpty(testPhone)) { - var result = await EmailSettingsService.TestEmailConfigurationAsync(testEmail); + var result = await SMSSettingsService.TestSMSConfigurationAsync(testPhone); if (result.Success) ToastService.ShowSuccess(result.Message); else @@ -378,15 +341,15 @@ } } - private async Task DisableEmail() + private async Task DisableSMS() { var confirmed = await JSRuntime.InvokeAsync("confirm", - "Are you sure you want to disable email notifications?\n\n" + - "Notifications will only appear in-app until you re-enable email."); + "Are you sure you want to disable SMS notifications?\n\n" + + "Notifications will only appear in-app until you re-enable SMS."); if (confirmed) { - var result = await EmailSettingsService.DisableEmailAsync(); + var result = await SMSSettingsService.DisableSMSAsync(); ToastService.ShowInfo(result.Message); await LoadSettings(); } @@ -410,26 +373,26 @@ { return percent switch { - < 50 => "bg-success", - < 75 => "bg-info", - < 90 => "bg-warning", + ( < 50) => "bg-success", + ( < 75) => "bg-info", + ( < 90) => "bg-warning", _ => "bg-danger" }; } public class ConfigurationModel { - [Required(ErrorMessage = "SendGrid API key is required")] - [StringLength(100, MinimumLength = 32, ErrorMessage = "API key must be at least 32 characters")] - public string? ApiKey { get; set; } + [Required(ErrorMessage = "Twilio Account SID is required")] + [StringLength(100, MinimumLength = 34, ErrorMessage = "Account SID must be at least 34 characters")] + public string? AccountSid { get; set; } - [Required(ErrorMessage = "From phone number is required")] - [Phone(ErrorMessage = "Invalid phone number")] - public string? FromPhoneNumber { get; set; } + [Required(ErrorMessage = "Twilio Auth Token is required")] + [StringLength(100, MinimumLength = 32, ErrorMessage = "Auth Token must be at least 32 characters")] + public string? AuthToken { get; set; } - [Required(ErrorMessage = "From name is required")] - [StringLength(200, MinimumLength = 2, ErrorMessage = "From name must be 2-200 characters")] - public string? FromName { get; set; } + [Required(ErrorMessage = "Twilio phone number is required")] + [Phone(ErrorMessage = "Invalid phone number format")] + public string? PhoneNumber { get; set; } } } diff --git a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs index 75cb056..91dd98d 100644 --- a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs +++ b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs @@ -60,6 +60,8 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) // Notification system public DbSet Notifications { get; set; } public DbSet NotificationPreferences { get; set; } + public DbSet OrganizationEmailSettings { get; set; } + public DbSet OrganizationSMSSettings { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs deleted file mode 100644 index a4b0c16..0000000 --- a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.Designer.cs +++ /dev/null @@ -1,4123 +0,0 @@ -// -using System; -using Aquiis.SimpleStart.Infrastructure.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Aquiis.SimpleStart.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20251229144549_AddNotificationInfrastructure")] - partial class AddNotificationInfrastructure - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.11"); - - modelBuilder.Entity("Aquiis.SimpleStart.Application.Services.Workflows.WorkflowAuditLog", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Action") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("EntityId") - .HasColumnType("TEXT"); - - b.Property("EntityType") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("FromStatus") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Metadata") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PerformedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PerformedOn") - .HasColumnType("TEXT"); - - b.Property("Reason") - .HasColumnType("TEXT"); - - b.Property("ToStatus") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Action"); - - b.HasIndex("EntityId"); - - b.HasIndex("EntityType"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PerformedBy"); - - b.HasIndex("PerformedOn"); - - b.HasIndex("EntityType", "EntityId"); - - b.ToTable("WorkflowAuditLogs"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("BackgroundCheckCompletedOn") - .HasColumnType("TEXT"); - - b.Property("BackgroundCheckNotes") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("BackgroundCheckPassed") - .HasColumnType("INTEGER"); - - b.Property("BackgroundCheckRequested") - .HasColumnType("INTEGER"); - - b.Property("BackgroundCheckRequestedOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("CreditCheckCompletedOn") - .HasColumnType("TEXT"); - - b.Property("CreditCheckNotes") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("CreditCheckPassed") - .HasColumnType("INTEGER"); - - b.Property("CreditCheckRequested") - .HasColumnType("INTEGER"); - - b.Property("CreditCheckRequestedOn") - .HasColumnType("TEXT"); - - b.Property("CreditScore") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("OverallResult") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("RentalApplicationId") - .HasColumnType("TEXT"); - - b.Property("ResultNotes") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("OverallResult"); - - b.HasIndex("RentalApplicationId") - .IsUnique(); - - b.ToTable("ApplicationScreenings"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Color") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("DurationMinutes") - .HasColumnType("INTEGER"); - - b.Property("EndOn") - .HasColumnType("TEXT"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("Icon") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Location") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("SourceEntityId") - .HasColumnType("TEXT"); - - b.Property("SourceEntityType") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("StartOn") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("EventType"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("SourceEntityId"); - - b.HasIndex("StartOn"); - - b.HasIndex("SourceEntityType", "SourceEntityId"); - - b.ToTable("CalendarEvents"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarSettings", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AutoCreateEvents") - .HasColumnType("INTEGER"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DefaultColor") - .HasColumnType("TEXT"); - - b.Property("DefaultIcon") - .HasColumnType("TEXT"); - - b.Property("DisplayOrder") - .HasColumnType("INTEGER"); - - b.Property("EntityType") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("ShowOnCalendar") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("OrganizationId", "EntityType") - .IsUnique(); - - b.ToTable("CalendarSettings"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ChecklistTemplateId") - .HasColumnType("TEXT"); - - b.Property("ChecklistType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("CompletedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CompletedOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DocumentId") - .HasColumnType("TEXT"); - - b.Property("GeneralNotes") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("ChecklistTemplateId"); - - b.HasIndex("ChecklistType"); - - b.HasIndex("CompletedOn"); - - b.HasIndex("DocumentId"); - - b.HasIndex("LeaseId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("Status"); - - b.ToTable("Checklists"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("CategorySection") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("ChecklistId") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("IsChecked") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("ItemOrder") - .HasColumnType("INTEGER"); - - b.Property("ItemText") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Notes") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PhotoUrl") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("RequiresValue") - .HasColumnType("INTEGER"); - - b.Property("SectionOrder") - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("ChecklistId"); - - b.ToTable("ChecklistItems"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("IsSystemTemplate") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Category"); - - b.HasIndex("OrganizationId"); - - b.ToTable("ChecklistTemplates"); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0001-000000000001"), - Category = "Tour", - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - Description = "Standard property showing checklist", - IsDeleted = false, - IsSystemTemplate = true, - Name = "Property Tour", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") - }, - new - { - Id = new Guid("00000000-0000-0000-0001-000000000002"), - Category = "MoveIn", - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - Description = "Move-in inspection checklist", - IsDeleted = false, - IsSystemTemplate = true, - Name = "Move-In", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") - }, - new - { - Id = new Guid("00000000-0000-0000-0001-000000000003"), - Category = "MoveOut", - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - Description = "Move-out inspection checklist", - IsDeleted = false, - IsSystemTemplate = true, - Name = "Move-Out", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") - }, - new - { - Id = new Guid("00000000-0000-0000-0001-000000000004"), - Category = "Tour", - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - Description = "Open house event checklist", - IsDeleted = false, - IsSystemTemplate = true, - Name = "Open House", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") - }); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AllowsNotes") - .HasColumnType("INTEGER"); - - b.Property("CategorySection") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("ChecklistTemplateId") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("IsRequired") - .HasColumnType("INTEGER"); - - b.Property("ItemOrder") - .HasColumnType("INTEGER"); - - b.Property("ItemText") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("RequiresValue") - .HasColumnType("INTEGER"); - - b.Property("SectionOrder") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ChecklistTemplateId"); - - b.ToTable("ChecklistTemplateItems"); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0002-000000000001"), - AllowsNotes = true, - CategorySection = "Arrival & Introduction", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 1, - ItemText = "Greeted prospect and verified appointment", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000002"), - AllowsNotes = true, - CategorySection = "Arrival & Introduction", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 2, - ItemText = "Reviewed property exterior and curb appeal", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000003"), - AllowsNotes = true, - CategorySection = "Arrival & Introduction", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 3, - ItemText = "Showed parking area/garage", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000004"), - AllowsNotes = true, - CategorySection = "Interior Tour", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 4, - ItemText = "Toured living room/common areas", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 2 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000005"), - AllowsNotes = true, - CategorySection = "Interior Tour", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 5, - ItemText = "Showed all bedrooms", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 2 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000006"), - AllowsNotes = true, - CategorySection = "Interior Tour", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 6, - ItemText = "Showed all bathrooms", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 2 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000007"), - AllowsNotes = true, - CategorySection = "Kitchen & Appliances", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 7, - ItemText = "Toured kitchen and demonstrated appliances", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 3 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000008"), - AllowsNotes = true, - CategorySection = "Kitchen & Appliances", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 8, - ItemText = "Explained which appliances are included", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 3 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000009"), - AllowsNotes = true, - CategorySection = "Utilities & Systems", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 9, - ItemText = "Explained HVAC system and thermostat controls", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 4 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000010"), - AllowsNotes = true, - CategorySection = "Utilities & Systems", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 10, - ItemText = "Reviewed utility responsibilities (tenant vs landlord)", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 4 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000011"), - AllowsNotes = true, - CategorySection = "Utilities & Systems", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 11, - ItemText = "Showed water heater location", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 4 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000012"), - AllowsNotes = true, - CategorySection = "Storage & Amenities", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 12, - ItemText = "Showed storage areas (closets, attic, basement)", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 5 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000013"), - AllowsNotes = true, - CategorySection = "Storage & Amenities", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 13, - ItemText = "Showed laundry facilities", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 5 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000014"), - AllowsNotes = true, - CategorySection = "Storage & Amenities", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 14, - ItemText = "Showed outdoor space (yard, patio, balcony)", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 5 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000015"), - AllowsNotes = true, - CategorySection = "Lease Terms", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 15, - ItemText = "Discussed monthly rent amount", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 6 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000016"), - AllowsNotes = true, - CategorySection = "Lease Terms", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 16, - ItemText = "Explained security deposit and move-in costs", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 6 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000017"), - AllowsNotes = true, - CategorySection = "Lease Terms", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 17, - ItemText = "Reviewed lease term length and start date", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 6 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000018"), - AllowsNotes = true, - CategorySection = "Lease Terms", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 18, - ItemText = "Explained pet policy", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 6 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000019"), - AllowsNotes = true, - CategorySection = "Next Steps", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 19, - ItemText = "Explained application process and requirements", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 7 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000020"), - AllowsNotes = true, - CategorySection = "Next Steps", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 20, - ItemText = "Reviewed screening process (background, credit check)", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 7 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000021"), - AllowsNotes = true, - CategorySection = "Next Steps", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 21, - ItemText = "Answered all prospect questions", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 7 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000022"), - AllowsNotes = true, - CategorySection = "Assessment", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 22, - ItemText = "Prospect Interest Level", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = true, - SectionOrder = 8 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000023"), - AllowsNotes = true, - CategorySection = "Assessment", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 23, - ItemText = "Overall showing feedback and notes", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 8 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000024"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 1, - ItemText = "Document property condition", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000025"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 2, - ItemText = "Collect keys and access codes", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000026"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 3, - ItemText = "Review lease terms with tenant", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000027"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 1, - ItemText = "Inspect property condition", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000028"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 2, - ItemText = "Collect all keys and access devices", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000029"), - AllowsNotes = true, - CategorySection = "General", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 3, - ItemText = "Document damages and needed repairs", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000030"), - AllowsNotes = true, - CategorySection = "Preparation", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 1, - ItemText = "Set up signage and directional markers", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000031"), - AllowsNotes = true, - CategorySection = "Preparation", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 2, - ItemText = "Prepare information packets", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }, - new - { - Id = new Guid("00000000-0000-0000-0002-000000000032"), - AllowsNotes = true, - CategorySection = "Preparation", - ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), - CreatedBy = "", - CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), - IsDeleted = false, - IsRequired = true, - ItemOrder = 3, - ItemText = "Set up visitor sign-in sheet", - OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), - RequiresValue = false, - SectionOrder = 1 - }); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("DocumentType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("FileData") - .IsRequired() - .HasColumnType("BLOB"); - - b.Property("FileExtension") - .IsRequired() - .HasMaxLength(10) - .HasColumnType("TEXT"); - - b.Property("FileName") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("FilePath") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("FileSize") - .HasColumnType("INTEGER"); - - b.Property("FileType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("InvoiceId") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PaymentId") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("TenantId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InvoiceId"); - - b.HasIndex("LeaseId"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PaymentId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("TenantId"); - - b.ToTable("Documents"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ActionItemsRequired") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("BathroomSinkGood") - .HasColumnType("INTEGER"); - - b.Property("BathroomSinkNotes") - .HasColumnType("TEXT"); - - b.Property("BathroomToiletGood") - .HasColumnType("INTEGER"); - - b.Property("BathroomToiletNotes") - .HasColumnType("TEXT"); - - b.Property("BathroomTubShowerGood") - .HasColumnType("INTEGER"); - - b.Property("BathroomTubShowerNotes") - .HasColumnType("TEXT"); - - b.Property("BathroomVentilationGood") - .HasColumnType("INTEGER"); - - b.Property("BathroomVentilationNotes") - .HasColumnType("TEXT"); - - b.Property("CalendarEventId") - .HasColumnType("TEXT"); - - b.Property("CarbonMonoxideDetectorsGood") - .HasColumnType("INTEGER"); - - b.Property("CarbonMonoxideDetectorsNotes") - .HasColumnType("TEXT"); - - b.Property("CompletedOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DocumentId") - .HasColumnType("TEXT"); - - b.Property("ElectricalSystemGood") - .HasColumnType("INTEGER"); - - b.Property("ElectricalSystemNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorDoorsGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorDoorsNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorFoundationGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorFoundationNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorGuttersGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorGuttersNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorRoofGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorRoofNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorSidingGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorSidingNotes") - .HasColumnType("TEXT"); - - b.Property("ExteriorWindowsGood") - .HasColumnType("INTEGER"); - - b.Property("ExteriorWindowsNotes") - .HasColumnType("TEXT"); - - b.Property("GeneralNotes") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("HvacSystemGood") - .HasColumnType("INTEGER"); - - b.Property("HvacSystemNotes") - .HasColumnType("TEXT"); - - b.Property("InspectedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("InspectionType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("InteriorCeilingsGood") - .HasColumnType("INTEGER"); - - b.Property("InteriorCeilingsNotes") - .HasColumnType("TEXT"); - - b.Property("InteriorDoorsGood") - .HasColumnType("INTEGER"); - - b.Property("InteriorDoorsNotes") - .HasColumnType("TEXT"); - - b.Property("InteriorFloorsGood") - .HasColumnType("INTEGER"); - - b.Property("InteriorFloorsNotes") - .HasColumnType("TEXT"); - - b.Property("InteriorWallsGood") - .HasColumnType("INTEGER"); - - b.Property("InteriorWallsNotes") - .HasColumnType("TEXT"); - - b.Property("InteriorWindowsGood") - .HasColumnType("INTEGER"); - - b.Property("InteriorWindowsNotes") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("KitchenAppliancesGood") - .HasColumnType("INTEGER"); - - b.Property("KitchenAppliancesNotes") - .HasColumnType("TEXT"); - - b.Property("KitchenCabinetsGood") - .HasColumnType("INTEGER"); - - b.Property("KitchenCabinetsNotes") - .HasColumnType("TEXT"); - - b.Property("KitchenCountersGood") - .HasColumnType("INTEGER"); - - b.Property("KitchenCountersNotes") - .HasColumnType("TEXT"); - - b.Property("KitchenSinkPlumbingGood") - .HasColumnType("INTEGER"); - - b.Property("KitchenSinkPlumbingNotes") - .HasColumnType("TEXT"); - - b.Property("LandscapingGood") - .HasColumnType("INTEGER"); - - b.Property("LandscapingNotes") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("OverallCondition") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("PlumbingSystemGood") - .HasColumnType("INTEGER"); - - b.Property("PlumbingSystemNotes") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("SmokeDetectorsGood") - .HasColumnType("INTEGER"); - - b.Property("SmokeDetectorsNotes") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CompletedOn"); - - b.HasIndex("DocumentId"); - - b.HasIndex("LeaseId"); - - b.HasIndex("PropertyId"); - - b.ToTable("Inspections"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("AmountPaid") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DocumentId") - .HasColumnType("TEXT"); - - b.Property("DueOn") - .HasColumnType("TEXT"); - - b.Property("InvoiceNumber") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("InvoicedOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LateFeeAmount") - .HasColumnType("decimal(18,2)"); - - b.Property("LateFeeApplied") - .HasColumnType("INTEGER"); - - b.Property("LateFeeAppliedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("Notes") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PaidOn") - .HasColumnType("TEXT"); - - b.Property("ReminderSent") - .HasColumnType("INTEGER"); - - b.Property("ReminderSentOn") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DocumentId"); - - b.HasIndex("InvoiceNumber") - .IsUnique(); - - b.HasIndex("LeaseId"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Invoices"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ActualMoveOutDate") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DeclinedOn") - .HasColumnType("TEXT"); - - b.Property("DocumentId") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("ExpectedMoveOutDate") - .HasColumnType("TEXT"); - - b.Property("ExpiresOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseOfferId") - .HasColumnType("TEXT"); - - b.Property("MonthlyRent") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("Notes") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OfferedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PreviousLeaseId") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("ProposedRenewalRent") - .HasColumnType("decimal(18,2)"); - - b.Property("RenewalNotes") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("RenewalNotificationSent") - .HasColumnType("INTEGER"); - - b.Property("RenewalNotificationSentOn") - .HasColumnType("TEXT"); - - b.Property("RenewalNumber") - .HasColumnType("INTEGER"); - - b.Property("RenewalOfferedOn") - .HasColumnType("TEXT"); - - b.Property("RenewalReminderSentOn") - .HasColumnType("TEXT"); - - b.Property("RenewalResponseOn") - .HasColumnType("TEXT"); - - b.Property("RenewalStatus") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("SecurityDeposit") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("SignedOn") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("TenantId") - .HasColumnType("TEXT"); - - b.Property("TerminationNoticedOn") - .HasColumnType("TEXT"); - - b.Property("TerminationReason") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("Terms") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DocumentId"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("TenantId"); - - b.ToTable("Leases"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConvertedLeaseId") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("ExpiresOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("MonthlyRent") - .HasColumnType("decimal(18,2)"); - - b.Property("Notes") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("OfferedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("ProspectiveTenantId") - .HasColumnType("TEXT"); - - b.Property("RentalApplicationId") - .HasColumnType("TEXT"); - - b.Property("RespondedOn") - .HasColumnType("TEXT"); - - b.Property("ResponseNotes") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SecurityDeposit") - .HasColumnType("decimal(18,2)"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("Terms") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("PropertyId"); - - b.HasIndex("ProspectiveTenantId"); - - b.HasIndex("RentalApplicationId"); - - b.ToTable("LeaseOffers"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ActualCost") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("AssignedTo") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CalendarEventId") - .HasColumnType("TEXT"); - - b.Property("CompletedOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("EstimatedCost") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("RequestType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("RequestedBy") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("RequestedByEmail") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("RequestedByPhone") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("RequestedOn") - .HasColumnType("TEXT"); - - b.Property("ResolutionNotes") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("ScheduledOn") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("LeaseId"); - - b.HasIndex("Priority"); - - b.HasIndex("PropertyId"); - - b.HasIndex("RequestedOn"); - - b.HasIndex("Status"); - - b.ToTable("MaintenanceRequests"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(5000) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("EntityId") - .HasColumnType("TEXT"); - - b.Property("EntityType") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("UserFullName") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("CreatedBy"); - - b.ToTable("Notes"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("EmailError") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("EmailSent") - .HasColumnType("INTEGER"); - - b.Property("EmailSentOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("IsRead") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Message") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("ReadOn") - .HasColumnType("TEXT"); - - b.Property("RecipientUserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("RelatedEntityId") - .HasColumnType("TEXT"); - - b.Property("RelatedEntityType") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("SMSError") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SMSSent") - .HasColumnType("INTEGER"); - - b.Property("SMSSentOn") - .HasColumnType("TEXT"); - - b.Property("SendEmail") - .HasColumnType("INTEGER"); - - b.Property("SendInApp") - .HasColumnType("INTEGER"); - - b.Property("SendSMS") - .HasColumnType("INTEGER"); - - b.Property("SentOn") - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Category"); - - b.HasIndex("IsRead"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("RecipientUserId"); - - b.HasIndex("SentOn"); - - b.ToTable("Notifications"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DailyDigestTime") - .HasColumnType("TEXT"); - - b.Property("EmailAddress") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("EmailApplicationStatusChange") - .HasColumnType("INTEGER"); - - b.Property("EmailInspectionScheduled") - .HasColumnType("INTEGER"); - - b.Property("EmailLeaseExpiring") - .HasColumnType("INTEGER"); - - b.Property("EmailMaintenanceUpdate") - .HasColumnType("INTEGER"); - - b.Property("EmailPaymentDue") - .HasColumnType("INTEGER"); - - b.Property("EmailPaymentReceived") - .HasColumnType("INTEGER"); - - b.Property("EnableDailyDigest") - .HasColumnType("INTEGER"); - - b.Property("EnableEmailNotifications") - .HasColumnType("INTEGER"); - - b.Property("EnableInAppNotifications") - .HasColumnType("INTEGER"); - - b.Property("EnableSMSNotifications") - .HasColumnType("INTEGER"); - - b.Property("EnableWeeklyDigest") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("SMSLeaseExpiringUrgent") - .HasColumnType("INTEGER"); - - b.Property("SMSMaintenanceEmergency") - .HasColumnType("INTEGER"); - - b.Property("SMSPaymentDue") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("WeeklyDigestDay") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "OrganizationId") - .IsUnique(); - - b.ToTable("NotificationPreferences"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DisplayName") - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("State") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("IsActive"); - - b.HasIndex("OwnerId"); - - b.ToTable("Organizations"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSettings", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AllowTenantDividendChoice") - .HasColumnType("INTEGER"); - - b.Property("ApplicationExpirationDays") - .HasColumnType("INTEGER"); - - b.Property("ApplicationFeeEnabled") - .HasColumnType("INTEGER"); - - b.Property("AutoCalculateSecurityDeposit") - .HasColumnType("INTEGER"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DefaultApplicationFee") - .HasPrecision(18, 2) - .HasColumnType("TEXT"); - - b.Property("DefaultDividendPaymentMethod") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("DividendDistributionMonth") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LateFeeAutoApply") - .HasColumnType("INTEGER"); - - b.Property("LateFeeEnabled") - .HasColumnType("INTEGER"); - - b.Property("LateFeeGracePeriodDays") - .HasColumnType("INTEGER"); - - b.Property("LateFeePercentage") - .HasPrecision(5, 4) - .HasColumnType("TEXT"); - - b.Property("MaxLateFeeAmount") - .HasPrecision(18, 2) - .HasColumnType("TEXT"); - - b.Property("Name") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("OrganizationSharePercentage") - .HasPrecision(18, 6) - .HasColumnType("decimal(18,6)"); - - b.Property("PaymentReminderDaysBefore") - .HasColumnType("INTEGER"); - - b.Property("PaymentReminderEnabled") - .HasColumnType("INTEGER"); - - b.Property("RefundProcessingDays") - .HasColumnType("INTEGER"); - - b.Property("SecurityDepositInvestmentEnabled") - .HasColumnType("INTEGER"); - - b.Property("SecurityDepositMultiplier") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("TourNoShowGracePeriodHours") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId") - .IsUnique(); - - b.ToTable("OrganizationSettings"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DocumentId") - .HasColumnType("TEXT"); - - b.Property("InvoiceId") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Notes") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PaidOn") - .HasColumnType("TEXT"); - - b.Property("PaymentMethod") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DocumentId"); - - b.HasIndex("InvoiceId"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Payments"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Address") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Bathrooms") - .HasMaxLength(3) - .HasColumnType("decimal(3,1)"); - - b.Property("Bedrooms") - .HasMaxLength(3) - .HasColumnType("INTEGER"); - - b.Property("City") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("IsAvailable") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LastRoutineInspectionDate") - .HasColumnType("TEXT"); - - b.Property("MonthlyRent") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("NextRoutineInspectionDueDate") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PropertyType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("RoutineInspectionIntervalMonths") - .HasColumnType("INTEGER"); - - b.Property("SquareFeet") - .HasMaxLength(7) - .HasColumnType("INTEGER"); - - b.Property("State") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("UnitNumber") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("ZipCode") - .IsRequired() - .HasMaxLength(10) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Address"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Properties"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DateOfBirth") - .HasColumnType("TEXT"); - - b.Property("DesiredMoveInDate") - .HasColumnType("TEXT"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("FirstContactedOn") - .HasColumnType("TEXT"); - - b.Property("FirstName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IdentificationNumber") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IdentificationState") - .HasMaxLength(2) - .HasColumnType("TEXT"); - - b.Property("InterestedPropertyId") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LastName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Notes") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Phone") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("Source") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Email"); - - b.HasIndex("InterestedPropertyId"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("Status"); - - b.ToTable("ProspectiveTenants"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ApplicationFee") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ApplicationFeePaid") - .HasColumnType("INTEGER"); - - b.Property("ApplicationFeePaidOn") - .HasColumnType("TEXT"); - - b.Property("ApplicationFeePaymentMethod") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("AppliedOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("CurrentAddress") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("CurrentCity") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CurrentRent") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("CurrentState") - .IsRequired() - .HasMaxLength(2) - .HasColumnType("TEXT"); - - b.Property("CurrentZipCode") - .IsRequired() - .HasMaxLength(10) - .HasColumnType("TEXT"); - - b.Property("DecidedOn") - .HasColumnType("TEXT"); - - b.Property("DecisionBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("DenialReason") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("EmployerName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("EmploymentLengthMonths") - .HasColumnType("INTEGER"); - - b.Property("ExpiresOn") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("JobTitle") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LandlordName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("LandlordPhone") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("MonthlyIncome") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("ProspectiveTenantId") - .HasColumnType("TEXT"); - - b.Property("Reference1Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Reference1Phone") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("Reference1Relationship") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Reference2Name") - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("Reference2Phone") - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("Reference2Relationship") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AppliedOn"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("ProspectiveTenantId"); - - b.HasIndex("Status"); - - b.ToTable("RentalApplications"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SchemaVersion", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AppliedOn") - .HasColumnType("TEXT"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("Version") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("SchemaVersions"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Amount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DateReceived") - .HasColumnType("TEXT"); - - b.Property("DeductionsAmount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("DeductionsReason") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("InInvestmentPool") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("Notes") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PaymentMethod") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("PoolEntryDate") - .HasColumnType("TEXT"); - - b.Property("PoolExitDate") - .HasColumnType("TEXT"); - - b.Property("RefundAmount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("RefundMethod") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("RefundProcessedDate") - .HasColumnType("TEXT"); - - b.Property("RefundReference") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("TenantId") - .HasColumnType("TEXT"); - - b.Property("TransactionReference") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("InInvestmentPool"); - - b.HasIndex("LeaseId") - .IsUnique(); - - b.HasIndex("Status"); - - b.HasIndex("TenantId"); - - b.ToTable("SecurityDeposits"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("BaseDividendAmount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("ChoiceMadeOn") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DividendAmount") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("InvestmentPoolId") - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LeaseId") - .HasColumnType("TEXT"); - - b.Property("MailingAddress") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("MonthsInPool") - .HasColumnType("INTEGER"); - - b.Property("Notes") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("PaymentMethod") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("PaymentProcessedOn") - .HasColumnType("TEXT"); - - b.Property("PaymentReference") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("ProrationFactor") - .HasPrecision(18, 6) - .HasColumnType("decimal(18,6)"); - - b.Property("SecurityDepositId") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("TenantId") - .HasColumnType("TEXT"); - - b.Property("Year") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("InvestmentPoolId"); - - b.HasIndex("LeaseId"); - - b.HasIndex("SecurityDepositId"); - - b.HasIndex("Status"); - - b.HasIndex("TenantId"); - - b.HasIndex("Year"); - - b.ToTable("SecurityDepositDividends"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ActiveLeaseCount") - .HasColumnType("INTEGER"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DividendPerLease") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("DividendsCalculatedOn") - .HasColumnType("TEXT"); - - b.Property("DividendsDistributedOn") - .HasColumnType("TEXT"); - - b.Property("EndingBalance") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("Notes") - .HasMaxLength(1000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("OrganizationShare") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("OrganizationSharePercentage") - .HasPrecision(18, 6) - .HasColumnType("decimal(18,6)"); - - b.Property("ReturnRate") - .HasPrecision(18, 6) - .HasColumnType("decimal(18,6)"); - - b.Property("StartingBalance") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("TenantShareTotal") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("TotalEarnings") - .HasPrecision(18, 2) - .HasColumnType("decimal(18,2)"); - - b.Property("Year") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("Status"); - - b.HasIndex("Year") - .IsUnique(); - - b.ToTable("SecurityDepositInvestmentPools"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DateOfBirth") - .HasColumnType("TEXT"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("EmergencyContactName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT"); - - b.Property("EmergencyContactPhone") - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("FirstName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IdentificationNumber") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("LastName") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("Notes") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("TEXT"); - - b.Property("ProspectiveTenantId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Email") - .IsUnique(); - - b.HasIndex("IdentificationNumber") - .IsUnique(); - - b.HasIndex("OrganizationId"); - - b.ToTable("Tenants"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("CalendarEventId") - .HasColumnType("TEXT"); - - b.Property("ChecklistId") - .HasColumnType("TEXT"); - - b.Property("ConductedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("DurationMinutes") - .HasColumnType("INTEGER"); - - b.Property("Feedback") - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("InterestLevel") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasMaxLength(100) - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PropertyId") - .HasColumnType("TEXT"); - - b.Property("ProspectiveTenantId") - .HasColumnType("TEXT"); - - b.Property("ScheduledOn") - .HasColumnType("TEXT"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("ChecklistId"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("PropertyId"); - - b.HasIndex("ProspectiveTenantId"); - - b.HasIndex("ScheduledOn"); - - b.HasIndex("Status"); - - b.ToTable("Tours"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CreatedOn") - .HasColumnType("TEXT"); - - b.Property("GrantedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("GrantedOn") - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModifiedBy") - .HasColumnType("TEXT"); - - b.Property("LastModifiedOn") - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("RevokedOn") - .HasColumnType("TEXT"); - - b.Property("Role") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("GrantedBy"); - - b.HasIndex("IsActive"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("Role"); - - b.HasIndex("UserId", "OrganizationId") - .IsUnique(); - - b.ToTable("UserOrganizations"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("ActiveOrganizationId") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginIP") - .HasColumnType("TEXT"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property("LoginCount") - .HasColumnType("INTEGER"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("PreviousLoginDate") - .HasColumnType("TEXT"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT"); - - b.Property("ProviderKey") - .HasColumnType("TEXT"); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("LoginProvider") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") - .WithOne("Screening") - .HasForeignKey("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", "RentalApplicationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("RentalApplication"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Property"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") - .WithMany("Checklists") - .HasForeignKey("ChecklistTemplateId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") - .WithMany() - .HasForeignKey("DocumentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany() - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("ChecklistTemplate"); - - b.Navigation("Document"); - - b.Navigation("Lease"); - - b.Navigation("Property"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") - .WithMany("Items") - .HasForeignKey("ChecklistId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Checklist"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") - .WithMany("Items") - .HasForeignKey("ChecklistTemplateId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ChecklistTemplate"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") - .WithMany() - .HasForeignKey("InvoiceId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany("Documents") - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Payment", "Payment") - .WithMany() - .HasForeignKey("PaymentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany("Documents") - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") - .WithMany() - .HasForeignKey("TenantId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Invoice"); - - b.Navigation("Lease"); - - b.Navigation("Payment"); - - b.Navigation("Property"); - - b.Navigation("Tenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") - .WithMany() - .HasForeignKey("DocumentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany() - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Document"); - - b.Navigation("Lease"); - - b.Navigation("Property"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") - .WithMany() - .HasForeignKey("DocumentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany("Invoices") - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Document"); - - b.Navigation("Lease"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") - .WithMany() - .HasForeignKey("DocumentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany("Leases") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany("Leases") - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") - .WithMany("Leases") - .HasForeignKey("TenantId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Document"); - - b.Navigation("Property"); - - b.Navigation("Tenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") - .WithMany() - .HasForeignKey("ProspectiveTenantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") - .WithMany() - .HasForeignKey("RentalApplicationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Property"); - - b.Navigation("ProspectiveTenant"); - - b.Navigation("RentalApplication"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany() - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Lease"); - - b.Navigation("Property"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", "User") - .WithMany() - .HasForeignKey("CreatedBy") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("RecipientUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") - .WithMany() - .HasForeignKey("DocumentId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") - .WithMany("Payments") - .HasForeignKey("InvoiceId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Document"); - - b.Navigation("Invoice"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany("Properties") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.NoAction) - .IsRequired(); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "InterestedProperty") - .WithMany() - .HasForeignKey("InterestedPropertyId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("InterestedProperty"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") - .WithMany("Applications") - .HasForeignKey("ProspectiveTenantId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Property"); - - b.Navigation("ProspectiveTenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany() - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") - .WithMany() - .HasForeignKey("TenantId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Lease"); - - b.Navigation("Tenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", "InvestmentPool") - .WithMany("Dividends") - .HasForeignKey("InvestmentPoolId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") - .WithMany() - .HasForeignKey("LeaseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", "SecurityDeposit") - .WithMany("Dividends") - .HasForeignKey("SecurityDepositId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") - .WithMany() - .HasForeignKey("TenantId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("InvestmentPool"); - - b.Navigation("Lease"); - - b.Navigation("SecurityDeposit"); - - b.Navigation("Tenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) - .WithMany("Tenants") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.NoAction) - .IsRequired(); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => - { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") - .WithMany() - .HasForeignKey("ChecklistId"); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") - .WithMany() - .HasForeignKey("PropertyId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") - .WithMany("Tours") - .HasForeignKey("ProspectiveTenantId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Checklist"); - - b.Navigation("Property"); - - b.Navigation("ProspectiveTenant"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("GrantedBy") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") - .WithMany("UserOrganizations") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => - { - b.Navigation("Checklists"); - - b.Navigation("Items"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => - { - b.Navigation("Payments"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => - { - b.Navigation("Documents"); - - b.Navigation("Invoices"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => - { - b.Navigation("Leases"); - - b.Navigation("Properties"); - - b.Navigation("Tenants"); - - b.Navigation("UserOrganizations"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => - { - b.Navigation("Documents"); - - b.Navigation("Leases"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => - { - b.Navigation("Applications"); - - b.Navigation("Tours"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => - { - b.Navigation("Screening"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => - { - b.Navigation("Dividends"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => - { - b.Navigation("Dividends"); - }); - - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => - { - b.Navigation("Leases"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs deleted file mode 100644 index 5a84a1e..0000000 --- a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251229144549_AddNotificationInfrastructure.cs +++ /dev/null @@ -1,666 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Aquiis.SimpleStart.Migrations -{ - /// - public partial class AddNotificationInfrastructure : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "NotificationPreferences", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - OrganizationId = table.Column(type: "TEXT", nullable: false), - UserId = table.Column(type: "TEXT", nullable: false), - EnableInAppNotifications = table.Column(type: "INTEGER", nullable: false), - EnableEmailNotifications = table.Column(type: "INTEGER", nullable: false), - EmailAddress = table.Column(type: "TEXT", maxLength: 200, nullable: true), - EmailLeaseExpiring = table.Column(type: "INTEGER", nullable: false), - EmailPaymentDue = table.Column(type: "INTEGER", nullable: false), - EmailPaymentReceived = table.Column(type: "INTEGER", nullable: false), - EmailApplicationStatusChange = table.Column(type: "INTEGER", nullable: false), - EmailMaintenanceUpdate = table.Column(type: "INTEGER", nullable: false), - EmailInspectionScheduled = table.Column(type: "INTEGER", nullable: false), - EnableSMSNotifications = table.Column(type: "INTEGER", nullable: false), - PhoneNumber = table.Column(type: "TEXT", maxLength: 20, nullable: true), - SMSPaymentDue = table.Column(type: "INTEGER", nullable: false), - SMSMaintenanceEmergency = table.Column(type: "INTEGER", nullable: false), - SMSLeaseExpiringUrgent = table.Column(type: "INTEGER", nullable: false), - EnableDailyDigest = table.Column(type: "INTEGER", nullable: false), - DailyDigestTime = table.Column(type: "TEXT", nullable: false), - EnableWeeklyDigest = table.Column(type: "INTEGER", nullable: false), - WeeklyDigestDay = table.Column(type: "INTEGER", nullable: false), - CreatedOn = table.Column(type: "TEXT", nullable: false), - CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), - LastModifiedOn = table.Column(type: "TEXT", nullable: true), - LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), - IsDeleted = table.Column(type: "INTEGER", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_NotificationPreferences", x => x.Id); - table.ForeignKey( - name: "FK_NotificationPreferences_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_NotificationPreferences_Organizations_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organizations", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Notifications", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - OrganizationId = table.Column(type: "TEXT", nullable: false), - Title = table.Column(type: "TEXT", maxLength: 200, nullable: false), - Message = table.Column(type: "TEXT", maxLength: 2000, nullable: false), - Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), - Category = table.Column(type: "TEXT", maxLength: 50, nullable: false), - RecipientUserId = table.Column(type: "TEXT", nullable: false), - SentOn = table.Column(type: "TEXT", nullable: false), - ReadOn = table.Column(type: "TEXT", nullable: true), - IsRead = table.Column(type: "INTEGER", nullable: false), - RelatedEntityId = table.Column(type: "TEXT", nullable: true), - RelatedEntityType = table.Column(type: "TEXT", maxLength: 50, nullable: true), - SendInApp = table.Column(type: "INTEGER", nullable: false), - SendEmail = table.Column(type: "INTEGER", nullable: false), - SendSMS = table.Column(type: "INTEGER", nullable: false), - EmailSent = table.Column(type: "INTEGER", nullable: false), - EmailSentOn = table.Column(type: "TEXT", nullable: true), - SMSSent = table.Column(type: "INTEGER", nullable: false), - SMSSentOn = table.Column(type: "TEXT", nullable: true), - EmailError = table.Column(type: "TEXT", maxLength: 500, nullable: true), - SMSError = table.Column(type: "TEXT", maxLength: 500, nullable: true), - CreatedOn = table.Column(type: "TEXT", nullable: false), - CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), - LastModifiedOn = table.Column(type: "TEXT", nullable: true), - LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), - IsDeleted = table.Column(type: "INTEGER", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Notifications", x => x.Id); - table.ForeignKey( - name: "FK_Notifications_AspNetUsers_RecipientUserId", - column: x => x.RecipientUserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Notifications_Organizations_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organizations", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000001"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000002"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000003"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000004"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000005"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000006"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000007"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000008"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000009"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000010"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000011"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000012"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000013"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000014"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000015"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000016"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000017"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000018"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000019"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000020"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000021"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000022"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000023"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000024"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000025"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000026"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000027"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000028"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000029"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000030"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000031"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000032"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000001"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000002"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000003"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000004"), - column: "LastModifiedBy", - value: null); - - migrationBuilder.CreateIndex( - name: "IX_NotificationPreferences_OrganizationId", - table: "NotificationPreferences", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_NotificationPreferences_UserId", - table: "NotificationPreferences", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_NotificationPreferences_UserId_OrganizationId", - table: "NotificationPreferences", - columns: new[] { "UserId", "OrganizationId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_Category", - table: "Notifications", - column: "Category"); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_IsRead", - table: "Notifications", - column: "IsRead"); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_OrganizationId", - table: "Notifications", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_RecipientUserId", - table: "Notifications", - column: "RecipientUserId"); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_SentOn", - table: "Notifications", - column: "SentOn"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "NotificationPreferences"); - - migrationBuilder.DropTable( - name: "Notifications"); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000001"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000002"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000003"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000004"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000005"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000006"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000007"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000008"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000009"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000010"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000011"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000012"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000013"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000014"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000015"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000016"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000017"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000018"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000019"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000020"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000021"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000022"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000023"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000024"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000025"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000026"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000027"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000028"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000029"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000030"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000031"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplateItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0002-000000000032"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000001"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000002"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000003"), - column: "LastModifiedBy", - value: ""); - - migrationBuilder.UpdateData( - table: "ChecklistTemplates", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0001-000000000004"), - column: "LastModifiedBy", - value: ""); - } - } -} diff --git a/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs index a248656..687b6ea 100644 --- a/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs +++ b/Aquiis.SimpleStart/Infrastructure/Services/SMSService.cs @@ -25,4 +25,5 @@ public async Task ValidatePhoneNumberAsync(string phoneNumber) var digits = new string(phoneNumber.Where(char.IsDigit).ToArray()); return await Task.FromResult(digits.Length >= 10); } + } \ No newline at end of file diff --git a/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs b/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs index 822f88b..727351a 100644 --- a/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs +++ b/Aquiis.SimpleStart/Infrastructure/Services/SendGridEmailService.cs @@ -147,6 +147,7 @@ public async Task SendTemplateEmailAsync(string to, string templateId, Dictionar public async Task ValidateEmailAddressAsync(string email) { + await Task.CompletedTask; return !string.IsNullOrWhiteSpace(email) && email.Contains("@") && email.Contains("."); diff --git a/Aquiis.SimpleStart/Program.cs b/Aquiis.SimpleStart/Program.cs index 7858b24..f476599 100644 --- a/Aquiis.SimpleStart/Program.cs +++ b/Aquiis.SimpleStart/Program.cs @@ -172,6 +172,12 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +// Phase 2.5: Email/SMS Integration +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + // Workflow services builder.Services.AddScoped(); builder.Services.AddScoped(); From 0425f2a634dbfef1dca2513572f1b0e376c7dd87 Mon Sep 17 00:00:00 2001 From: CIS Guru Date: Tue, 30 Dec 2025 13:48:27 -0600 Subject: [PATCH 5/5] Phase 2.5 Email & SMS Integration --- .../Application/Pages/ManageDatabase.razor | 3 +- .../Features/Administration/Dashboard.razor | 14 + .../Settings/Pages/CalendarSettings.razor | 2 +- .../Settings/Pages/EmailSettings.razor | 26 +- .../Settings/Pages/LateFeeSettings.razor | 2 +- .../Settings/Pages/OrganizationSettings.razor | 15 +- .../Settings/Pages/SMSSettings.razor | 26 +- .../Data/ApplicationDbContext.cs | 33 + ...0_OrganizationEmailSMSSettings.Designer.cs | 4324 ++++++ ...1230141240_OrganizationEmailSMSSettings.cs | 116 + .../ApplicationDbContextModelSnapshot.cs | 261 +- Aquiis.SimpleStart/Shared/App.razor | 2 +- .../Shared/Layout/NavMenu.razor | 5 + Aquiis.SimpleStart/appsettings.json | 10 + Aquiis.SimpleStart/libman.json | 10 + .../wwwroot/assets/database-fill-gear.svg | 4 + .../wwwroot/assets/database.svg | 3 + .../lib/bootstrap/css/bootstrap-grid.css | 4085 ++++++ .../lib/bootstrap/css/bootstrap-grid.css.map | 1 + .../lib/bootstrap/css/bootstrap-grid.min.css | 6 + .../bootstrap/css/bootstrap-grid.min.css.map | 1 + .../lib/bootstrap/css/bootstrap-grid.rtl.css | 4084 ++++++ .../bootstrap/css/bootstrap-grid.rtl.css.map | 1 + .../bootstrap/css/bootstrap-grid.rtl.min.css | 6 + .../css/bootstrap-grid.rtl.min.css.map | 1 + .../lib/bootstrap/css/bootstrap-reboot.css | 601 + .../bootstrap/css/bootstrap-reboot.css.map | 1 + .../bootstrap/css/bootstrap-reboot.min.css | 6 + .../css/bootstrap-reboot.min.css.map | 1 + .../bootstrap/css/bootstrap-reboot.rtl.css | 598 + .../css/bootstrap-reboot.rtl.css.map | 1 + .../css/bootstrap-reboot.rtl.min.css | 6 + .../css/bootstrap-reboot.rtl.min.css.map | 1 + .../lib/bootstrap/css/bootstrap-utilities.css | 5406 +++++++ .../bootstrap/css/bootstrap-utilities.css.map | 1 + .../bootstrap/css/bootstrap-utilities.min.css | 6 + .../css/bootstrap-utilities.min.css.map | 1 + .../bootstrap/css/bootstrap-utilities.rtl.css | 5397 +++++++ .../css/bootstrap-utilities.rtl.css.map | 1 + .../css/bootstrap-utilities.rtl.min.css | 6 + .../css/bootstrap-utilities.rtl.min.css.map | 1 + .../wwwroot/lib/bootstrap/css/bootstrap.css | 12048 ++++++++++++++++ .../lib/bootstrap/css/bootstrap.css.map | 1 + .../lib/bootstrap/css/bootstrap.min.css | 6 + .../lib/bootstrap/css/bootstrap.min.css.map | 1 + .../lib/bootstrap/css/bootstrap.rtl.css | 12021 +++++++++++++++ .../lib/bootstrap/css/bootstrap.rtl.css.map | 1 + .../lib/bootstrap/css/bootstrap.rtl.min.css | 6 + .../bootstrap/css/bootstrap.rtl.min.css.map | 1 + .../lib/bootstrap/js/bootstrap.bundle.js | 6312 ++++++++ .../lib/bootstrap/js/bootstrap.bundle.js.map | 1 + .../lib/bootstrap/js/bootstrap.bundle.min.js | 7 + .../bootstrap/js/bootstrap.bundle.min.js.map | 1 + .../wwwroot/lib/bootstrap/js/bootstrap.esm.js | 4447 ++++++ .../lib/bootstrap/js/bootstrap.esm.js.map | 1 + .../lib/bootstrap/js/bootstrap.esm.min.js | 7 + .../lib/bootstrap/js/bootstrap.esm.min.js.map | 1 + .../wwwroot/lib/bootstrap/js/bootstrap.js | 4494 ++++++ .../wwwroot/lib/bootstrap/js/bootstrap.js.map | 1 + .../wwwroot/lib/bootstrap/js/bootstrap.min.js | 7 + .../lib/bootstrap/js/bootstrap.min.js.map | 1 + .../lib/bootstrap/scss/_accordion.scss | 153 + .../wwwroot/lib/bootstrap/scss/_alert.scss | 68 + .../wwwroot/lib/bootstrap/scss/_badge.scss | 38 + .../lib/bootstrap/scss/_breadcrumb.scss | 40 + .../lib/bootstrap/scss/_button-group.scss | 147 + .../wwwroot/lib/bootstrap/scss/_buttons.scss | 216 + .../wwwroot/lib/bootstrap/scss/_card.scss | 238 + .../wwwroot/lib/bootstrap/scss/_carousel.scss | 226 + .../wwwroot/lib/bootstrap/scss/_close.scss | 66 + .../lib/bootstrap/scss/_containers.scss | 41 + .../wwwroot/lib/bootstrap/scss/_dropdown.scss | 250 + .../wwwroot/lib/bootstrap/scss/_forms.scss | 9 + .../lib/bootstrap/scss/_functions.scss | 302 + .../wwwroot/lib/bootstrap/scss/_grid.scss | 39 + .../wwwroot/lib/bootstrap/scss/_helpers.scss | 12 + .../wwwroot/lib/bootstrap/scss/_images.scss | 42 + .../lib/bootstrap/scss/_list-group.scss | 199 + .../wwwroot/lib/bootstrap/scss/_maps.scss | 174 + .../wwwroot/lib/bootstrap/scss/_mixins.scss | 42 + .../wwwroot/lib/bootstrap/scss/_modal.scss | 240 + .../wwwroot/lib/bootstrap/scss/_nav.scss | 197 + .../wwwroot/lib/bootstrap/scss/_navbar.scss | 289 + .../lib/bootstrap/scss/_offcanvas.scss | 147 + .../lib/bootstrap/scss/_pagination.scss | 109 + .../lib/bootstrap/scss/_placeholders.scss | 51 + .../wwwroot/lib/bootstrap/scss/_popover.scss | 196 + .../wwwroot/lib/bootstrap/scss/_progress.scss | 68 + .../wwwroot/lib/bootstrap/scss/_reboot.scss | 617 + .../wwwroot/lib/bootstrap/scss/_root.scss | 187 + .../wwwroot/lib/bootstrap/scss/_spinners.scss | 86 + .../wwwroot/lib/bootstrap/scss/_tables.scss | 171 + .../wwwroot/lib/bootstrap/scss/_toasts.scss | 73 + .../wwwroot/lib/bootstrap/scss/_tooltip.scss | 119 + .../lib/bootstrap/scss/_transitions.scss | 27 + .../wwwroot/lib/bootstrap/scss/_type.scss | 106 + .../lib/bootstrap/scss/_utilities.scss | 806 ++ .../lib/bootstrap/scss/_variables-dark.scss | 102 + .../lib/bootstrap/scss/_variables.scss | 1753 +++ .../lib/bootstrap/scss/bootstrap-grid.scss | 62 + .../lib/bootstrap/scss/bootstrap-reboot.scss | 10 + .../bootstrap/scss/bootstrap-utilities.scss | 19 + .../wwwroot/lib/bootstrap/scss/bootstrap.scss | 52 + .../scss/forms/_floating-labels.scss | 97 + .../lib/bootstrap/scss/forms/_form-check.scss | 189 + .../bootstrap/scss/forms/_form-control.scss | 214 + .../lib/bootstrap/scss/forms/_form-range.scss | 91 + .../bootstrap/scss/forms/_form-select.scss | 80 + .../lib/bootstrap/scss/forms/_form-text.scss | 11 + .../bootstrap/scss/forms/_input-group.scss | 132 + .../lib/bootstrap/scss/forms/_labels.scss | 36 + .../lib/bootstrap/scss/forms/_validation.scss | 12 + .../lib/bootstrap/scss/helpers/_clearfix.scss | 3 + .../lib/bootstrap/scss/helpers/_color-bg.scss | 7 + .../scss/helpers/_colored-links.scss | 30 + .../bootstrap/scss/helpers/_focus-ring.scss | 5 + .../bootstrap/scss/helpers/_icon-link.scss | 25 + .../lib/bootstrap/scss/helpers/_position.scss | 36 + .../lib/bootstrap/scss/helpers/_ratio.scss | 26 + .../lib/bootstrap/scss/helpers/_stacks.scss | 15 + .../scss/helpers/_stretched-link.scss | 15 + .../scss/helpers/_text-truncation.scss | 7 + .../scss/helpers/_visually-hidden.scss | 8 + .../lib/bootstrap/scss/helpers/_vr.scss | 8 + .../lib/bootstrap/scss/mixins/_alert.scss | 18 + .../lib/bootstrap/scss/mixins/_backdrop.scss | 14 + .../lib/bootstrap/scss/mixins/_banner.scss | 7 + .../bootstrap/scss/mixins/_border-radius.scss | 78 + .../bootstrap/scss/mixins/_box-shadow.scss | 24 + .../bootstrap/scss/mixins/_breakpoints.scss | 127 + .../lib/bootstrap/scss/mixins/_buttons.scss | 70 + .../lib/bootstrap/scss/mixins/_caret.scss | 69 + .../lib/bootstrap/scss/mixins/_clearfix.scss | 9 + .../bootstrap/scss/mixins/_color-mode.scss | 21 + .../bootstrap/scss/mixins/_color-scheme.scss | 7 + .../lib/bootstrap/scss/mixins/_container.scss | 11 + .../lib/bootstrap/scss/mixins/_deprecate.scss | 10 + .../lib/bootstrap/scss/mixins/_forms.scss | 163 + .../lib/bootstrap/scss/mixins/_gradients.scss | 47 + .../lib/bootstrap/scss/mixins/_grid.scss | 151 + .../lib/bootstrap/scss/mixins/_image.scss | 16 + .../bootstrap/scss/mixins/_list-group.scss | 26 + .../lib/bootstrap/scss/mixins/_lists.scss | 7 + .../bootstrap/scss/mixins/_pagination.scss | 10 + .../bootstrap/scss/mixins/_reset-text.scss | 17 + .../lib/bootstrap/scss/mixins/_resize.scss | 6 + .../scss/mixins/_table-variants.scss | 24 + .../bootstrap/scss/mixins/_text-truncate.scss | 8 + .../bootstrap/scss/mixins/_transition.scss | 26 + .../lib/bootstrap/scss/mixins/_utilities.scss | 97 + .../scss/mixins/_visually-hidden.scss | 38 + .../lib/bootstrap/scss/utilities/_api.scss | 47 + .../lib/bootstrap/scss/vendor/_rfs.scss | 348 + 153 files changed, 74597 insertions(+), 175 deletions(-) create mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.Designer.cs create mode 100644 Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.cs create mode 100644 Aquiis.SimpleStart/libman.json create mode 100644 Aquiis.SimpleStart/wwwroot/assets/database-fill-gear.svg create mode 100644 Aquiis.SimpleStart/wwwroot/assets/database.svg create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.rtl.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.rtl.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.rtl.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-grid.rtl.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.rtl.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.rtl.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.rtl.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-reboot.rtl.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.rtl.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.rtl.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.rtl.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap-utilities.rtl.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.rtl.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.rtl.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.rtl.min.css create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/css/bootstrap.rtl.min.css.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.bundle.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.bundle.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.bundle.min.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.bundle.min.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.esm.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.esm.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.esm.min.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.esm.min.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.min.js create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/js/bootstrap.min.js.map create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_accordion.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_alert.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_badge.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_breadcrumb.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_button-group.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_buttons.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_card.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_carousel.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_close.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_containers.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_dropdown.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_forms.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_functions.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_grid.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_helpers.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_images.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_list-group.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_maps.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_mixins.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_modal.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_nav.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_navbar.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_offcanvas.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_pagination.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_placeholders.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_popover.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_progress.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_reboot.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_root.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_spinners.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_tables.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_toasts.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_tooltip.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_transitions.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_type.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_utilities.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_variables-dark.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/_variables.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/bootstrap-grid.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/bootstrap-reboot.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/bootstrap-utilities.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/bootstrap.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_floating-labels.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_form-check.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_form-control.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_form-range.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_form-select.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_form-text.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_input-group.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_labels.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/forms/_validation.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_clearfix.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_color-bg.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_colored-links.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_focus-ring.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_icon-link.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_position.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_ratio.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_stacks.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_stretched-link.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_text-truncation.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_visually-hidden.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/helpers/_vr.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_alert.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_backdrop.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_banner.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_border-radius.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_box-shadow.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_breakpoints.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_buttons.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_caret.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_clearfix.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_color-mode.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_color-scheme.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_container.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_deprecate.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_forms.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_gradients.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_grid.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_image.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_list-group.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_lists.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_pagination.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_reset-text.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_resize.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_table-variants.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_text-truncate.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_transition.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_utilities.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/mixins/_visually-hidden.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/utilities/_api.scss create mode 100644 Aquiis.SimpleStart/wwwroot/lib/bootstrap/scss/vendor/_rfs.scss diff --git a/Aquiis.SimpleStart/Features/Administration/Application/Pages/ManageDatabase.razor b/Aquiis.SimpleStart/Features/Administration/Application/Pages/ManageDatabase.razor index 1d8c843..7e09fb1 100644 --- a/Aquiis.SimpleStart/Features/Administration/Application/Pages/ManageDatabase.razor +++ b/Aquiis.SimpleStart/Features/Administration/Application/Pages/ManageDatabase.razor @@ -21,7 +21,8 @@
-

Database Backup & Recovery

+

+ Database Backup & Recovery

Manage database backups and recover from corruption

diff --git a/Aquiis.SimpleStart/Features/Administration/Dashboard.razor b/Aquiis.SimpleStart/Features/Administration/Dashboard.razor index 7a95f2b..de90337 100644 --- a/Aquiis.SimpleStart/Features/Administration/Dashboard.razor +++ b/Aquiis.SimpleStart/Features/Administration/Dashboard.razor @@ -98,6 +98,8 @@ + +
@@ -144,6 +146,18 @@ } + private void GoToEmailSettings() + { + // Logic to navigate to the email notification settings page + NavigationManager.NavigateTo("/administration/settings/email"); + } + + private void GoToSMSSettings() + { + // Logic to navigate to the SMS notification settings page + NavigationManager.NavigateTo("/administration/settings/sms"); + } + private void GoToLateFeeSettings() { // Logic to view the daily system status report diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/CalendarSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/CalendarSettings.razor index 58da31c..131ec64 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/CalendarSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/CalendarSettings.razor @@ -19,7 +19,7 @@
-

Calendar Settings

+

Calendar Settings

@if (!string.IsNullOrEmpty(organizationName)) {

diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor index d90317a..d15070a 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/EmailSettings.razor @@ -1,4 +1,4 @@ -@page "/settings/email" +@page "/administration/settings/email" @using Aquiis.SimpleStart.Application.Services @using Aquiis.SimpleStart.Infrastructure.Services @using SocketIOClient.Messages @@ -8,20 +8,26 @@ @inject ToastService ToastService @inject IJSRuntime JSRuntime +@inject NavigationManager Navigation + @inject UserContextService _userContext +@rendermode InteractiveServer + Email Settings - Aquiis -

-
-
-

- Email Configuration -

+
+
+

+ Email Configuration +

Configure SendGrid integration for automated email notifications

+
@if (settings == null) @@ -230,7 +236,6 @@
} -
@* Configuration Modal *@ @if (showConfigModal) @@ -416,6 +421,11 @@ }; } + private void BackToDashboard() + { + Navigation.NavigateTo("/administration/dashboard"); + } + public class ConfigurationModel { [Required(ErrorMessage = "SendGrid API key is required")] diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/LateFeeSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/LateFeeSettings.razor index c2e1dc8..4b1fc2e 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/LateFeeSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/LateFeeSettings.razor @@ -20,7 +20,7 @@
-

Late Fee Settings

+

Late Fee Settings

@if (!string.IsNullOrEmpty(organizationName)) {

diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/OrganizationSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/OrganizationSettings.razor index e38dd36..915ab02 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/OrganizationSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/OrganizationSettings.razor @@ -20,7 +20,7 @@ Organization Settings

-
+ @*
-
+
*@
-

Organization Settings

+

Organization Settings

@if (!string.IsNullOrEmpty(organizationName)) {

@@ -54,6 +54,9 @@ Manage Organizations } +

@@ -498,9 +501,13 @@ } } + private void BackToDashboard(){ + Navigation.NavigateTo("/administration/dashboard"); + } + private void Cancel() { - Navigation.NavigateTo("/administration"); + Navigation.NavigateTo("/administration/dashboard"); } private string GetRoleBadgeClass() diff --git a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor index 4f226a3..ee97020 100644 --- a/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor +++ b/Aquiis.SimpleStart/Features/Administration/Settings/Pages/SMSSettings.razor @@ -1,4 +1,4 @@ -@page "/settings/sms" +@page "/administration/settings/sms" @using Aquiis.SimpleStart.Application.Services @using Aquiis.SimpleStart.Infrastructure.Services @using SocketIOClient.Messages @@ -11,17 +11,23 @@ @inject UserContextService _userContext +@inject NavigationManager Navigation + +@rendermode InteractiveServer + SMS Settings - Aquiis -
-
-
-

- SMS Configuration -

+
+
+

+ SMS Configuration +

Configure Twilio integration for automated SMS notifications

+
@if (settings == null) @@ -194,7 +200,6 @@
} -
@* Configuration Modal *@ @if (showConfigModal) @@ -380,6 +385,11 @@ }; } + private void BackToDashboard() + { + Navigation.NavigateTo("/administration/dashboard"); + } + public class ConfigurationModel { [Required(ErrorMessage = "Twilio Account SID is required")] diff --git a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs index 91dd98d..d6dd7f2 100644 --- a/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs +++ b/Aquiis.SimpleStart/Infrastructure/Data/ApplicationDbContext.cs @@ -587,6 +587,39 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade); }); + // Configure OrganizationEmailSettings entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.OrganizationId).IsUnique(); + + // Organization relationship - one settings record per organization + entity.HasOne(es => es.Organization) + .WithMany() + .HasForeignKey(es => es.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + + }); + + // Configure OrganizationSMSSettings entity + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id); + + entity.HasIndex(e => e.OrganizationId).IsUnique(); + + // Organization relationship - one settings record per organization + entity.HasOne(ss => ss.Organization) + .WithMany() + .HasForeignKey(ss => ss.OrganizationId) + .OnDelete(DeleteBehavior.Cascade); + + // Precision for financial fields + entity.Property(e => e.AccountBalance).HasPrecision(18, 2); + entity.Property(e => e.CostPerSMS).HasPrecision(18, 4); + }); + // Seed System Checklist Templates SeedChecklistTemplates(modelBuilder); } diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.Designer.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.Designer.cs new file mode 100644 index 0000000..5783ab7 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.Designer.cs @@ -0,0 +1,4324 @@ +// +using System; +using Aquiis.SimpleStart.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Aquiis.SimpleStart.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251230141240_OrganizationEmailSMSSettings")] + partial class OrganizationEmailSMSSettings + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.11"); + + modelBuilder.Entity("Aquiis.SimpleStart.Application.Services.Workflows.WorkflowAuditLog", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasColumnType("TEXT"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FromStatus") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Metadata") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PerformedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PerformedOn") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("ToStatus") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Action"); + + b.HasIndex("EntityId"); + + b.HasIndex("EntityType"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PerformedBy"); + + b.HasIndex("PerformedOn"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("WorkflowAuditLogs"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckCompletedOn") + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("BackgroundCheckPassed") + .HasColumnType("INTEGER"); + + b.Property("BackgroundCheckRequested") + .HasColumnType("INTEGER"); + + b.Property("BackgroundCheckRequestedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("CreditCheckCompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreditCheckNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("CreditCheckPassed") + .HasColumnType("INTEGER"); + + b.Property("CreditCheckRequested") + .HasColumnType("INTEGER"); + + b.Property("CreditCheckRequestedOn") + .HasColumnType("TEXT"); + + b.Property("CreditScore") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OverallResult") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RentalApplicationId") + .HasColumnType("TEXT"); + + b.Property("ResultNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("OverallResult"); + + b.HasIndex("RentalApplicationId") + .IsUnique(); + + b.ToTable("ApplicationScreenings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Color") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("DurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("EndOn") + .HasColumnType("TEXT"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Icon") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Location") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("SourceEntityId") + .HasColumnType("TEXT"); + + b.Property("SourceEntityType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("StartOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventType"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("SourceEntityId"); + + b.HasIndex("StartOn"); + + b.HasIndex("SourceEntityType", "SourceEntityId"); + + b.ToTable("CalendarEvents"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AutoCreateEvents") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DefaultColor") + .HasColumnType("TEXT"); + + b.Property("DefaultIcon") + .HasColumnType("TEXT"); + + b.Property("DisplayOrder") + .HasColumnType("INTEGER"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ShowOnCalendar") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("OrganizationId", "EntityType") + .IsUnique(); + + b.ToTable("CalendarSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ChecklistTemplateId") + .HasColumnType("TEXT"); + + b.Property("ChecklistType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CompletedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("GeneralNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistTemplateId"); + + b.HasIndex("ChecklistType"); + + b.HasIndex("CompletedOn"); + + b.HasIndex("DocumentId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("Status"); + + b.ToTable("Checklists"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CategorySection") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ChecklistId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("IsChecked") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemOrder") + .HasColumnType("INTEGER"); + + b.Property("ItemText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhotoUrl") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("RequiresValue") + .HasColumnType("INTEGER"); + + b.Property("SectionOrder") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistId"); + + b.ToTable("ChecklistItems"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsSystemTemplate") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Category"); + + b.HasIndex("OrganizationId"); + + b.ToTable("ChecklistTemplates"); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0001-000000000001"), + Category = "Tour", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Standard property showing checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Property Tour", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000002"), + Category = "MoveIn", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Move-in inspection checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Move-In", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000003"), + Category = "MoveOut", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Move-out inspection checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Move-Out", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }, + new + { + Id = new Guid("00000000-0000-0000-0001-000000000004"), + Category = "Tour", + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + Description = "Open house event checklist", + IsDeleted = false, + IsSystemTemplate = true, + Name = "Open House", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000") + }); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllowsNotes") + .HasColumnType("INTEGER"); + + b.Property("CategorySection") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ChecklistTemplateId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsRequired") + .HasColumnType("INTEGER"); + + b.Property("ItemOrder") + .HasColumnType("INTEGER"); + + b.Property("ItemText") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RequiresValue") + .HasColumnType("INTEGER"); + + b.Property("SectionOrder") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistTemplateId"); + + b.ToTable("ChecklistTemplateItems"); + + b.HasData( + new + { + Id = new Guid("00000000-0000-0000-0002-000000000001"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Greeted prospect and verified appointment", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000002"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Reviewed property exterior and curb appeal", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000003"), + AllowsNotes = true, + CategorySection = "Arrival & Introduction", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Showed parking area/garage", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000004"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 4, + ItemText = "Toured living room/common areas", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000005"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 5, + ItemText = "Showed all bedrooms", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000006"), + AllowsNotes = true, + CategorySection = "Interior Tour", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 6, + ItemText = "Showed all bathrooms", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 2 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000007"), + AllowsNotes = true, + CategorySection = "Kitchen & Appliances", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 7, + ItemText = "Toured kitchen and demonstrated appliances", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 3 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000008"), + AllowsNotes = true, + CategorySection = "Kitchen & Appliances", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 8, + ItemText = "Explained which appliances are included", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 3 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000009"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 9, + ItemText = "Explained HVAC system and thermostat controls", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000010"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 10, + ItemText = "Reviewed utility responsibilities (tenant vs landlord)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000011"), + AllowsNotes = true, + CategorySection = "Utilities & Systems", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 11, + ItemText = "Showed water heater location", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 4 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000012"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 12, + ItemText = "Showed storage areas (closets, attic, basement)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000013"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 13, + ItemText = "Showed laundry facilities", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000014"), + AllowsNotes = true, + CategorySection = "Storage & Amenities", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 14, + ItemText = "Showed outdoor space (yard, patio, balcony)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 5 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000015"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 15, + ItemText = "Discussed monthly rent amount", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000016"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 16, + ItemText = "Explained security deposit and move-in costs", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000017"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 17, + ItemText = "Reviewed lease term length and start date", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000018"), + AllowsNotes = true, + CategorySection = "Lease Terms", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 18, + ItemText = "Explained pet policy", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 6 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000019"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 19, + ItemText = "Explained application process and requirements", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000020"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 20, + ItemText = "Reviewed screening process (background, credit check)", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000021"), + AllowsNotes = true, + CategorySection = "Next Steps", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 21, + ItemText = "Answered all prospect questions", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 7 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000022"), + AllowsNotes = true, + CategorySection = "Assessment", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 22, + ItemText = "Prospect Interest Level", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = true, + SectionOrder = 8 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000023"), + AllowsNotes = true, + CategorySection = "Assessment", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000001"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 23, + ItemText = "Overall showing feedback and notes", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 8 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000024"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Document property condition", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000025"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Collect keys and access codes", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000026"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000002"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Review lease terms with tenant", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000027"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Inspect property condition", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000028"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Collect all keys and access devices", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000029"), + AllowsNotes = true, + CategorySection = "General", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000003"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Document damages and needed repairs", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000030"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 1, + ItemText = "Set up signage and directional markers", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000031"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 2, + ItemText = "Prepare information packets", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }, + new + { + Id = new Guid("00000000-0000-0000-0002-000000000032"), + AllowsNotes = true, + CategorySection = "Preparation", + ChecklistTemplateId = new Guid("00000000-0000-0000-0001-000000000004"), + CreatedBy = "", + CreatedOn = new DateTime(2025, 11, 30, 0, 0, 0, 0, DateTimeKind.Utc), + IsDeleted = false, + IsRequired = true, + ItemOrder = 3, + ItemText = "Set up visitor sign-in sheet", + OrganizationId = new Guid("00000000-0000-0000-0000-000000000000"), + RequiresValue = false, + SectionOrder = 1 + }); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DocumentType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("FileData") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("FileExtension") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("FileSize") + .HasColumnType("INTEGER"); + + b.Property("FileType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("InvoiceId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PaymentId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("TenantId"); + + b.ToTable("Documents"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActionItemsRequired") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("BathroomSinkGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomSinkNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomToiletGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomToiletNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomTubShowerGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomTubShowerNotes") + .HasColumnType("TEXT"); + + b.Property("BathroomVentilationGood") + .HasColumnType("INTEGER"); + + b.Property("BathroomVentilationNotes") + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("CarbonMonoxideDetectorsGood") + .HasColumnType("INTEGER"); + + b.Property("CarbonMonoxideDetectorsNotes") + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("ElectricalSystemGood") + .HasColumnType("INTEGER"); + + b.Property("ElectricalSystemNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorDoorsGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorDoorsNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorFoundationGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorFoundationNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorGuttersGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorGuttersNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorRoofGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorRoofNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorSidingGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorSidingNotes") + .HasColumnType("TEXT"); + + b.Property("ExteriorWindowsGood") + .HasColumnType("INTEGER"); + + b.Property("ExteriorWindowsNotes") + .HasColumnType("TEXT"); + + b.Property("GeneralNotes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("HvacSystemGood") + .HasColumnType("INTEGER"); + + b.Property("HvacSystemNotes") + .HasColumnType("TEXT"); + + b.Property("InspectedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("InspectionType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("InteriorCeilingsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorCeilingsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorDoorsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorDoorsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorFloorsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorFloorsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorWallsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorWallsNotes") + .HasColumnType("TEXT"); + + b.Property("InteriorWindowsGood") + .HasColumnType("INTEGER"); + + b.Property("InteriorWindowsNotes") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("KitchenAppliancesGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenAppliancesNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenCabinetsGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenCabinetsNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenCountersGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenCountersNotes") + .HasColumnType("TEXT"); + + b.Property("KitchenSinkPlumbingGood") + .HasColumnType("INTEGER"); + + b.Property("KitchenSinkPlumbingNotes") + .HasColumnType("TEXT"); + + b.Property("LandscapingGood") + .HasColumnType("INTEGER"); + + b.Property("LandscapingNotes") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OverallCondition") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("PlumbingSystemGood") + .HasColumnType("INTEGER"); + + b.Property("PlumbingSystemNotes") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("SmokeDetectorsGood") + .HasColumnType("INTEGER"); + + b.Property("SmokeDetectorsNotes") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CompletedOn"); + + b.HasIndex("DocumentId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("PropertyId"); + + b.ToTable("Inspections"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("AmountPaid") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("DueOn") + .HasColumnType("TEXT"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("InvoicedOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LateFeeAmount") + .HasColumnType("decimal(18,2)"); + + b.Property("LateFeeApplied") + .HasColumnType("INTEGER"); + + b.Property("LateFeeAppliedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaidOn") + .HasColumnType("TEXT"); + + b.Property("ReminderSent") + .HasColumnType("INTEGER"); + + b.Property("ReminderSentOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("InvoiceNumber") + .IsUnique(); + + b.HasIndex("LeaseId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Invoices"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActualMoveOutDate") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DeclinedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("ExpectedMoveOutDate") + .HasColumnType("TEXT"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseOfferId") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OfferedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PreviousLeaseId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProposedRenewalRent") + .HasColumnType("decimal(18,2)"); + + b.Property("RenewalNotes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("RenewalNotificationSent") + .HasColumnType("INTEGER"); + + b.Property("RenewalNotificationSentOn") + .HasColumnType("TEXT"); + + b.Property("RenewalNumber") + .HasColumnType("INTEGER"); + + b.Property("RenewalOfferedOn") + .HasColumnType("TEXT"); + + b.Property("RenewalReminderSentOn") + .HasColumnType("TEXT"); + + b.Property("RenewalResponseOn") + .HasColumnType("TEXT"); + + b.Property("RenewalStatus") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("SecurityDeposit") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("SignedOn") + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("TerminationNoticedOn") + .HasColumnType("TEXT"); + + b.Property("TerminationReason") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("Terms") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("TenantId"); + + b.ToTable("Leases"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConvertedLeaseId") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasColumnType("decimal(18,2)"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OfferedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("RentalApplicationId") + .HasColumnType("TEXT"); + + b.Property("RespondedOn") + .HasColumnType("TEXT"); + + b.Property("ResponseNotes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SecurityDeposit") + .HasColumnType("decimal(18,2)"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Terms") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("RentalApplicationId"); + + b.ToTable("LeaseOffers"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActualCost") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("AssignedTo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("CompletedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EstimatedCost") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Priority") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RequestedBy") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("RequestedByEmail") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("RequestedByPhone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("RequestedOn") + .HasColumnType("TEXT"); + + b.Property("ResolutionNotes") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ScheduledOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LeaseId"); + + b.HasIndex("Priority"); + + b.HasIndex("PropertyId"); + + b.HasIndex("RequestedOn"); + + b.HasIndex("Status"); + + b.ToTable("MaintenanceRequests"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(5000) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EntityId") + .HasColumnType("TEXT"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("UserFullName") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.ToTable("Notes"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IsActive"); + + b.HasIndex("OwnerId"); + + b.ToTable("Organizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationEmailSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DailyCountResetOn") + .HasColumnType("TEXT"); + + b.Property("DailyLimit") + .HasColumnType("INTEGER"); + + b.Property("EmailsSentThisMonth") + .HasColumnType("INTEGER"); + + b.Property("EmailsSentToday") + .HasColumnType("INTEGER"); + + b.Property("FromEmail") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("FromName") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsEmailEnabled") + .HasColumnType("INTEGER"); + + b.Property("IsVerified") + .HasColumnType("INTEGER"); + + b.Property("LastEmailSentOn") + .HasColumnType("TEXT"); + + b.Property("LastError") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("LastErrorOn") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastVerifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyCountResetOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyLimit") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PlanType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SendGridApiKeyEncrypted") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("StatsLastUpdatedOn") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationEmailSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSMSSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccountBalance") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("AccountType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CostPerSMS") + .HasPrecision(18, 4) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DailyCountResetOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsSMSEnabled") + .HasColumnType("INTEGER"); + + b.Property("IsVerified") + .HasColumnType("INTEGER"); + + b.Property("LastError") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastSMSSentOn") + .HasColumnType("TEXT"); + + b.Property("LastVerifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyCountResetOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("SMSSentThisMonth") + .HasColumnType("INTEGER"); + + b.Property("SMSSentToday") + .HasColumnType("INTEGER"); + + b.Property("StatsLastUpdatedOn") + .HasColumnType("TEXT"); + + b.Property("TwilioAccountSidEncrypted") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("TwilioAuthTokenEncrypted") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("TwilioPhoneNumber") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationSMSSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSettings", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AllowTenantDividendChoice") + .HasColumnType("INTEGER"); + + b.Property("ApplicationExpirationDays") + .HasColumnType("INTEGER"); + + b.Property("ApplicationFeeEnabled") + .HasColumnType("INTEGER"); + + b.Property("AutoCalculateSecurityDeposit") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DefaultApplicationFee") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("DefaultDividendPaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("DividendDistributionMonth") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LateFeeAutoApply") + .HasColumnType("INTEGER"); + + b.Property("LateFeeEnabled") + .HasColumnType("INTEGER"); + + b.Property("LateFeeGracePeriodDays") + .HasColumnType("INTEGER"); + + b.Property("LateFeePercentage") + .HasPrecision(5, 4) + .HasColumnType("TEXT"); + + b.Property("MaxLateFeeAmount") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationSharePercentage") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("PaymentReminderDaysBefore") + .HasColumnType("INTEGER"); + + b.Property("PaymentReminderEnabled") + .HasColumnType("INTEGER"); + + b.Property("RefundProcessingDays") + .HasColumnType("INTEGER"); + + b.Property("SecurityDepositInvestmentEnabled") + .HasColumnType("INTEGER"); + + b.Property("SecurityDepositMultiplier") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("TourNoShowGracePeriodHours") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationSettings"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DocumentId") + .HasColumnType("TEXT"); + + b.Property("InvoiceId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaidOn") + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("InvoiceId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Bathrooms") + .HasMaxLength(3) + .HasColumnType("decimal(3,1)"); + + b.Property("Bedrooms") + .HasMaxLength(3) + .HasColumnType("INTEGER"); + + b.Property("City") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("IsAvailable") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastRoutineInspectionDate") + .HasColumnType("TEXT"); + + b.Property("MonthlyRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("NextRoutineInspectionDueDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RoutineInspectionIntervalMonths") + .HasColumnType("INTEGER"); + + b.Property("SquareFeet") + .HasMaxLength(7) + .HasColumnType("INTEGER"); + + b.Property("State") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("UnitNumber") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Address"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Properties"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateOfBirth") + .HasColumnType("TEXT"); + + b.Property("DesiredMoveInDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("FirstContactedOn") + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationNumber") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationState") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("InterestedPropertyId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Source") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("InterestedPropertyId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Status"); + + b.ToTable("ProspectiveTenants"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ApplicationFee") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationFeePaid") + .HasColumnType("INTEGER"); + + b.Property("ApplicationFeePaidOn") + .HasColumnType("TEXT"); + + b.Property("ApplicationFeePaymentMethod") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("AppliedOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("CurrentAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("CurrentCity") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CurrentRent") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CurrentState") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("CurrentZipCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("DecidedOn") + .HasColumnType("TEXT"); + + b.Property("DecisionBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DenialReason") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("EmployerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmploymentLengthMonths") + .HasColumnType("INTEGER"); + + b.Property("ExpiresOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("JobTitle") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LandlordName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("LandlordPhone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("MonthlyIncome") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("Reference1Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Reference1Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Reference1Relationship") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Reference2Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Reference2Phone") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("Reference2Relationship") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AppliedOn"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("Status"); + + b.ToTable("RentalApplications"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SchemaVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AppliedOn") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SchemaVersions"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateReceived") + .HasColumnType("TEXT"); + + b.Property("DeductionsAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("DeductionsReason") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("InInvestmentPool") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PoolEntryDate") + .HasColumnType("TEXT"); + + b.Property("PoolExitDate") + .HasColumnType("TEXT"); + + b.Property("RefundAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("RefundMethod") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RefundProcessedDate") + .HasColumnType("TEXT"); + + b.Property("RefundReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("TransactionReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("InInvestmentPool"); + + b.HasIndex("LeaseId") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("TenantId"); + + b.ToTable("SecurityDeposits"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BaseDividendAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ChoiceMadeOn") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("InvestmentPoolId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LeaseId") + .HasColumnType("TEXT"); + + b.Property("MailingAddress") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("MonthsInPool") + .HasColumnType("INTEGER"); + + b.Property("Notes") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PaymentProcessedOn") + .HasColumnType("TEXT"); + + b.Property("PaymentReference") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("ProrationFactor") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("SecurityDepositId") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantId") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("InvestmentPoolId"); + + b.HasIndex("LeaseId"); + + b.HasIndex("SecurityDepositId"); + + b.HasIndex("Status"); + + b.HasIndex("TenantId"); + + b.HasIndex("Year"); + + b.ToTable("SecurityDepositDividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActiveLeaseCount") + .HasColumnType("INTEGER"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendPerLease") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("DividendsCalculatedOn") + .HasColumnType("TEXT"); + + b.Property("DividendsDistributedOn") + .HasColumnType("TEXT"); + + b.Property("EndingBalance") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OrganizationShare") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("OrganizationSharePercentage") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("ReturnRate") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("StartingBalance") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TenantShareTotal") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("TotalEarnings") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Status"); + + b.HasIndex("Year") + .IsUnique(); + + b.ToTable("SecurityDepositInvestmentPools"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DateOfBirth") + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("EmergencyContactName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IdentificationNumber") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Notes") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("IdentificationNumber") + .IsUnique(); + + b.HasIndex("OrganizationId"); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CalendarEventId") + .HasColumnType("TEXT"); + + b.Property("ChecklistId") + .HasColumnType("TEXT"); + + b.Property("ConductedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("Feedback") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("InterestLevel") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PropertyId") + .HasColumnType("TEXT"); + + b.Property("ProspectiveTenantId") + .HasColumnType("TEXT"); + + b.Property("ScheduledOn") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ChecklistId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("PropertyId"); + + b.HasIndex("ProspectiveTenantId"); + + b.HasIndex("ScheduledOn"); + + b.HasIndex("Status"); + + b.ToTable("Tours"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("GrantedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("GrantedOn") + .HasColumnType("TEXT"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevokedOn") + .HasColumnType("TEXT"); + + b.Property("Role") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GrantedBy"); + + b.HasIndex("IsActive"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("Role"); + + b.HasIndex("UserId", "OrganizationId") + .IsUnique(); + + b.ToTable("UserOrganizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ActiveOrganizationId") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginIP") + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("LoginCount") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("PreviousLoginDate") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Notification", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Category") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("EmailError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("EmailSent") + .HasColumnType("INTEGER"); + + b.Property("EmailSentOn") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsRead") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ReadOn") + .HasColumnType("TEXT"); + + b.Property("RecipientUserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RelatedEntityId") + .HasColumnType("TEXT"); + + b.Property("RelatedEntityType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("SMSError") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SMSSent") + .HasColumnType("INTEGER"); + + b.Property("SMSSentOn") + .HasColumnType("TEXT"); + + b.Property("SendEmail") + .HasColumnType("INTEGER"); + + b.Property("SendInApp") + .HasColumnType("INTEGER"); + + b.Property("SendSMS") + .HasColumnType("INTEGER"); + + b.Property("SentOn") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Category"); + + b.HasIndex("IsRead"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("RecipientUserId"); + + b.HasIndex("SentOn"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("NotificationPreferences", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .HasColumnType("TEXT"); + + b.Property("DailyDigestTime") + .HasColumnType("TEXT"); + + b.Property("EmailAddress") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("EmailApplicationStatusChange") + .HasColumnType("INTEGER"); + + b.Property("EmailInspectionScheduled") + .HasColumnType("INTEGER"); + + b.Property("EmailLeaseExpiring") + .HasColumnType("INTEGER"); + + b.Property("EmailMaintenanceUpdate") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("EmailPaymentReceived") + .HasColumnType("INTEGER"); + + b.Property("EnableDailyDigest") + .HasColumnType("INTEGER"); + + b.Property("EnableEmailNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableInAppNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableSMSNotifications") + .HasColumnType("INTEGER"); + + b.Property("EnableWeeklyDigest") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModifiedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("LastModifiedOn") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("SMSLeaseExpiringUrgent") + .HasColumnType("INTEGER"); + + b.Property("SMSMaintenanceEmergency") + .HasColumnType("INTEGER"); + + b.Property("SMSPaymentDue") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WeeklyDigestDay") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "OrganizationId") + .IsUnique(); + + b.ToTable("NotificationPreferences"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") + .WithOne("Screening") + .HasForeignKey("Aquiis.SimpleStart.Core.Entities.ApplicationScreening", "RentalApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RentalApplication"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.CalendarEvent", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") + .WithMany("Checklists") + .HasForeignKey("ChecklistTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("ChecklistTemplate"); + + b.Navigation("Document"); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistItem", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") + .WithMany("Items") + .HasForeignKey("ChecklistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Checklist"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplateItem", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", "ChecklistTemplate") + .WithMany("Items") + .HasForeignKey("ChecklistTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChecklistTemplate"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Document", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") + .WithMany() + .HasForeignKey("InvoiceId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany("Documents") + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Payment", "Payment") + .WithMany() + .HasForeignKey("PaymentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany("Documents") + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Invoice"); + + b.Navigation("Lease"); + + b.Navigation("Payment"); + + b.Navigation("Property"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Inspection", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany("Invoices") + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Lease"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Leases") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany("Leases") + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany("Leases") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Property"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.LeaseOffer", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany() + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.RentalApplication", "RentalApplication") + .WithMany() + .HasForeignKey("RentalApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + + b.Navigation("RentalApplication"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.MaintenanceRequest", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Lease"); + + b.Navigation("Property"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Note", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", "User") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationEmailSettings", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSMSSettings", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Properties") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "InterestedProperty") + .WithMany() + .HasForeignKey("InterestedPropertyId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("InterestedProperty"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany("Applications") + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Lease"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositDividend", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", "InvestmentPool") + .WithMany("Dividends") + .HasForeignKey("InvestmentPoolId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Lease", "Lease") + .WithMany() + .HasForeignKey("LeaseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", "SecurityDeposit") + .WithMany("Dividends") + .HasForeignKey("SecurityDepositId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("InvestmentPool"); + + b.Navigation("Lease"); + + b.Navigation("SecurityDeposit"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", null) + .WithMany("Tenants") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tour", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Checklist", "Checklist") + .WithMany() + .HasForeignKey("ChecklistId"); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Property", "Property") + .WithMany() + .HasForeignKey("PropertyId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", "ProspectiveTenant") + .WithMany("Tours") + .HasForeignKey("ProspectiveTenantId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Checklist"); + + b.Navigation("Property"); + + b.Navigation("ProspectiveTenant"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.UserOrganization", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("GrantedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany("UserOrganizations") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Notification", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("RecipientUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("NotificationPreferences", b => + { + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Checklist", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ChecklistTemplate", b => + { + b.Navigation("Checklists"); + + b.Navigation("Items"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Lease", b => + { + b.Navigation("Documents"); + + b.Navigation("Invoices"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + { + b.Navigation("Leases"); + + b.Navigation("Properties"); + + b.Navigation("Tenants"); + + b.Navigation("UserOrganizations"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Property", b => + { + b.Navigation("Documents"); + + b.Navigation("Leases"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.ProspectiveTenant", b => + { + b.Navigation("Applications"); + + b.Navigation("Tours"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.RentalApplication", b => + { + b.Navigation("Screening"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDeposit", b => + { + b.Navigation("Dividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.SecurityDepositInvestmentPool", b => + { + b.Navigation("Dividends"); + }); + + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Tenant", b => + { + b.Navigation("Leases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.cs new file mode 100644 index 0000000..0e01295 --- /dev/null +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/20251230141240_OrganizationEmailSMSSettings.cs @@ -0,0 +1,116 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Aquiis.SimpleStart.Migrations +{ + /// + public partial class OrganizationEmailSMSSettings : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "OrganizationEmailSettings", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + IsEmailEnabled = table.Column(type: "INTEGER", nullable: false), + SendGridApiKeyEncrypted = table.Column(type: "TEXT", maxLength: 1000, nullable: true), + FromEmail = table.Column(type: "TEXT", maxLength: 200, nullable: true), + FromName = table.Column(type: "TEXT", maxLength: 200, nullable: true), + EmailsSentToday = table.Column(type: "INTEGER", nullable: false), + EmailsSentThisMonth = table.Column(type: "INTEGER", nullable: false), + LastEmailSentOn = table.Column(type: "TEXT", nullable: true), + StatsLastUpdatedOn = table.Column(type: "TEXT", nullable: true), + DailyCountResetOn = table.Column(type: "TEXT", nullable: true), + MonthlyCountResetOn = table.Column(type: "TEXT", nullable: true), + DailyLimit = table.Column(type: "INTEGER", nullable: true), + MonthlyLimit = table.Column(type: "INTEGER", nullable: true), + PlanType = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsVerified = table.Column(type: "INTEGER", nullable: false), + LastVerifiedOn = table.Column(type: "TEXT", nullable: true), + LastError = table.Column(type: "TEXT", maxLength: 1000, nullable: true), + LastErrorOn = table.Column(type: "TEXT", nullable: true), + CreatedOn = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), + LastModifiedOn = table.Column(type: "TEXT", nullable: true), + LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsDeleted = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OrganizationEmailSettings", x => x.Id); + table.ForeignKey( + name: "FK_OrganizationEmailSettings_Organizations_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organizations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OrganizationSMSSettings", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + IsSMSEnabled = table.Column(type: "INTEGER", nullable: false), + TwilioAccountSidEncrypted = table.Column(type: "TEXT", maxLength: 1000, nullable: true), + TwilioAuthTokenEncrypted = table.Column(type: "TEXT", maxLength: 1000, nullable: true), + TwilioPhoneNumber = table.Column(type: "TEXT", maxLength: 20, nullable: true), + SMSSentToday = table.Column(type: "INTEGER", nullable: false), + SMSSentThisMonth = table.Column(type: "INTEGER", nullable: false), + LastSMSSentOn = table.Column(type: "TEXT", nullable: true), + StatsLastUpdatedOn = table.Column(type: "TEXT", nullable: true), + DailyCountResetOn = table.Column(type: "TEXT", nullable: true), + MonthlyCountResetOn = table.Column(type: "TEXT", nullable: true), + AccountBalance = table.Column(type: "TEXT", precision: 18, scale: 2, nullable: true), + CostPerSMS = table.Column(type: "TEXT", precision: 18, scale: 4, nullable: true), + AccountType = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsVerified = table.Column(type: "INTEGER", nullable: false), + LastVerifiedOn = table.Column(type: "TEXT", nullable: true), + LastError = table.Column(type: "TEXT", maxLength: 1000, nullable: true), + CreatedOn = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", maxLength: 100, nullable: false), + LastModifiedOn = table.Column(type: "TEXT", nullable: true), + LastModifiedBy = table.Column(type: "TEXT", maxLength: 100, nullable: true), + IsDeleted = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OrganizationSMSSettings", x => x.Id); + table.ForeignKey( + name: "FK_OrganizationSMSSettings_Organizations_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organizations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_OrganizationEmailSettings_OrganizationId", + table: "OrganizationEmailSettings", + column: "OrganizationId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OrganizationSMSSettings_OrganizationId", + table: "OrganizationSMSSettings", + column: "OrganizationId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "OrganizationEmailSettings"); + + migrationBuilder.DropTable( + name: "OrganizationSMSSettings"); + } + } +} diff --git a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs index ef8cbdc..363e36e 100644 --- a/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Aquiis.SimpleStart/Infrastructure/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -1978,117 +1978,55 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Notes"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => { b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("Category") - .IsRequired() - .HasMaxLength(50) + .ValueGeneratedOnAdd() .HasColumnType("TEXT"); b.Property("CreatedBy") .IsRequired() - .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("CreatedOn") .HasColumnType("TEXT"); - b.Property("EmailError") - .HasMaxLength(500) + b.Property("DisplayName") .HasColumnType("TEXT"); - b.Property("EmailSent") + b.Property("IsActive") .HasColumnType("INTEGER"); - b.Property("EmailSentOn") - .HasColumnType("TEXT"); - b.Property("IsDeleted") .HasColumnType("INTEGER"); - b.Property("IsRead") - .HasColumnType("INTEGER"); - b.Property("LastModifiedBy") - .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("LastModifiedOn") .HasColumnType("TEXT"); - b.Property("Message") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("TEXT"); - - b.Property("OrganizationId") - .HasColumnType("TEXT"); - - b.Property("ReadOn") - .HasColumnType("TEXT"); - - b.Property("RecipientUserId") + b.Property("Name") .IsRequired() .HasColumnType("TEXT"); - b.Property("RelatedEntityId") - .HasColumnType("TEXT"); - - b.Property("RelatedEntityType") - .HasMaxLength(50) - .HasColumnType("TEXT"); - - b.Property("SMSError") - .HasMaxLength(500) - .HasColumnType("TEXT"); - - b.Property("SMSSent") - .HasColumnType("INTEGER"); - - b.Property("SMSSentOn") - .HasColumnType("TEXT"); - - b.Property("SendEmail") - .HasColumnType("INTEGER"); - - b.Property("SendInApp") - .HasColumnType("INTEGER"); - - b.Property("SendSMS") - .HasColumnType("INTEGER"); - - b.Property("SentOn") - .HasColumnType("TEXT"); - - b.Property("Title") + b.Property("OwnerId") .IsRequired() - .HasMaxLength(200) .HasColumnType("TEXT"); - b.Property("Type") - .IsRequired() - .HasMaxLength(50) + b.Property("State") .HasColumnType("TEXT"); b.HasKey("Id"); - b.HasIndex("Category"); - - b.HasIndex("IsRead"); - - b.HasIndex("OrganizationId"); - - b.HasIndex("RecipientUserId"); + b.HasIndex("IsActive"); - b.HasIndex("SentOn"); + b.HasIndex("OwnerId"); - b.ToTable("Notifications"); + b.ToTable("Organizations"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationEmailSettings", b => { b.Property("Id") .HasColumnType("TEXT"); @@ -2101,48 +2039,44 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedOn") .HasColumnType("TEXT"); - b.Property("DailyDigestTime") - .HasColumnType("TEXT"); - - b.Property("EmailAddress") - .HasMaxLength(200) + b.Property("DailyCountResetOn") .HasColumnType("TEXT"); - b.Property("EmailApplicationStatusChange") - .HasColumnType("INTEGER"); - - b.Property("EmailInspectionScheduled") + b.Property("DailyLimit") .HasColumnType("INTEGER"); - b.Property("EmailLeaseExpiring") + b.Property("EmailsSentThisMonth") .HasColumnType("INTEGER"); - b.Property("EmailMaintenanceUpdate") + b.Property("EmailsSentToday") .HasColumnType("INTEGER"); - b.Property("EmailPaymentDue") - .HasColumnType("INTEGER"); + b.Property("FromEmail") + .HasMaxLength(200) + .HasColumnType("TEXT"); - b.Property("EmailPaymentReceived") - .HasColumnType("INTEGER"); + b.Property("FromName") + .HasMaxLength(200) + .HasColumnType("TEXT"); - b.Property("EnableDailyDigest") + b.Property("IsDeleted") .HasColumnType("INTEGER"); - b.Property("EnableEmailNotifications") + b.Property("IsEmailEnabled") .HasColumnType("INTEGER"); - b.Property("EnableInAppNotifications") + b.Property("IsVerified") .HasColumnType("INTEGER"); - b.Property("EnableSMSNotifications") - .HasColumnType("INTEGER"); + b.Property("LastEmailSentOn") + .HasColumnType("TEXT"); - b.Property("EnableWeeklyDigest") - .HasColumnType("INTEGER"); + b.Property("LastError") + .HasMaxLength(1000) + .HasColumnType("TEXT"); - b.Property("IsDeleted") - .HasColumnType("INTEGER"); + b.Property("LastErrorOn") + .HasColumnType("TEXT"); b.Property("LastModifiedBy") .HasMaxLength(100) @@ -2151,87 +2085,124 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastModifiedOn") .HasColumnType("TEXT"); - b.Property("OrganizationId") + b.Property("LastVerifiedOn") .HasColumnType("TEXT"); - b.Property("PhoneNumber") - .HasMaxLength(20) + b.Property("MonthlyCountResetOn") .HasColumnType("TEXT"); - b.Property("SMSLeaseExpiringUrgent") + b.Property("MonthlyLimit") .HasColumnType("INTEGER"); - b.Property("SMSMaintenanceEmergency") - .HasColumnType("INTEGER"); + b.Property("OrganizationId") + .HasColumnType("TEXT"); - b.Property("SMSPaymentDue") - .HasColumnType("INTEGER"); + b.Property("PlanType") + .HasMaxLength(100) + .HasColumnType("TEXT"); - b.Property("UserId") - .IsRequired() + b.Property("SendGridApiKeyEncrypted") + .HasMaxLength(1000) .HasColumnType("TEXT"); - b.Property("WeeklyDigestDay") - .HasColumnType("INTEGER"); + b.Property("StatsLastUpdatedOn") + .HasColumnType("TEXT"); b.HasKey("Id"); - b.HasIndex("OrganizationId"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "OrganizationId") + b.HasIndex("OrganizationId") .IsUnique(); - b.ToTable("NotificationPreferences"); + b.ToTable("OrganizationEmailSettings"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSMSSettings", b => { b.Property("Id") - .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AccountBalance") + .HasPrecision(18, 2) + .HasColumnType("TEXT"); + + b.Property("AccountType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("CostPerSMS") + .HasPrecision(18, 4) .HasColumnType("TEXT"); b.Property("CreatedBy") .IsRequired() + .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("CreatedOn") .HasColumnType("TEXT"); - b.Property("DisplayName") + b.Property("DailyCountResetOn") .HasColumnType("TEXT"); - b.Property("IsActive") + b.Property("IsDeleted") .HasColumnType("INTEGER"); - b.Property("IsDeleted") + b.Property("IsSMSEnabled") .HasColumnType("INTEGER"); + b.Property("IsVerified") + .HasColumnType("INTEGER"); + + b.Property("LastError") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + b.Property("LastModifiedBy") + .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("LastModifiedOn") .HasColumnType("TEXT"); - b.Property("Name") - .IsRequired() + b.Property("LastSMSSentOn") .HasColumnType("TEXT"); - b.Property("OwnerId") - .IsRequired() + b.Property("LastVerifiedOn") .HasColumnType("TEXT"); - b.Property("State") + b.Property("MonthlyCountResetOn") .HasColumnType("TEXT"); - b.HasKey("Id"); + b.Property("OrganizationId") + .HasColumnType("TEXT"); - b.HasIndex("IsActive"); + b.Property("SMSSentThisMonth") + .HasColumnType("INTEGER"); - b.HasIndex("OwnerId"); + b.Property("SMSSentToday") + .HasColumnType("INTEGER"); - b.ToTable("Organizations"); + b.Property("StatsLastUpdatedOn") + .HasColumnType("TEXT"); + + b.Property("TwilioAccountSidEncrypted") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("TwilioAuthTokenEncrypted") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("TwilioPhoneNumber") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId") + .IsUnique(); + + b.ToTable("OrganizationSMSSettings"); }); modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSettings", b => @@ -3987,24 +3958,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Notification", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => { - b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) .WithMany() - .HasForeignKey("RecipientUserId") - .OnDelete(DeleteBehavior.Cascade) + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - - b.Navigation("Organization"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.NotificationPreferences", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationEmailSettings", b => { b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") .WithMany() @@ -4012,22 +3975,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.Navigation("Organization"); }); - modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Organization", b => + modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.OrganizationSMSSettings", b => { - b.HasOne("Aquiis.SimpleStart.Shared.Components.Account.ApplicationUser", null) + b.HasOne("Aquiis.SimpleStart.Core.Entities.Organization", "Organization") .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Restrict) + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("Organization"); }); modelBuilder.Entity("Aquiis.SimpleStart.Core.Entities.Payment", b => diff --git a/Aquiis.SimpleStart/Shared/App.razor b/Aquiis.SimpleStart/Shared/App.razor index 0e82665..d955c9d 100644 --- a/Aquiis.SimpleStart/Shared/App.razor +++ b/Aquiis.SimpleStart/Shared/App.razor @@ -5,7 +5,7 @@ - + diff --git a/Aquiis.SimpleStart/Shared/Layout/NavMenu.razor b/Aquiis.SimpleStart/Shared/Layout/NavMenu.razor index 77df859..078d011 100644 --- a/Aquiis.SimpleStart/Shared/Layout/NavMenu.razor +++ b/Aquiis.SimpleStart/Shared/Layout/NavMenu.razor @@ -40,6 +40,11 @@
Dashboard
+