196 lines
8.4 KiB
C#
196 lines
8.4 KiB
C#
using System.Data;
|
|
using Marco.Pms.DataAccess.Data;
|
|
using Marco.Pms.Model.Dtos.Mail;
|
|
using Marco.Pms.Model.Employees;
|
|
using Marco.Pms.Model.Mail;
|
|
using Marco.Pms.Model.Utilities;
|
|
using Marco.Pms.Services.Helpers;
|
|
using MarcoBMS.Services.Helpers;
|
|
using MarcoBMS.Services.Service;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using MongoDB.Driver;
|
|
|
|
namespace Marco.Pms.Services.Controllers
|
|
{
|
|
[Route("api/[controller]")]
|
|
[ApiController]
|
|
[Authorize]
|
|
public class ReportController : ControllerBase
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
private readonly IEmailSender _emailSender;
|
|
private readonly ILoggingService _logger;
|
|
private readonly UserHelper _userHelper;
|
|
private readonly IWebHostEnvironment _env;
|
|
private readonly ReportHelper _reportHelper;
|
|
public ReportController(ApplicationDbContext context, IEmailSender emailSender, ILoggingService logger, UserHelper userHelper, IWebHostEnvironment env, ReportHelper reportHelper)
|
|
{
|
|
_context = context;
|
|
_emailSender = emailSender;
|
|
_logger = logger;
|
|
_userHelper = userHelper;
|
|
_env = env;
|
|
_reportHelper = reportHelper;
|
|
}
|
|
|
|
[HttpPost("set-mail")]
|
|
public async Task<IActionResult> AddMailDetails([FromBody] MailDetailsDto mailDetailsDto)
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
MailDetails mailDetails = new MailDetails
|
|
{
|
|
ProjectId = mailDetailsDto.ProjectId,
|
|
Recipient = mailDetailsDto.Recipient,
|
|
Schedule = mailDetailsDto.Schedule,
|
|
MailListId = mailDetailsDto.MailListId,
|
|
TenantId = tenantId
|
|
};
|
|
_context.MailDetails.Add(mailDetails);
|
|
await _context.SaveChangesAsync();
|
|
return Ok("Success");
|
|
}
|
|
|
|
[HttpPost("mail-template")]
|
|
public async Task<IActionResult> AddMailTemplate([FromBody] MailTemeplateDto mailTemeplateDto)
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
if (string.IsNullOrWhiteSpace(mailTemeplateDto.Body) && string.IsNullOrWhiteSpace(mailTemeplateDto.Title))
|
|
{
|
|
_logger.LogWarning("User tries to set email template but send invalid data");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Provided Invalid data", "Provided Invalid data", 400));
|
|
}
|
|
var existngTemalate = await _context.MailingList.FirstOrDefaultAsync(t => t.Title.ToLower() == mailTemeplateDto.Title.ToLower());
|
|
if (existngTemalate != null)
|
|
{
|
|
_logger.LogWarning("User tries to set email template, but title already existed in database");
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Email title is already existed", "Email title is already existed", 400));
|
|
}
|
|
MailingList mailingList = new MailingList
|
|
{
|
|
Title = mailTemeplateDto.Title,
|
|
Body = mailTemeplateDto.Body,
|
|
Subject = mailTemeplateDto.Subject,
|
|
Keywords = mailTemeplateDto.Keywords,
|
|
TenantId = tenantId
|
|
};
|
|
_context.MailingList.Add(mailingList);
|
|
await _context.SaveChangesAsync();
|
|
return Ok("Success");
|
|
}
|
|
|
|
[HttpGet("project-statistics")]
|
|
public async Task<IActionResult> SendProjectReport()
|
|
{
|
|
Guid tenantId = _userHelper.GetTenantId();
|
|
|
|
// Use AsNoTracking() for read-only queries to improve performance
|
|
List<MailDetails> mailDetails = await _context.MailDetails
|
|
.AsNoTracking()
|
|
.Include(m => m.MailBody)
|
|
.Where(m => m.TenantId == tenantId)
|
|
.ToListAsync();
|
|
|
|
int successCount = 0;
|
|
int notFoundCount = 0;
|
|
int invalidIdCount = 0;
|
|
|
|
var groupedMails = mailDetails
|
|
.GroupBy(m => new { m.ProjectId, m.MailListId })
|
|
.Select(g => new
|
|
{
|
|
ProjectId = g.Key.ProjectId,
|
|
MailListId = g.Key.MailListId,
|
|
Recipients = g.Select(m => m.Recipient).Distinct().ToList(),
|
|
MailBody = g.FirstOrDefault()?.MailBody?.Body ?? "",
|
|
Subject = g.FirstOrDefault()?.MailBody?.Subject ?? string.Empty,
|
|
})
|
|
.ToList();
|
|
|
|
var semaphore = new SemaphoreSlim(1);
|
|
|
|
// Using Task.WhenAll to send reports concurrently for better performance
|
|
var sendTasks = groupedMails.Select(async mailDetail =>
|
|
{
|
|
await semaphore.WaitAsync();
|
|
try
|
|
{
|
|
var response = await GetProjectStatistics(mailDetail.ProjectId, mailDetail.Recipients, mailDetail.MailBody, mailDetail.Subject, tenantId);
|
|
if (response.StatusCode == 200)
|
|
Interlocked.Increment(ref successCount);
|
|
else if (response.StatusCode == 404)
|
|
Interlocked.Increment(ref notFoundCount);
|
|
else if (response.StatusCode == 400)
|
|
Interlocked.Increment(ref invalidIdCount);
|
|
}
|
|
finally
|
|
{
|
|
semaphore.Release();
|
|
}
|
|
}).ToList();
|
|
|
|
await Task.WhenAll(sendTasks);
|
|
//var response = await GetProjectStatistics(Guid.Parse("2618eb89-2823-11f0-9d9e-bc241163f504"), "ashutosh.nehete@marcoaiot.com", tenantId);
|
|
|
|
|
|
_logger.LogInfo(
|
|
"Emails of project reports sent for tenant {TenantId}. Successfully sent: {SuccessCount}, Projects not found: {NotFoundCount}, Invalid IDs: {InvalidIdsCount}",
|
|
tenantId, successCount, notFoundCount, invalidIdCount);
|
|
|
|
return Ok(ApiResponse<object>.SuccessResponse(
|
|
new { },
|
|
$"Reports sent successfully: {successCount}. Projects not found: {notFoundCount}. Invalid IDs: {invalidIdCount}.",
|
|
200));
|
|
}
|
|
/// <summary>
|
|
/// Retrieves project statistics for a given project ID and sends an email report.
|
|
/// </summary>
|
|
/// <param name="projectId">The ID of the project.</param>
|
|
/// <param name="recipientEmail">The email address of the recipient.</param>
|
|
/// <returns>An ApiResponse indicating the success or failure of retrieving statistics and sending the email.</returns>
|
|
private async Task<ApiResponse<object>> GetProjectStatistics(Guid projectId, List<string> recipientEmails, string body, string subject, Guid tenantId)
|
|
{
|
|
|
|
if (projectId == Guid.Empty)
|
|
{
|
|
_logger.LogError("Provided empty project ID while fetching project report.");
|
|
return ApiResponse<object>.ErrorResponse("Provided empty Project ID.", "Provided empty Project ID.", 400);
|
|
}
|
|
|
|
|
|
var statisticReport = await _reportHelper.GetDailyProjectReport(projectId, tenantId);
|
|
|
|
if (statisticReport == null)
|
|
{
|
|
_logger.LogWarning("User attempted to fetch project progress for project ID {ProjectId} but not found.", projectId);
|
|
return ApiResponse<object>.ErrorResponse("Project not found.", "Project not found.", 404);
|
|
}
|
|
|
|
// Send Email
|
|
var emailBody = await _emailSender.SendProjectStatisticsEmail(recipientEmails, body, subject, statisticReport);
|
|
var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Email != null && recipientEmails.Contains(e.Email)) ?? new Employee();
|
|
|
|
List<MailLog> mailLogs = new List<MailLog>();
|
|
foreach (var recipientEmail in recipientEmails)
|
|
{
|
|
mailLogs.Add(
|
|
new MailLog
|
|
{
|
|
ProjectId = projectId,
|
|
EmailId = recipientEmail,
|
|
Body = emailBody,
|
|
EmployeeId = employee.Id,
|
|
TimeStamp = DateTime.UtcNow,
|
|
TenantId = tenantId
|
|
});
|
|
}
|
|
|
|
_context.MailLogs.AddRange(mailLogs);
|
|
|
|
await _context.SaveChangesAsync();
|
|
return ApiResponse<object>.SuccessResponse(statisticReport, "Email sent successfully", 200);
|
|
}
|
|
}
|
|
}
|