From 576b1c238ac25b101673e836a17462eeaa2d7fd0 Mon Sep 17 00:00:00 2001
From: esantangelo <enzo020895@gmail.com>
Date: Sun, 15 Nov 2020 15:20:40 -0300
Subject: [PATCH] communication controller and service

---
 .../Controllers/CommunicationController.cs    |  99 +++++++++++++
 Tsi1.Api/Tsi1.Api/Startup.cs                  |   1 +
 .../Dtos/CommunicationCreateDto.cs            |  17 +++
 .../Dtos/CommunicationPreviewDto.cs           |  13 ++
 .../Helpers/ErrorMessages.cs                  |   3 +
 .../Helpers/MappingProfile.cs                 |   4 +
 .../Interfaces/ICommunicationService.cs       |  20 +++
 .../Services/CommunicationService.cs          | 139 ++++++++++++++++++
 8 files changed, 296 insertions(+)
 create mode 100644 Tsi1.Api/Tsi1.Api/Controllers/CommunicationController.cs
 create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationCreateDto.cs
 create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationPreviewDto.cs
 create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICommunicationService.cs
 create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Services/CommunicationService.cs

diff --git a/Tsi1.Api/Tsi1.Api/Controllers/CommunicationController.cs b/Tsi1.Api/Tsi1.Api/Controllers/CommunicationController.cs
new file mode 100644
index 0000000..7cdda5f
--- /dev/null
+++ b/Tsi1.Api/Tsi1.Api/Controllers/CommunicationController.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.Interfaces;
+
+namespace Tsi1.Api.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class CommunicationController : ControllerBase
+    {
+        private readonly ICommunicationService _communicationService;
+
+        public CommunicationController(ICommunicationService communicationService)
+        {
+            _communicationService = communicationService;
+        }
+
+        [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)]
+        [HttpPost("CreateCourseCommunication/{courseId}")]
+        public async Task<IActionResult> CreateCourseCommunication(CommunicationCreateDto newCommunication, int courseId)
+        {
+            var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
+            var validationResult = await _communicationService.TenantValidation(tenantId, courseId);
+
+            if (validationResult.HasError)
+            {
+                return BadRequest(validationResult.Message);
+            }
+
+            var result = await _communicationService.Create(newCommunication, courseId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+        [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)]
+        [HttpPost("CreateTenantCommunication")]
+        public async Task<IActionResult> CreateTenantCommunication(CommunicationCreateDto newCommunication, int tenantId)
+        {
+            var userType = HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Role).Value;
+            if (userType == UserTypes.FacultyAdmin)
+            {
+                tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
+            }
+
+            newCommunication.IsGlobal = true;
+            var result = await _communicationService.Create(newCommunication, tenantId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+        [Authorize(Roles = UserTypes.Student)]
+        [HttpGet("GetMyCommunications")]
+        public async Task<IActionResult> GetMyCommunications()
+        {
+            var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value);
+
+            var result = await _communicationService.GetMyCommunications(userId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok(result.Data);
+        }
+
+        [Authorize(Roles = UserTypes.FacultyAdmin + ", " + UserTypes.UdelarAdmin)]
+        [HttpDelete("Delete/{communicationId}")]
+        public async Task<IActionResult> Delete(int communicationId)
+        {
+            var result = await _communicationService.Delete(communicationId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs
index 369da76..d6ded58 100644
--- a/Tsi1.Api/Tsi1.Api/Startup.cs
+++ b/Tsi1.Api/Tsi1.Api/Startup.cs
@@ -92,6 +92,7 @@ namespace Tsi1.Api
             services.AddScoped<ISectionItemTypeService, SectionItemTypeService>();
             services.AddScoped<IDataLoad, DataLoad>();
             services.AddScoped<ISurveyService, SurveyService>();
+            services.AddScoped<ICommunicationService, CommunicationService>();
 
             services.Configure<MailSettings>(Configuration.GetSection("MailSettings"));
             services.AddScoped<IEmailService, EmailService>();
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationCreateDto.cs
new file mode 100644
index 0000000..24f82ce
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationCreateDto.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json.Serialization;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class CommunicationCreateDto
+    {
+        public string Text { get; set; }
+
+        [JsonIgnore]
+        public bool IsGlobal { get; set; }
+
+        public DateTime ValidUntil { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationPreviewDto.cs
new file mode 100644
index 0000000..6945046
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/CommunicationPreviewDto.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class CommunicationPreviewDto
+    {
+        public int Id { get; set; }
+
+        public string Text { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
index c61742a..b049c02 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
@@ -61,5 +61,8 @@ namespace Tsi1.BusinessLayer.Helpers
         public const string SurveyHasNoQuestions = "La encuesta no tiene preguntas";
         public const string InvalidSurvey = "La encuesta no pertenece a la facultad con id '{0}'";
         public const string SurveyResponseAlreadyExist = "El usuario '{0}' ya completo la encuesta '{1}'";
+
+        public const string CommunicationDoesNotExist = "La comunicación con id '{0}' no existe";
+        public const string InvalidTenant = "El usuario no pertenece a la facultad con id '{0}'";
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
index d7f378c..2793c82 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
@@ -49,6 +49,8 @@ namespace Tsi1.BusinessLayer.Helpers
             CreateMap<SurveyResponse, SurveyResponseDetailDto>();
             CreateMap<SurveyAnswer, SurveyAnswerDetailDto>();
             CreateMap<SurveyAnswer, SurveyAnswerCreateDto>();
+            CreateMap<Communication, CommunicationCreateDto>();
+            CreateMap<Communication, CommunicationPreviewDto>();
 
             CreateMap<ForumCreateDto, Forum>();
             CreateMap<ForumPreviewDto, Forum>();
@@ -87,6 +89,8 @@ namespace Tsi1.BusinessLayer.Helpers
             CreateMap<SurveyResponseDetailDto, SurveyResponse>();
             CreateMap<SurveyAnswerDetailDto, SurveyAnswer>();
             CreateMap<SurveyAnswerCreateDto, SurveyAnswer>();
+            CreateMap<CommunicationCreateDto, Communication>();
+            CreateMap<CommunicationPreviewDto, Communication>();
         }
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICommunicationService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICommunicationService.cs
new file mode 100644
index 0000000..ce39e10
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ICommunicationService.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+
+namespace Tsi1.BusinessLayer.Interfaces
+{
+    public interface ICommunicationService
+    {
+        Task<ServiceResult<bool>> Create(CommunicationCreateDto newCommunication, int id);
+
+        Task<ServiceResult<bool>> Delete(int communicationId);
+
+        Task<ServiceResult<List<CommunicationPreviewDto>>> GetMyCommunications(int userId);
+
+        Task<ServiceResult<bool>> TenantValidation(int tenantId, int courseId);
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/CommunicationService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/CommunicationService.cs
new file mode 100644
index 0000000..9f7e31b
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/CommunicationService.cs
@@ -0,0 +1,139 @@
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.Interfaces;
+using Tsi1.DataLayer;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Services
+{
+    public class CommunicationService : ICommunicationService
+    {
+        private readonly Tsi1Context _context;
+        private readonly IMapper _mapper;
+
+        public CommunicationService(Tsi1Context context, IMapper mapper)
+        {
+            _context = context;
+            _mapper = mapper;
+        }
+
+        public async Task<ServiceResult<bool>> Create(CommunicationCreateDto newCommunication, int id)
+        {
+            var result = new ServiceResult<bool>();
+            var isGlobal = newCommunication.IsGlobal;
+            var commmunication = _mapper.Map<Communication>(newCommunication);
+
+            var validationResult = await this.CreateValidation(id, isGlobal, commmunication);
+
+            if (validationResult.HasError)
+            {
+                return validationResult;
+            }
+
+            _context.Communications.Add(commmunication);
+
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+
+        public async Task<ServiceResult<bool>> Delete(int communicationId)
+        {
+            var result = new ServiceResult<bool>();
+            var commmunication = await _context.Communications.FirstOrDefaultAsync(x => x.Id == communicationId);
+
+            if (commmunication == null)
+            {
+                result.HasError = true;
+                result.AddMessage(string.Format(ErrorMessages.CommunicationDoesNotExist, communicationId));
+                return result;
+            }
+
+            _context.Communications.Remove(commmunication);
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<CommunicationPreviewDto>>> GetMyCommunications(int userId)
+        {
+            var result = new ServiceResult<List<CommunicationPreviewDto>>();
+            var user = await _context.Users.AsNoTracking().FirstOrDefaultAsync(x => x.Id == userId);
+
+            var courseIds = await _context.StudentCourses
+                .AsNoTracking()
+                .Where(x => x.StudentId == user.StudentId)
+                .Select(x => x.CourseId)
+                .ToListAsync();
+
+            var communications = await _context.Communications
+                .AsNoTracking()
+                .Include(x => x.Tenant)
+                .Include(x => x.Course)
+                .Where(x => (x.Tenant.Id == userId || courseIds.Contains(x.Course.Id))
+                    && x.ValidUntil >= DateTime.Now)
+                .ToListAsync();
+
+            result.Data = _mapper.Map<List<CommunicationPreviewDto>>(communications);
+
+            return result;
+        }
+
+        public async Task<ServiceResult<bool>> TenantValidation(int tenantId, int courseId)
+        {
+            var result = new ServiceResult<bool>();
+
+            var tenantAdmin = await _context.Tenants.AsNoTracking().FirstOrDefaultAsync(x => x.Name == TenantAdmin.Name);
+            var course = await _context.Courses.AsNoTracking().FirstOrDefaultAsync(x => x.Id == courseId);
+
+            if (tenantAdmin.Id != tenantId)
+            {
+                result.HasError = course.TenantId != tenantId;
+                result.AddMessage(string.Format(ErrorMessages.InvalidTenant, course.TenantId));
+            }
+
+            return result;
+        }
+
+        private async Task<ServiceResult<bool>> CreateValidation(int id, bool isGlobal, Communication commmunication)
+        {
+            var result = new ServiceResult<bool>();
+
+            if (isGlobal)
+            {
+                var tenant = await _context.Tenants.FirstOrDefaultAsync(x => x.Id == id && x.Name != TenantAdmin.Name);
+
+                if (tenant == null)
+                {
+                    result.HasError = true;
+                    result.AddMessage(string.Format(ErrorMessages.TenantDoesNotExist, id));
+                    return result;
+                }
+
+                commmunication.Tenant = tenant;
+            }
+            else
+            {
+                var course = await _context.Courses.FirstOrDefaultAsync(x => x.Id == id);
+
+                if (course == null)
+                {
+                    result.HasError = true;
+                    result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, id));
+                    return result;
+                }
+
+                commmunication.Course = course;
+            }           
+
+            return result;
+        }
+    }
+}
-- 
GitLab