fix: insignia + leave Error

This commit is contained in:
Suphonchai Phoonsawat 2024-07-10 10:46:26 +07:00
parent 41d28c4d7f
commit 7d8a80e9df
72 changed files with 132 additions and 142 deletions

View file

@ -0,0 +1,76 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>349e3764-b6a4-4dce-969a-e6976cd10d3e</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DockerfileContext>.</DockerfileContext>
<RootNamespace>BMA.EHR.Leave.Service</RootNamespace>
<AssemblyName>BMA.EHR.Leave</AssemblyName>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Controllers\CheckInController.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\.dockerignore" Link=".dockerignore">
<DependentUpon>$(DockerDefaultDockerfile)</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Hangfire" Version="1.8.6" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
<PackageReference Include="Hangfire.MySqlStorage" Version="2.0.3" />
<PackageReference Include="iTextSharp" Version="5.5.13.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.IdentityModel.Logging" Version="6.31.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Version="6.0.5.128" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Sentry.AspNetCore" Version="3.33.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BMA.EHR.Infrastructure\BMA.EHR.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\keycloak.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\keycloak.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="SeedLeaveData.xlsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,85 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
namespace BMA.EHR.Leave.Service
{
public class ConfigureSwaggerOptions : IConfigureNamedOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider _provider;
public ConfigureSwaggerOptions(
IApiVersionDescriptionProvider provider)
{
_provider = provider;
}
public void Configure(SwaggerGenOptions options)
{
// add swagger document for every API version discovered
foreach (var description in _provider.ApiVersionDescriptions)
{
options.EnableAnnotations();
options.SwaggerDoc(
description.GroupName,
CreateVersionInfo(description));
}
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{}
}
});
// generate the XML docs that'll drive the swagger docs
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
}
public void Configure(string name, SwaggerGenOptions options)
{
Configure(options);
}
private OpenApiInfo CreateVersionInfo(
ApiVersionDescription desc)
{
var info = new OpenApiInfo()
{
Title = "BMA EHR Leave Service Document",
Version = desc.ApiVersion.ToString(),
};
if (desc.IsDeprecated)
{
info.Description += " This API version has been deprecated. Please use one of the new APIs available from the explorer.";
}
return info;
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,98 @@
using BMA.EHR.Application.Repositories;
using BMA.EHR.Application.Repositories.Leaves.LeaveRequests;
using BMA.EHR.Domain.Common;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using System.Security.Claims;
namespace BMA.EHR.Leave.Service.Controllers
{
[Route("api/v{version:apiVersion}/leave")]
[ApiVersion("1.0")]
[ApiController]
[Produces("application/json")]
[Authorize]
[SwaggerTag("API ระบบลงเวลาและการลา (ประเภทการลา)")]
public class LeaveTypeController : BaseController
{
#region " Fields "
private readonly LeaveTypeRepository _leaveTypeRepository;
private readonly LeaveDbContext _context;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly IConfiguration _configuration;
private readonly UserProfileRepository _userProfileRepository;
#endregion
#region " Constuctor and Destructor "
public LeaveTypeController(LeaveTypeRepository leaveTypeRepository,
LeaveDbContext context,
IHttpContextAccessor httpContextAccessor,
IWebHostEnvironment hostingEnvironment,
IConfiguration configuration,
UserProfileRepository userProfileRepository)
{
_leaveTypeRepository = leaveTypeRepository;
_context = context;
_httpContextAccessor = httpContextAccessor;
_hostingEnvironment = hostingEnvironment;
_configuration = configuration;
_userProfileRepository = userProfileRepository;
}
#endregion
#region " Properties "
private string? UserId => _httpContextAccessor?.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
private string? FullName => _httpContextAccessor?.HttpContext?.User?.FindFirst("name")?.Value;
private bool? PlacementAdmin => _httpContextAccessor?.HttpContext?.User?.IsInRole("placement1");
private string? AccessToken => _httpContextAccessor?.HttpContext?.Request.Headers["Authorization"];
private Guid OcId
{
get
{
if (UserId != null || UserId != "")
return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!), AccessToken);
else
return Guid.Empty;
}
}
#endregion
#region " Methods "
/// <summary>
/// LV2_011 - รายการประเภทการลา (ADMIN)
/// </summary>
/// <returns>
/// </returns>
/// <response code="200">เมื่อทำรายการสำเร็จ</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("type")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetAllAsync()
{
var leaveTypes = (await _leaveTypeRepository.GetAllAsync()).AsQueryable()
.OrderBy(l => l.Code)
.ToList();
return Success(leaveTypes);
}
#endregion
}
}

View file

@ -0,0 +1,15 @@
namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck
{
public class ApproveRequestDto
{
public string CheckInTime { get; set; }
public string CheckOutTime { get; set; }
public string CheckInStatus { get; set; }
public string CheckOutStatus { get; set; }
public string Reason { get; set; }
}
}

View file

@ -0,0 +1,13 @@
namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck
{
public class CreateAdditionalCheckRequestDto
{
public DateTime CheckDate { get; set; }
public bool CheckInEdit { get; set; }
public bool CheckOutEdit { get; set;}
public string Description { get; set; }
}
}

View file

