1+
2+ using Aquiis . SimpleStart . Core . Constants ;
3+ using Aquiis . SimpleStart . Core . Entities ;
4+ using Aquiis . SimpleStart . Core . Interfaces . Services ;
5+ using Aquiis . SimpleStart . Core . Services ;
6+ using Aquiis . SimpleStart . Infrastructure . Data ;
7+ using Aquiis . SimpleStart . Shared . Services ;
8+ using Microsoft . EntityFrameworkCore ;
9+ using Microsoft . Extensions . Options ;
10+
11+ namespace Aquiis . SimpleStart . Application . Services
12+ {
13+ public class NotificationService : BaseService < Notification >
14+ {
15+ private readonly IEmailService _emailService ;
16+ private readonly ISMSService _smsService ;
17+ private new readonly ILogger < NotificationService > _logger ;
18+
19+ public NotificationService (
20+ ApplicationDbContext context ,
21+ ILogger < NotificationService > logger ,
22+ UserContextService userContext ,
23+ IOptions < ApplicationSettings > settings ,
24+ IEmailService emailService ,
25+ ISMSService smsService )
26+ : base ( context , logger , userContext , settings )
27+ {
28+ _emailService = emailService ;
29+ _smsService = smsService ;
30+ _logger = logger ;
31+ }
32+
33+ /// <summary>
34+ /// Create and send a notification to a user
35+ /// </summary>
36+ public async Task < Notification > SendNotificationAsync (
37+ string recipientUserId ,
38+ string title ,
39+ string message ,
40+ string type ,
41+ string category ,
42+ Guid ? relatedEntityId = null ,
43+ string ? relatedEntityType = null )
44+ {
45+ var organizationId = await _userContext . GetActiveOrganizationIdAsync ( ) ;
46+
47+ // Get user preferences
48+ var preferences = await GetNotificationPreferencesAsync ( recipientUserId ) ;
49+
50+ var notification = new Notification
51+ {
52+ Id = Guid . NewGuid ( ) ,
53+ OrganizationId = organizationId ! . Value ,
54+ RecipientUserId = recipientUserId ,
55+ Title = title ,
56+ Message = message ,
57+ Type = type ,
58+ Category = category ,
59+ RelatedEntityId = relatedEntityId ,
60+ RelatedEntityType = relatedEntityType ,
61+ SentOn = DateTime . UtcNow ,
62+ IsRead = false ,
63+ SendInApp = preferences . EnableInAppNotifications ,
64+ SendEmail = preferences . EnableEmailNotifications && ShouldSendEmail ( category , preferences ) ,
65+ SendSMS = preferences . EnableSMSNotifications && ShouldSendSMS ( category , preferences )
66+ } ;
67+
68+ // Save in-app notification
69+ await CreateAsync ( notification ) ;
70+
71+ // Send email if enabled
72+ if ( notification . SendEmail && ! string . IsNullOrEmpty ( preferences . EmailAddress ) )
73+ {
74+ try
75+ {
76+ await _emailService . SendEmailAsync (
77+ preferences . EmailAddress ,
78+ title ,
79+ message ) ;
80+
81+ notification . EmailSent = true ;
82+ notification . EmailSentOn = DateTime . UtcNow ;
83+ }
84+ catch ( Exception ex )
85+ {
86+ _logger . LogError ( ex , $ "Failed to send email notification to { recipientUserId } ") ;
87+ notification . EmailError = ex . Message ;
88+ }
89+ }
90+
91+ // Send SMS if enabled
92+ if ( notification . SendSMS && ! string . IsNullOrEmpty ( preferences . PhoneNumber ) )
93+ {
94+ try
95+ {
96+ await _smsService . SendSMSAsync (
97+ preferences . PhoneNumber ,
98+ $ "{ title } : { message } ") ;
99+
100+ notification . SMSSent = true ;
101+ notification . SMSSentOn = DateTime . UtcNow ;
102+ }
103+ catch ( Exception ex )
104+ {
105+ _logger . LogError ( ex , $ "Failed to send SMS notification to { recipientUserId } ") ;
106+ notification . SMSError = ex . Message ;
107+ }
108+ }
109+
110+ await UpdateAsync ( notification ) ;
111+
112+ return notification ;
113+ }
114+
115+ /// <summary>
116+ /// Mark notification as read
117+ /// </summary>
118+ public async Task MarkAsReadAsync ( Guid notificationId )
119+ {
120+ var notification = await GetByIdAsync ( notificationId ) ;
121+ if ( notification == null ) return ;
122+
123+ notification . IsRead = true ;
124+ notification . ReadOn = DateTime . UtcNow ;
125+
126+ await UpdateAsync ( notification ) ;
127+ }
128+
129+ /// <summary>
130+ /// Get unread notifications for current user
131+ /// </summary>
132+ public async Task < List < Notification > > GetUnreadNotificationsAsync ( )
133+ {
134+ var userId = await _userContext . GetUserIdAsync ( ) ;
135+ var organizationId = await _userContext . GetActiveOrganizationIdAsync ( ) ;
136+
137+ return await _context . Notifications
138+ . Where ( n => n . OrganizationId == organizationId
139+ && n . RecipientUserId == userId
140+ && ! n . IsRead
141+ && ! n . IsDeleted )
142+ . OrderByDescending ( n => n . SentOn )
143+ . Take ( 50 )
144+ . ToListAsync ( ) ;
145+ }
146+
147+ /// <summary>
148+ /// Get notification history for current user
149+ /// </summary>
150+ public async Task < List < Notification > > GetNotificationHistoryAsync ( int count = 100 )
151+ {
152+ var userId = await _userContext . GetUserIdAsync ( ) ;
153+ var organizationId = await _userContext . GetActiveOrganizationIdAsync ( ) ;
154+
155+ return await _context . Notifications
156+ . Where ( n => n . OrganizationId == organizationId
157+ && n . RecipientUserId == userId
158+ && ! n . IsDeleted )
159+ . OrderByDescending ( n => n . SentOn )
160+ . Take ( count )
161+ . ToListAsync ( ) ;
162+ }
163+
164+ /// <summary>
165+ /// Get or create notification preferences for user
166+ /// </summary>
167+ private async Task < NotificationPreferences > GetNotificationPreferencesAsync ( string userId )
168+ {
169+ var organizationId = await _userContext . GetActiveOrganizationIdAsync ( ) ;
170+
171+ var preferences = await _context . NotificationPreferences
172+ . FirstOrDefaultAsync ( p => p . OrganizationId == organizationId
173+ && p . UserId == userId
174+ && ! p . IsDeleted ) ;
175+
176+ if ( preferences == null )
177+ {
178+ // Create default preferences
179+ preferences = new NotificationPreferences
180+ {
181+ Id = Guid . NewGuid ( ) ,
182+ OrganizationId = organizationId ! . Value ,
183+ UserId = userId ,
184+ EnableInAppNotifications = true ,
185+ EnableEmailNotifications = true ,
186+ EnableSMSNotifications = false ,
187+ EmailLeaseExpiring = true ,
188+ EmailPaymentDue = true ,
189+ EmailPaymentReceived = true ,
190+ EmailApplicationStatusChange = true ,
191+ EmailMaintenanceUpdate = true ,
192+ EmailInspectionScheduled = true
193+ } ;
194+
195+ _context . NotificationPreferences . Add ( preferences ) ;
196+ await _context . SaveChangesAsync ( ) ;
197+ }
198+
199+ return preferences ;
200+ }
201+
202+ private bool ShouldSendEmail ( string category , NotificationPreferences prefs )
203+ {
204+ return category switch
205+ {
206+ NotificationConstants . Categories . Lease => prefs . EmailLeaseExpiring ,
207+ NotificationConstants . Categories . Payment => prefs . EmailPaymentDue ,
208+ NotificationConstants . Categories . Application => prefs . EmailApplicationStatusChange ,
209+ NotificationConstants . Categories . Maintenance => prefs . EmailMaintenanceUpdate ,
210+ NotificationConstants . Categories . Inspection => prefs . EmailInspectionScheduled ,
211+ _ => true
212+ } ;
213+ }
214+
215+ private bool ShouldSendSMS ( string category , NotificationPreferences prefs )
216+ {
217+ return category switch
218+ {
219+ NotificationConstants . Categories . Payment => prefs . SMSPaymentDue ,
220+ NotificationConstants . Categories . Maintenance => prefs . SMSMaintenanceEmergency ,
221+ NotificationConstants . Categories . Lease => prefs . SMSLeaseExpiringUrgent ,
222+ _ => false
223+ } ;
224+ }
225+ }
226+ }
0 commit comments