Compare commits
17 commits
placement-
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0365fad723 | ||
|
|
20e8dfddd6 | ||
|
|
91c479ef9e | ||
|
|
80fcda61cf | ||
|
|
f02413f2b2 | ||
|
|
1739aa8057 | ||
|
|
bc3bba547f | ||
|
|
4161fcc1cf | ||
|
|
6d0921a76a | ||
|
|
df7bebe0ba | ||
|
|
82a45b6811 | ||
|
|
63d983f831 | ||
|
|
e326e43ae6 | ||
|
|
4dab3c5cd9 | ||
|
|
4bd46d13e5 | ||
|
|
132a59b946 | ||
|
|
740a9984c9 |
28 changed files with 25585 additions and 61 deletions
|
|
@ -149,7 +149,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -215,7 +215,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -288,7 +288,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
@ -376,7 +376,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
var prevRemain = 0.0;
|
||||
if (prev != null)
|
||||
{
|
||||
prevRemain = prev.LeaveDays - prev.LeaveDaysUsed;
|
||||
prevRemain = prev.LeaveDays - (prev.LeaveDaysUsed ?? 0.0);
|
||||
}
|
||||
|
||||
if (govAge >= 180)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ using Microsoft.Extensions.Configuration;
|
|||
using System.IO.Compression;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
|
||||
using BMA.EHR.Domain.Models.Leave.TimeAttendants;
|
||||
|
||||
namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
||||
{
|
||||
|
|
@ -29,6 +31,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
private readonly MinIOLeaveService _minIOService;
|
||||
|
||||
private readonly LeaveBeginningRepository _leaveBeginningRepository;
|
||||
private readonly ProcessUserTimeStampRepository _processUserTimeStampRepository;
|
||||
|
||||
private readonly string URL = string.Empty;
|
||||
|
||||
|
|
@ -44,7 +47,8 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
EmailSenderService emailSenderService,
|
||||
IApplicationDBContext appDbContext,
|
||||
MinIOLeaveService minIOService,
|
||||
LeaveBeginningRepository leaveBeginningRepository) : base(dbContext, httpContextAccessor)
|
||||
LeaveBeginningRepository leaveBeginningRepository,
|
||||
ProcessUserTimeStampRepository processUserTimeStampRepository) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
|
@ -58,6 +62,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
Console.WriteLine($"URL : {URL}");
|
||||
_minIOService = minIOService;
|
||||
_leaveBeginningRepository = leaveBeginningRepository;
|
||||
_processUserTimeStampRepository = processUserTimeStampRepository;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -522,7 +527,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
//.Where(x => x.LeaveStatus != "REJECT" && x.LeaveStatus != "DELETE")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Sum(x => x.LeaveTotal) + (beginningLeave == null ? 0 : beginningLeave.LeaveDaysUsed);
|
||||
return data.Sum(x => x.LeaveTotal) + (beginningLeave == null ? 0 : (beginningLeave.LeaveDaysUsed ?? 0.0));
|
||||
}
|
||||
|
||||
//public async Task<double> GetSumApproveLeaveByTypeForUserAsync(Guid keycloakUserId, Guid leaveTypeId, int year)
|
||||
|
|
@ -1325,9 +1330,68 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
}
|
||||
await _appDbContext.SaveChangesAsync();
|
||||
|
||||
// insert to process timestamp
|
||||
|
||||
|
||||
// ปรับสถานะการลงเวลา
|
||||
if (rawData.LeaveStartDate.Date == rawData.LeaveEndDate.Date)
|
||||
{
|
||||
var processCheckIn = await _dbContext.Set<ProcessUserTimeStamp>()
|
||||
.Where(x => x.KeycloakUserId == rawData.KeycloakUserId)
|
||||
.Where(x => x.CheckIn.Date == rawData.LeaveStartDate.Date)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
|
||||
if (processCheckIn is not null)
|
||||
{
|
||||
switch (rawData.LeaveRange.Trim().ToUpper())
|
||||
{
|
||||
case "MORNING":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
break;
|
||||
case "AFTERNOON":
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
case "ALL":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
var from = rawData.LeaveStartDate.Date;
|
||||
var to = rawData.LeaveEndDate.Date;
|
||||
for (var day = from.Date; day <= to.Date; day = day.AddDays(1))
|
||||
{
|
||||
var processCheckIn = await _dbContext.Set<ProcessUserTimeStamp>()
|
||||
.Where(x => x.KeycloakUserId == rawData.KeycloakUserId)
|
||||
.Where(x => x.CheckIn.Date == day.Date)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (processCheckIn is not null)
|
||||
{
|
||||
switch (rawData.LeaveRange.Trim().ToUpper())
|
||||
{
|
||||
case "MORNING":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
break;
|
||||
case "AFTERNOON":
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
case "ALL":
|
||||
processCheckIn.CheckInStatus = "NORMAL";
|
||||
processCheckIn.CheckOutStatus = "NORMAL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// Send Noti
|
||||
var noti = new Notification
|
||||
{
|
||||
|
|
@ -1486,7 +1550,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
KeycloakUserId = pf.Keycloak == null ? Guid.Empty : pf.Keycloak.Value,
|
||||
LeaveTypeId = b.LeaveTypeId,
|
||||
LeaveTypeCode = b.LeaveType!.Code,
|
||||
SumLeaveDay = b.LeaveDaysUsed
|
||||
SumLeaveDay = b.LeaveDaysUsed ?? 0.0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1877,7 +1941,7 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
.Include(x => x.Type)
|
||||
.Where(x => x.KeycloakUserId == keycloakUserId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt).Date >= startDate && (x.DateSendLeave ??x.CreatedAt).Date < endDate))
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
|
@ -1887,6 +1951,51 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<double> GetSumApproveLeaveTotalByTypeAndRangeForUserByProfile(Guid profileId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.ProfileId == profileId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
if (data.Count > 0)
|
||||
return data.Sum(x => x.LeaveTotal);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<int> GetSumApproveLeaveCountByTypeAndRangeForUserByProfile(Guid profileId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.ProfileId == profileId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Count;
|
||||
}
|
||||
|
||||
public async Task<int> GetSumApproveLeaveCountByTypeAndRangeForUser2(Guid keycloakUserId, Guid leaveTypeId, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var data = await _dbContext.Set<LeaveRequest>().AsQueryable().AsNoTracking()
|
||||
.Include(x => x.Type)
|
||||
.Where(x => x.KeycloakUserId == keycloakUserId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) <= endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "APPROVE" || x.LeaveStatus == "DELETING")
|
||||
.ToListAsync();
|
||||
|
||||
return data.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// วันลาที่สร้างแบบร่างยังไม่ได้ยื่น
|
||||
|
|
@ -1928,9 +2037,9 @@ namespace BMA.EHR.Application.Repositories.Leaves.LeaveRequests
|
|||
.Include(x => x.Type)
|
||||
.Where(x => x.KeycloakUserId == keycloakUserId)
|
||||
.Where(x => x.Type.Id == leaveTypeId)
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt).Date >= startDate && (x.DateSendLeave ??x.CreatedAt).Date < endDate))
|
||||
.Where(x => ((x.DateSendLeave ?? x.CreatedAt) >= startDate && (x.DateSendLeave ??x.CreatedAt) < endDate))
|
||||
//.Where(x => x.LeaveStartDate.Date >= startDate.Date && x.LeaveStartDate.Date <= endDate.Date)
|
||||
.Where(x => x.LeaveStatus == "NEW")
|
||||
.Where(x => (x.LeaveStatus == "NEW" || x.LeaveStatus == "PENDING"))
|
||||
.ToListAsync();
|
||||
|
||||
if (data.Count > 0)
|
||||
|
|
|
|||
|
|
@ -213,6 +213,79 @@ namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<List<AdditionalCheckRequest>> GetAdditionalCheckRequestsByAdminRole2(DateTime startDate, DateTime endDate, string role, string nodeId, int? node, string? keyword, string? status)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = await _dbContext.Set<AdditionalCheckRequest>().AsQueryable()
|
||||
.Where(x => (x.CheckDate.Date >= startDate.Date && x.CheckDate.Date <= endDate.Date))
|
||||
.OrderByDescending(x => x.CreatedAt.Date)
|
||||
.ToListAsync();
|
||||
|
||||
if(!string.IsNullOrEmpty(status))
|
||||
data = data.Where(x => x.Status == status).ToList();
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
data = data.Where(x =>
|
||||
(
|
||||
(x.Prefix ?? "") + (x.FirstName ?? "") + " " + (x.LastName ?? "")).Contains(keyword)
|
||||
|| x.Description.Contains(keyword)
|
||||
|
||||
).ToList();
|
||||
}
|
||||
|
||||
if (role == "OWNER")
|
||||
{
|
||||
node = null;
|
||||
}
|
||||
if (role == "OWNER" || role == "CHILD")
|
||||
{
|
||||
data = data
|
||||
.Where(x => node == 4 ? x.Child4DnaId == Guid.Parse(nodeId!) : (node == 3 ? x.Child3DnaId == Guid.Parse(nodeId!) : (node == 2 ? x.Child2DnaId == Guid.Parse(nodeId!) : (node == 1 ? x.Child1DnaId == Guid.Parse(nodeId!) : (node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) : (node == null ? true : true))))))
|
||||
.ToList();
|
||||
}
|
||||
else if (role == "BROTHER")
|
||||
{
|
||||
data = data
|
||||
.Where(x => node == 4 ? x.Child3DnaId == Guid.Parse(nodeId!) : (node == 3 ? x.Child2DnaId == Guid.Parse(nodeId!) : (node == 2 ? x.Child1DnaId == Guid.Parse(nodeId!) : (node == 1 || node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) : (node == null ? true : true)))))
|
||||
.ToList();
|
||||
}
|
||||
else if (role == "ROOT")
|
||||
{
|
||||
data = data
|
||||
.Where(x => x.RootDnaId == Guid.Parse(nodeId!)).ToList();
|
||||
}
|
||||
// else if (role == "PARENT")
|
||||
// {
|
||||
// data = data
|
||||
// .Where(x => x.RootDnaId == Guid.Parse(nodeId!) && x.Child1DnaId != null && x.Child1DnaId != Guid.Empty).ToList();
|
||||
// }
|
||||
else if (role == "NORMAL")
|
||||
{
|
||||
data = data.Where(x =>
|
||||
node == 0 ? x.RootDnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child1DnaId == Guid.Empty || x.Child1DnaId == null) :
|
||||
node == 1 ? x.Child1DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child2DnaId == Guid.Empty || x.Child2DnaId == null) :
|
||||
node == 2 ? x.Child2DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child3DnaId == Guid.Empty || x.Child3DnaId == null) :
|
||||
node == 3 ? x.Child3DnaId == Guid.Parse(nodeId!) &&
|
||||
(x.Child4DnaId == Guid.Empty || x.Child4DnaId == null) :
|
||||
node == 4 ? x.Child4DnaId == Guid.Parse(nodeId!) :
|
||||
true
|
||||
).ToList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,16 @@ namespace BMA.EHR.Application.Repositories.MetaData
|
|||
|
||||
public async Task<int> GetHolidayCountAsync(DateTime startDate, DateTime endDate, string category = "NORMAL")
|
||||
{
|
||||
var data = await _dbContext.Set<Holiday>().AsQueryable()
|
||||
var query = _dbContext.Set<Holiday>().AsQueryable()
|
||||
.Where(x => x.Category == category)
|
||||
.Where(x => x.HolidayDate.Date >= startDate && x.HolidayDate.Date <= endDate)
|
||||
.CountAsync();
|
||||
.Where(x => x.HolidayDate.Date >= startDate && x.HolidayDate.Date <= endDate);
|
||||
|
||||
return data;
|
||||
if (category == "NORMAL")
|
||||
query = query.Where(x => x.HolidayDate.DayOfWeek != DayOfWeek.Saturday && x.HolidayDate.DayOfWeek != DayOfWeek.Sunday);
|
||||
else
|
||||
query = query.Where(x => x.HolidayDate.DayOfWeek != DayOfWeek.Sunday);
|
||||
|
||||
return await query.CountAsync();
|
||||
}
|
||||
|
||||
public List<DateTime> GetWeekEnd(DateTime startDate, DateTime endDate, string category = "NORMAL")
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ namespace BMA.EHR.Domain.Common
|
|||
protected Guid? ProfileId => User.GetProfileId();
|
||||
protected string? Prefix => User.GetPrefix();
|
||||
protected string? FullNameFromClaim => User.GetName();
|
||||
|
||||
protected string? FirstName => User.GetFirstName();
|
||||
protected string? LastName => User.GetLastName();
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -26,5 +26,7 @@ namespace BMA.EHR.Domain.Extensions
|
|||
public static Guid? GetProfileId(this ClaimsPrincipal user) => user.GetGuidClaim(BmaClaimTypes.ProfileId);
|
||||
public static string? GetPrefix(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.Prefix);
|
||||
public static string? GetName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.Name);
|
||||
public static string? GetFirstName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.GivenName);
|
||||
public static string? GetLastName(this ClaimsPrincipal user) => user.GetClaimValue(BmaClaimTypes.FamilyName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
|
|||
[Required, Comment("จำนวนวันลาทั้งหมด")]
|
||||
public double LeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Required, Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double LeaveDaysUsed { get; set; } = 0.0;
|
||||
[Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double? LeaveDaysUsed { get; set; } = 0.0;
|
||||
|
||||
[Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int LeaveCount { get; set; } = 0;
|
||||
public int? LeaveCount { get; set; } = 0;
|
||||
|
||||
public Guid? RootDnaId { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -38,5 +38,10 @@ namespace BMA.EHR.Domain.Models.Leave.Requests
|
|||
public string Comment { get; set; } = string.Empty;
|
||||
|
||||
public string? ApproveType { get; set; } = string.Empty; // ผู้บังคับบัญชา = commander, ผู้มีอำนาจอนุมัติ = Approver
|
||||
|
||||
|
||||
public bool IsAct { get; set; } = false;
|
||||
|
||||
public string KeyId { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ namespace BMA.EHR.Domain.Models.Placement
|
|||
public string? profileId { get; set; }
|
||||
[Comment("คำนำหน้า")]
|
||||
public string? prefix { get; set; }
|
||||
|
||||
[Comment("ยศ")]
|
||||
public string? rank { get; set; }
|
||||
|
||||
[Comment("ชื่อ")]
|
||||
public string? firstName { get; set; }
|
||||
[Comment("นามสกุล")]
|
||||
|
|
|
|||
21250
BMA.EHR.Infrastructure/Migrations/20260512073417_update_PlacementReceives_add_rank.Designer.cs
generated
Normal file
21250
BMA.EHR.Infrastructure/Migrations/20260512073417_update_PlacementReceives_add_rank.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,30 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class update_PlacementReceives_add_rank : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "rank",
|
||||
table: "PlacementReceives",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
comment: "ยศ")
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "rank",
|
||||
table: "PlacementReceives");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13693,6 +13693,10 @@ namespace BMA.EHR.Infrastructure.Migrations
|
|||
.HasColumnType("longtext")
|
||||
.HasComment("profile Id");
|
||||
|
||||
b.Property<string>("rank")
|
||||
.HasColumnType("longtext")
|
||||
.HasComment("ยศ");
|
||||
|
||||
b.Property<string>("root")
|
||||
.HasColumnType("longtext")
|
||||
.HasComment("ชื่อหน่วยงาน root");
|
||||
|
|
|
|||
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260505035145_Change Field.Designer.cs
generated
Normal file
1805
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260505035145_Change Field.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,62 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ChangeField : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "LeaveDaysUsed",
|
||||
table: "LeaveBeginnings",
|
||||
type: "double",
|
||||
nullable: true,
|
||||
comment: "จำนวนวันลาที่ใช้ไป",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double",
|
||||
oldComment: "จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "LeaveCount",
|
||||
table: "LeaveBeginnings",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
comment: "จำนวนครั้งที่ลาสะสม",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldComment: "จำนวนครั้งที่ลาสะสม");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<double>(
|
||||
name: "LeaveDaysUsed",
|
||||
table: "LeaveBeginnings",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0,
|
||||
comment: "จำนวนวันลาที่ใช้ไป",
|
||||
oldClrType: typeof(double),
|
||||
oldType: "double",
|
||||
oldNullable: true,
|
||||
oldComment: "จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "LeaveCount",
|
||||
table: "LeaveBeginnings",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
comment: "จำนวนครั้งที่ลาสะสม",
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true,
|
||||
oldComment: "จำนวนครั้งที่ลาสะสม");
|
||||
}
|
||||
}
|
||||
}
|
||||
1812
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260511075931_Add Approver Field.Designer.cs
generated
Normal file
1812
BMA.EHR.Infrastructure/Migrations/LeaveDb/20260511075931_Add Approver Field.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,40 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddApproverField : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsAct",
|
||||
table: "LeaveRequestApprovers",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "KeyId",
|
||||
table: "LeaveRequestApprovers",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsAct",
|
||||
table: "LeaveRequestApprovers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "KeyId",
|
||||
table: "LeaveRequestApprovers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.HasColumnOrder(102)
|
||||
.HasComment("แก้ไขข้อมูลล่าสุดเมื่อ");
|
||||
|
||||
b.Property<int>("LeaveCount")
|
||||
b.Property<int?>("LeaveCount")
|
||||
.HasColumnType("int")
|
||||
.HasComment("จำนวนครั้งที่ลาสะสม");
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.HasColumnType("double")
|
||||
.HasComment("จำนวนวันลาทั้งหมด");
|
||||
|
||||
b.Property<double>("LeaveDaysUsed")
|
||||
b.Property<double?>("LeaveDaysUsed")
|
||||
.HasColumnType("double")
|
||||
.HasComment("จำนวนวันลาที่ใช้ไป");
|
||||
|
||||
|
|
@ -713,6 +713,13 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb
|
|||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsAct")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("KeyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<Guid>("KeycloakId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
private readonly IConfiguration _configuration;
|
||||
private readonly UserProfileRepository _userProfileRepository;
|
||||
private readonly PermissionRepository _permission;
|
||||
private readonly LeaveRequestRepository _leaveRequestRepository;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
@ -44,7 +45,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
IWebHostEnvironment hostingEnvironment,
|
||||
IConfiguration configuration,
|
||||
UserProfileRepository userProfileRepository,
|
||||
PermissionRepository permission)
|
||||
PermissionRepository permission,
|
||||
LeaveRequestRepository leaveRequestRepository)
|
||||
{
|
||||
_leaveBeginningRepository = leaveBeginningRepository;
|
||||
_context = context;
|
||||
|
|
@ -53,6 +55,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
_configuration = configuration;
|
||||
_userProfileRepository = userProfileRepository;
|
||||
_permission = permission;
|
||||
_leaveRequestRepository = leaveRequestRepository;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -375,6 +378,15 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
try
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
// var profileId = ProfileId ?? Guid.Empty;
|
||||
// var prefix = Prefix ?? "";
|
||||
// var firstName = FirstName ?? "";
|
||||
// var lastName = LastName ?? "";
|
||||
// var rootDnaId = OrgRootDnaId ?? Guid.Empty;
|
||||
// var child1DnaId = OrgChild1DnaId ?? Guid.Empty;
|
||||
// var child2DnaId = OrgChild2DnaId ?? Guid.Empty;
|
||||
// var child3DnaId = OrgChild3DnaId ?? Guid.Empty;
|
||||
// var child4DnaId = OrgChild4DnaId ?? Guid.Empty;
|
||||
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("UPDATE", "SYS_LEAVE_HISTORY");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
|
|
@ -386,20 +398,41 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
if (leaveBeginning == null)
|
||||
return Error("ไม่พบข้อมูลที่ต้องการแก้ไข", StatusCodes.Status404NotFound);
|
||||
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByProfileIdAsync(req.ProfileId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
return Error("ไม่พบข้อมูลข้าราชการหรือลูกจ้าง", StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var startFiscalDate = new DateTime(DateTime.Now.Year - 1, 10, 1);
|
||||
var endFiscalDate = new DateTime(DateTime.Now.Year, 9, 30);
|
||||
|
||||
|
||||
if (req.LeaveDaysUsed is null || req.LeaveCount is null)
|
||||
{
|
||||
var systemLeaveDays = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUserByProfile(req.ProfileId, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
var systemLeaveCount = await _leaveRequestRepository.GetSumApproveLeaveCountByTypeAndRangeForUserByProfile(req.ProfileId, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
|
||||
leaveBeginning.LeaveDaysUsed = req.BeginningLeaveDays + systemLeaveDays;
|
||||
leaveBeginning.LeaveCount = req.BeginningLeaveCount + systemLeaveCount;
|
||||
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
//var systemLeaveDays = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUser2(profile.Keycloak ?? Guid.Empty, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
//var systemLeaveCount = await _leaveRequestRepository.GetSumApproveLeaveCountByTypeAndRangeForUser2(profile.Keycloak ?? Guid.Empty, req.LeaveTypeId, startFiscalDate, endFiscalDate);
|
||||
}
|
||||
|
||||
leaveBeginning.LeaveTypeId = req.LeaveTypeId;
|
||||
leaveBeginning.LeaveYear = req.LeaveYear;
|
||||
leaveBeginning.LeaveDays = req.LeaveDays;
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
|
||||
|
||||
leaveBeginning.ProfileId = req.ProfileId;
|
||||
leaveBeginning.Prefix = profile.Prefix;
|
||||
|
|
@ -440,6 +473,17 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
try
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
|
||||
// var profileId = ProfileId ?? Guid.Empty;
|
||||
// var prefix = Prefix ?? "";
|
||||
// var firstName = FirstName ?? "";
|
||||
// var lastName = LastName ?? "";
|
||||
// var rootDnaId = OrgRootDnaId ?? Guid.Empty;
|
||||
// var child1DnaId = OrgChild1DnaId ?? Guid.Empty;
|
||||
// var child2DnaId = OrgChild2DnaId ?? Guid.Empty;
|
||||
// var child3DnaId = OrgChild3DnaId ?? Guid.Empty;
|
||||
// var child4DnaId = OrgChild4DnaId ?? Guid.Empty;
|
||||
|
||||
var getPermission = await _permission.GetPermissionAPIAsync("CREATE", "SYS_LEAVE_HISTORY");
|
||||
var jsonData = JsonConvert.DeserializeObject<JObject>(getPermission);
|
||||
if (jsonData["status"]?.ToString() != "200")
|
||||
|
|
@ -464,13 +508,26 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
var leaveBeginning = new LeaveBeginning();
|
||||
|
||||
if (req.LeaveDaysUsed is null || req.LeaveCount is null)
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.BeginningLeaveDays;
|
||||
leaveBeginning.LeaveCount = req.BeginningLeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
}
|
||||
|
||||
leaveBeginning.LeaveTypeId = req.LeaveTypeId;
|
||||
leaveBeginning.LeaveYear = req.LeaveYear;
|
||||
leaveBeginning.LeaveDays = req.LeaveDays;
|
||||
leaveBeginning.LeaveDaysUsed = req.LeaveDaysUsed;
|
||||
leaveBeginning.LeaveCount = req.LeaveCount;
|
||||
leaveBeginning.BeginningLeaveDays = req.BeginningLeaveDays;
|
||||
leaveBeginning.BeginningLeaveCount = req.BeginningLeaveCount;
|
||||
|
||||
|
||||
leaveBeginning.ProfileId = req.ProfileId;
|
||||
leaveBeginning.Prefix = profile.Prefix;
|
||||
|
|
|
|||
|
|
@ -446,29 +446,30 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
public async Task<ActionResult<ResponseObject>> CheckTimeAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId);
|
||||
var profileId = ProfileId ?? Guid.Empty;
|
||||
|
||||
// Get user's last check-in record and profile in parallel
|
||||
var dataTask = _userTimeStampRepository.GetLastRecord(userId);
|
||||
var profileTask = _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
//var profileTask = _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
var defaultRoundTask = _dutyTimeRepository.GetDefaultAsync();
|
||||
|
||||
await Task.WhenAll(dataTask, profileTask, defaultRoundTask);
|
||||
await Task.WhenAll(dataTask, defaultRoundTask);
|
||||
|
||||
var data = await dataTask;
|
||||
var profile = await profileTask;
|
||||
//var profile = await profileTask;
|
||||
var getDefaultRound = await defaultRoundTask;
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
throw new Exception(GlobalMessages.DataNotFound);
|
||||
}
|
||||
// if (profile == null)
|
||||
// {
|
||||
// throw new Exception(GlobalMessages.DataNotFound);
|
||||
// }
|
||||
|
||||
if (getDefaultRound == null)
|
||||
{
|
||||
return Error("ไม่พบรอบลงเวลา Default", StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profile.Id);
|
||||
var effectiveDate = await _userDutyTimeRepository.GetLastEffectRound(profileId);
|
||||
var roundId = effectiveDate != null ? effectiveDate.DutyTimeId : Guid.Empty;
|
||||
var userRound = await _dutyTimeRepository.GetByIdAsync(roundId);
|
||||
|
||||
|
|
@ -1934,7 +1935,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ProfileType = d.ProfileType ?? "",
|
||||
|
||||
CheckInDate = d.CheckIn.Date,
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm:ss"),
|
||||
CheckInTime = d.CheckIn.ToString("HH:mm"),
|
||||
CheckInLocation = d.CheckInPOI,
|
||||
CheckInLat = d.CheckInLat,
|
||||
CheckInLon = d.CheckInLon,
|
||||
|
|
@ -1945,7 +1946,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
CheckInLocationName = d.CheckInLocationName ?? "",
|
||||
|
||||
CheckOutDate = d.CheckOut?.Date,
|
||||
CheckOutTime = d.CheckOut == null ? "" : d.CheckOut.Value.ToString("HH:mm:ss"),
|
||||
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,
|
||||
|
|
@ -3010,6 +3011,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> CheckoutCheckAsync(string isSeminar = "N")
|
||||
{
|
||||
// "S" = Seminar, "N" = Normal, "O" = One Stop Service
|
||||
|
||||
var time = DateTime.Now;
|
||||
|
||||
var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty;
|
||||
|
|
@ -3041,9 +3044,11 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
|
||||
//var endTime = DateTimeOffset.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00").ToLocalTime().DateTime;
|
||||
|
||||
//var endTime = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00");
|
||||
var endTime = isSeminar.Trim().ToUpper() == "Y"
|
||||
//var endTime = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")}T{duty.EndTimeAfternoon}:00.0000000+07:00");
|
||||
var endTime = isSeminar.Trim().ToUpper() == "S"
|
||||
? DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} 14:30")
|
||||
: isSeminar.Trim().ToUpper() == "O"
|
||||
? DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} 18:30")
|
||||
: DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} {duty.EndTimeAfternoon}");
|
||||
|
||||
var endTimeMorning = DateTime.Parse($"{DateTime.Now.Date.ToString("yyyy-MM-dd")} {duty.EndTimeMorning}");
|
||||
|
|
@ -3131,8 +3136,17 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
return Error("ไม่สามารถขอลงเวลากรณีพิเศษในวันที่มากกว่าวันที่ปัจจุบันได้", StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var userId = UserId != null ? Guid.Parse(UserId) : Guid.Empty;
|
||||
|
||||
var checkin = await _userTimeStampRepository.GetTimestampByDateAsync(userId, req.CheckDate.Date);
|
||||
if (checkin != null && checkin.CheckOut == null)
|
||||
{
|
||||
return Error("ระบบพบรายการลงเวลาของวันที่ต้องการแก้ไข แต่ยังไม่มีข้อมูลการลงเวลาออก กรุณาลงเวลาออกให้เรียบร้อยก่อนดำเนินการ");
|
||||
}
|
||||
|
||||
var profile = await _userProfileRepository.GetProfileByKeycloakIdNew2Async(userId, AccessToken);
|
||||
if (profile == null)
|
||||
{
|
||||
|
|
@ -3180,7 +3194,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<ActionResult<ResponseObject>> GetAdditionalCheckRequestAsync([Required] int year, [Required] int month, [Required] int page = 1, [Required] int pageSize = 10, string keyword = "", string? sortBy = "", bool? descending = false)
|
||||
public async Task<ActionResult<ResponseObject>> GetAdditionalCheckRequestAsync([Required] DateTime startDate, [Required] DateTime endDate, [Required] int page = 1, [Required] int pageSize = 10, string keyword = "", string? sortBy = "", bool? descending = false,string? status = "")
|
||||
{
|
||||
var jsonData = await _permission.GetPermissionWithActingAPIAsync("LIST", "SYS_CHECKIN_SPECIAL");
|
||||
//var jsonData = JsonConvert.DeserializeObject<GetPermissionWithActingResultDto>(getPermission);
|
||||
|
|
@ -3225,7 +3239,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
}
|
||||
|
||||
//var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequests(year, month);
|
||||
var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, role, nodeId, profileAdmin?.Node, keyword);
|
||||
var rawData = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole2(startDate, endDate, role, nodeId, profileAdmin?.Node, keyword,status);
|
||||
|
||||
// ถ้ามีการรักษาการ
|
||||
if (jsonData.result.isAct)
|
||||
|
|
@ -3293,7 +3307,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
actNode = 0;
|
||||
}
|
||||
|
||||
var rawDataAct = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole(year, month, actRole, actNodeId, profileAdmin?.Node, keyword);
|
||||
var rawDataAct = await _additionalCheckRequestRepository.GetAdditionalCheckRequestsByAdminRole2(startDate, endDate, actRole, actNodeId, profileAdmin?.Node, keyword,status);
|
||||
if (rawDataAct != null)
|
||||
{
|
||||
if (rawData != null)
|
||||
|
|
@ -3809,6 +3823,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
"ABSENT" :
|
||||
"NORMAL",
|
||||
CheckOutDescription = d.CheckOutRemark ?? "",
|
||||
IsLocationCheckIn = d.IsLocationCheckIn,
|
||||
IsLocationCheckOut = d.IsLocationCheckOut,
|
||||
CheckInLocationName = d.CheckInLocationName ?? "",
|
||||
CheckOutLocationName = d.CheckOutLocationName ?? ""
|
||||
};
|
||||
|
||||
return Success(result);
|
||||
|
|
@ -3873,6 +3891,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
{
|
||||
resultCheckInDate = checkInData == null ? null : checkInData.CheckIn;
|
||||
resultCheckInTime = checkInData == null ? "00:00" : checkInData.CheckIn.ToString("HH:mm");
|
||||
resultCheckInLocation = checkInData == null ? "" : checkInData!.CheckInPOI;
|
||||
}
|
||||
|
||||
if (data.CheckOutEdit)
|
||||
|
|
@ -3890,6 +3909,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
resultCheckOutTime = checkInData == null ? "00:00" :
|
||||
checkInData.CheckOut == null ? "00:00" :
|
||||
checkInData.CheckOut.Value.ToString("HH:mm");
|
||||
resultCheckOutLocation = checkInData == null ? "" : checkInData!.CheckOutPOI;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
data.Type.Id, data.CreatedAt);
|
||||
|
||||
var startFiscalYear = (new DateTime(data.LeaveStartDate.Year - 1, 10, 1)).Date;
|
||||
var endFiscalYear = (data.DateSendLeave ?? data.CreatedAt).Date;
|
||||
var endFiscalYear = (data.DateSendLeave ?? data.CreatedAt);
|
||||
|
||||
var thisYear = data.LeaveStartDate.Year;
|
||||
var toDay = data.LeaveStartDate.Date;
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
LastUpdateFullName = FullName ?? "",
|
||||
LastUpdateUserId = UserId!,
|
||||
LastUpdatedAt = DateTime.Now,
|
||||
|
||||
IsAct = r.isAct,
|
||||
KeyId = r.keyId
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -943,8 +946,8 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
OrganizationName = orgName, //profile.Oc ?? "",
|
||||
|
||||
LeaveLimit = leaveLimit, // จำนวนวันลาทั้งหมดในปีนั้นๆที่ลาได้ โดยรวมยอดที่เหลือจากปีก่อนมา (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveTotal = sumLeave, // จำนวนวันลาที่ลาไปแล้วในปีนั้นๆ โดยเมื่อมีการอนุมัติลา จะมาบวกค่านี้ไปเรื่อยๆ (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveRemain = leaveLimit - sumLeave,
|
||||
LeaveTotal = sumLeave ?? 0, // จำนวนวันลาที่ลาไปแล้วในปีนั้นๆ โดยเมื่อมีการอนุมัติลา จะมาบวกค่านี้ไปเรื่อยๆ (เอาค่ามาจากตาราง Beginning เลย)
|
||||
LeaveRemain = leaveLimit - (sumLeave ?? 0),
|
||||
RestDayTotalOld = restOldDay, // เอา leaveLimit มาลบ 10 (LV-005)
|
||||
RestDayTotalCurrent = restCurrentDay,// 10 วันเสมอ (LV-005)
|
||||
BirthDate = profile.BirthDate.Date,
|
||||
|
|
@ -2835,8 +2838,9 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
var leaveData = await _leaveBeginningRepository.GetByYearAndTypeIdForUser2Async(thisYear, rawData.Type.Id, rawData.KeycloakUserId);
|
||||
|
||||
var startFiscalYear = new DateTime(rawData.LeaveStartDate.Year - 1, 10, 1);
|
||||
var endFiscalYear = rawData.CreatedAt;
|
||||
var endFiscalYear = rawData.DateSendLeave ?? rawData.CreatedAt;
|
||||
var endFiscalYear2 = new DateTime(rawData.LeaveStartDate.Year, 9, 30);
|
||||
//var endFiscalYear3 = rawData.DateSendLeave ?? rawData.CreatedAt;
|
||||
var leaveSummary = await _leaveRequestRepository.GetSumApproveLeaveTotalByTypeAndRangeForUser2(rawData.KeycloakUserId, rawData.Type.Id, startFiscalYear, endFiscalYear);
|
||||
|
||||
// วันลาแบบร่างและที่ยื่นลาไปแล้ว
|
||||
|
|
@ -2987,7 +2991,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ApproveStatus = x.ApproveStatus,
|
||||
Comment = x.Comment,
|
||||
ProfileId = x.ProfileId,
|
||||
KeycloakId = x.KeycloakId
|
||||
KeycloakId = x.KeycloakId,
|
||||
isAct = x.IsAct,
|
||||
keyId = x.KeyId
|
||||
|
||||
}).ToList();
|
||||
|
||||
var approvers = rawData.Approvers.Where(x => x.ApproveType.ToUpper() == "APPROVER")
|
||||
|
|
@ -3002,7 +3009,10 @@ namespace BMA.EHR.Leave.Service.Controllers
|
|||
ApproveStatus = x.ApproveStatus,
|
||||
Comment = x.Comment,
|
||||
ProfileId = x.ProfileId,
|
||||
KeycloakId = x.KeycloakId
|
||||
KeycloakId = x.KeycloakId,
|
||||
|
||||
isAct = x.IsAct,
|
||||
keyId = x.KeyId
|
||||
}).ToList();
|
||||
|
||||
result.Approvers.AddRange(approvers);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveBeginnings
|
|||
[Required, Comment("จำนวนวันลายกมา")]
|
||||
public double LeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Required, Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double LeaveDaysUsed { get; set; } = 0.0;
|
||||
[Comment("จำนวนวันลาที่ใช้ไป")]
|
||||
public double? LeaveDaysUsed { get; set; }
|
||||
|
||||
[Required, Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int LeaveCount { get; set; } = 0;
|
||||
[Comment("จำนวนครั้งที่ลาสะสม")]
|
||||
public int? LeaveCount { get; set; }
|
||||
|
||||
[Required, Comment("จำนวนวันลายกมา")]
|
||||
[Required, Comment("จำนวนวันลายกมาก่อนใช้ระบบ")]
|
||||
public double BeginningLeaveDays { get; set; } = 0.0;
|
||||
|
||||
[Comment("จำนวนครั้งที่ลายกมา")]
|
||||
[Comment("จำนวนครั้งที่ลายกมาก่อนใช้ระบบ")]
|
||||
public int BeginningLeaveCount { get; set; } = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -174,5 +174,8 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
public string ApproveStatus { get; set; } = string.Empty;
|
||||
|
||||
public string Comment { get; set; } = string.Empty;
|
||||
|
||||
public bool isAct { get; set; } = false;
|
||||
public string keyId { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,5 +37,11 @@ namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
|
|||
[JsonProperty("organizationName")]
|
||||
public string OrganizationName { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty("isAct")]
|
||||
public bool isAct { get; set; } = false;
|
||||
|
||||
[JsonProperty("keyId")]
|
||||
public string keyId { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
{
|
||||
p.Id,
|
||||
p.prefix,
|
||||
p.rank,
|
||||
p.firstName,
|
||||
p.lastName,
|
||||
p.citizenId,
|
||||
|
|
@ -280,6 +281,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// ProfileId = p.Profile.Id,
|
||||
p.citizenId,
|
||||
p.prefix,
|
||||
p.rank,
|
||||
p.firstName,
|
||||
p.lastName,
|
||||
p.DateOfBirth,
|
||||
|
|
@ -377,6 +379,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// data.ProfileId,
|
||||
data.citizenId,
|
||||
data.prefix,
|
||||
data.rank,
|
||||
data.firstName,
|
||||
data.lastName,
|
||||
data.DateOfBirth,
|
||||
|
|
@ -484,6 +487,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
// Profile = profile,
|
||||
citizenId = req.citizenId,
|
||||
prefix = req.prefix,
|
||||
rank = req.rank,
|
||||
firstName = req.firstName,
|
||||
lastName = req.lastName,
|
||||
DateOfBirth = req.BirthDate,
|
||||
|
|
@ -852,6 +856,7 @@ namespace BMA.EHR.Placement.Service.Controllers
|
|||
uppdated.Gender = req.Gender;
|
||||
uppdated.citizenId = req.citizenId;
|
||||
uppdated.prefix = req.prefix;
|
||||
uppdated.rank = req.rank;
|
||||
uppdated.firstName = req.firstName;
|
||||
uppdated.lastName = req.lastName;
|
||||
uppdated.DateOfBirth = req.DateOfBirth;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ namespace BMA.EHR.Placement.Service.Requests
|
|||
public class PlacementReceiveEditRequest
|
||||
{
|
||||
public string citizenId { get; set; }
|
||||
public string prefix { get; set; }
|
||||
public string? prefix { get; set; }
|
||||
public string? rank { get; set; }
|
||||
public string firstName { get; set; }
|
||||
public string lastName { get; set; }
|
||||
public DateTime DateOfBirth { get; set; }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ namespace BMA.EHR.Placement.Service.Requests
|
|||
public class PlacementReceiveRequest
|
||||
{
|
||||
public string citizenId { get; set; }
|
||||
public string prefix { get; set; }
|
||||
|
||||
public string? prefix { get; set; }
|
||||
public string? rank { get; set; }
|
||||
public string firstName { get; set; }
|
||||
public string lastName { get; set; }
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
|
|
|||
210
README.md
Normal file
210
README.md
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
# BMA.EHR - HRMS API Backend
|
||||
|
||||
ระบบบริหารจัดการทรัพยากรบุคคล (Human Resource Management System) พัฒนาด้วยสถาปัตยกรรม Microservices บน .NET
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Category | Technology |
|
||||
| ----------------- | ----------------------------- |
|
||||
| Framework | .NET 6.0 / 7.0 / 8.0 |
|
||||
| Architecture | Clean Architecture, DDD, CQRS |
|
||||
| Database | MySQL (Entity Framework Core) |
|
||||
| Authentication | JWT + Keycloak |
|
||||
| Message Queue | RabbitMQ |
|
||||
| Object Storage | MinIO |
|
||||
| Background Jobs | Hangfire |
|
||||
| Logging | Serilog + Elasticsearch |
|
||||
| Error Tracking | Sentry |
|
||||
| API Documentation | Swagger / OpenAPI |
|
||||
| Containerization | Docker |
|
||||
| Testing | xUnit, k6 (Load Testing) |
|
||||
|
||||
---
|
||||
|
||||
## โครงสร้างโปรเจกต์ (Project Structure)
|
||||
|
||||
```
|
||||
BMA.EHR.Solution.sln
|
||||
├── src/ # Core Libraries
|
||||
│ ├── BMA.EHR.Domain/ # Domain layer (Entities, Business Rules)
|
||||
│ ├── BMA.EHR.Application/ # Application layer (Use Cases, Interfaces)
|
||||
│ └── BMA.EHR.Infrastructure/ # Infrastructure layer (Data Access, External Services)
|
||||
│
|
||||
└── Service/ # Microservices
|
||||
├── BMA.EHR.Command.Service/ # Command/CQRS API Gateway
|
||||
├── BMA.EHR.MetaData.Service/ # ข้อมูลอ้างอิง (คำนำหน้า, หมู่เลือด, ศาสนา ฯลฯ)
|
||||
├── BMA.EHR.Placement.Service/ # การบริจาค/สั่งย้าย/แต่งตั้ง
|
||||
├── BMA.EHR.OrganizationEmployee.Service/ # โครงสร้างองค์กรและบุคลากร
|
||||
├── BMA.EHR.Discipline.Service/ # การ discipline บุคลากร
|
||||
├── BMA.EHR.Retirement.Service/ # การเกษียณอายุราชการ
|
||||
├── BMA.EHR.Report.Service/ # รายงาน
|
||||
├── BMA.EHR.Insignia/ # เครื่องราชอิสริยาภรณ์
|
||||
├── BMA.EHR.Leave/ # ระบบลา
|
||||
└── BMA.EHR.CheckInConsumer/ # ลงเวลาปฏิบัติงาน
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## โมดูลหลัก (Key Modules)
|
||||
|
||||
### การบริหารทรัพยากรบุคคล
|
||||
|
||||
- **Placement Service** - สั่งย้าย, แต่งตั้ง, เลื่อนตำแหน่ง, โอนย้ายบุคลากร
|
||||
- **Organization Employee Service** - จัดการโครงสร้างองค์กร, ตำแหน่ง, ข้อมูลบุคลากร
|
||||
- **Leave Service** - การลางาน, การอนุมัติ, วันหยุดนักขัตฤกษ์, ยอดวันลาคงเหลือ
|
||||
- **Discipline Service** - การดำเนินการ discipline, การสืบสวน, เอกสารที่เกี่ยวข้อง
|
||||
- **Retirement Service** - การเกษียณอายุ, เอกสาร, สิทธิประโยชน์
|
||||
- **Insignia Service** - เครื่องราชอิสริยาภรณ์และรางวัล
|
||||
- **CheckIn Consumer** - ติดตามการลงเวลาปฏิบัติงาน
|
||||
|
||||
### ระบบสนับสนุน
|
||||
|
||||
- **Metadata Service** - ข้อมูลอ้างอิง (คำนำหน้าชื่อ, หมู่เลือด, ศาสนา, ระดับการศึกษา ฯลฯ)
|
||||
- **Report Service** - สร้างรายงาน PDF/Excel
|
||||
- **Command Service** - API Gateway สำหรับ CQRS command operations
|
||||
|
||||
### ฟีเจอร์เด่น
|
||||
|
||||
- **Real-time Notifications** - แจ้งเตือนผ่าน WebSocket
|
||||
- **Background Processing** - งานที่กำหนดเวลาผ่าน Hangfire
|
||||
- **Event-Driven Communication** - สื่อสารระหว่าง services ผ่าน RabbitMQ
|
||||
- **Document Generation** - สร้างเอกสาร PDF/Excel
|
||||
- **Audit Trail** - บันทึกประวัติการเปลี่ยนแปลงข้อมูลทั้งหมด
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
API ใช้ versioning และสามารถดูรายละเอียดได้ผ่าน Swagger UI:
|
||||
|
||||
```
|
||||
/api/v1/placement # การบริจาค/สั่งย้าย/แต่งตั้ง
|
||||
/api/v1/leave # ระบบลา
|
||||
/api/v1/discipline # การ discipline
|
||||
/api/v1/organization # โครงสร้างองค์กร
|
||||
/api/v1/metadata # ข้อมูลอ้างอิง
|
||||
/api/v1/retirement # การเกษียณอายุ
|
||||
/api/v1/insignia # เครื่องราชอิสริยาภรณ์
|
||||
/api/v1/reports # รายงาน
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- .NET SDK 6.0 / 7.0 / 8.0
|
||||
- MySQL Server
|
||||
- Keycloak (Authentication Server)
|
||||
- RabbitMQ
|
||||
- MinIO (Object Storage)
|
||||
- Docker (สำหรับ deployment)
|
||||
|
||||
### Configuration
|
||||
|
||||
แต่ละ service มีไฟล์ `appsettings.json` สำหรับ config ดังนี้:
|
||||
|
||||
- **JWT Authentication** - เชื่อมต่อกับ Keycloak
|
||||
- **Database Connection** - MySQL connection string
|
||||
- **RabbitMQ** - Message queue connection
|
||||
- **MinIO** - File storage endpoint
|
||||
- **Elasticsearch** - Logging endpoint
|
||||
- **Mail Server** - สำหรับส่งอีเมล
|
||||
|
||||
### Build & Run
|
||||
|
||||
```bash
|
||||
# Restore dependencies
|
||||
dotnet restore
|
||||
|
||||
# Build solution
|
||||
dotnet build
|
||||
|
||||
# Run specific service
|
||||
dotnet run --project Service/BMA.EHR.Command.Service
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Build Docker image
|
||||
docker build -t bma-ehr-service .
|
||||
|
||||
# Run container
|
||||
docker run -d -p 5000:80 bma-ehr-service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ Swagger │ │ Client │ │ WebSocket │
|
||||
│ UI │ │ Apps │ │ Clients │
|
||||
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ API Gateway │
|
||||
│ (Keycloak JWT) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
┌──────▼──────┐ ┌────────▼──────┐ ┌────────▼──────┐
|
||||
│ Placement │ │ Leave │ │ Discipline │
|
||||
│ Service │ │ Service │ │ Service │
|
||||
└──────┬──────┘ └────────┬──────┘ └────────┬──────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌─────────────▼──────────────┐
|
||||
│ MySQL Database │
|
||||
│ (Entity Framework) │
|
||||
└────────────────────────────┘
|
||||
|
||||
┌────────────────────────────┐
|
||||
│ RabbitMQ / MinIO / │
|
||||
│ Elasticsearch / Hangfire │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies ที่สำคัญ
|
||||
|
||||
| Package | หน้าที่ |
|
||||
| --------------------- | ------------------------- |
|
||||
| Entity Framework Core | ORM สำหรับ MySQL |
|
||||
| Serilog | Structured Logging |
|
||||
| Swashbuckle | API Documentation |
|
||||
| Hangfire | Background Job Processing |
|
||||
| EPPlus | สร้าง/อ่านไฟล์ Excel |
|
||||
| iTextSharp | สร้างไฟล์ PDF |
|
||||
| RabbitMQ.Client | Message Queue |
|
||||
| NEST | Elasticsearch Client |
|
||||
| ThaiBahtText | แปลงตัวเลขเป็นหน่วยบาทไทย |
|
||||
| NodaTime | Date/Time Handling |
|
||||
| Sentry | Error Tracking |
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Run unit tests
|
||||
dotnet test
|
||||
|
||||
# Run with coverage
|
||||
dotnet test --collect:"XPlat Code Coverage"
|
||||
|
||||
# Run load tests (k6)
|
||||
k6 run tests/load/*.js
|
||||
```
|
||||
|
||||
---
|
||||
Loading…
Add table
Add a link
Reference in a new issue