Merge pull request 'Ashutosh_Bug#108_Attendance_log' (#25) from Ashutosh_Bug#108_Attendance_log into Feature_Forum
Reviewed-on: #25
This commit is contained in:
commit
fce124ac8b
2641
Marco.Pms.DataAccess/Migrations/20250424060618_Made_ComentId_Nullable_In_TicketAttachment.Designer.cs
generated
Normal file
2641
Marco.Pms.DataAccess/Migrations/20250424060618_Made_ComentId_Nullable_In_TicketAttachment.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Made_ComentId_Nullable_In_TicketAttachment : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_TicketAttachments_TicketComments_CommentId",
|
||||||
|
table: "TicketAttachments");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "CommentId",
|
||||||
|
table: "TicketAttachments",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)")
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_TicketAttachments_TicketComments_CommentId",
|
||||||
|
table: "TicketAttachments",
|
||||||
|
column: "CommentId",
|
||||||
|
principalTable: "TicketComments",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_TicketAttachments_TicketComments_CommentId",
|
||||||
|
table: "TicketAttachments");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<Guid>(
|
||||||
|
name: "CommentId",
|
||||||
|
table: "TicketAttachments",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||||
|
collation: "ascii_general_ci",
|
||||||
|
oldClrType: typeof(Guid),
|
||||||
|
oldType: "char(36)",
|
||||||
|
oldNullable: true)
|
||||||
|
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_TicketAttachments_TicketComments_CommentId",
|
||||||
|
table: "TicketAttachments",
|
||||||
|
column: "CommentId",
|
||||||
|
principalTable: "TicketComments",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1157,7 +1157,7 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
b.Property<Guid>("CommentId")
|
b.Property<Guid?>("CommentId")
|
||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
b.Property<Guid>("FileId")
|
b.Property<Guid>("FileId")
|
||||||
@ -2372,9 +2372,7 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
{
|
{
|
||||||
b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment")
|
b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment")
|
||||||
.WithMany("Attachments")
|
.WithMany("Attachments")
|
||||||
.HasForeignKey("CommentId")
|
.HasForeignKey("CommentId");
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket")
|
b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
|
28
Marco.Pms.Model/Mapper/AttendanceMapper.cs
Normal file
28
Marco.Pms.Model/Mapper/AttendanceMapper.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Marco.Pms.Model.AttendanceModule;
|
||||||
|
using Marco.Pms.Model.ViewModels.AttendanceVM;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Mapper
|
||||||
|
{
|
||||||
|
public static class AttendanceMapper
|
||||||
|
{
|
||||||
|
public static AttendanceLogVM ToAttendanceLogVMFromAttendanceLog(this AttendanceLog attendanceLog, string preSignedUrl, string thumbPreSignedUrl)
|
||||||
|
{
|
||||||
|
return new AttendanceLogVM
|
||||||
|
{
|
||||||
|
Id = attendanceLog.Id,
|
||||||
|
Comment = attendanceLog.Comment,
|
||||||
|
Employee = attendanceLog.Employee.ToBasicEmployeeVMFromEmployee(),
|
||||||
|
ActivityTime = attendanceLog.ActivityTime,
|
||||||
|
Activity = attendanceLog.Activity,
|
||||||
|
Photo = attendanceLog.Photo,
|
||||||
|
Latitude = attendanceLog.Latitude,
|
||||||
|
Longitude = attendanceLog.Longitude,
|
||||||
|
UpdatedOn = attendanceLog.UpdatedOn,
|
||||||
|
UpdatedByEmployee = attendanceLog.UpdatedByEmployee.ToBasicEmployeeVMFromEmployee(),
|
||||||
|
DocumentId = attendanceLog.Document.Id,
|
||||||
|
PreSignedUrl = preSignedUrl,
|
||||||
|
ThumbPreSignedUrl = thumbPreSignedUrl,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,4 @@
|
|||||||
using System;
|
namespace Marco.Pms.Model.ViewModels.Activities
|
||||||
|
|
||||||
namespace Marco.Pms.Model.ViewModels.Activities
|
|
||||||
{
|
{
|
||||||
public class BasicEmployeeVM
|
public class BasicEmployeeVM
|
||||||
{
|
{
|
||||||
|
23
Marco.Pms.Model/ViewModels/AttendanceVM/AttendanceLogVM.cs
Normal file
23
Marco.Pms.Model/ViewModels/AttendanceVM/AttendanceLogVM.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
||||||
|
{
|
||||||
|
public class AttendanceLogVM
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Comment { get; set; } = string.Empty;
|
||||||
|
public BasicEmployeeVM? Employee { get; set; }
|
||||||
|
public DateTime? ActivityTime { get; set; }
|
||||||
|
public ATTENDANCE_MARK_TYPE Activity { get; set; }
|
||||||
|
public byte[]? Photo { get; set; } // To store the captured photo
|
||||||
|
public string? Latitude { get; set; }
|
||||||
|
public string? Longitude { get; set; }
|
||||||
|
|
||||||
|
public DateTime UpdatedOn { get; set; }
|
||||||
|
public BasicEmployeeVM? UpdatedByEmployee { get; set; }
|
||||||
|
public Guid DocumentId { get; set; }
|
||||||
|
public string? PreSignedUrl { get; set; }
|
||||||
|
public string? ThumbPreSignedUrl { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
using Marco.Pms.Model.Dtos.Attendance;
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
|
|
||||||
namespace Marco.Pms.Model.ViewModels.Attendance
|
namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
||||||
{
|
{
|
||||||
public class EmployeeAttendanceVM
|
public class EmployeeAttendanceVM
|
||||||
{
|
{
|
||||||
@ -14,6 +14,7 @@ namespace Marco.Pms.Model.ViewModels.Attendance
|
|||||||
public string? JobRoleName { get; set; }
|
public string? JobRoleName { get; set; }
|
||||||
public ATTENDANCE_MARK_TYPE Activity { get; set; }
|
public ATTENDANCE_MARK_TYPE Activity { get; set; }
|
||||||
|
|
||||||
|
public Guid? DocumentId { get; set; }
|
||||||
public string? ThumbPreSignedUrl { get; set; }
|
public string? ThumbPreSignedUrl { get; set; }
|
||||||
public string? PreSignedUrl { get; set; }
|
public string? PreSignedUrl { get; set; }
|
||||||
|
|
@ -3,9 +3,10 @@ using Marco.Pms.DataAccess.Data;
|
|||||||
using Marco.Pms.Model.AttendanceModule;
|
using Marco.Pms.Model.AttendanceModule;
|
||||||
using Marco.Pms.Model.Dtos.Attendance;
|
using Marco.Pms.Model.Dtos.Attendance;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
|
using Marco.Pms.Model.Mapper;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.Attendance;
|
using Marco.Pms.Model.ViewModels.AttendanceVM;
|
||||||
using Marco.Pms.Services.Service;
|
using Marco.Pms.Services.Service;
|
||||||
using MarcoBMS.Services.Helpers;
|
using MarcoBMS.Services.Helpers;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@ -51,9 +52,15 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
int TenantId = GetTenantId();
|
int TenantId = GetTenantId();
|
||||||
|
|
||||||
List<AttendanceLog> lstAttendance = await _context.AttendanceLogs.Where(c => c.AttendanceId == attendanceid && c.TenantId == TenantId).ToListAsync();
|
List<AttendanceLog> lstAttendance = await _context.AttendanceLogs.Include(a => a.Document).Include(a => a.Employee).Include(a => a.UpdatedByEmployee).Where(c => c.AttendanceId == attendanceid && c.TenantId == TenantId).ToListAsync();
|
||||||
|
List<AttendanceLogVM> attendanceLogVMs = new List<AttendanceLogVM>();
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(lstAttendance, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
|
foreach (var attendanceLog in lstAttendance)
|
||||||
|
{
|
||||||
|
string objectKey = attendanceLog.Document.S3Key;
|
||||||
|
string preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
|
||||||
|
attendanceLogVMs.Add(attendanceLog.ToAttendanceLogVMFromAttendanceLog(preSignedUrl, preSignedUrl));
|
||||||
|
}
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(attendanceLogVMs, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
|
||||||
|
|
||||||
}
|
}
|
||||||
[HttpGet("log/employee/{employeeid}")]
|
[HttpGet("log/employee/{employeeid}")]
|
||||||
@ -104,39 +111,38 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<EmployeeAttendanceVM>();
|
var result = new List<EmployeeAttendanceVM>();
|
||||||
Attendance? attendance = null;
|
//Attendance? attendance = null;
|
||||||
|
ProjectAllocation? teamMember = null;
|
||||||
|
|
||||||
if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
|
if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
|
||||||
if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1);
|
if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1);
|
||||||
|
|
||||||
|
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date <= fromDate && c.AttendanceDate.Date >= toDate && c.TenantId == TenantId).ToListAsync();
|
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date >= fromDate && c.AttendanceDate.Date <= toDate && c.TenantId == TenantId).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectsHelper.GetTeamByProject(TenantId, projectId, true);
|
List<ProjectAllocation> projectteam = await _projectsHelper.GetTeamByProject(TenantId, projectId, true);
|
||||||
foreach (ProjectAllocation teamMember in projectteam)
|
foreach (Attendance? attendance in lstAttendance)
|
||||||
{
|
{
|
||||||
|
|
||||||
var result1 = new EmployeeAttendanceVM()
|
var result1 = new EmployeeAttendanceVM()
|
||||||
{
|
{
|
||||||
EmployeeAvatar = null,
|
Id = attendance.Id,
|
||||||
EmployeeId = teamMember.EmployeeId,
|
CheckInTime = attendance.InTime,
|
||||||
FirstName = teamMember.Employee.FirstName,
|
CheckOutTime = attendance.OutTime,
|
||||||
LastName = teamMember.Employee.LastName
|
Activity = attendance.Activity
|
||||||
};
|
};
|
||||||
|
teamMember = projectteam.Find(x => x.EmployeeId == attendance.EmployeeID);
|
||||||
attendance = lstAttendance.Find(x => x.EmployeeID == teamMember.EmployeeId) ?? new Attendance();
|
if (teamMember != null)
|
||||||
if (attendance != null)
|
|
||||||
{
|
{
|
||||||
result1.Id = attendance.Id;
|
result1.EmployeeAvatar = null;
|
||||||
result1.CheckInTime = attendance.InTime;
|
result1.EmployeeId = teamMember.EmployeeId;
|
||||||
result1.CheckOutTime = attendance.OutTime;
|
result1.FirstName = teamMember.Employee.FirstName;
|
||||||
result1.Activity = attendance.Activity;
|
result1.LastName = teamMember.Employee.LastName;
|
||||||
|
|
||||||
|
result.Add(result1);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(result1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,69 +502,99 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
_context.Attendes.Add(attendance);
|
_context.Attendes.Add(attendance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Document? document = null;
|
||||||
byte[] fileBytes;
|
|
||||||
var Image = recordAttendanceDot.Image;
|
var Image = recordAttendanceDot.Image;
|
||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
var objectKey = string.Empty;
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
var preSignedUrl = string.Empty;
|
||||||
try
|
|
||||||
{
|
|
||||||
//If base64 has a data URI prefix, strip it
|
|
||||||
var base64 = Image.Base64Data.Contains(",")
|
|
||||||
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
|
||||||
: Image.Base64Data;
|
|
||||||
|
|
||||||
fileBytes = Convert.FromBase64String(base64);
|
if (Image != null && Image.ContentType != null)
|
||||||
|
{
|
||||||
|
byte[] fileBytes;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
fileBytes = Convert.FromBase64String(base64);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var stream = new MemoryStream(fileBytes);
|
||||||
|
|
||||||
|
string fileName = _s3Service.GenerateFileName(Image.ContentType, TenantId, "Attendance");
|
||||||
|
objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
|
||||||
|
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
|
||||||
|
|
||||||
|
document = new Document
|
||||||
|
{
|
||||||
|
FileName = Image.FileName ?? fileName,
|
||||||
|
ContentType = Image.ContentType,
|
||||||
|
S3Key = objectKey,
|
||||||
|
Base64Data = Image.Base64Data,
|
||||||
|
FileSize = Image.FileSize,
|
||||||
|
UploadedAt = recordAttendanceDot.Date,
|
||||||
|
TenantId = TenantId
|
||||||
|
};
|
||||||
|
_context.Documents.Add(document);
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = new MemoryStream(fileBytes);
|
|
||||||
var objectKey = await _s3Service.UploadFileAsync(stream, Image.FileName, Image.ContentType);
|
|
||||||
var preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
|
|
||||||
|
|
||||||
Document document = new Document
|
|
||||||
{
|
|
||||||
FileName = Image.FileName,
|
|
||||||
ContentType = Image.ContentType,
|
|
||||||
S3Key = objectKey,
|
|
||||||
Base64Data = Image.Base64Data,
|
|
||||||
FileSize = Image.FileSize,
|
|
||||||
UploadedAt = recordAttendanceDot.Date,
|
|
||||||
TenantId = TenantId
|
|
||||||
};
|
|
||||||
_context.Documents.Add(document);
|
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Step 3: Always insert a new log entry
|
// Step 3: Always insert a new log entry
|
||||||
var attendanceLog = new AttendanceLog
|
if (document != null)
|
||||||
{
|
{
|
||||||
AttendanceId = attendance.Id, // Use existing or new AttendanceId
|
var attendanceLog = new AttendanceLog
|
||||||
Activity = attendance.Activity,
|
{
|
||||||
|
AttendanceId = attendance.Id, // Use existing or new AttendanceId
|
||||||
|
Activity = attendance.Activity,
|
||||||
|
|
||||||
|
ActivityTime = finalDateTime,
|
||||||
|
Comment = recordAttendanceDot.Comment,
|
||||||
|
EmployeeID = recordAttendanceDot.EmployeeID,
|
||||||
|
Latitude = recordAttendanceDot.Latitude,
|
||||||
|
Longitude = recordAttendanceDot.Longitude,
|
||||||
|
DocumentId = document.Id,
|
||||||
|
TenantId = TenantId,
|
||||||
|
UpdatedBy = recordAttendanceDot.EmployeeID,
|
||||||
|
UpdatedOn = recordAttendanceDot.Date
|
||||||
|
};
|
||||||
|
_context.AttendanceLogs.Add(attendanceLog);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var attendanceLog = new AttendanceLog
|
||||||
|
{
|
||||||
|
AttendanceId = attendance.Id, // Use existing or new AttendanceId
|
||||||
|
Activity = attendance.Activity,
|
||||||
|
|
||||||
|
ActivityTime = finalDateTime,
|
||||||
|
Comment = recordAttendanceDot.Comment,
|
||||||
|
EmployeeID = recordAttendanceDot.EmployeeID,
|
||||||
|
Latitude = recordAttendanceDot.Latitude,
|
||||||
|
Longitude = recordAttendanceDot.Longitude,
|
||||||
|
DocumentId = document.Id,
|
||||||
|
TenantId = TenantId,
|
||||||
|
UpdatedBy = recordAttendanceDot.EmployeeID,
|
||||||
|
UpdatedOn = recordAttendanceDot.Date
|
||||||
|
};
|
||||||
|
_context.AttendanceLogs.Add(attendanceLog);
|
||||||
|
}
|
||||||
|
|
||||||
ActivityTime = finalDateTime,
|
|
||||||
Comment = recordAttendanceDot.Comment,
|
|
||||||
EmployeeID = recordAttendanceDot.EmployeeID,
|
|
||||||
Latitude = recordAttendanceDot.Latitude,
|
|
||||||
Longitude = recordAttendanceDot.Longitude,
|
|
||||||
DocumentId = document.Id,
|
|
||||||
TenantId = TenantId,
|
|
||||||
UpdatedBy = recordAttendanceDot.EmployeeID,
|
|
||||||
UpdatedOn = recordAttendanceDot.Date
|
|
||||||
};
|
|
||||||
//if (recordAttendanceDot.Image != null && recordAttendanceDot.Image.Count > 0)
|
//if (recordAttendanceDot.Image != null && recordAttendanceDot.Image.Count > 0)
|
||||||
//{
|
//{
|
||||||
// attendanceLog.Photo = recordAttendanceDot.Image[0].Base64Data;
|
// attendanceLog.Photo = recordAttendanceDot.Image[0].Base64Data;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
_context.AttendanceLogs.Add(attendanceLog);
|
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
await transaction.CommitAsync(); // Commit transaction
|
await transaction.CommitAsync(); // Commit transaction
|
||||||
@ -566,20 +602,43 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
Employee employee = await _employeeHelper.GetEmployeeByID(recordAttendanceDot.EmployeeID);
|
Employee employee = await _employeeHelper.GetEmployeeByID(recordAttendanceDot.EmployeeID);
|
||||||
if (employee.JobRole != null)
|
if (employee.JobRole != null)
|
||||||
{
|
{
|
||||||
EmployeeAttendanceVM vm = new EmployeeAttendanceVM()
|
EmployeeAttendanceVM vm = new EmployeeAttendanceVM();
|
||||||
|
if (document != null)
|
||||||
{
|
{
|
||||||
CheckInTime = attendance.InTime,
|
vm = new EmployeeAttendanceVM()
|
||||||
CheckOutTime = attendance.OutTime,
|
{
|
||||||
EmployeeAvatar = null,
|
CheckInTime = attendance.InTime,
|
||||||
EmployeeId = recordAttendanceDot.EmployeeID,
|
CheckOutTime = attendance.OutTime,
|
||||||
FirstName = employee.FirstName,
|
EmployeeAvatar = null,
|
||||||
LastName = employee.LastName,
|
EmployeeId = recordAttendanceDot.EmployeeID,
|
||||||
Id = attendance.Id,
|
FirstName = employee.FirstName,
|
||||||
Activity = attendance.Activity,
|
LastName = employee.LastName,
|
||||||
JobRoleName = employee.JobRole.Name,
|
Id = attendance.Id,
|
||||||
ThumbPreSignedUrl = preSignedUrl,
|
Activity = attendance.Activity,
|
||||||
PreSignedUrl = preSignedUrl
|
JobRoleName = employee.JobRole.Name,
|
||||||
};
|
DocumentId = document.Id,
|
||||||
|
ThumbPreSignedUrl = preSignedUrl ?? string.Empty,
|
||||||
|
PreSignedUrl = preSignedUrl ?? string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vm = new EmployeeAttendanceVM()
|
||||||
|
{
|
||||||
|
CheckInTime = attendance.InTime,
|
||||||
|
CheckOutTime = attendance.OutTime,
|
||||||
|
EmployeeAvatar = null,
|
||||||
|
EmployeeId = recordAttendanceDot.EmployeeID,
|
||||||
|
FirstName = employee.FirstName,
|
||||||
|
LastName = employee.LastName,
|
||||||
|
Id = attendance.Id,
|
||||||
|
Activity = attendance.Activity,
|
||||||
|
JobRoleName = employee.JobRole.Name,
|
||||||
|
DocumentId = Guid.Empty,
|
||||||
|
ThumbPreSignedUrl = string.Empty,
|
||||||
|
PreSignedUrl = string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200));
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,4 @@
|
|||||||
<ProjectReference Include="..\Marco.Pms.Utility\Marco.Pms.Utility.csproj" />
|
<ProjectReference Include="..\Marco.Pms.Utility\Marco.Pms.Utility.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="images\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -16,13 +16,23 @@ using Serilog;
|
|||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add Serilog Configuration
|
||||||
|
string? mongoConn = builder.Configuration["MongoDB:SerilogDatabaseUrl"];
|
||||||
|
string timeString = "00:00:30";
|
||||||
|
TimeSpan.TryParse(timeString, out TimeSpan timeSpan);
|
||||||
|
|
||||||
// Add Serilog Configuration
|
// Add Serilog Configuration
|
||||||
builder.Host.UseSerilog((context, config) =>
|
builder.Host.UseSerilog((context, config) =>
|
||||||
{
|
{
|
||||||
config.ReadFrom.Configuration(context.Configuration); // Taking all configuration from appsetting.json
|
config.ReadFrom.Configuration(context.Configuration) // Taking all configuration from appsetting.json
|
||||||
|
.WriteTo.MongoDB(
|
||||||
|
databaseUrl: mongoConn,
|
||||||
|
collectionName: "api-logs",
|
||||||
|
batchPostingLimit: 100,
|
||||||
|
period: timeSpan
|
||||||
|
);
|
||||||
|
|
||||||
})
|
});
|
||||||
;
|
|
||||||
|
|
||||||
// Add services
|
// Add services
|
||||||
var corsSettings = builder.Configuration.GetSection("Cors");
|
var corsSettings = builder.Configuration.GetSection("Cors");
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using Amazon.S3.Model;
|
using Amazon.S3.Model;
|
||||||
using Amazon.S3.Transfer;
|
using Amazon.S3.Transfer;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
|
using MarcoBMS.Services.Service;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Marco.Pms.Services.Service
|
namespace Marco.Pms.Services.Service
|
||||||
@ -11,9 +12,11 @@ namespace Marco.Pms.Services.Service
|
|||||||
{
|
{
|
||||||
private readonly IAmazonS3 _s3Client;
|
private readonly IAmazonS3 _s3Client;
|
||||||
private readonly string _bucketName = "your-bucket-name";
|
private readonly string _bucketName = "your-bucket-name";
|
||||||
|
private readonly ILoggingService _logger;
|
||||||
|
|
||||||
public S3UploadService(IOptions<AWSSettings> awsOptions)
|
public S3UploadService(IOptions<AWSSettings> awsOptions, ILoggingService logger)
|
||||||
{
|
{
|
||||||
|
_logger = logger;
|
||||||
var settings = awsOptions.Value;
|
var settings = awsOptions.Value;
|
||||||
|
|
||||||
var region = Amazon.RegionEndpoint.GetBySystemName(settings.Region);
|
var region = Amazon.RegionEndpoint.GetBySystemName(settings.Region);
|
||||||
@ -25,7 +28,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
public async Task<string> UploadFileAsync(Stream fileStream, string fileName, string contentType)
|
public async Task<string> UploadFileAsync(Stream fileStream, string fileName, string contentType)
|
||||||
{
|
{
|
||||||
// Generate a unique object key (you can customize this)
|
// Generate a unique object key (you can customize this)
|
||||||
var objectKey = $"{Guid.NewGuid()}_{fileName}";
|
var objectKey = $"{fileName}";
|
||||||
|
|
||||||
var uploadRequest = new TransferUtilityUploadRequest
|
var uploadRequest = new TransferUtilityUploadRequest
|
||||||
{
|
{
|
||||||
@ -38,7 +41,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
var transferUtility = new TransferUtility(_s3Client);
|
var transferUtility = new TransferUtility(_s3Client);
|
||||||
await transferUtility.UploadAsync(uploadRequest);
|
await transferUtility.UploadAsync(uploadRequest);
|
||||||
|
_logger.LogInfo("File uploaded to Amazon S3");
|
||||||
return objectKey;
|
return objectKey;
|
||||||
}
|
}
|
||||||
public async Task<string> GeneratePreSignedUrlAsync(string objectKey)
|
public async Task<string> GeneratePreSignedUrlAsync(string objectKey)
|
||||||
@ -53,7 +56,16 @@ namespace Marco.Pms.Services.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
string url = _s3Client.GetPreSignedURL(request);
|
string url = _s3Client.GetPreSignedURL(request);
|
||||||
|
_logger.LogInfo("Requested presigned url from Amazon S3");
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
public string GenerateFileName(string contentType, int tenantId, string? name)
|
||||||
|
{
|
||||||
|
string extenstion = contentType.Split("/")[1];
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
return $"{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}.{extenstion}";
|
||||||
|
return $"{name}_{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}.{extenstion}";
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,5 +9,11 @@
|
|||||||
"AllowedOrigins": "*",
|
"AllowedOrigins": "*",
|
||||||
"AllowedMethods": "*",
|
"AllowedMethods": "*",
|
||||||
"AllowedHeaders": "*"
|
"AllowedHeaders": "*"
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnectionString": "Server=localhost;port=3306;User ID=root;Password=root;Database=MarcoBMS2"
|
||||||
|
},
|
||||||
|
"MongoDB": {
|
||||||
|
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,24 @@
|
|||||||
{
|
{
|
||||||
"AllowedHosts": "*",
|
|
||||||
"Cors": {
|
"Cors": {
|
||||||
"AllowedOrigins": "http://localhost:4173",
|
"AllowedOrigins": "https://app.marcoaiot.com",
|
||||||
"AllowedMethods": "*",
|
"AllowedMethods": "*",
|
||||||
"AllowedHeaders": "*"
|
"AllowedHeaders": "*"
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
|
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
|
||||||
|
},
|
||||||
|
"AppSettings": {
|
||||||
|
"WebFrontendUrl": "https://app.marcoaiot.com",
|
||||||
|
"ImagesBaseUrl": "https://app.marcoaiot.com"
|
||||||
|
},
|
||||||
|
"Jwt": {
|
||||||
|
"Issuer": "https://app.marcoaiot.com",
|
||||||
|
"Audience": "https://app.marcoaiot.com",
|
||||||
|
"Key": "sworffishhkjfa9dnfdndfu33infnajfj",
|
||||||
|
"ExpiresInMinutes": 60,
|
||||||
|
"RefreshTokenExpiresInDays": 7
|
||||||
|
},
|
||||||
|
"MongoDB": {
|
||||||
|
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,6 @@
|
|||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
"Microsoft.EntityFrameworkCore.Database.Command": "Warning",
|
"Microsoft.EntityFrameworkCore.Database.Command": "Warning",
|
||||||
"Microsoft.AspNetCore.Mvc.Infrastructure": "Warning"
|
"Microsoft.AspNetCore.Mvc.Infrastructure": "Warning"
|
||||||
//"Serilog.AspNetCore.RequestLoggingMiddleware": "Warning"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"WriteTo": [
|
"WriteTo": [
|
||||||
@ -19,19 +18,6 @@
|
|||||||
"Name": "Async",
|
"Name": "Async",
|
||||||
"Args": {
|
"Args": {
|
||||||
"configure": [
|
"configure": [
|
||||||
{
|
|
||||||
"Name": "MongoDB",
|
|
||||||
"Args": {
|
|
||||||
"databaseUrl": "mongodb://localhost:27017/DotNetLogs",
|
|
||||||
//"databaseUrl": "mongodb://devuser:xxxxx@147.93.98.152:27017/MarcoPMS?authSource=admin",
|
|
||||||
"collectionName": "application_logs",
|
|
||||||
"batchPostingLimit": 50,
|
|
||||||
"cappedMaxSizeMb": "1024",
|
|
||||||
"cappedMaxDocuments": "1000",
|
|
||||||
"rollingInterval": "Day"
|
|
||||||
//"outputTemplate": "[{Timestamp:yyyy/MM/dd HH:mm} {Level:u3}] {SourceContext}:{NewLine} {Message:lj}{Exception}{NewLine}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Name": "File",
|
"Name": "File",
|
||||||
"Args": {
|
"Args": {
|
||||||
@ -61,12 +47,6 @@
|
|||||||
"WithThreadId"
|
"WithThreadId"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"ConnectionStrings": {
|
|
||||||
// "DefaultConnectionString": "Server=103.50.160.45;User ID=marcowvh_admin;Password=Marcoemp@123;Database=marcowvh_empattendanceci",
|
|
||||||
//"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=MarcoBMS1"
|
|
||||||
},
|
|
||||||
"AppSettings": {
|
"AppSettings": {
|
||||||
"WebFrontendUrl": "http://localhost:5173",
|
"WebFrontendUrl": "http://localhost:5173",
|
||||||
"ImagesBaseUrl": "http://localhost:5173"
|
"ImagesBaseUrl": "http://localhost:5173"
|
||||||
@ -96,8 +76,10 @@
|
|||||||
"Password": "qrtq wfuj hwpp fhqr"
|
"Password": "qrtq wfuj hwpp fhqr"
|
||||||
},
|
},
|
||||||
"Contact": {
|
"Contact": {
|
||||||
//"Emails": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
"Emails": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||||
"Emails": "ashutosh.nehete@marcoaiot.com"
|
},
|
||||||
|
"MongoDB": {
|
||||||
|
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs"
|
||||||
},
|
},
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user