Files
meezi/src/Meezi.API/Services/NotificationInboxService.cs
T
soroush.asadi ef15fd6247 feat(api): .NET 10 multi-tenant REST API
Full backend implementation:
- Multi-tenant cafe/restaurant management (menus, orders, tables, staff)
- POS order flow with ZarinPal and Snappfood payment integration
- OTP authentication via Kavenegar SMS
- QR digital menu with public discover/finder endpoints
- Customer loyalty, coupons, CRM
- PostgreSQL via EF Core, Redis for caching/sessions
- Background jobs, webhook handlers
- Full migration history

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:48 +03:30

81 lines
2.3 KiB
C#

using Meezi.API.Models.Notifications;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace Meezi.API.Services;
public interface INotificationInboxService
{
Task<NotificationListDto> ListAsync(
string cafeId,
bool unreadOnly,
int limit,
CancellationToken ct = default);
Task<int> GetUnreadCountAsync(string cafeId, CancellationToken ct = default);
Task MarkReadAsync(string cafeId, MarkNotificationsReadRequest request, CancellationToken ct = default);
}
public class NotificationInboxService : INotificationInboxService
{
private readonly AppDbContext _db;
public NotificationInboxService(AppDbContext db)
{
_db = db;
}
public async Task<NotificationListDto> ListAsync(
string cafeId,
bool unreadOnly,
int limit,
CancellationToken ct = default)
{
limit = Math.Clamp(limit, 1, 100);
var q = _db.CafeNotifications.AsNoTracking().Where(n => n.CafeId == cafeId);
if (unreadOnly)
q = q.Where(n => !n.IsRead);
var unread = await q.CountAsync(n => !n.IsRead, ct);
var items = await q
.OrderByDescending(n => n.CreatedAt)
.Take(limit)
.Select(n => new CafeNotificationDto(
n.Id,
n.Type,
n.Title,
n.Body,
n.ReferenceId,
n.TableNumber,
n.IsRead,
n.CreatedAt))
.ToListAsync(ct);
return new NotificationListDto(items, unread);
}
public Task<int> GetUnreadCountAsync(string cafeId, CancellationToken ct = default) =>
_db.CafeNotifications.CountAsync(n => n.CafeId == cafeId && !n.IsRead, ct);
public async Task MarkReadAsync(
string cafeId,
MarkNotificationsReadRequest request,
CancellationToken ct = default)
{
var q = _db.CafeNotifications.Where(n => n.CafeId == cafeId && !n.IsRead);
if (!request.All && request.Ids is { Count: > 0 })
q = q.Where(n => request.Ids.Contains(n.Id));
var rows = await q.ToListAsync(ct);
var now = DateTime.UtcNow;
foreach (var row in rows)
{
row.IsRead = true;
row.ReadAt = now;
}
await _db.SaveChangesAsync(ct);
}
}