Compare commits
80 Commits
f1a7394aa2
...
27a7044ede
| Author | SHA1 | Date | |
|---|---|---|---|
| 27a7044ede | |||
| c4a1c52acd | |||
| 80a22741b2 | |||
| 2ce81b8b9a | |||
| 13d8935b72 | |||
| 62f9b2256e | |||
| a9d20b8077 | |||
| 616cebbf94 | |||
|
|
8f267f9ef9 | ||
| afbfea3fc0 | |||
| ac7197c197 | |||
| 811e0ac807 | |||
| efc5e22f7b | |||
| d4b2d6025d | |||
| 999b2f06e0 | |||
| 13b93d5bd5 | |||
| 77a1cfd9dc | |||
| 5f90ddf454 | |||
| d014fcd1e4 | |||
| 50f698bf89 | |||
| 65a0e60c8a | |||
| a97b95eb00 | |||
| 57d430be1e | |||
| f50cb8e2dd | |||
| 2d939e5372 | |||
| c785b270f0 | |||
| b41640a120 | |||
| 5a487076ab | |||
|
|
9fa3351795 | ||
| 2d126bf5b9 | |||
| 53c210915a | |||
| aa60551524 | |||
| 34f32bdd33 | |||
|
|
e3e19a938a | ||
| c25a7c4b9c | |||
| a752bc39fe | |||
| 70ec3b6a44 | |||
| b381397e40 | |||
| 4492c60159 | |||
| 24968be0ff | |||
| 9af085c2fd | |||
| e76c203614 | |||
| 871493bf61 | |||
| 9d8ab76388 | |||
| f560a0207d | |||
| 10a68125ba | |||
| a005db4150 | |||
| 7a91db7ac1 | |||
| 4a33e54ebc | |||
| 5c5bf6b9e6 | |||
| a0b36b204e | |||
| 23db7c4861 | |||
| 4d1126b3f8 | |||
|
|
1a64879a05 | ||
| 0809d26517 | |||
| b4505827bb | |||
| cf9f6ce5a3 | |||
| 94434e8068 | |||
| 3e4f29b186 | |||
| c95a666c31 | |||
|
|
172aab1b01 | ||
| 57dbfab32f | |||
| 0f70263ecb | |||
| 1fccbb4e3a | |||
| 000cf74c1f | |||
| f30ae5ed5c | |||
| ad4b618bee | |||
| b05c3509ad | |||
| 235ca073ce | |||
| 276b253e2d | |||
| 7e70297e7c | |||
| 56aeceb1f9 | |||
| 40134d1f14 | |||
| 52ee06d47e | |||
| 7ddcc8cf13 | |||
| 6b33c4baf4 | |||
| 0414c2366e | |||
| 68c393c05d | |||
| 4e3d981beb | |||
| 7833d79541 |
9
Marco.Pms.Model/ViewModels/DashBoard/ActivityReport.cs
Normal file
9
Marco.Pms.Model/ViewModels/DashBoard/ActivityReport.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DashBoard
|
||||
{
|
||||
public class ActivityReport
|
||||
{
|
||||
public List<PerformedActivites>? PerformedActivites { get; set; }
|
||||
public double TotalPlannedWork { get; set; }
|
||||
public double TotalCompletedWork { get; set; }
|
||||
}
|
||||
}
|
||||
12
Marco.Pms.Model/ViewModels/DashBoard/EmployeeAttendanceVM.cs
Normal file
12
Marco.Pms.Model/ViewModels/DashBoard/EmployeeAttendanceVM.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DashBoard
|
||||
{
|
||||
public class EmployeeAttendanceVM
|
||||
{
|
||||
public string? FirstName { get; set; }
|
||||
public string? LastName { get; set; }
|
||||
public string? MiddleName { get; set; }
|
||||
public string? Comment { get; set; }
|
||||
public DateTime InTime { get; set; }
|
||||
public DateTime OutTime { get; set; }
|
||||
}
|
||||
}
|
||||
15
Marco.Pms.Model/ViewModels/DashBoard/PerformedActivites.cs
Normal file
15
Marco.Pms.Model/ViewModels/DashBoard/PerformedActivites.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DashBoard
|
||||
{
|
||||
public class PerformedActivites
|
||||
{
|
||||
public string? BuldingName { get; set; }
|
||||
public string? FloorName { get; set; }
|
||||
public string? WorkAreaName { get; set; }
|
||||
public string? ActivityName { get; set; }
|
||||
public string? Comment { get; set; }
|
||||
public double Pending { get; set; }
|
||||
public double AssignedToday { get; set; }
|
||||
public double CompletedToday { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DashBoard
|
||||
{
|
||||
public class ProjectAttendanceVM
|
||||
{
|
||||
public List<EmployeeAttendanceVM>? AttendanceTable { get; set; }
|
||||
public int CheckedInEmployee { get; set; }
|
||||
public int AssignedEmployee { get; set; }
|
||||
}
|
||||
}
|
||||
12
Marco.Pms.Model/ViewModels/Report/PerformedAttendance.cs
Normal file
12
Marco.Pms.Model/ViewModels/Report/PerformedAttendance.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Report
|
||||
{
|
||||
public class PerformedAttendance
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? RoleName { get; set; }
|
||||
public DateTime InTime { get; set; }
|
||||
public DateTime? OutTime { get; set; }
|
||||
public string? Comment { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
13
Marco.Pms.Model/ViewModels/Report/PerformedTask.cs
Normal file
13
Marco.Pms.Model/ViewModels/Report/PerformedTask.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Report
|
||||
{
|
||||
public class PerformedTask
|
||||
{
|
||||
public required string Activity { get; set; }
|
||||
public required string Location { get; set; }
|
||||
public double AssignedToday { get; set; }
|
||||
public double Pending { get; set; }
|
||||
public double CompletedToday { get; set; }
|
||||
public List<TaskTeam> Team { get; set; } = new List<TaskTeam>();
|
||||
public string? Comment { get; set; }
|
||||
}
|
||||
}
|
||||
26
Marco.Pms.Model/ViewModels/Report/ProjectStatisticReport.cs
Normal file
26
Marco.Pms.Model/ViewModels/Report/ProjectStatisticReport.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Report
|
||||
{
|
||||
public class ProjectStatisticReport
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public required string ProjectName { get; set; }
|
||||
public required string TimeStamp { get; set; }
|
||||
public int TodaysAttendances { get; set; }
|
||||
public int TotalEmployees { get; set; }
|
||||
public int RegularizationPending { get; set; }
|
||||
public int CheckoutPending { get; set; }
|
||||
public double TotalPlannedWork { get; set; }
|
||||
public double TotalCompletedWork { get; set; }
|
||||
public double TotalPlannedTask { get; set; }
|
||||
public double TotalCompletedTask { get; set; }
|
||||
public double CompletionStatus { get; set; }
|
||||
public int ReportPending { get; set; }
|
||||
public int TodaysAssignTasks { get; set; }
|
||||
public List<TeamOnSite> TeamOnSite { get; set; } = new List<TeamOnSite>();
|
||||
public List<PerformedTask> PerformedTasks { get; set; } = new List<PerformedTask>();
|
||||
public List<PerformedAttendance> PerformedAttendance { get; set; } = new List<PerformedAttendance>();
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
8
Marco.Pms.Model/ViewModels/Report/TaskTeam.cs
Normal file
8
Marco.Pms.Model/ViewModels/Report/TaskTeam.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Report
|
||||
{
|
||||
public class TaskTeam
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? RoleName { get; set; }
|
||||
}
|
||||
}
|
||||
8
Marco.Pms.Model/ViewModels/Report/TeamOnSite.cs
Normal file
8
Marco.Pms.Model/ViewModels/Report/TeamOnSite.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Report
|
||||
{
|
||||
public class TeamOnSite
|
||||
{
|
||||
public string? RoleName { get; set; }
|
||||
public int NumberofEmployees { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,12 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Activities;
|
||||
using Marco.Pms.Model.Dtos.Attendance;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.DashBoard;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -17,15 +20,19 @@ namespace Marco.Pms.Services.Controllers
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly UserHelper _userHelper;
|
||||
public DashboardController(ApplicationDbContext context, UserHelper userHelper)
|
||||
private readonly ILoggingService _logger;
|
||||
public DashboardController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger)
|
||||
{
|
||||
_context = context;
|
||||
_userHelper = userHelper;
|
||||
_logger = logger;
|
||||
}
|
||||
[HttpGet("progression")]
|
||||
public async Task<IActionResult> GetGraph([FromQuery] double days, [FromQuery] string FromDate, [FromQuery] Guid? projectId)
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
DateTime fromDate = new DateTime();
|
||||
DateTime toDate = new DateTime();
|
||||
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
|
||||
@ -78,6 +85,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
}
|
||||
flagDays -= 1;
|
||||
}
|
||||
_logger.LogInfo("Project Progression report for all projects fetched successfully by employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -125,6 +133,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
flagDays -= 1;
|
||||
}
|
||||
}
|
||||
_logger.LogInfo("Project Progression for project {ProjectId} fetched successfully by employee {EmployeeId}", projectId, LoggedInEmployee.Id);
|
||||
}
|
||||
}
|
||||
return Ok(ApiResponse<object>.SuccessResponse(projectProgressionVMs, "Success", 200));
|
||||
@ -134,6 +143,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
public async Task<IActionResult> GetProjectCount()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
var projects = await _context.Projects.Where(p => p.TenantId == tenantId).ToListAsync();
|
||||
var projectStatus = await _context.StatusMasters.Where(s => s.Status == "Active" || s.Status == "In Progress").ToListAsync();
|
||||
@ -145,6 +155,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
TotalProjects = projects.Count(),
|
||||
OngoingProjects = ongoingProjects.Count()
|
||||
};
|
||||
_logger.LogInfo("Number of total ongoing projects fetched by employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(projectDashboardVM, "Success", 200));
|
||||
}
|
||||
|
||||
@ -153,6 +164,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
public async Task<IActionResult> GetTotalEmployees()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var date = DateTime.UtcNow.Date;
|
||||
|
||||
var Employees = await _context.Employees.Where(e => e.TenantId == tenantId && e.IsActive == true).Select(e => e.Id).ToListAsync();
|
||||
@ -164,6 +176,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
TotalEmployees = Employees.Count(),
|
||||
InToday = checkedInEmployee.Distinct().Count()
|
||||
};
|
||||
_logger.LogInfo("Today's total checked in employees fetched by employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(teamDashboardVM, "Success", 200));
|
||||
}
|
||||
|
||||
@ -171,7 +184,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
public async Task<IActionResult> GetTotalTasks()
|
||||
{
|
||||
var tenantId = _userHelper.GetTenantId();
|
||||
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var Tasks = await _context.WorkItems.Where(t => t.TenantId == tenantId).Select(t => new { PlannedWork = t.PlannedWork, CompletedWork = t.CompletedWork }).ToListAsync();
|
||||
TasksDashboardVM tasksDashboardVM = new TasksDashboardVM
|
||||
{
|
||||
@ -183,8 +196,166 @@ namespace Marco.Pms.Services.Controllers
|
||||
tasksDashboardVM.TotalTasks += task.PlannedWork;
|
||||
tasksDashboardVM.CompletedTasks += task.CompletedWork;
|
||||
}
|
||||
|
||||
_logger.LogInfo("Total targeted tasks and total completed tasks fetched by employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(tasksDashboardVM, "Success", 200));
|
||||
}
|
||||
|
||||
[HttpGet("pending-attendance")]
|
||||
public async Task<IActionResult> GetPendingAttendance()
|
||||
{
|
||||
Guid tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
var attendance = await _context.Attendes.Where(a => a.EmployeeID == LoggedInEmployee.Id && a.TenantId == tenantId).ToListAsync();
|
||||
if (attendance.Any())
|
||||
{
|
||||
var pendingRegularization = attendance.Where(a => a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE).ToList().Count;
|
||||
var pendingCheckOut = attendance.Where(a => a.OutTime == null).ToList().Count;
|
||||
var response = new
|
||||
{
|
||||
PendingRegularization = pendingRegularization,
|
||||
PendingCheckOut = pendingCheckOut
|
||||
};
|
||||
_logger.LogInfo("Number of pending regularization and pending check-out are fetched successfully for employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Pending regularization and pending check-out are fetched successfully", 200));
|
||||
}
|
||||
_logger.LogError("No attendance entry was found for employee {EmployeeId}", LoggedInEmployee.Id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("No attendance entry was found for this employee", "No attendance entry was found for this employee", 404));
|
||||
}
|
||||
|
||||
[HttpGet("project-attdendance/{projectId}")]
|
||||
public async Task<IActionResult> GetProjectAttendance(Guid projectId, [FromQuery] string? date)
|
||||
{
|
||||
Guid tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
DateTime currentDate = DateTime.UtcNow;
|
||||
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
|
||||
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
||||
{
|
||||
_logger.LogError($"user send invalid date");
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
||||
|
||||
}
|
||||
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
||||
if (project == null)
|
||||
{
|
||||
_logger.LogError("Employee {EmployeeId} was attempted to get project attendance for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||
}
|
||||
List<ProjectAllocation>? projectAllocation = await _context.ProjectAllocations.Where(p => p.ProjectId == projectId && p.IsActive && p.TenantId == tenantId).ToListAsync();
|
||||
var employeeIds = projectAllocation.Select(p => p.EmployeeId).Distinct().ToList();
|
||||
List<Employee>? employees = await _context.Employees.Where(e => employeeIds.Contains(e.Id)).ToListAsync();
|
||||
|
||||
var attendances = await _context.Attendes.Where(a => employeeIds.Contains(a.EmployeeID) && a.ProjectID == projectId && a.InTime.HasValue && a.InTime.Value.Date == currentDate.Date).ToListAsync();
|
||||
List<EmployeeAttendanceVM> employeeAttendanceVMs = new List<EmployeeAttendanceVM>();
|
||||
foreach (var attendance in attendances)
|
||||
{
|
||||
|
||||
Employee? employee = employees.FirstOrDefault(e => e.Id == attendance.EmployeeID);
|
||||
if (employee != null)
|
||||
{
|
||||
EmployeeAttendanceVM employeeAttendanceVM = new EmployeeAttendanceVM
|
||||
{
|
||||
FirstName = employee.FirstName,
|
||||
LastName = employee.LastName,
|
||||
MiddleName = employee.MiddleName,
|
||||
Comment = attendance.Comment,
|
||||
InTime = attendance.InTime ?? DateTime.UtcNow,
|
||||
OutTime = attendance.OutTime ?? DateTime.UtcNow
|
||||
};
|
||||
|
||||
employeeAttendanceVMs.Add(employeeAttendanceVM);
|
||||
}
|
||||
}
|
||||
ProjectAttendanceVM projectAttendanceVM = new ProjectAttendanceVM();
|
||||
projectAttendanceVM.AttendanceTable = employeeAttendanceVMs;
|
||||
projectAttendanceVM.CheckedInEmployee = attendances.Count;
|
||||
projectAttendanceVM.AssignedEmployee = employeeIds.Count;
|
||||
|
||||
_logger.LogInfo($"Attendance record for project {projectId} for date {currentDate.Date} by employee {LoggedInEmployee.Id}");
|
||||
return Ok(ApiResponse<object>.SuccessResponse(projectAttendanceVM, $"Attendance record for project {project.Name} for date {currentDate.Date}", 200));
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("activities/{projectId}")]
|
||||
public async Task<IActionResult> GetActivities(Guid projectId, [FromQuery] string? date)
|
||||
{
|
||||
Guid tenantId = _userHelper.GetTenantId();
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
DateTime currentDate = DateTime.UtcNow;
|
||||
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
|
||||
if (date != null && DateTime.TryParse(date, out currentDate) == false)
|
||||
{
|
||||
_logger.LogError($"user send invalid date");
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
|
||||
|
||||
}
|
||||
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
|
||||
if (project == null)
|
||||
{
|
||||
_logger.LogError("Employee {EmployeeId} was attempted to get activities performed for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||
}
|
||||
|
||||
var buildings = await _context.Buildings.Where(b => b.ProjectId == project.Id).ToListAsync();
|
||||
var buildingIds = buildings.Select(b => b.Id).Distinct().ToList();
|
||||
|
||||
var floors = await _context.Floor.Where(f => buildingIds.Contains(f.BuildingId)).ToListAsync();
|
||||
var floorIds = floors.Select(f => f.Id).Distinct().ToList();
|
||||
|
||||
var areas = await _context.WorkAreas.Where(a => floorIds.Contains(a.FloorId)).ToListAsync();
|
||||
var areaIds = areas.Select(a => a.Id).Distinct().ToList();
|
||||
|
||||
var workItems = await _context.WorkItems.Include(i => i.ActivityMaster).Where(i => areaIds.Contains(i.WorkAreaId)).ToListAsync();
|
||||
var itemIds = workItems.Select(i => i.Id).Distinct().ToList();
|
||||
|
||||
var tasks = await _context.TaskAllocations.Where(t => itemIds.Contains(t.WorkItemId) && t.AssignmentDate.Date == currentDate.Date).ToListAsync();
|
||||
double totalPlannedTask = 0;
|
||||
double totalCompletedTask = 0;
|
||||
List<PerformedActivites> performedActivites = new List<PerformedActivites>();
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
totalPlannedTask += task.PlannedTask;
|
||||
totalCompletedTask += task.CompletedTask;
|
||||
|
||||
WorkItem workItem = workItems.FirstOrDefault(i => i.Id == task.WorkItemId) ?? new WorkItem();
|
||||
string activityName = (workItem.ActivityMaster != null ? workItem.ActivityMaster.ActivityName : "") ?? "";
|
||||
|
||||
WorkArea workArea = areas.FirstOrDefault(a => a.Id == workItem.WorkAreaId) ?? new WorkArea();
|
||||
string areaName = workArea.AreaName ?? "";
|
||||
|
||||
Floor floor = floors.FirstOrDefault(f => f.Id == workArea.FloorId) ?? new Floor();
|
||||
string floorName = floor.FloorName ?? "";
|
||||
|
||||
Building building = buildings.FirstOrDefault(b => b.Id == floor.BuildingId) ?? new Building();
|
||||
string buildingName = building.Name ?? "";
|
||||
|
||||
double pending = workItem.PlannedWork - workItem.CompletedWork;
|
||||
|
||||
PerformedActivites performedTask = new PerformedActivites
|
||||
{
|
||||
ActivityName = activityName,
|
||||
BuldingName = buildingName,
|
||||
FloorName = floorName,
|
||||
WorkAreaName = areaName,
|
||||
AssignedToday = task.PlannedTask,
|
||||
Pending = pending,
|
||||
CompletedToday = task.CompletedTask,
|
||||
Comment = task.Description
|
||||
};
|
||||
performedActivites.Add(performedTask);
|
||||
}
|
||||
ActivityReport report = new ActivityReport
|
||||
{
|
||||
PerformedActivites = performedActivites,
|
||||
TotalCompletedWork = totalCompletedTask,
|
||||
TotalPlannedWork = totalPlannedTask
|
||||
};
|
||||
_logger.LogInfo($"Record of performed activities for project {projectId} for date {currentDate.Date} by employee {LoggedInEmployee.Id}");
|
||||
return Ok(ApiResponse<object>.SuccessResponse(report, $"Record of performed activities for project {project.Name} for date {currentDate.Date}", 200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
if (industry != null && industry.Name != null)
|
||||
{
|
||||
InquiryEmailObject inquiryEmailObject = inquiryDto.ToInquiryEmailObjectFromInquiriesDto(industry.Name);
|
||||
string emails = _configuration["Contact:Emails"] ?? "";
|
||||
string emails = _configuration["MailingList:RequestDemoReceivers"] ?? "";
|
||||
List<string> result = emails
|
||||
.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(item => item.Trim())
|
||||
|
||||
218
Marco.Pms.Services/Controllers/ReportController.cs
Normal file
218
Marco.Pms.Services/Controllers/ReportController.cs
Normal file
@ -0,0 +1,218 @@
|
||||
using System.Globalization;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Dtos.Attendance;
|
||||
using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.Roles;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Report;
|
||||
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 IConfiguration _configuration;
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly UserHelper _userHelper;
|
||||
public ReportController(ApplicationDbContext context, IEmailSender emailSender, IConfiguration configuration, ILoggingService logger, UserHelper userHelper)
|
||||
{
|
||||
_context = context;
|
||||
_emailSender = emailSender;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_userHelper = userHelper;
|
||||
}
|
||||
|
||||
[HttpGet("project-statistics/{id}")]
|
||||
public async Task<IActionResult> GetProjectStatistics(Guid id, [FromQuery] string? date)
|
||||
{
|
||||
DateTime reportDate = DateTime.UtcNow;
|
||||
if (date != null && DateTime.TryParse(date, out reportDate) == false)
|
||||
{
|
||||
_logger.LogError("User sent Invalid from Date while featching project report");
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
||||
}
|
||||
if (id == Guid.Empty)
|
||||
{
|
||||
_logger.LogError("Provided empty project ID while fetching project report");
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Provided empty ProjectID", "Provided empty ProjectID", 400));
|
||||
}
|
||||
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == id);
|
||||
if (project == null)
|
||||
{
|
||||
_logger.LogWarning("User attempted to fetch project progress of project ID {ProjectId} but not found in database", id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
|
||||
}
|
||||
ProjectStatisticReport statisticReport = new ProjectStatisticReport
|
||||
{
|
||||
Date = reportDate,
|
||||
ProjectName = project.Name ?? "",
|
||||
TimeStamp = DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture)
|
||||
};
|
||||
var projectAllocations = await _context.ProjectAllocations.Include(p => p.Employee).Where(p => p.ProjectId == project.Id && p.IsActive).ToListAsync();
|
||||
var assignedEmployeeIds = projectAllocations.Select(p => p.EmployeeId).ToList();
|
||||
var attendances = await _context.Attendes.AsNoTracking().Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date).ToListAsync();
|
||||
var checkedInEmployeeIds = attendances.Select(p => p.EmployeeID).Distinct().ToList();
|
||||
var checkedOutPendingEmployeeIds = attendances.Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date && a.OutTime == null).Select(p => p.EmployeeID).Distinct().ToList();
|
||||
var regularizationEmployeeIds = attendances.Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date && a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE).Select(p => p.EmployeeID).Distinct().ToList();
|
||||
|
||||
var buildings = await _context.Buildings.Where(b => b.ProjectId == project.Id).ToListAsync();
|
||||
var buildingIds = buildings.Select(b => b.Id).Distinct().ToList();
|
||||
|
||||
var floors = await _context.Floor.Where(f => buildingIds.Contains(f.BuildingId)).ToListAsync();
|
||||
var floorIds = floors.Select(f => f.Id).Distinct().ToList();
|
||||
|
||||
var areas = await _context.WorkAreas.Where(a => floorIds.Contains(a.FloorId)).ToListAsync();
|
||||
var areaIds = areas.Select(a => a.Id).Distinct().ToList();
|
||||
|
||||
var workItems = await _context.WorkItems.Include(i => i.ActivityMaster).Where(i => areaIds.Contains(i.WorkAreaId)).ToListAsync();
|
||||
var itemIds = workItems.Select(i => i.Id).Distinct().ToList();
|
||||
|
||||
var tasks = await _context.TaskAllocations.Where(t => itemIds.Contains(t.WorkItemId)).ToListAsync();
|
||||
var taskIds = tasks.Select(t => t.Id).Distinct().ToList();
|
||||
|
||||
var taskMembers = await _context.TaskMembers.Include(m => m.Employee).Where(m => taskIds.Contains(m.TaskAllocationId)).ToListAsync();
|
||||
|
||||
double totalPlannedWork = 0;
|
||||
double totalCompletedWork = 0;
|
||||
foreach (var items in workItems)
|
||||
{
|
||||
totalPlannedWork += items.PlannedWork;
|
||||
totalCompletedWork += items.CompletedWork;
|
||||
}
|
||||
|
||||
var todayAssigned = tasks.Where(t => t.AssignmentDate.Date == reportDate.Date).ToList();
|
||||
var reportPending = tasks.Where(t => t.ReportedDate == null).ToList();
|
||||
|
||||
double totalPlannedTask = 0;
|
||||
double totalCompletedTask = 0;
|
||||
foreach (var items in todayAssigned)
|
||||
{
|
||||
totalPlannedTask += items.PlannedTask;
|
||||
totalCompletedTask += items.CompletedTask;
|
||||
}
|
||||
|
||||
var jobRoles = await _context.JobRoles.Where(r => r.TenantId == project.TenantId).ToListAsync();
|
||||
List<TeamOnSite> teamOnSite = new List<TeamOnSite>();
|
||||
foreach (var role in jobRoles)
|
||||
{
|
||||
int numberOfEmployees = 0;
|
||||
var roleassigned = projectAllocations.Where(p => p.JobRoleId == role.Id && checkedInEmployeeIds.Contains(p.EmployeeId)).ToList();
|
||||
if (roleassigned.Count > 0)
|
||||
{
|
||||
numberOfEmployees = roleassigned.Count;
|
||||
}
|
||||
TeamOnSite team = new TeamOnSite
|
||||
{
|
||||
RoleName = role.Name,
|
||||
NumberofEmployees = numberOfEmployees,
|
||||
};
|
||||
teamOnSite.Add(team);
|
||||
}
|
||||
List<PerformedTask> performedTasks = new List<PerformedTask>();
|
||||
var todaysTask = tasks.Where(t => t.AssignmentDate.Date == reportDate.Date).ToList();
|
||||
foreach (var task in todaysTask)
|
||||
{
|
||||
WorkItem workItem = workItems.FirstOrDefault(i => i.Id == task.WorkItemId) ?? new WorkItem();
|
||||
string activityName = (workItem.ActivityMaster != null ? workItem.ActivityMaster.ActivityName : "") ?? "";
|
||||
|
||||
WorkArea workArea = areas.FirstOrDefault(a => a.Id == workItem.WorkAreaId) ?? new WorkArea();
|
||||
string areaName = workArea.AreaName ?? "";
|
||||
|
||||
Floor floor = floors.FirstOrDefault(f => f.Id == workArea.FloorId) ?? new Floor();
|
||||
string floorName = floor.FloorName ?? "";
|
||||
|
||||
Building building = buildings.FirstOrDefault(b => b.Id == floor.BuildingId) ?? new Building();
|
||||
string buildingName = building.Name ?? "";
|
||||
|
||||
string location = $"{buildingName} > {floorName} </span><br/><span style=\"color: gray; font-size: small; padding-left: 10px;\"> {floorName}-{areaName}";
|
||||
double pending = workItem.PlannedWork - workItem.CompletedWork;
|
||||
PerformedTask performedTask = new PerformedTask
|
||||
{
|
||||
Activity = activityName,
|
||||
Location = location,
|
||||
AssignedToday = task.PlannedTask,
|
||||
Pending = pending,
|
||||
CompletedToday = task.CompletedTask,
|
||||
Comment = task.Description
|
||||
};
|
||||
|
||||
var taskTeams = taskMembers.Where(m => m.TaskAllocationId == task.Id).ToList();
|
||||
List<TaskTeam> Team = new List<TaskTeam>();
|
||||
foreach (var team in taskTeams)
|
||||
{
|
||||
string firstName = (team.Employee != null ? team.Employee.FirstName : "") ?? "";
|
||||
string lastName = (team.Employee != null ? team.Employee.LastName : "") ?? "";
|
||||
string name = $"{firstName} {lastName}";
|
||||
|
||||
JobRole role = jobRoles.FirstOrDefault(r => r.Id == (team.Employee != null ? team.Employee.JobRoleId : Guid.Empty)) ?? new JobRole();
|
||||
string roleName = role.Name ?? "";
|
||||
|
||||
TaskTeam taskTeam = new TaskTeam
|
||||
{
|
||||
Name = name,
|
||||
RoleName = roleName,
|
||||
};
|
||||
Team.Add(taskTeam);
|
||||
}
|
||||
performedTask.Team = Team;
|
||||
performedTasks.Add(performedTask);
|
||||
}
|
||||
|
||||
List<PerformedAttendance> performedAttendances = new List<PerformedAttendance>();
|
||||
foreach (var attendance in attendances)
|
||||
{
|
||||
ProjectAllocation projectAllocation = projectAllocations.FirstOrDefault(p => p.EmployeeId == attendance.EmployeeID) ?? new ProjectAllocation();
|
||||
JobRole role = jobRoles.FirstOrDefault(r => r.Id == projectAllocation.JobRoleId) ?? new JobRole();
|
||||
|
||||
string firstName = (projectAllocation.Employee != null ? projectAllocation.Employee.FirstName : "") ?? "";
|
||||
string lastName = (projectAllocation.Employee != null ? projectAllocation.Employee.LastName : "") ?? "";
|
||||
string name = $"{firstName} {lastName}";
|
||||
PerformedAttendance performedAttendance = new PerformedAttendance
|
||||
{
|
||||
Name = name,
|
||||
RoleName = role.Name ?? "",
|
||||
InTime = attendance.InTime ?? DateTime.UtcNow,
|
||||
OutTime = attendance.OutTime,
|
||||
Comment = attendance.Comment
|
||||
};
|
||||
performedAttendances.Add(performedAttendance);
|
||||
}
|
||||
|
||||
statisticReport.TodaysAttendances = checkedInEmployeeIds.Count;
|
||||
statisticReport.TotalEmployees = assignedEmployeeIds.Count;
|
||||
statisticReport.RegularizationPending = regularizationEmployeeIds.Count;
|
||||
statisticReport.CheckoutPending = checkedOutPendingEmployeeIds.Count;
|
||||
statisticReport.TotalPlannedWork = totalPlannedWork;
|
||||
statisticReport.TotalCompletedWork = totalCompletedWork;
|
||||
statisticReport.TotalPlannedTask = totalPlannedTask;
|
||||
statisticReport.TotalCompletedTask = totalCompletedTask;
|
||||
statisticReport.CompletionStatus = totalCompletedWork / totalPlannedWork;
|
||||
statisticReport.TodaysAssignTasks = todayAssigned.Count;
|
||||
statisticReport.ReportPending = reportPending.Count;
|
||||
statisticReport.TeamOnSite = teamOnSite.OrderByDescending(c => c.NumberofEmployees).ToList();
|
||||
statisticReport.PerformedTasks = performedTasks;
|
||||
statisticReport.PerformedAttendance = performedAttendances;
|
||||
|
||||
string emails = _configuration["MailingList:ProjectStatisticsReceivers"] ?? "";
|
||||
List<string> result = emails
|
||||
.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(item => item.Trim())
|
||||
.ToList();
|
||||
await _emailSender.SendProjectStatisticsEmail(result, statisticReport);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Email sent successfully", 200));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
870
Marco.Pms.Services/EmailTemplates/project-report.html
Normal file
870
Marco.Pms.Services/EmailTemplates/project-report.html
Normal file
@ -0,0 +1,870 @@
|
||||
<!DOCTYPE HTML
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
|
||||
xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
|
||||
<head>
|
||||
<!--[if gte mso 9]>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
<![endif]-->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<!--[if !mso]><!-->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]-->
|
||||
<title></title>
|
||||
|
||||
<style type="text/css">
|
||||
@media only screen and (min-width: 620px) {
|
||||
.u-row {
|
||||
width: 95% !important;
|
||||
}
|
||||
|
||||
.u-row .u-col {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
||||
.u-row .u-col-50 {
|
||||
width: 300px !important;
|
||||
}
|
||||
|
||||
|
||||
.u-row .u-col-100 {
|
||||
width: 95% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 620px) {
|
||||
.u-row-container {
|
||||
max-width: 100% !important;
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
|
||||
.u-row {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.u-row .u-col {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
max-width: 95% !important;
|
||||
}
|
||||
|
||||
.u-row .u-col > div {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
.u-row .u-col img {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
table,
|
||||
td,
|
||||
tr {
|
||||
border-collapse: collapse;
|
||||
vertical-align: top
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.ie-container table,
|
||||
.mso-container table {
|
||||
table-layout: fixed
|
||||
}
|
||||
|
||||
* {
|
||||
line-height: inherit
|
||||
}
|
||||
|
||||
a[x-apple-data-detectors=true] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important
|
||||
}
|
||||
|
||||
|
||||
table,
|
||||
td {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#u_body a {
|
||||
color: #e93f32;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 450px) {
|
||||
.column {
|
||||
width: 100% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 450px) and (max-width: 760px) {
|
||||
.column {
|
||||
width: 45% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 760px) {
|
||||
.column {
|
||||
width: 30% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 420px) {
|
||||
.team {
|
||||
width: 45% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 420px) and (max-width: 760px) {
|
||||
.team {
|
||||
width: 30% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 760px) {
|
||||
.team {
|
||||
width: 16% !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!--[if !mso]><!-->
|
||||
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css"><!--<![endif]-->
|
||||
|
||||
</head>
|
||||
|
||||
<body class="clean-body u_body"
|
||||
style="margin: 0;padding: 0;-webkit-text-size-adjust: 100%;background-color: #f9f9f9;color: #000000">
|
||||
<!--[if IE]><div class="ie-container"><![endif]-->
|
||||
<!--[if mso]><div class="mso-container"><![endif]-->
|
||||
<table id="u_body"
|
||||
style="border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;min-width: 320px;Margin: 0 auto;background-color: #f9f9f9;width:100%"
|
||||
cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color: #f9f9f9;"><![endif]-->
|
||||
<!--<div>Top Spacing</div>-->
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: #f9f9f9">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto;min-width: 320px;max-width: 95%;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: #f9f9f9;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: #f9f9f9;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #f9f9f9;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:15px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<table height="0px" align="center" border="0"
|
||||
cellpadding="0" cellspacing="0" width="100%"
|
||||
style="border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;border-top: 1px solid #f9f9f9;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td style="word-break: break-word;border-collapse: collapse !important;vertical-align: top;font-size: 0px;line-height: 0px;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%">
|
||||
Sita
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!--<div>Logo Block</div>-->
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: transparent">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto;min-width: 320px;max-width: 95%;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: #ffffff;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #ffffff;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:25px 10px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0"
|
||||
border="0">
|
||||
<tr>
|
||||
<td style="padding-right: 0px;padding-left: 0px;"
|
||||
align="center">
|
||||
|
||||
<img border="0"
|
||||
src="https://stageapi.marcoaiot.com/logos/marco-aiot-tech-logo.jpg"
|
||||
alt="Image" title="Image"
|
||||
style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: inline-block !important;border: none;height: auto;float: none;width: 29%;max-width: 168.2px;"
|
||||
width="168" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--<div>Title Block</div>-->
|
||||
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: transparent">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto; min-width: 320px; max-width: 95%; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #f46b61;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #e93f32;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:35px 10px 10px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0"
|
||||
border="0">
|
||||
<tr>
|
||||
<td style="padding-right: 0px;padding-left: 0px;"
|
||||
align="center">
|
||||
|
||||
<img border="0"
|
||||
src="https://cdn.templates.unlayer.com/assets/1593141680866-reset.png"
|
||||
alt="Image" title="Image"
|
||||
style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: inline-block !important;border: none;height: auto;float: none;width: 10%;max-width: 58px;"
|
||||
width="58" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px 10px 30px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: left; word-wrap: break-word;">
|
||||
<p style="font-size: 14px; line-height: 140%; text-align: center;">
|
||||
<span style="font-size: 18px; line-height: 39.2px; color: #ffffff; font-family: Lato, sans-serif;">
|
||||
Daily
|
||||
Progress Report - {{DATE}}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<!--<p style="font-size: 14px; line-height: 140%; text-align: center;"><span style="font-size: 28px; line-height: 39.2px; color: #ffffff; font-family: Lato, sans-serif;">{{PROJECT_NAME}} </span></p>.-->
|
||||
<p style="font-size: 14px; line-height: 140%; text-align: center;">
|
||||
<span style="font-size: 28px; line-height: 39.2px; color: #ffffff; font-family: Lato, sans-serif;">
|
||||
Raja
|
||||
{{PROJECT_NAME}}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--<div>Mail Body</div>-->
|
||||
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: transparent">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto;min-width: 320px;max-width: 95%;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: #ffffff;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #ffffff;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:40px 10px 30px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: center; word-wrap: break-word;">
|
||||
<span style="font-size: 18px; line-height: 25.2px; color: #666666;">
|
||||
Project Status Reported - Generated at {{TIMESTAMP}}
|
||||
</span>
|
||||
<table cellpadding="1" cellspacing="0" width="100%"
|
||||
border="0" style="margin-top: 15px">
|
||||
<tr style="vertical-align:middle">
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 135px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Todays Attendane
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803;margin:20px 20px 0px!important; font-weight:bold; ">
|
||||
{{TODAYS_ATTENDANCES}} /
|
||||
{{TOTAL_EMPLOYEES}}
|
||||
</div>
|
||||
<span style="font-size: 10px; color: #0984e3; font-weight: bold;">
|
||||
Checked-in / Assigned
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 135px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Daily Tasks Completed
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803; margin: 20px 20px 0px !important; font-weight: bold;">
|
||||
{{TODAYS_COMPLETED}} /
|
||||
{{TODAYS_PLANNED}}
|
||||
</div>
|
||||
<span style="font-size: 10px; color: #0984e3; font-weight: bold;">
|
||||
Today's Completed Task / Today's Planned Task
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 135px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Project Completion Status
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803; margin: 20px 20px 0px !important; font-weight: bold; ">
|
||||
{{TOTAL_COMPLETED}} /
|
||||
{{TOTAL_PLANNED}}
|
||||
<div style="padding-top: 5px;"> ({{PROJECT_STATUS}})</div>
|
||||
</div>
|
||||
<span style="font-size: 10px; color: #0984e3; font-weight: bold;">
|
||||
Total Completed Task / Total Planned Task
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align:middle">
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 100px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Regularization Pending
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803; margin: 20px 20px 0px !important; font-weight: bold;">
|
||||
{{REGULRIZATION_PENDING}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 100px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Checkout Pending
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803; margin: 20px 20px 0px !important; font-weight: bold;">
|
||||
{{CHECKOUT_PRNDING}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="column" style="text-align:center">
|
||||
<div style="border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px; height: 100px !important">
|
||||
<div style="font-size: 18px; color: #525b75 ">
|
||||
Activity Report Pending
|
||||
</div>
|
||||
<div style="font-size: 25px; color: #bc3803; margin: 20px 20px 0px !important; font-weight: bold;">
|
||||
{{REPORT_PENDING}} /
|
||||
{{TODAYS_ASSIGNED}}
|
||||
</div>
|
||||
<span style="font-size: 10px; color: #0984e3; font-weight: bold;">
|
||||
Total Pending Report / Today's' Assigned Task
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px 1px 30px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: center; word-wrap: break-word;">
|
||||
<span style="font-size: 18px; line-height: 25.2px; color: #666666;">
|
||||
Team
|
||||
Available On Site Today
|
||||
</span>
|
||||
<table cellpadding="1" cellspacing="0" width="100%"
|
||||
border="0">
|
||||
{{TEAM_ON_SITE}}
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px 10px 30px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: center; word-wrap: break-word;">
|
||||
<span style="font-size: 18px; line-height: 25.2px; color: #666666;margin:10px">
|
||||
Activities
|
||||
(Tasks) Performed Today
|
||||
</span> <br />
|
||||
|
||||
<table cellpadding="1" cellspacing="0" width="100%"
|
||||
border="1">
|
||||
<tr style="vertical-align:middle">
|
||||
<th style="text-align:center">
|
||||
Activity/ <br />
|
||||
Location
|
||||
</th>
|
||||
<th style="text-align:center">
|
||||
Assigned
|
||||
Today/<br /> Pending
|
||||
</th>
|
||||
<th style="text-align:center">
|
||||
Completed Today
|
||||
</th>
|
||||
<th style="text-align:center">Date </th>
|
||||
<th style="text-align:center">Team Members</th>
|
||||
<th style="text-align:center">Comment</th>
|
||||
</tr>
|
||||
<tr></tr>
|
||||
{{PERFORMED_TASK}}
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:0px 10px 30px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: center; word-wrap: break-word;">
|
||||
<span style="font-size: 18px; line-height: 25.2px; color: #666666;margin:10px">
|
||||
Attendance
|
||||
Performed Today
|
||||
</span> <br />
|
||||
|
||||
<table cellpadding="1" cellspacing="0" width="100%"
|
||||
border="1">
|
||||
<tr style="vertical-align:middle">
|
||||
<th style="text-align:center">Name</th>
|
||||
<th style="text-align:center">Job Role</th>
|
||||
<th style="text-align:center">Check In</th>
|
||||
<th style="text-align:center">Check Out </th>
|
||||
<th style="text-align:center">Comment</th>
|
||||
</tr>
|
||||
<tr></tr>
|
||||
{{PERFORMED_ATTENDANCE}}
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--<div>Contact</div>-->
|
||||
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: transparent">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto;min-width: 320px;max-width: 95%;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: #e93f32;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #e93f32;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="300" style="width: 300px;padding: 20px 20px 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-50"
|
||||
style="max-width: 320px;min-width: 300px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 20px 0px 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:10px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: left; word-wrap: break-word;">
|
||||
<!--<p style="font-size: 14px; line-height: 140%;"><span style="font-size: 16px; line-height: 22.4px; color: #ecf0f1;">Contact</span></p>-->
|
||||
<!--<p style="font-size: 14px; line-height: 140%;"><span style="font-size: 14px; line-height: 19.6px; color: #ecf0f1;">2nd Floor, Fullora Building, Tejas CHS, Dahanukar Colony, Kothrud, Pune (INDIA) - 411038</span></p>-->
|
||||
<p style="font-size: 14px; line-height: 140%;">
|
||||
<span style="font-size: 14px; line-height: 19.6px; color: #ecf0f1;">
|
||||
Contact
|
||||
Us: <a href="mailto:info@marcoaiot.com"
|
||||
style="color:#ffff"
|
||||
target="_blank">info@marcoaiot.com</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="300" style="width: 300px;padding: 0px 0px 0px 20px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-50"
|
||||
style="max-width: 320px;min-width: 300px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px 0px 0px 20px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:25px 10px 10px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div align="right" style="direction: ltr;">
|
||||
<div style="display: table; max-width:187px;">
|
||||
<!--[if (mso)|(IE)]><table width="187" cellpadding="0" cellspacing="0" border="0"><tr><td style="border-collapse:collapse;" align="left"><table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse; mso-table-lspace: 0pt;mso-table-rspace: 0pt; width:187px;"><tr><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td width="32" style="width:32px; padding-right: 15px;" valign="top"><![endif]-->
|
||||
<table border="0" cellspacing="0" cellpadding="0"
|
||||
width="32" height="32"
|
||||
style="width: 32px !important;height: 32px !important;display: inline-block;border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;margin-right: 15px">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td valign="middle"
|
||||
style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
|
||||
<a href=" " title="Facebook"
|
||||
target="_blank">
|
||||
<img src="https://cdn.tools.unlayer.com/social/icons/circle-white/facebook.png"
|
||||
alt="Facebook"
|
||||
title="Facebook" width="32"
|
||||
style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: block !important;border: none;height: auto;float: none;max-width: 32px !important">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td width="32" style="width:32px; padding-right: 15px;" valign="top"><![endif]-->
|
||||
<table border="0" cellspacing="0" cellpadding="0"
|
||||
width="32" height="32"
|
||||
style="width: 32px !important;height: 32px !important;display: inline-block;border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;margin-right: 15px">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td valign="middle"
|
||||
style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
|
||||
<a href="https://x.com/marcoaiot"
|
||||
title="X" target="_blank">
|
||||
<img src="https://cdn.tools.unlayer.com/social/icons/circle-white/x.png"
|
||||
alt="Twitter"
|
||||
title="Twitter" width="32"
|
||||
style="color:#000;outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: block !important;border: none;height: auto;float: none;max-width: 32px !important">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td width="32" style="width:32px; padding-right: 15px;" valign="top"><![endif]-->
|
||||
<table border="0" cellspacing="0" cellpadding="0"
|
||||
width="32" height="32"
|
||||
style="width: 32px !important;height: 32px !important;display: inline-block;border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;margin-right: 15px">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td valign="middle"
|
||||
style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
|
||||
<a href=" " title="Instagram"
|
||||
target="_blank">
|
||||
<img src="https://cdn.tools.unlayer.com/social/icons/circle-white/instagram.png"
|
||||
alt="Instagram"
|
||||
title="Instagram" width="32"
|
||||
style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: block !important;border: none;height: auto;float: none;max-width: 32px !important">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td width="32" style="width:32px; padding-right: 0px;" valign="top"><![endif]-->
|
||||
<table border="0" cellspacing="0" cellpadding="0"
|
||||
width="32" height="32"
|
||||
style="width: 32px !important;height: 32px !important;display: inline-block;border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;margin-right: 0px">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td valign="middle"
|
||||
style="word-break: break-word;border-collapse: collapse !important;vertical-align: top">
|
||||
<a href=" " title="LinkedIn"
|
||||
target="_blank">
|
||||
<img src="https://cdn.tools.unlayer.com/social/icons/circle-white/linkedin.png"
|
||||
alt="LinkedIn"
|
||||
title="LinkedIn" width="32"
|
||||
style="outline: none;text-decoration: none;-ms-interpolation-mode: bicubic;clear: both;display: block !important;border: none;height: auto;float: none;max-width: 32px !important">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--<table style="font-family:'Lato',sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:5px 10px 10px;font-family:'Lato',sans-serif;" align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: left; word-wrap: break-word;">
|
||||
<p style="line-height: 140%; font-size: 14px;"><span style="font-size: 14px; line-height: 19.6px;"><span style="color: #ecf0f1; font-size: 14px; line-height: 19.6px;"><span style="line-height: 19.6px; font-size: 14px;">Marco AIoT Technologies Pvt. Ltd. © All Rights Reserved</span></span></span></p>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>-->
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!--<div>Bottom Spacing - light red</div>-->
|
||||
|
||||
<div class="u-row-container" style="padding: 0px;background-color: #f9f9f9">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto; min-width: 320px; max-width: 95%; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: #f46b61;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: #f9f9f9;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #e93f32;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:15px;font-family:'Lato',sans-serif;"
|
||||
align="center">
|
||||
<p style="line-height: 140%; font-size: 14px;">
|
||||
<span style="font-size: 14px; line-height: 19.6px;">
|
||||
<span style="color: #ecf0f1; font-size: 14px; line-height: 19.6px;">
|
||||
<span style="line-height: 19.6px; font-size: 14px;">
|
||||
Marco
|
||||
AIoT
|
||||
Technologies Pvt. Ltd. © All
|
||||
Rights
|
||||
Reserved
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<!--<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;table-layout: fixed;border-spacing: 0;mso-table-lspace: 0pt;mso-table-rspace: 0pt;vertical-align: top;border-top: 1px solid #e93f32;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%">
|
||||
<tbody>
|
||||
<tr style="vertical-align: top">
|
||||
<td style="word-break: break-word;border-collapse: collapse !important;vertical-align: top;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>-->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="u-row-container" style="padding: 0px;background-color: transparent">
|
||||
<div class="u-row"
|
||||
style="margin: 0 auto;min-width: 320px;max-width: 95%;overflow-wrap: break-word;word-wrap: break-word;word-break: break-word;background-color: #f9f9f9;">
|
||||
<div style="border-collapse: collapse;display: table;width: 100%;height: 100%;background-color: transparent;">
|
||||
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding: 0px;background-color: transparent;" align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:600px;"><tr style="background-color: #f9f9f9;"><![endif]-->
|
||||
<!--[if (mso)|(IE)]><td align="center" width="600" style="width: 600px;padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;" valign="top"><![endif]-->
|
||||
<div class="u-col u-col-100"
|
||||
style="max-width: 320px;min-width: 600px;display: table-cell;vertical-align: top;">
|
||||
<div style="height: 100%;width: 100% !important;">
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
<div style="box-sizing: border-box; height: 100%; padding: 0px;border-top: 0px solid transparent;border-left: 0px solid transparent;border-right: 0px solid transparent;border-bottom: 0px solid transparent;">
|
||||
<!--<![endif]-->
|
||||
|
||||
<table style="font-family:'Lato',sans-serif;" role="presentation"
|
||||
cellpadding="0" cellspacing="0" width="100%" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="overflow-wrap:break-word;word-break:break-word;padding:20px 40px 30px 20px;font-family:'Lato',sans-serif;"
|
||||
align="left">
|
||||
|
||||
<div style="font-size: 14px; line-height: 140%; text-align: left; word-wrap: break-word;">
|
||||
<small style="color: #a5a3a3;">
|
||||
You're receiving this
|
||||
email because you
|
||||
have a MarcoPMS account. This email is not a
|
||||
marketing or
|
||||
promotional email. That is why this email does not
|
||||
contain an
|
||||
unsubscribe link. You will receive this email even
|
||||
if you have
|
||||
unsubscribed from MarcoPMS's marketing
|
||||
emails
|
||||
</small>
|
||||
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!--[if (!mso)&(!IE)]><!-->
|
||||
</div><!--<![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td><![endif]-->
|
||||
<!--[if (mso)|(IE)]></tr></table></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--[if mso]></div><![endif]-->
|
||||
<!--[if IE]></div><![endif]-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -98,7 +98,7 @@ builder.Services.AddSwaggerGen(option =>
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("EmailSettings"));
|
||||
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("SmtpSettings"));
|
||||
builder.Services.AddTransient<IEmailSender, EmailSender>();
|
||||
|
||||
builder.Services.Configure<AWSSettings>(builder.Configuration.GetSection("AWS")); // For uploading images to aws s3
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
using MailKit.Net.Smtp;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using MailKit.Net.Smtp;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Report;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
|
||||
@ -109,6 +112,92 @@ namespace MarcoBMS.Services.Service
|
||||
|
||||
}
|
||||
|
||||
public async Task SendProjectStatisticsEmail(List<string> toEmails, ProjectStatisticReport report)
|
||||
{
|
||||
//List<string> toEmails = [
|
||||
// "ashutosh.nehete@marcoaiot.com"
|
||||
//];
|
||||
var date = report.Date.ToString("dd-MMM-yyyy", CultureInfo.InvariantCulture);
|
||||
var replacements = new Dictionary<string, string>
|
||||
{
|
||||
{"DATE",date },
|
||||
{"PROJECT_NAME",report.ProjectName },
|
||||
{"TIMESTAMP",report.TimeStamp },
|
||||
{"TODAYS_ATTENDANCES", report.TodaysAttendances.ToString("N0")},
|
||||
{"TOTAL_EMPLOYEES",report.TotalEmployees.ToString("N0") },
|
||||
{"TODAYS_PLANNED",report.TotalPlannedTask.ToString("N0") },
|
||||
{"TODAYS_COMPLETED",report.TotalCompletedTask.ToString("N0") },
|
||||
{"REGULRIZATION_PENDING", report.RegularizationPending.ToString("N0") },
|
||||
{"CHECKOUT_PRNDING",report.CheckoutPending.ToString("N0") },
|
||||
{"TOTAL_PLANNED",report.TotalPlannedWork.ToString("N0") },
|
||||
{"TOTAL_COMPLETED",report.TotalCompletedWork.ToString() },
|
||||
{"PROJECT_STATUS",report.CompletionStatus.ToString("P") },
|
||||
{"TODAYS_ASSIGNED",report.TodaysAssignTasks.ToString("N0") },
|
||||
{"REPORT_PENDING",report.ReportPending.ToString("N0") }
|
||||
};
|
||||
|
||||
string emailBody = await GetEmailTemplate("project-report", replacements);
|
||||
//string emailBody = await GetEmailTemplate("test-project", replacements);
|
||||
|
||||
var teamHtml = new StringBuilder();
|
||||
teamHtml.Append("<tr style=\"vertical-align:middle\">");
|
||||
int flag = 0;
|
||||
foreach (var item in report.TeamOnSite)
|
||||
{
|
||||
if (flag == 6)
|
||||
{
|
||||
teamHtml.Append("</tr>");
|
||||
teamHtml.Append("<tr style=\"vertical-align:middle\">");
|
||||
flag = 0;
|
||||
}
|
||||
teamHtml.AppendFormat("<td class=\"team\" style=\"text-align:center\"><div style=\"border: 1px solid #d5d5d5; border-radius: 10px; margin: 10px 10px; padding: 10px;\"><div style=\"font-size: 15px; color: #525b75 \">{0}</div> <div style=\"font-size: 20px; color: #003cc7; margin: 20px !important; font-weight: bold; \">{1}</div></div></td>", item.RoleName, item.NumberofEmployees);
|
||||
flag += 1;
|
||||
}
|
||||
teamHtml.Append("</tr>");
|
||||
emailBody = emailBody.Replace("{{TEAM_ON_SITE}}", teamHtml.ToString());
|
||||
|
||||
var taskHtml = new StringBuilder();
|
||||
if (report.PerformedTasks.Count > 0)
|
||||
{
|
||||
foreach (var task in report.PerformedTasks)
|
||||
{
|
||||
taskHtml.AppendFormat("<tr>\r\n<td style=\"text-align:left;\">\r\n<span style=\"padding-left: 10px; text-align: left;\">\r\n {0} \r\n</span><br />\r\n<span style=\"color: gray; font-size: small; padding-left: 10px;\"> {1} </span>\r\n</td>\r\n<td style=\"text-align:center\">\r\n {2} / {3} \r\n</td>\r\n<td style=\"text-align:center\">\r\n {4} \r\n</td>\r\n<td style=\"text-align:center\"> {5} </td>\r\n <td style=\"padding-left: 10px; text-align: left;\">\r\n",
|
||||
task.Activity, task.Location, task.AssignedToday, task.Pending, task.CompletedToday, report.Date.ToString("dd-MMM-yyy"));
|
||||
foreach (var member in task.Team)
|
||||
{
|
||||
taskHtml.AppendFormat(" {0} \r\n<span style=\"color: gray; font-size: small; padding-left: 10px;\">({1})</span>\r\n<br />",
|
||||
member.Name, member.RoleName);
|
||||
}
|
||||
taskHtml.AppendFormat("</td>\r\n<td style=\"padding-left: 10px; max-width: 150px; text-align: left;\"> {0} </td>\r\n</tr>", task.Comment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
taskHtml.Append("<tr><td style=\"padding: 10px 0px 5px;\" colspan=\"6\"><span style=\"line-height: 25.2px; color: #666666;margin:10px\">No Activities (Tasks) Performed Today</span></td></tr>");
|
||||
}
|
||||
|
||||
emailBody = emailBody.Replace("{{PERFORMED_TASK}}", taskHtml.ToString());
|
||||
|
||||
var attendanceHtml = new StringBuilder();
|
||||
if (report.PerformedAttendance.Count > 0)
|
||||
{
|
||||
foreach (var attendance in report.PerformedAttendance)
|
||||
{
|
||||
attendanceHtml.AppendFormat("<tr>\r\n<td style=\"text-align:left\">\r\n<span style=\"padding-left:10px;\"> {0} </span>\r\n</td>\r\n<td style=\"text-align:center\"> {1} </td>\r\n<td style=\"text-align:center\"> {2} </td>\r\n<td style=\"text-align:center\"> {3} </td>\r\n<td style=\"padding-left:10px; max-width:150px\"> {4} </td>\r\n</tr>",
|
||||
attendance.Name, attendance.RoleName, attendance.InTime.ToString("dd-MMM-yyyy h:mm tt", CultureInfo.InvariantCulture), (attendance.OutTime != null ? attendance.OutTime.Value.ToString("dd-MMM-yyyy h:mm tt", CultureInfo.InvariantCulture) : ""), attendance.Comment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attendanceHtml.Append("<tr><td style=\"padding: 10px 0px 5px;\" colspan=\"5\"><span style=\"line-height: 25.2px; color: #666666;margin:10px\">No Attendance Performed Today</span></td></tr>");
|
||||
}
|
||||
|
||||
emailBody = emailBody.Replace("{{PERFORMED_ATTENDANCE}}", attendanceHtml.ToString());
|
||||
string subject = $"DPR - {date} - {report.ProjectName}";
|
||||
await SendEmailAsync(toEmails, subject, emailBody);
|
||||
|
||||
}
|
||||
|
||||
public async Task SendEmailAsync(List<string> toEmails, string subject, string body)
|
||||
{
|
||||
var email = new MimeMessage();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Report;
|
||||
|
||||
namespace MarcoBMS.Services.Service
|
||||
{
|
||||
@ -9,5 +10,6 @@ namespace MarcoBMS.Services.Service
|
||||
Task SendResetPasswordSuccessEmail(string toEmail, string userName);
|
||||
Task SendRequestDemoEmail(List<string> toEmails, InquiryEmailObject demoEmailObject);
|
||||
Task SendEmailAsync(List<string> toEmails, string subject, string body);
|
||||
Task SendProjectStatisticsEmail(List<string> toEmails, ProjectStatisticReport report);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,49 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"Cors": {
|
||||
"AllowedOrigins": "*",
|
||||
"AllowedMethods": "*",
|
||||
"AllowedHeaders": "*"
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
//"DefaultConnectionString": "Server=localhost;port=3306;User ID=root;Password=root;Database=MarcoBMS2"
|
||||
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMSGuid"
|
||||
},
|
||||
"SmtpSettings": {
|
||||
"SmtpServer": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"SenderName": "MarcoAIOT",
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
//"SmtpSettings": {
|
||||
// "SmtpServer": "mail.marcoaiot.com",
|
||||
// "Port": 587,
|
||||
// "SenderName": "MarcoAIOT",
|
||||
// "SenderEmail": "ashutosh.nehete@marcoaiot.com",
|
||||
// "Password": "Reset@123"
|
||||
//},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "http://localhost:5173",
|
||||
"ImagesBaseUrl": "http://localhost:5173"
|
||||
},
|
||||
"Jwt": {
|
||||
"Issuer": "http://localhost:5246",
|
||||
"Audience": "http://localhost:5246",
|
||||
"Key": "sworffishhkjfa9dnfdndfu33infnajfj",
|
||||
"ExpiresInMinutes": 60,
|
||||
"RefreshTokenExpiresInDays": 7
|
||||
},
|
||||
"MailingList": {
|
||||
"RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com",
|
||||
"ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
},
|
||||
"AWS": {
|
||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
|
||||
"Region": "us-east-1",
|
||||
"BucketName": "testenv-marco-pms-documents"
|
||||
},
|
||||
"MongoDB": {
|
||||
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||
}
|
||||
|
||||
@ -7,6 +7,13 @@
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
|
||||
},
|
||||
"SmtpSettings": {
|
||||
"SmtpServer": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"SenderName": "MarcoAIOT",
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "https://app.marcoaiot.com",
|
||||
"ImagesBaseUrl": "https://app.marcoaiot.com"
|
||||
@ -18,6 +25,16 @@
|
||||
"ExpiresInMinutes": 60,
|
||||
"RefreshTokenExpiresInDays": 7
|
||||
},
|
||||
"MailingList": {
|
||||
"RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com",
|
||||
"ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
},
|
||||
"AWS": {
|
||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
|
||||
"Region": "us-east-1",
|
||||
"BucketName": "testenv-marco-pms-documents"
|
||||
},
|
||||
"MongoDB": {
|
||||
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||
}
|
||||
|
||||
@ -47,46 +47,7 @@
|
||||
"WithThreadId"
|
||||
]
|
||||
},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "http://localhost:5173",
|
||||
"ImagesBaseUrl": "http://localhost:5173"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Jwt": {
|
||||
"Issuer": "http://localhost:5246",
|
||||
"Audience": "http://localhost:5246",
|
||||
"Key": "sworffishhkjfa9dnfdndfu33infnajfj",
|
||||
"ExpiresInMinutes": 60,
|
||||
"RefreshTokenExpiresInDays": 7
|
||||
},
|
||||
"SmtpSettings": {
|
||||
"Server": "mail.marcobms.com",
|
||||
"Port": 465, //587,
|
||||
"SenderName": "Marco",
|
||||
"SenderEmail": "vikas@marcobms.com",
|
||||
"Username": "vikas@marcobms.com",
|
||||
"Password": "MarcoVikas@123",
|
||||
"EnableSsl": true
|
||||
},
|
||||
"EmailSettings": {
|
||||
"SmtpServer": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"SenderName": "MarcoIoIT",
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
"Contact": {
|
||||
"Emails": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
},
|
||||
"MongoDB": {
|
||||
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||
},
|
||||
"AWS": {
|
||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
|
||||
"Region": "us-east-1",
|
||||
"BucketName": "testenv-marco-pms-documents"
|
||||
},
|
||||
|
||||
"WhiteList": {
|
||||
"ContentType": [
|
||||
"application/pdf", // pdf
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user