add api เพิ่มเติมระบบลงเวลา
This commit is contained in:
parent
8782aec4c3
commit
19bcc6bed2
11 changed files with 291 additions and 11 deletions
13
BMA.EHR.Application/Common/Interfaces/ILeaveDbContext.cs
Normal file
13
BMA.EHR.Application/Common/Interfaces/ILeaveDbContext.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BMA.EHR.Application.Common.Interfaces
|
||||
{
|
||||
public interface ILeaveDbContext
|
||||
{
|
||||
DbSet<T> Set<T>() where T : class;
|
||||
|
||||
void Attatch<T>(T entity) where T : class;
|
||||
|
||||
Task<int> SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
using BMA.EHR.Application.Common.Interfaces;
|
||||
using BMA.EHR.Domain.Models.Base;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BMA.EHR.Application.Repositories.Leaves
|
||||
{
|
||||
public class GenericLeaveRepository<S, T> : IGenericRepository<S, T> where T : class
|
||||
{
|
||||
#region " Field "
|
||||
|
||||
private readonly ILeaveDbContext _dbContext;
|
||||
private readonly DbSet<T> _dbSet;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Constructor and Destructor "
|
||||
|
||||
public GenericLeaveRepository(ILeaveDbContext dbContext,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_dbSet = _dbContext.Set<T>();
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Properties "
|
||||
|
||||
protected string? UserId => _httpContextAccessor?.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||
|
||||
protected string? FullName => _httpContextAccessor?.HttpContext?.User?.FindFirst("name")?.Value;
|
||||
|
||||
protected bool? IsPlacementAdmin => _httpContextAccessor?.HttpContext?.User?.IsInRole("placement1");
|
||||
|
||||
#endregion
|
||||
|
||||
#region " Methods "
|
||||
|
||||
public virtual async Task<IReadOnlyList<T>> GetAllAsync()
|
||||
{
|
||||
return await _dbSet.ToListAsync();
|
||||
}
|
||||
|
||||
public virtual async Task<T?> GetByIdAsync(S id)
|
||||
{
|
||||
return await _dbSet.FindAsync(id);
|
||||
}
|
||||
|
||||
public virtual async Task<T> AddAsync(T entity)
|
||||
{
|
||||
if (entity is EntityBase)
|
||||
{
|
||||
(entity as EntityBase).CreatedUserId = UserId!;
|
||||
(entity as EntityBase).CreatedFullName = FullName!;
|
||||
(entity as EntityBase).CreatedAt = DateTime.Now;
|
||||
}
|
||||
|
||||
await _dbSet.AddAsync(entity);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public virtual async Task<T> UpdateAsync(T entity)
|
||||
{
|
||||
if (entity is EntityBase)
|
||||
{
|
||||
(entity as EntityBase).LastUpdateUserId = UserId!;
|
||||
(entity as EntityBase).LastUpdateFullName = FullName!;
|
||||
(entity as EntityBase).LastUpdatedAt = DateTime.Now;
|
||||
}
|
||||
|
||||
_dbSet.Update(entity);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public virtual async Task DeleteAsync(T entity)
|
||||
{
|
||||
_dbSet.Remove(entity);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,11 @@ using Microsoft.Extensions.Configuration;
|
|||
|
||||
namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
||||
{
|
||||
public class DutyTimeRepository : GenericRepository<Guid, DutyTime>
|
||||
public class DutyTimeRepository : GenericLeaveRepository<Guid, DutyTime>
|
||||
{
|
||||
#region " Fields "
|
||||
|
||||
private readonly IApplicationDBContext _dbContext;
|
||||
private readonly ILeaveDbContext _dbContext;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly OrganizationCommonRepository _organizationCommonRepository;
|
||||
private readonly UserProfileRepository _userProfileRepository;
|
||||
|
|
@ -22,7 +22,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
|||
|
||||
#region " Constructor and Destuctor "
|
||||
|
||||
public DutyTimeRepository(IApplicationDBContext dbContext,
|
||||
public DutyTimeRepository(ILeaveDbContext dbContext,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
OrganizationCommonRepository organizationCommonRepository,
|
||||
UserProfileRepository userProfileRepository,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BMA.EHR.Application.Common.Interfaces;
|
||||
using BMA.EHR.Application.Messaging;
|
||||
using BMA.EHR.Domain.Extensions;
|
||||
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
|
@ -7,11 +8,11 @@ using Microsoft.Extensions.Configuration;
|
|||
|
||||
namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
||||
{
|
||||
public class UserTimeStampRepository : GenericRepository<Guid, UserTimeStamp>
|
||||
public class UserTimeStampRepository : GenericLeaveRepository<Guid, UserTimeStamp>
|
||||
{
|
||||
#region " Fields "
|
||||
|
||||
private readonly IApplicationDBContext _dbContext;
|
||||
private readonly ILeaveDbContext _dbContext;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly OrganizationCommonRepository _organizationCommonRepository;
|
||||
private readonly UserProfileRepository _userProfileRepository;
|
||||
|
|
@ -22,7 +23,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
|||
|
||||
#region " Constructor and Destuctor "
|
||||
|
||||
public UserTimeStampRepository(IApplicationDBContext dbContext,
|
||||
public UserTimeStampRepository(ILeaveDbContext dbContext,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
OrganizationCommonRepository organizationCommonRepository,
|
||||
UserProfileRepository userProfileRepository,
|
||||
|
|
@ -66,6 +67,31 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
|||
return data;
|
||||
}
|
||||
|
||||
public async Task<List<UserTimeStamp>> GetTimeStampHistoryAsync(Guid keycloakId, int year, int page = 1, int pageSize = 10, string keyword = "")
|
||||
{
|
||||
var data = await _dbContext.Set<UserTimeStamp>()
|
||||
.Where(u => u.KeycloakUserId == keycloakId)
|
||||
.Where(u => u.CheckIn.Year.ToCeYear() == year.ToCeYear())
|
||||
.OrderBy(u => u.CheckIn)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public async Task<List<UserTimeStamp>> GetTimeStampHistoryForAdminAsync(DateTime startDate,DateTime endDate, int page = 1, int pageSize = 10, string keyword = "")
|
||||
{
|
||||
var data = await _dbContext.Set<UserTimeStamp>()
|
||||
.Where(u => u.CheckIn >= startDate && u.CheckIn <= endDate)
|
||||
.OrderBy(u => u.CheckIn)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -361,12 +361,12 @@ namespace BMA.EHR.Application.Repositories
|
|||
|
||||
var fileExt = Path.GetExtension(fileName);
|
||||
var fileType = MimeTypeMap.GetMimeType(fileExt);
|
||||
var file_name = Path.GetFileName(fileName);
|
||||
//var file_name = Path.GetFileName(fileName);
|
||||
|
||||
var request = new PutObjectRequest
|
||||
{
|
||||
BucketName = _bucketName,
|
||||
Key = file_name,
|
||||
Key = fileName,
|
||||
InputStream = fileStream,
|
||||
ContentType = fileType,
|
||||
CannedACL = S3CannedACL.BucketOwnerFullControl
|
||||
|
|
|
|||
|
|
@ -28,6 +28,24 @@ namespace BMA.EHR.Application.Repositories
|
|||
|
||||
#region " Methods "
|
||||
|
||||
public string GetUserFullName(Guid keycloakId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = _dbContext.Set<Profile>().AsQueryable()
|
||||
.Include(x => x.Prefix)
|
||||
.Where(x => x.KeycloakId == keycloakId)
|
||||
.Select(x => $"{x.Prefix!.Name}{x.FirstName} {x.LastName}")
|
||||
.FirstOrDefault();
|
||||
|
||||
return data ?? "-";
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid GetUserOCId(Guid keycloakId)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace BMA.EHR.Infrastructure
|
|||
}),
|
||||
ServiceLifetime.Transient);
|
||||
|
||||
services.AddScoped<IApplicationDBContext>(provider => provider.GetService<LeaveDbContext>());
|
||||
services.AddScoped<ILeaveDbContext>(provider => provider.GetService<LeaveDbContext>());
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace BMA.EHR.Infrastructure.Persistence
|
||||
{
|
||||
public class LeaveDbContext : DbContext, IApplicationDBContext
|
||||
public class LeaveDbContext : DbContext, ILeaveDbContext
|
||||
{
|
||||
#region " Check-In "
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using BMA.EHR.Domain.Shared;
|
|||
using BMA.EHR.Infrastructure.Persistence;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Sentry;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
using System.Security.Claims;
|
||||
|
||||
|
|
@ -342,7 +343,7 @@ namespace BMA.EHR.Command.Service.Controllers
|
|||
EndTimeAfternoon = duty == null ? "00:00" : duty.EndTimeAfternoon,
|
||||
Description = duty == null ? "-" : duty.Description,
|
||||
CheckInTime = data.CheckIn,
|
||||
CheckInId = data.CheckOut == null ? null : data.Id,
|
||||
CheckInId = data.Id,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -415,6 +416,75 @@ namespace BMA.EHR.Command.Service.Controllers
|
|||
return Success(new { date = currentDate });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LV1_007 - ประวัติการลงเวลา (USER)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
|
||||
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
|
||||
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
|
||||
[HttpGet("check-in/history")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckInHistoryAsync(int year, int page = 1, int pageSize = 10, string keyword = "")
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var data = (await _userTimeStampRepository.GetTimeStampHistoryAsync(userId, year, page, pageSize, keyword))
|
||||
.Select(d => new CheckInHistoryDto
|
||||
{
|
||||
CheckInId = d.Id,
|
||||
|
||||
CheckInDate = d.CheckIn.Date,
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm"),
|
||||
CheckInLocation = d.CheckInPOI,
|
||||
CheckInStatus = "NORMAL", // TODO : เอาจากที่ประมวลแล้ว
|
||||
|
||||
CheckOutDate = d.CheckOut == null ? null : d.CheckOut.Value.Date,
|
||||
CheckOutTime = d.CheckOut == null ? "" : d.CheckOut.Value.ToString("HH:mm"),
|
||||
CheckOutLocation = d.CheckOutPOI ?? "",
|
||||
CheckOutStatus = d.CheckOut == null ? "" : "NORMAL" // TODO : เอาจากที่ประมวลแล้ว
|
||||
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return Success(data);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("log-record")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> LogRecordAsync(DateTime startDate, DateTime endDate, int page = 1, int pageSize = 10, string keyword = "")
|
||||
{
|
||||
var imgUrl = $"{_configuration["MinIO:Endpoint"]}{_configuration["MinIO:BucketName"]}";
|
||||
var data = (await _userTimeStampRepository.GetTimeStampHistoryForAdminAsync(startDate, endDate, page, pageSize, keyword))
|
||||
.Select(d => new CheckInHistoryForAdminDto
|
||||
{
|
||||
CheckInId = d.Id,
|
||||
FullName = _userProfileRepository.GetUserFullName(d.KeycloakUserId),
|
||||
|
||||
CheckInDate = d.CheckIn.Date,
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm"),
|
||||
CheckInLocation = d.CheckInPOI,
|
||||
CheckInLat = d.CheckInLat,
|
||||
CheckInLon = d.CheckInLon,
|
||||
CheckInImageUrl = $"{imgUrl}/{d.CheckInImageUrl}",
|
||||
|
||||
CheckOutDate = d.CheckOut == null ? null : d.CheckOut.Value.Date,
|
||||
CheckOutTime = d.CheckOut == null ? "" : d.CheckOut.Value.ToString("HH:mm"),
|
||||
CheckOutLocation = d.CheckOut == null ? "" : d.CheckOutPOI,
|
||||
CheckOutLat = d.CheckOut == null ? null : d.CheckOutLat,
|
||||
CheckOutLon = d.CheckOut == null ? null : d.CheckOutLon,
|
||||
CheckOutImageUrl = d.CheckOut == null ? "" : $"{imgUrl}/{d.CheckOutImageUrl}",
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return Success(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
23
BMA.EHR.Leave.Service/DTOs/CheckIn/CheckInHistoryDto.cs
Normal file
23
BMA.EHR.Leave.Service/DTOs/CheckIn/CheckInHistoryDto.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
namespace BMA.EHR.Command.Service.DTOs.CheckIn
|
||||
{
|
||||
public class CheckInHistoryDto
|
||||
{
|
||||
public Guid CheckInId { get; set; } = Guid.Empty;
|
||||
|
||||
public DateTime? CheckInDate { get; set; } = DateTime.MinValue;
|
||||
|
||||
public string? CheckInTime { get; set; } = "00:00";
|
||||
|
||||
public string? CheckInLocation { get; set; } = string.Empty;
|
||||
|
||||
public string? CheckInStatus { get; set; } = string.Empty;
|
||||
|
||||
public DateTime? CheckOutDate { get; set; } = DateTime.MinValue;
|
||||
|
||||
public string? CheckOutTime { get; set; } = "00:00";
|
||||
|
||||
public string? CheckOutLocation { get; set; } = string.Empty;
|
||||
|
||||
public string? CheckOutStatus { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
namespace BMA.EHR.Command.Service.DTOs.CheckIn
|
||||
{
|
||||
public class CheckInHistoryForAdminDto
|
||||
{
|
||||
public Guid CheckInId { get; set; } = Guid.Empty;
|
||||
|
||||
public string FullName { get; set; } = string.Empty;
|
||||
|
||||
public DateTime? CheckInDate { get; set; } = DateTime.MinValue;
|
||||
|
||||
public string? CheckInTime { get; set; } = "00:00";
|
||||
|
||||
public string? CheckInLocation { get; set; } = string.Empty;
|
||||
|
||||
public double? CheckInLat { get; set; } = 0;
|
||||
|
||||
public double? CheckInLon { get; set; } = 0;
|
||||
|
||||
public string? CheckInImageUrl { get; set; } = string.Empty;
|
||||
|
||||
public DateTime? CheckOutDate { get; set; } = DateTime.MinValue;
|
||||
|
||||
public string? CheckOutTime { get; set; } = "00:00";
|
||||
|
||||
public string? CheckOutLocation { get; set; } = string.Empty;
|
||||
|
||||
public double? CheckOutLat { get; set; } = 0;
|
||||
|
||||
public double? CheckOutLon { get; set; } = 0;
|
||||
|
||||
public string? CheckOutImageUrl { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue