From 670d04e3388a80a4043c196160fd8a005050ec61 Mon Sep 17 00:00:00 2001
From: snemeckayova <514641@mail.muni.cz>
Date: Tue, 5 Nov 2024 17:32:13 +0100
Subject: [PATCH] Implement event related interfaces

---
 .../EventCommentService.cs                    | 146 ++++++++++++++++++
 .../EventParticipantService.cs                | 128 +++++++++++++++
 .../Services/EventService/EventService.cs     | 123 +++++++++++++++
 3 files changed, 397 insertions(+)
 create mode 100644 BusinessLayer/Services/EventCommentService/EventCommentService.cs
 create mode 100644 BusinessLayer/Services/EventParticipantService/EventParticipantService.cs
 create mode 100644 BusinessLayer/Services/EventService/EventService.cs

diff --git a/BusinessLayer/Services/EventCommentService/EventCommentService.cs b/BusinessLayer/Services/EventCommentService/EventCommentService.cs
new file mode 100644
index 0000000..942bbfe
--- /dev/null
+++ b/BusinessLayer/Services/EventCommentService/EventCommentService.cs
@@ -0,0 +1,146 @@
+using BusinessLayer.DTOs.EventComment;
+using BusinessLayer.Utils.Filters;
+using BusinessLayer.Utils.Pagination;
+using DAL.Data;
+using DAL.Models;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+
+namespace BusinessLayer.Services.EventCommentService
+{
+    public class EventCommentService : BaseService, IEventCommentService
+    {
+        private readonly RestaurantDBContext _dbContext;
+
+        public EventCommentService(RestaurantDBContext dbContext) : base(dbContext)
+        {
+            _dbContext = dbContext;
+        }
+
+        public async Task<EventCommentDTO?> CreateCommentAsync(EventCommentCreateDTO data, bool save = true)
+        {
+            var poster = await _dbContext.Users.FindAsync(data.PosterId);
+            if (poster is null || poster.DeletedAt is not null)
+            {
+                return null;
+            }
+
+            var eventEntity = await _dbContext.Events.FindAsync(data.EventId);
+            if (eventEntity is null || eventEntity.DeletedAt is not null)
+            {
+                return null;
+            }
+
+            if (data.ParentCommentId is not null)
+            {
+                var parentComment = await _dbContext.EventComments.FindAsync(data.ParentCommentId);
+                if (parentComment is null || parentComment.DeletedAt is not null)
+                {
+                    return null;
+                }
+            }
+
+            var comment = data.Adapt<EventComment>();
+            comment.Id = Guid.NewGuid();
+            comment.CreatedAt = DateTime.UtcNow;
+            comment.UpdatedAt = DateTime.UtcNow;
+
+            await _dbContext.EventComments.AddAsync(comment);
+            await SaveAsync(save);
+            return comment.Adapt<EventCommentDTO?>();
+        }
+
+        public async Task<bool> DeleteCommentAsync(Guid id, bool save = true)
+        {
+            var comment = await _dbContext.EventComments.FindAsync(id);
+            if (comment is null || comment.DeletedAt is not null)
+            {
+                return false;
+            }
+
+            comment.UpdatedAt = DateTime.UtcNow;
+            comment.DeletedAt = DateTime.UtcNow;
+
+            _dbContext.EventComments.Update(comment);
+            await SaveAsync(save);
+            return true;
+        }
+
+        public async Task<bool> DoesCommentExistAsync(params Guid[] ids)
+        {
+            return await _dbContext.EventComments.AnyAsync(c => ids.Contains(c.Id) && c.DeletedAt == null);
+        }
+
+        public async Task<EventCommentDTO?> GetByIdAsync(Guid id, bool includeUser = true, bool includeEvent = false, bool includeChildren = false)
+        {
+            var query = BuildQuery(includeUser, includeEvent, includeChildren);
+
+            var result = await query.SingleOrDefaultAsync(c => c.Id == id && c.DeletedAt == null);
+            if (result == null
+                || (includeUser && result.Poster.DeletedAt != null)
+                || (includeEvent && result.Event.DeletedAt != null))
+            {
+                return null;
+            }
+
+            return result.Adapt<EventCommentDTO?>();
+        }
+
+        public async Task<List<EventCommentDTO>> GetCommentsAsync(EventCommentFilter filter,
+            int limit = 0,
+            int offset = 0,
+            Guid[]? ids = null,
+            bool includeUser = true,
+            bool includeEvent = false,
+            bool includeChildren = false)
+        {
+            IQueryable<EventComment> query = BuildQuery(includeUser, includeEvent, includeChildren);
+
+            return await query
+                .Where(filter.ComposeFilterFunction(ids))
+                .OrderByDescending(c => c.CreatedAt)
+                .ApplyPagination(limit, offset)
+                .Select(c => c.Adapt<EventCommentDTO>())
+                .ToListAsync();
+        }
+
+        public async Task<EventCommentDTO?> UpdateCommentAsync(Guid id, EventCommentUpdateDTO data, bool save = true)
+        {
+            var comment = await _dbContext.EventComments.FindAsync(id);
+            if (comment is null || comment.DeletedAt is not null)
+            {
+                return null;
+            }
+
+            comment.Content = data.Content ?? comment.Content;
+            comment.UpdatedAt = DateTime.UtcNow;
+
+            _dbContext.EventComments.Update(comment);
+            await SaveAsync(save);
+
+            return comment.Adapt<EventCommentDTO?>();
+        }
+
+        private IQueryable<EventComment> BuildQuery(bool includeUser, bool includeEvent, bool includeChildren)
+        {
+            IQueryable<EventComment> query = _dbContext.EventComments;
+
+            if (includeUser)
+            {
+                query = query.Include(c => c.Poster);
+            }
+
+            if (includeEvent)
+            {
+                query = query.Include(c => c.Event);
+            }
+
+            if (includeChildren)
+            {
+                query = query.Include(c => c.ChildComments);
+            }
+
+            return query;
+        }
+    }
+}
diff --git a/BusinessLayer/Services/EventParticipantService/EventParticipantService.cs b/BusinessLayer/Services/EventParticipantService/EventParticipantService.cs
new file mode 100644
index 0000000..8488849
--- /dev/null
+++ b/BusinessLayer/Services/EventParticipantService/EventParticipantService.cs
@@ -0,0 +1,128 @@
+using BusinessLayer.DTOs.EventParticipant;
+using BusinessLayer.Utils.Filters;
+using DAL.Data;
+using DAL.Models;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+
+namespace BusinessLayer.Services.EventParticipantService
+{
+    public class EventParticipantService : BaseService, IEventParticipantService
+    {
+        private readonly RestaurantDBContext _dbContext;
+
+        public EventParticipantService(RestaurantDBContext dbContext) : base(dbContext)
+        {
+            _dbContext = dbContext;
+        }
+
+        public async Task<EventParticipantDTO?> GetParticipantByIdAsync(Guid userId, Guid eventId)
+        {
+            var participant = await _dbContext.EventParticipants
+                .Include(p => p.User)
+                .Include(p => p.Event)
+                .FirstOrDefaultAsync(p => p.UserId == userId && p.EventId == eventId && p.DeletedAt == null);
+
+            return participant?.Adapt<EventParticipantDTO>();
+        }
+
+        public async Task<List<EventParticipantDTO>> GetParticipantsAsync(EventParticipantFilter filter, int limit = 0, int offset = 0)
+        {
+            var query = _dbContext.EventParticipants
+                .Include(p => p.User)
+                .Include(p => p.Event)
+                .Where(filter.ComposeFilterFunction())
+                .OrderBy(p => p.User!.Name)
+                .Skip(offset);
+
+            var participants = limit > 0
+                ? await query.Take(limit).ToListAsync()
+                : await query.ToListAsync();
+
+            return participants.Adapt<List<EventParticipantDTO>>();
+        }
+
+        public async Task<EventParticipantDTO?> CreateParticipantAsync(EventParticipantCreateDTO data, bool save = true)
+        {
+            var user = await _dbContext.Users.FindAsync(data.UserId);
+            if (user == null || user.DeletedAt != null)
+            {
+                return null;
+            }
+
+            var eventEntity = await _dbContext.Events.FindAsync(data.EventId);
+            if (eventEntity == null || eventEntity.DeletedAt != null)
+            {
+                return null;
+            }
+
+            var oldParticipant = await _dbContext.EventParticipants
+                .FirstOrDefaultAsync(p => p.UserId == data.UserId && p.EventId == data.EventId);
+
+            if (oldParticipant != null)
+            {
+                if (oldParticipant.DeletedAt != null)
+                {
+                    oldParticipant.CreatedAt = DateTime.UtcNow;
+                    oldParticipant.UpdatedAt = DateTime.UtcNow;
+                    oldParticipant.DeletedAt = null;
+                    oldParticipant.Attendance = data.Attendance;
+
+                    _dbContext.EventParticipants.Update(oldParticipant);
+                    await SaveAsync(save);
+                    return oldParticipant.Adapt<EventParticipantDTO>();
+                }
+
+                return null;
+            }
+
+            var participant = new EventParticipant
+            {
+                UserId = data.UserId,
+                EventId = data.EventId,
+                Attendance = data.Attendance,
+                CreatedAt = DateTime.UtcNow,
+                UpdatedAt = DateTime.UtcNow
+            };
+
+            await _dbContext.EventParticipants.AddAsync(participant);
+            await SaveAsync(save);
+
+            return participant.Adapt<EventParticipantDTO>();
+        }
+
+        public async Task<EventParticipantDTO?> UpdateParticipantAsync(Guid participantId, EventParticipantUpdateDTO data, bool save = true)
+        {
+            var participant = await _dbContext.EventParticipants.FindAsync(participantId);
+            if (participant == null || participant.DeletedAt != null)
+            {
+                return null;
+            }
+
+            participant.Attendance = data.Attendance;
+            participant.UpdatedAt = DateTime.UtcNow;
+
+            _dbContext.EventParticipants.Update(participant);
+            await SaveAsync(save);
+
+            return participant.Adapt<EventParticipantDTO>();
+        }
+
+        public async Task<bool> DeleteParticipantAsync(Guid participantId, bool save = true)
+        {
+            var participant = await _dbContext.EventParticipants.FindAsync(participantId);
+            if (participant == null || participant.DeletedAt != null)
+            {
+                return false;
+            }
+
+            participant.UpdatedAt = DateTime.UtcNow;
+            participant.DeletedAt = DateTime.UtcNow;
+
+            _dbContext.EventParticipants.Update(participant);
+            await SaveAsync(save);
+
+            return true;
+        }
+    }
+}
diff --git a/BusinessLayer/Services/EventService/EventService.cs b/BusinessLayer/Services/EventService/EventService.cs
new file mode 100644
index 0000000..09ade8c
--- /dev/null
+++ b/BusinessLayer/Services/EventService/EventService.cs
@@ -0,0 +1,123 @@
+using BusinessLayer.DTOs.Event;
+using BusinessLayer.Utils.Filters;
+using DAL.Data;
+using DAL.Models;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+
+namespace BusinessLayer.Services.EventService
+{
+    public class EventService : BaseService, IEventService
+    {
+        private readonly RestaurantDBContext _dbContext;
+
+        public EventService(RestaurantDBContext dbContext) : base(dbContext)
+        {
+            _dbContext = dbContext;
+        }
+
+        public async Task<EventDTO?> GetEventByIdAsync(Guid eventId, bool includeRestaurant = true)
+        {
+            var query = _dbContext.Events.AsQueryable();
+            if (includeRestaurant)
+            {
+                query = query.Include(e => e.Restaurant);
+            }
+
+            var eventEntity = await query
+                .SingleOrDefaultAsync(e => e.Id == eventId && e.DeletedAt == null);
+
+            return eventEntity?.Adapt<EventDTO>();
+        }
+
+        public async Task<List<EventDTO>> GetEventsAsync(EventFilter filter, int limit = 0, int offset = 0)
+        {
+            var eventsQuery = _dbContext.Events
+                .Include(e => e.Restaurant)
+                .Where(filter.ComposeFilterFunction())
+                .OrderBy(e => e.Date)
+                .Skip(offset);
+
+            var events = limit > 0
+                ? await eventsQuery.Take(limit).ToListAsync()
+                : await eventsQuery.ToListAsync();
+
+            return events.Adapt<List<EventDTO>>();
+        }
+
+        public async Task<EventDTO?> CreateEventAsync(EventCreateDTO data, bool save = true)
+        {
+            var user = await _dbContext.Users.FindAsync(data.CreatorId);
+            if (user == null || user.DeletedAt != null)
+            {
+                return null;
+            }
+
+            var restaurant = await _dbContext.Restaurants.FindAsync(data.RestaurantId);
+            if (restaurant == null || restaurant.DeletedAt != null)
+            {
+                return null;
+            }
+
+            var eventEntity = new Event
+            {
+                Id = Guid.NewGuid(),
+                Title = data.Title,
+                RestaurantId = data.RestaurantId,
+                Content = data.Content,
+                Date = data.Date,
+                CreatedAt = DateTime.UtcNow,
+                UpdatedAt = DateTime.UtcNow,
+            };
+
+            var creator = new EventParticipant
+            {
+                EventId = eventEntity.Id,
+                UserId = data.CreatorId,
+                Attendance = DAL.Enums.ParticipantType.Creator
+            };
+
+            await _dbContext.Events.AddAsync(eventEntity);
+            await _dbContext.EventParticipants.AddAsync(creator);
+            await SaveAsync(save);
+
+            return eventEntity.Adapt<EventDTO>();
+        }
+
+        public async Task<EventDTO?> UpdateEventAsync(Guid eventId, EventUpdateDTO data, bool save = true)
+        {
+            var eventEntity = await _dbContext.Events.FindAsync(eventId);
+            if (eventEntity == null || eventEntity.DeletedAt != null)
+            {
+                return null;
+            }
+
+            eventEntity.Title = data.Title ?? eventEntity.Title;
+            eventEntity.Content = data.Content ?? eventEntity.Content;
+            eventEntity.Date = data.Date ?? eventEntity.Date;
+            eventEntity.UpdatedAt = DateTime.UtcNow;
+
+            _dbContext.Events.Update(eventEntity);
+            await SaveAsync(save);
+
+            return eventEntity.Adapt<EventDTO>();
+        }
+
+        public async Task<bool> DeleteEventAsync(Guid eventId, bool save = true)
+        {
+            var eventEntity = await _dbContext.Events.FindAsync(eventId);
+            if (eventEntity == null || eventEntity.DeletedAt != null)
+            {
+                return false;
+            }
+
+            eventEntity.UpdatedAt = DateTime.UtcNow;
+            eventEntity.DeletedAt = DateTime.UtcNow;
+
+            _dbContext.Events.Update(eventEntity);
+            await SaveAsync(save);
+
+            return true;
+        }
+    }
+}
-- 
GitLab