@ -0,0 +1,41 @@
namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck
{
public class GetAdditionalCheckRequestDto
{
public Guid Id { get; set; }
public string FullName { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime CheckDate { get; set; }
public bool CheckInEdit { get; set; }
public bool CheckOutEdit { get; set; }
public string CheckInTime { get; set; }
public string CheckOutTime { get; set; }
public string? CheckInStatus { get; set; }
public string? CheckOutStatus { get; set; }
public string StartTimeMorning { get; set; }
public string EndTimeMorning { get; set; }
public string StartTimeAfternoon { get; set; }
public string EndTimeAfternoon { get; set; }
public string Reason { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public int StatusSort { get; set; } = 0;
}
}

View file

@ -0,0 +1,27 @@
namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck
{
public class GetAdditionalCheckRequestHistoryDto
{
public Guid Id { get; set; }
public DateTime? CheckInDate { get; set; }
public DateTime? CheckOutDate { get; set; }
public string CheckInTime { get; set; }
public string CheckOutTime { get; set; }
public string CheckInLocation { get; set; }
public string CheckOutLocation { get; set; }
public string? CheckInStatus { get; set; }
public string? CheckOutStatus { get; set; }
public string? EditReason { get; set; }
public string? EditStatus { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Leave.Service.DTOs.AdditionalCheck
{
public class RejectRequestDto
{
public string Reason { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Leave.Service.DTOs.Calendar
{
public class UpdateCalendarDto
{
public string Work { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,16 @@
namespace BMA.EHR.Leave.Service.DTOs.ChangeRound
{
public class ChangeRoundHistoryDto
{
public int Round { get; set; }
public string StartTimeMorning { get; set; }
public string LeaveTimeAfternoon { get; set; }
public DateTime EffectiveDate { get; set; }
public string Remark { get; set; }
}
}

View file

@ -0,0 +1,15 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
namespace BMA.EHR.Leave.Service.DTOs.ChangeRound
{
public class CreateChangeRoundDto
{
public Guid ProfileId { get; set; }
public Guid RoundId { get; set; }
public DateTime EffectiveDate { get; set; }
public string Remark { get; set; }
}
}

View file

@ -0,0 +1,17 @@
namespace BMA.EHR.Leave.Service.DTOs.ChangeRound
{
public class SearchProfileDto
{
public string? CitizenId { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public int Page { get; set; } = 1;
public int PageSize { get; set; } = 10;
public string? Keyword { get; set; }
}
}

View file

@ -0,0 +1,17 @@
namespace BMA.EHR.Leave.Service.DTOs.ChangeRound
{
public class SearchProfileResultDto
{
public Guid ProfileId { get; set; }
public string CitizenId { get; set; }
public string FullName { get; set; }
public string StartTimeMorning { get; set; }
public string LeaveTimeAfterNoon { get;set; }
public DateTime? EffectiveDate { get; set; }
}
}

View file

@ -0,0 +1,49 @@
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class CheckInDetailForAdminDto
{
public Guid Id { get; set; } = Guid.Empty;
public string FullName { get; set; } = string.Empty;
public DateTime? CheckInDate { get; set; } = DateTime.MinValue;
public string? CheckInStatus { get; set; } = string.Empty;
public string? CheckInTime { get; set; } = "00:00";
public string? CheckInPOI { get; set; } = string.Empty;
public double? CheckInLat { get; set; } = 0;
public double? CheckInLon { get; set; } = 0;
public string? CheckInImg { get; set; } = string.Empty;
public string CheckInDescription { get; set; } = string.Empty;
public bool IsLocationCheckIn { get; set; } = true;
public string? CheckInLocationName { get; set; } = string.Empty;
public DateTime? CheckOutDate { get; set; } = DateTime.MinValue;
public string? CheckOutStatus { get; set; } = string.Empty;
public string? CheckOutTime { get; set; } = "00:00";
public string? CheckOutPOI { get; set; } = string.Empty;
public double? CheckOutLat { get; set; } = 0;
public double? CheckOutLon { get; set; } = 0;
public string? CheckOutImg { get; set; } = string.Empty;
public string? CheckOutDescription { get; set; } = string.Empty;
public bool IsLocationCheckOut { get; set; } = true;
public string? CheckOutLocationName { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,37 @@
namespace BMA.EHR.Leave.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 bool CheckInIsLocation { get; set; } = false;
public string? CheckInLocationName { 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;
public bool CheckOutIsLocation { get; set; } = false;
public string? CheckOutLocationName { get; set; } = string.Empty;
//public string EditStatus { get; set; } = string.Empty;
//public string EditReason { get; set; } = string.Empty;
public bool IsEdit { get; set; } = false;
}
}

View file

@ -0,0 +1,41 @@
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class CheckInHistoryForAdminDto
{
public Guid Id { 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? CheckInImage { get; set; } = string.Empty;
public bool IsLocationCheckIn { get; set; } = true;
public string? CheckInLocationName { 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? CheckOutImage { get; set; } = string.Empty;
public bool IsLocationCheckOut { get; set; } = true;
public string? CheckOutLocationName { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,41 @@
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class CheckInProcessHistoryForAdminDto
{
public Guid Id { 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? 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 double? CheckOutLat { get; set; } = 0;
public double? CheckOutLon { get; set; } = 0;
public string? CheckOutStatus { get; set; } = string.Empty;
public bool CheckInIsLocation { get; set; } = false;
public string? CheckInLocationName { get; set; } = string.Empty;
public bool CheckOutIsLocation { get; set; } = false;
public string? CheckOutLocationName { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,19 @@
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class CheckInResultDto
{
public Guid? CheckInId { get; set; }
public DateTime? CheckInTime { get; set; }
public string Description { get; set; } = string.Empty;
public string StartTimeMorning { get; set; } = "00:00";
public string EndTimeMorning { get; set; } = "00:00";
public string StartTimeAfternoon { get; set; } = "00:00";
public string EndTimeAfternoon { get; set; } = "00:00";
}
}

View file

@ -0,0 +1,28 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class CheckTimeDto
{
public Guid? CheckInId { get; set; }
[Required]
public IFormFile? Img { get; set; }
[Required]
public double Lat { get; set; } = 0;
[Required]
public double Lon { get; set; } = 0;
[Required]
public string POI { get; set; } = string.Empty;
[Required]
public bool IsLocation { get; set; } = true;
public string? LocationName { get; set; } = string.Empty;
public string? Remark { get; set;} = string.Empty;
}
}

View file

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.CheckIn
{
public class EditCheckInStatusDto
{
[Required]
public string CheckInStatus { get; set; } = string.Empty;
[Required]
public string CheckOutStatus { get; set; } = string.Empty;
public string? Reason { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.DutyTime
{
public class CreateDutyTimeDto
{
[Comment("คำอธิบาย")]
public string? Description { get; set; } = string.Empty;
[Required, Comment("เวลาเข้างานช่วงเช้า")]
public string StartTimeMorning { get; set; } = "00:00";
[Required, Comment("เวลาออกงานช่วงเช้า")]
public string EndTimeMorning { get; set; } = "00:00";
[Required, Comment("เวลาเข้างานช่วงบ่าย")]
public string StartTimeAfternoon { get; set; } = "00:00";
[Required, Comment("เวลาออกงานช่วงบ่าย")]
public string EndTimeAfternoon { get; set; } = "00:00";
[Required, Comment("สถานะว่ารอบใดเป็นค่า Default ของข้าราชการ (สำหรับทุกคนที่ยังไม่ได้ทำการเลือกรอบ)")]
public bool IsDefault { get; set; } = false;
[Required, Comment("Is Active")]
public bool IsActive { get; set; } = false;
}
}

View file

@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.DutyTime
{
public class UpdateDutyTimeDto
{
[Comment("คำอธิบาย")]
public string? Description { get; set; } = string.Empty;
[Required, Comment("สถานะว่ารอบใดเป็นค่า Default ของข้าราชการ (สำหรับทุกคนที่ยังไม่ได้ทำการเลือกรอบ)")]
public bool IsDefault { get; set; } = false;
[Required, Comment("สถานะการเปิดใช้งาน (เปิด/ปิด)")]
public bool IsActive { get; set; } = true;
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class CancelLeaveRequestApproveDto
{
public string? Reason { get; set; }
}
}

View file

@ -0,0 +1,11 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class CancelLeaveRequestDto
{
public string? Reason { get; set; }
public IFormFile? Doc { get; set; }
public string? LeaveWrote { get; set; }
}
}

View file

@ -0,0 +1,101 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class CreateLeaveRequestDto
{
[Required]
public Guid Type { get; set; } = Guid.Empty;
[Required]
public DateTime LeaveStartDate { get; set; } = DateTime.Now;
[Required]
public DateTime LeaveEndDate { get; set; } = DateTime.Now;
public string? LeaveWrote { get; set; }
public string? LeaveRange { get; set; } = "ALL";
public double LeaveTotal { get; set; } = 0.0;
public string? LeaveAddress { get; set; }
public string? LeaveNumber { get; set; }
public string? LeaveDetail { get; set; }
public List<IFormFile> LeaveDocument { get; set; } = new();
public IFormFile? LeaveDraftDocument { get; set; }
public string? LeaveSalaryText { get; set; }
public string? WifeDayName { get; set; }
public string? WifeDayDateBorn { get; set; }
public int? RestDayOldTotal { get; set; }
public int? RestDayCurrentTotal { get; set; }
public bool? OrdainDayStatus { get; set; }
public string? OrdainDayLocationName { get; set; }
public string? OrdainDayLocationAddress { get; set; }
public string? OrdainDayLocationNumber { get; set; }
public DateTime? OrdainDayOrdination { get; set; }
public string? OrdainDayBuddhistLentName { get; set; }
public string? OrdainDayBuddhistLentAddress { get; set; }
public bool? HajjDayStatus { get; set; }
public string? AbsentDaySummon { get; set; }
public string? AbsentDayLocation { get; set; }
public DateTime? AbsentDayRegistorDate { get; set; }
public string? AbsentDayGetIn { get; set; }
public string? AbsentDayAt { get; set; }
public string? StudyDaySubject { get; set; }
public string? StudyDayDegreeLevel { get; set; }
public string? StudyDayUniversityName { get; set; }
public string? StudyDayTrainingSubject { get; set; }
public string? StudyDayTrainingName { get; set; }
public string? StudyDayCountry { get; set; }
public string? StudyDayScholarship { get; set; }
public string? CoupleDayName { get; set; }
public string? CoupleDayPosition { get; set; }
public string? CoupleDayLevel { get; set; }
public string? CoupleDayLevelCountry { get; set; }
public string? CoupleDayCountryHistory { get; set; }
public string? CoupleDayTotalHistory { get; set; }
public DateTime? CoupleDayStartDateHistory { get; set; }
public DateTime? CoupleDayEndDateHistory { get; set; }
public string? CoupleDaySumTotalHistory { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class DeleteLeaveDocumentDto
{
[Required]
public Guid Id { get; set; } = Guid.Empty;
[Required]
public Guid DocId { get; set; } = Guid.Empty;
}
}

View file

@ -0,0 +1,31 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetCancelLeaveRequestByIdDto
{
public Guid Id { get; set; } = Guid.Empty;
public string LeaveTypeName { get; set; } = string.Empty;
public string FullName { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string LeaveDocDelete { get; set; } = string.Empty;
public string LeaveReasonDelete { get; set; } = string.Empty;
public string LeaveWrote { get; set; } = string.Empty;
public string LeaveAddress { get; set; } = string.Empty;
public string LeaveNumber { get; set; } = string.Empty;
public string LeaveDetail { get; set; } = string.Empty;
public double LeaveTotal { get; set; } = 0;
public DateTime LeaveStartDate { get; set; } = DateTime.MinValue;
public DateTime LeaveEndDate { get; set;} = DateTime.MinValue;
}
}

View file

@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveCancelRequestDto
{
[Required]
public Guid Type { get; set; } = Guid.Empty;
[Required]
public string Status { get; set; } = string.Empty;
[Required]
public int Page { get; set; } = 1;
[Required]
public int PageSize { get; set; } = 10;
public string Keyword { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,17 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveCancelRequestResultDto
{
public Guid Id { get; set; }
public string LeaveTypeName { get; set; }
public Guid LeaveTypeId { get; set; }
public string FullName { get; set; }
public DateTime DateSendLeave { get; set; }
public string Status { get; set; }
}
}

View file

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveCheckDto
{
[Required]
public Guid Type { get; set; } = Guid.Empty;
[Required]
public DateTime StartLeaveDate { get; set; } = DateTime.MinValue;
[Required]
public DateTime EndLeaveDate { get; set;} = DateTime.MinValue;
}
}

View file

@ -0,0 +1,13 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveCheckResultDto
{
public bool IsLeave { get; set; } = false;
public double SumDateWork { get; set; } = 0;
public double TotalDate { get; set; } = 0;
public double SumDateHoliday { get; set; } = 0;
}
}

View file

@ -0,0 +1,128 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestByIdDto
{
public Guid Id { get; set; } = Guid.Empty;
public string LeaveTypeName { get; set; } = string.Empty;
public Guid LeaveTypeId { get; set; } = Guid.Empty;
public string FullName { get; set; } = string.Empty;
public DateTime DateSendLeave { get; set; } = DateTime.MinValue;
public string Status { get; set; } = string.Empty;
public DateTime LeaveStartDate { get; set; } = DateTime.Now;
public DateTime LeaveEndDate { get; set; } = DateTime.Now;
public string LeaveWrote { get; set; } = string.Empty;
public string? LeaveRange { get; set; } = string.Empty;
public string LeaveAddress { get; set; } = string.Empty;
public string LeaveNumber { get; set; } = string.Empty;
public string LeaveDetail { get; set; } = string.Empty;
public List<LeaveDocumentDto> LeaveDocument { get; set; } = new();
public string LeaveDraftDocument { get; set; }
public DateTime? LeaveLastStart { get; set; } = DateTime.MinValue;
public DateTime? LeaveLastEnd { get; set; } = DateTime.MinValue;
public double LeaveTotal { get; set; } = 0;
public DateTime? LeaveBirthDate { get; set; } = DateTime.MinValue;
public DateTime? LeaveGovernmentDate { get; set; } = DateTime.MinValue;
public double LeaveSalary { get; set; } = 0;
public string LeaveSalaryText { get; set; } = string.Empty;
public string WifeDayName { get; set; } = string.Empty;
public string WifeDayDateBorn { get; set; } = string.Empty;
public double RestDayOldTotal { get; set; } = 0;
public double RestDayCurrentTotal { get; set; } = 0;
public bool OrdainDayStatus { get; set; } = false;
public string OrdainDayLocationName { get; set; } = string.Empty;
public string OrdainDayLocationAddress { get; set; } = string.Empty;
public string OrdainDayLocationNumber { get; set; } = string.Empty;
public DateTime OrdainDayOrdination { get; set; } = DateTime.Now;
public string OrdainDayBuddhistLentName { get; set; } = string.Empty;
public string OrdainDayBuddhistLentAddress { get; set; } = string.Empty;
public bool HajjDayStatus { get; set; } = false;
public string AbsentDaySummon { get; set; } = string.Empty;
public string AbsentDayLocation { get; set; } = string.Empty;
public DateTime AbsentDayRegistorDate { get; set; } = DateTime.Now;
public string AbsentDayGetIn { get; set; } = string.Empty;
public string AbsentDayAt { get; set; } = string.Empty;
public string StudyDaySubject { get; set; } = string.Empty;
public string StudyDayDegreeLevel { get; set; } = string.Empty;
public string StudyDayUniversityName { get; set; } = string.Empty;
public string StudyDayTrainingSubject { get; set; } = string.Empty;
public string StudyDayTrainingName { get; set; } = string.Empty;
public string StudyDayCountry { get; set; } = string.Empty;
public string StudyDayScholarship { get; set; } = string.Empty;
public string CoupleDayName { get; set; } = string.Empty;
public string CoupleDayPosition { get; set; } = string.Empty;
public string CoupleDayLevel { get; set; } = string.Empty;
public string CoupleDayLevelCountry { get; set; } = string.Empty;
public string CoupleDayCountryHistory { get; set; } = string.Empty;
public string CoupleDayTotalHistory { get; set; } = string.Empty;
public DateTime CoupleDayStartDateHistory { get; set; } = DateTime.Now;
public DateTime CoupleDayEndDateHistory { get; set; } = DateTime.Now;
public string CoupleDaySumTotalHistory { get; set; } = string.Empty;
public string? Dear { get; set; } = string.Empty;
public string? LeaveTypeCode { get; set; } = string.Empty;
public string? PositionName { get; set; } = string.Empty;
public string? PositionLevelName { get; set; } = string.Empty;
public string? OrganizationName { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestCalendarDto
{
public int Year { get; set; } = DateTime.Now.Year;
}
}

View file

@ -0,0 +1,23 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestCalendarResultDto
{
public Guid Id { get; set; }
public string LeaveTypeName { get; set; }
public Guid LeaveTypeId { get; set; }
public DateTime DateSendLeave { get; set; }
public string Status { get; set; }
public string FullName { get; set; }
public DateTime LeaveStartDate { get; set; }
public DateTime LeaveEndDate { get; set; }
public Guid KeycloakId { get; set; }
}
}

View file

@ -0,0 +1,137 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestForAdminByIdDto
{
public Guid Id { get; set; } = Guid.Empty;
public string? ReasonCommander { get; set; }
public string? ReasonOligarch { get; set; }
public string? PositionName { get; set; }
public string? PositionLevelName { get; set; }
public string? OrganizationName { get; set; }
public string LeaveTypeName { get; set; } = string.Empty;
public Guid LeaveTypeId { get; set; } = Guid.Empty;
public string FullName { get; set; } = string.Empty;
public DateTime DateSendLeave { get; set; } = DateTime.MinValue;
public string Status { get; set; } = string.Empty;
public DateTime LeaveStartDate { get; set; } = DateTime.Now;
public DateTime LeaveEndDate { get; set; } = DateTime.Now;
public string LeaveWrote { get; set; } = string.Empty;
public string LeaveAddress { get; set; } = string.Empty;
public string LeaveNumber { get; set; } = string.Empty;
public string LeaveDetail { get; set; } = string.Empty;
public List<LeaveDocumentDto> LeaveDocument { get; set; } = new();
public string LeaveDraftDocument { get; set; }
public DateTime? LeaveLastStart { get; set; } = DateTime.MinValue;
public DateTime? LeaveLastEnd { get; set; } = DateTime.MinValue;
public double LeaveTotal { get; set; } = 0;
public DateTime? LeaveBirthDate { get; set; } = DateTime.MinValue;
public DateTime? LeaveGovernmentDate { get; set; } = DateTime.MinValue;
public double LeaveSalary { get; set; } = 0;
public string LeaveSalaryText { get; set; } = string.Empty;
public string WifeDayName { get; set; } = string.Empty;
public string WifeDayDateBorn { get; set; } = string.Empty;
public double RestDayOldTotal { get; set; } = 0;
public double RestDayCurrentTotal { get; set; } = 0;
public bool OrdainDayStatus { get; set; } = false;
public string OrdainDayLocationName { get; set; } = string.Empty;
public string OrdainDayLocationAddress { get; set; } = string.Empty;
public string OrdainDayLocationNumber { get; set; } = string.Empty;
public DateTime OrdainDayOrdination { get; set; } = DateTime.Now;
public string OrdainDayBuddhistLentName { get; set; } = string.Empty;
public string OrdainDayBuddhistLentAddress { get; set; } = string.Empty;
public bool HajjDayStatus { get; set; } = false;
public string AbsentDaySummon { get; set; } = string.Empty;
public string AbsentDayLocation { get; set; } = string.Empty;
public DateTime AbsentDayRegistorDate { get; set; } = DateTime.Now;
public string AbsentDayGetIn { get; set; } = string.Empty;
public string AbsentDayAt { get; set; } = string.Empty;
public string StudyDaySubject { get; set; } = string.Empty;
public string StudyDayDegreeLevel { get; set; } = string.Empty;
public string StudyDayUniversityName { get; set; } = string.Empty;
public string StudyDayTrainingSubject { get; set; } = string.Empty;
public string StudyDayTrainingName { get; set; } = string.Empty;
public string StudyDayCountry { get; set; } = string.Empty;
public string StudyDayScholarship { get; set; } = string.Empty;
public string CoupleDayName { get; set; } = string.Empty;
public string CoupleDayPosition { get; set; } = string.Empty;
public string CoupleDayLevel { get; set; } = string.Empty;
public string CoupleDayLevelCountry { get; set; } = string.Empty;
public string CoupleDayCountryHistory { get; set; } = string.Empty;
public string CoupleDayTotalHistory { get; set; } = string.Empty;
public DateTime CoupleDayStartDateHistory { get; set; } = DateTime.Now;
public DateTime CoupleDayEndDateHistory { get; set; } = DateTime.Now;
public string CoupleDaySumTotalHistory { get; set; } = string.Empty;
public string Dear { get; set; } = string.Empty;
public string ApproveStep { get; set; } = string.Empty;
public double LeaveLimit { get; set; } = 0;
public double LeaveSummary { get; set; } = 0;
public double LeaveRemain { get; set; } = 0;
public string LeaveRange { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,29 @@
using Org.BouncyCastle.Asn1.X509;
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestForAdminDto
{
[Required]
public int Year { get; set; } = 0;
[Required]
public Guid Type { get; set; } = Guid.Empty;
[Required]
public string Status { get; set; } = string.Empty;
[Required]
public int Page { get; set; } = 1;
[Required]
public int PageSize { get; set; } = 10;
public string Keyword { get; set; } = string.Empty;
public DateTime StartDate { get; set; } = DateTime.MinValue;
public DateTime EndDate { get; set; } = DateTime.MinValue;
}
}

View file

@ -0,0 +1,33 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestForAdminResultDto
{
public Guid Id { get; set; } = Guid.Empty;
public string LeaveTypeName { get; set; } = string.Empty;
public Guid LeaveTypeId { get; set; } = Guid.Empty;
public string FullName { get; set; } = string.Empty;
public DateTime DateSendLeave { get; set; } = DateTime.MinValue;
public string Status { get; set; } = string.Empty;
public string CitizenId { get; set; } = string.Empty;
public DateTime LeaveStartDate { get; set; } = DateTime.MinValue;
public DateTime LeaveEndDate { get; set; } = DateTime.MinValue;
public string Agency { get; set; } = string.Empty;
public string Org { get; set; } = string.Empty;
public string Position { get; set; } = string.Empty;
public string Level { get; set; } = string.Empty;
public string LeaveRange { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestTableDto
{
[Required]
public int Year { get; set; } = 0;
[Required]
public Guid Type { get; set; } = Guid.Empty;
[Required]
public string Status { get; set; } = "ALL";
[Required]
public int Page = 1;
[Required]
public int PageSize = 10;
public string? Keyword { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,23 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveRequestTableResultDto
{
public Guid Id { get; set; }
public string LeaveTypeName { get; set; }
public Guid LeaveTypeId { get; set; }
public string FullName { get; set; }
public DateTime DateSendLeave { get; set; }
public string Status { get; set; }
public bool IsDelete { get; set; }
public DateTime LeaveStartDate { get; set; } = DateTime.Now;
public DateTime LeaveEndDate { get; set; } = DateTime.Now;
}
}

View file

@ -0,0 +1,9 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetLeaveSummaryDto
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}

View file

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetUserLeaveProfileDto
{
[Required]
public Guid Type { get; set; } = Guid.Empty;
}
}

View file

@ -0,0 +1,37 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class GetUserLeaveProfileResultDto
{
public DateTime DateSendLeave { get; set; }
public string LeaveTypeName { get; set; }
public string Dear { get; set; }
public string FullName { get; set; }
public string PositionName { get; set; }
public string PositionLevelName { get; set; }
public string OrganizationName { get; set; }
public double LeaveLimit { get; set; }
public double LeaveTotal { get; set; }
public double LeaveRemain { get; set; }
public double RestDayTotalOld { get; set; }
public DateTime BirthDate { get; set; }
public DateTime? DateAppoint { get; set; }
public int Salary { get; set; }
public string SalaryText { get; set; }
public DateTime? LeaveLast { get; set; }
}
}

View file

@ -0,0 +1,9 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class LeaveDocumentDto
{
public Guid DocId { get; set; } = Guid.Empty;
public string Path { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,7 @@
namespace BMA.EHR.Leave.Service.DTOs.LeaveRequest
{
public class LeaveRequestApproveDto
{
public string? Reason { get; set; }
}
}

View file

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace BMA.EHR.Leave.Service.DTOs.LeaveTypes
{
public class CreateLeaveTypeDto
{
[Required]
public Guid Id { get; set; } = Guid.Empty;
[Required]
public string Name { get; set; } = string.Empty;
[Required]
public string Code { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,9 @@
namespace BMA.EHR.Leave.Service.DTOs.POI
{
public class GetPOIDto
{
public double Lat { get; set; } = 0;
public double Lon { get; set; } = 0;
}
}

View file

@ -0,0 +1,28 @@
namespace BMA.EHR.Leave.Service.DTOs.POI
{
public class GetPOIResultDto
{
public List<POIItem> results { get; set; } = new List<POIItem>();
}
public class POIItem
{
public string place_id { get; set; } = string.Empty;
public string name { get; set; } = string.Empty;
public GeometryItem geometry { get; set; } = new();
}
public class GeometryItem
{
public LocationItem location { get; set; } = new();
}
public class LocationItem
{
public double lat { get; set; } = 0;
public double lng { get; set; } = 0;
}
}

View file

@ -0,0 +1,13 @@
namespace BMA.EHR.Leave.Service.DTOs.POI
{
public class POIResultDto
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public double Latitude { get; set; } = 0;
public double Longitude { get; set; } = 0;
}
}

View file

@ -0,0 +1,11 @@
namespace BMA.EHR.Leave.Service.DTOs.Reports
{
public class GetLeaveDetailReportDto
{
public DateTime StartDate { get; set; } = DateTime.MinValue;
public DateTime EndDate { get; set; } = DateTime.MinValue;
public string Type { get; set; } = string.Empty;
}
}

View file

@ -0,0 +1,12 @@
namespace BMA.EHR.Leave.Service.DTOs.Reports
{
public class GetLeaveReportDto
{
public string? Type { get; set; } = "FULL";
public DateTime StartDate { get; set; } = DateTime.MinValue;
public DateTime EndDate { get; set; } = DateTime.MinValue;
}
}

27
BMA.EHR.Leave/Dockerfile Normal file
View file

@ -0,0 +1,27 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["BMA.EHR.Domain/BMA.EHR.Domain.csproj", "BMA.EHR.Domain/"]
COPY ["BMA.EHR.Application/BMA.EHR.Application.csproj", "BMA.EHR.Application/"]
COPY ["BMA.EHR.Infrastructure/BMA.EHR.Infrastructure.csproj", "BMA.EHR.Infrastructure/"]
COPY ["BMA.EHR.Leave/BMA.EHR.Leave.csproj", "BMA.EHR.Leave/"]
RUN dotnet restore "BMA.EHR.Leave/BMA.EHR.Leave.csproj"
COPY . .
WORKDIR "/src/BMA.EHR.Leave"
RUN dotnet build "BMA.EHR.Leave.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "BMA.EHR.Leave.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "BMA.EHR.Leave.dll"]

View file

@ -0,0 +1,15 @@
using Hangfire.Dashboard;
using System.Diagnostics.CodeAnalysis;
namespace BMA.EHR.Leave.Service.Filters
{
public class CustomAuthorizeFilter : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
//var httpcontext = context.GetHttpContext();
//return httpcontext.User.Identity.IsAuthenticated;
return true;
}
}
}

208
BMA.EHR.Leave/Program.cs Normal file
View file

@ -0,0 +1,208 @@
using BMA.EHR.Application;
using BMA.EHR.Leave.Service;
using BMA.EHR.Domain.Middlewares;
using BMA.EHR.Infrastructure;
using BMA.EHR.Infrastructure.Persistence;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using Serilog;
using Serilog.Exceptions;
using Serilog.Sinks.Elasticsearch;
using System.Reflection;
using System.Text;
using Hangfire;
using Hangfire.MySql;
using System.Transactions;
using BMA.EHR.Leave.Service.Filters;
using Hangfire.Common;
using BMA.EHR.Application.Repositories.Leaves.TimeAttendants;
var builder = WebApplication.CreateBuilder(args);
{
var issuer = builder.Configuration["Jwt:Issuer"];
var key = builder.Configuration["Jwt:Key"];
IdentityModelEventSource.ShowPII = true;
builder.Services.AddHttpContextAccessor();
builder.Services.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
});
builder.Services.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
builder.Services.AddEndpointsApiExplorer();
// Authorization
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{
opt.SaveToken = true;
opt.RequireHttpsMetadata = false; //false for dev
opt.Authority = issuer;
opt.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
builder.Services.AddAuthorization();
// use serilog
ConfigureLogs();
builder.Host.UseSerilog();
// Add config CORS
builder.Services.AddCors(options => options.AddDefaultPolicy(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowedToAllowWildcardSubdomains();
}));
// Add services to the container.
builder.Services.AddApplication();
builder.Services.AddLeaveApplication();
builder.Services.AddPersistence(builder.Configuration);
builder.Services.AddLeavePersistence(builder.Configuration);
builder.Services.AddControllers(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
})
.AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
builder.Services.AddSwaggerGen();
builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
builder.Services.AddHealthChecks();
// Add Hangfire services.
var defaultConnection = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseStorage(
new MySqlStorage(
defaultConnection,
new MySqlStorageOptions
{
TransactionIsolationLevel = IsolationLevel.ReadCommitted,
QueuePollInterval = TimeSpan.FromSeconds(15),
JobExpirationCheckInterval = TimeSpan.FromHours(1),
CountersAggregateInterval = TimeSpan.FromMinutes(5),
PrepareSchemaIfNecessary = true,
DashboardJobListLimit = 50000,
TransactionTimeout = TimeSpan.FromMinutes(1),
TablesPrefix = "Hangfire"
})));
builder.Services.AddHangfireServer();
}
var app = builder.Build();
{
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
}
app.MapHealthChecks("/health");
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapControllers();
app.UseMiddleware<ErrorHandlerMiddleware>();
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
Authorization = new[] { new CustomAuthorizeFilter() }
});
var manager = new RecurringJobManager();
if (manager != null)
{
manager.AddOrUpdate("ปรับปรุงรอบการลงเวลาทำงาน", Job.FromExpression<UserDutyTimeRepository>(x => x.UpdateUserDutyTime()), Cron.Daily(1, 0), TimeZoneInfo.Local);
}
// apply migrations
await using var scope = app.Services.CreateAsyncScope();
await using var db = scope.ServiceProvider.GetRequiredService<LeaveDbContext>();
await db.Database.MigrateAsync();
// seed default data
await LeaveSeeder.SeedLeaveType(app);
app.Run();
}
void ConfigureLogs()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",
optional: true)
.Build();
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Error()
.WriteTo.Console()
.Enrich.WithExceptionDetails()
.WriteTo.Elasticsearch(ConfigureElasticSink(configuration, environment ?? ""))
.Enrich.WithProperty("Environment", environment)
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
ElasticsearchSinkOptions ConfigureElasticSink(IConfigurationRoot configuration, string environment)
{
return new ElasticsearchSinkOptions(new Uri(configuration["ElasticConfiguration:Uri"] ?? ""))
{
AutoRegisterTemplate = true,
IndexFormat = $"{Assembly.GetExecutingAssembly()?.GetName()?.Name?.ToLower().Replace(".", "-")}-{environment?.ToLower().Replace(".", "-")}"
};
}

View file

@ -0,0 +1,51 @@
{
"profiles": {
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7283;http://localhost:5028"
},
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5028"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_URLS": "https://+:443;http://+:80"
},
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:27010",
"sslPort": 44373
}
}
}

Binary file not shown.

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -0,0 +1,50 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
},
"AllowedHosts": "*",
"ConnectionStrings": {
//"DefaultConnection": "User Id=sys;Password=P@ssw0rd;DBA Privilege=SYSDBA;Data Source=localhost:1521/ORCLCDB",
//"DefaultConnection": "server=192.168.1.81;user=root;password=adminVM123;port=4061;database=bma_ehr;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;",
"DefaultConnection": "server=192.168.1.80;user=root;password=adminVM123;port=3306;database=bma_ehr_demo;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;",
"ExamConnection": "server=192.168.1.80;user=root;password=adminVM123;port=3306;database=bma_ehr_exam_demo;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;",
//"LeaveConnection": "server=192.168.4.11;user=root;password=P@ssw0rd;port=3306;database=bma_ehr_leave;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;"
"LeaveConnection": "server=192.168.1.80;user=root;password=adminVM123;port=3306;database=bma_ehr_leave_demo;Convert Zero Datetime=True;Allow User Variables=true;Pooling=True;"
},
"Jwt": {
"Key": "HP-FnQMUj9msHMSD3T9HtdEnphAKoCJLEl85CIqROFI",
"Issuer": "https://id.frappet.synology.me/realms/bma-ehr"
},
"EPPlus": {
"ExcelPackage": {
"LicenseContext": "NonCommercial"
}
},
"MinIO": {
"Endpoint": "https://s3cluster.frappet.com/",
"AccessKey": "frappet",
"SecretKey": "FPTadmin2357",
"BucketName": "bma-ehr-fpt"
},
"Protocol": "HTTPS",
"Node": {
"API": "https://bma-ehr.frappet.synology.me/api/v1/probation"
},
"Mail": {
"Server": "mail.bangkok.go.th",
"User": "saraban.csc.rd@bangkok.go.th",
"Password": "Saraban5222",
"MailFrom": "saraban.csc.rd@bangkok.go.th",
"Port": "25"
},
"API": "https://bma-ehr.frappet.synology.me/api/v1"
}

View file

@ -0,0 +1,184 @@
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<head>
<script src="./keycloak.js"></script>
</head>
<body>
<div>
<button onclick="keycloak.login()">Login</button>
<button onclick="keycloak.login({ action: 'UPDATE_PASSWORD' })">Update Password</button>
<button onclick="keycloak.logout()">Logout</button>
<button onclick="keycloak.register()">Register</button>
<button onclick="keycloak.accountManagement()">Account</button>
<button onclick="refreshToken(9999)">Refresh Token</button>
<button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
<button onclick="loadProfile()">Get Profile</button>
<button onclick="updateProfile()">Update profile</button>
<button onclick="loadUserInfo()">Get User Info</button>
<button onclick="output(keycloak.tokenParsed)">Show Token</button>
<button onclick="output(keycloak.refreshTokenParsed)">Show Refresh Token</button>
<button onclick="output(keycloak.idTokenParsed)">Show ID Token</button>
<button onclick="showExpires()">Show Expires</button>
<button onclick="output(keycloak)">Show Details</button>
<button onclick="output(keycloak.createLoginUrl())">Show Login URL</button>
<button onclick="output(keycloak.createLogoutUrl())">Show Logout URL</button>
<button onclick="output(keycloak.createRegisterUrl())">Show Register URL</button>
<button onclick="output(keycloak.createAccountUrl())">Show Account URL</button>
</div>
<h2>Result</h2>
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px; word-wrap: break-word; white-space: pre-wrap;" id="output"></pre>
<h2>Events</h2>
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px; word-wrap: break-word; white-space: pre-wrap;" id="events"></pre>
<script>
function loadProfile() {
keycloak.loadUserProfile().success(function(profile) {
output(profile);
}).error(function() {
output('Failed to load profile');
});
}
function updateProfile() {
var url = keycloak.createAccountUrl().split('?')[0];
var req = new XMLHttpRequest();
req.open('POST', url, true);
req.setRequestHeader('Accept', 'application/json');
req.setRequestHeader('Content-Type', 'application/json');
req.setRequestHeader('Authorization', 'bearer ' + keycloak.token);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
output('Success');
} else {
output('Failed');
}
}
}
req.send('{"email":"myemail@foo.bar","firstName":"test","lastName":"bar"}');
}
function loadUserInfo() {
keycloak.loadUserInfo().success(function(userInfo) {
output(userInfo);
}).error(function() {
output('Failed to load user info');
});
}
function refreshToken(minValidity) {
keycloak.updateToken(minValidity).then(function(refreshed) {
if (refreshed) {
output(keycloak.tokenParsed);
} else {
output('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
}
}).catch(function() {
output('Failed to refresh token');
});
}
function showExpires() {
if (!keycloak.tokenParsed) {
output("Not authenticated");
return;
}
var o = 'Token Expires:\t\t' + new Date((keycloak.tokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
o += 'Token Expires in:\t' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds\n';
if (keycloak.refreshTokenParsed) {
o += 'Refresh Token Expires:\t' + new Date((keycloak.refreshTokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
o += 'Refresh Expires in:\t' + Math.round(keycloak.refreshTokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds';
}
output(o);
}
function output(data) {
if (typeof data === 'object') {
data = JSON.stringify(data, null, ' ');
}
document.getElementById('output').innerHTML = data;
}
function event(event) {
var e = document.getElementById('events').innerHTML;
document.getElementById('events').innerHTML = new Date().toLocaleString() + "\t" + event + "\n" + e;
}
var keycloak = Keycloak();
keycloak.onAuthSuccess = function () {
event('Auth Success');
};
keycloak.onAuthError = function (errorData) {
event("Auth Error: " + JSON.stringify(errorData) );
};
keycloak.onAuthRefreshSuccess = function () {
event('Auth Refresh Success');
};
keycloak.onAuthRefreshError = function () {
event('Auth Refresh Error');
};
keycloak.onAuthLogout = function () {
event('Auth Logout');
};
keycloak.onTokenExpired = function () {
event('Access token expired.');
};
keycloak.onActionUpdate = function (status) {
switch (status) {
case 'success':
event('Action completed successfully'); break;
case 'cancelled':
event('Action cancelled by user'); break;
case 'error':
event('Action failed'); break;
}
};
// Flow can be changed to 'implicit' or 'hybrid', but then client must enable implicit flow in admin console too
var initOptions = {
responseMode: 'fragment',
flow: 'standard'
};
keycloak.init(initOptions).then(function(authenticated) {
output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')');
}).catch(function() {
output('Init Error');
});
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,7 @@
{
"realm": "bma-ehr",
"auth-server-url": "https://id.frappet.synology.me",
"ssl-required": "external",
"resource": "bma-ehr",
"public-client": true
}