diff --git a/BMA.EHR.Application/ApplicationServicesRegistration.cs b/BMA.EHR.Application/ApplicationServicesRegistration.cs index f470820d..175de254 100644 --- a/BMA.EHR.Application/ApplicationServicesRegistration.cs +++ b/BMA.EHR.Application/ApplicationServicesRegistration.cs @@ -1,7 +1,7 @@ using BMA.EHR.Application.Messaging; using BMA.EHR.Application.Repositories; using BMA.EHR.Application.Repositories.Commands; -using BMA.EHR.Application.Repositories.Leaves; +using BMA.EHR.Application.Repositories.Leaves.TimeAttendants; using BMA.EHR.Application.Repositories.MessageQueue; using BMA.EHR.Application.Repositories.Reports; using Microsoft.Extensions.DependencyInjection; @@ -36,6 +36,7 @@ namespace BMA.EHR.Application services.AddTransient(); services.AddTransient(); + services.AddTransient(); return services; } diff --git a/BMA.EHR.Application/Repositories/Leaves/DutyTimeRepository.cs b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/DutyTimeRepository.cs similarity index 88% rename from BMA.EHR.Application/Repositories/Leaves/DutyTimeRepository.cs rename to BMA.EHR.Application/Repositories/Leaves/TimeAttendants/DutyTimeRepository.cs index 57e5880f..49a3d9aa 100644 --- a/BMA.EHR.Application/Repositories/Leaves/DutyTimeRepository.cs +++ b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/DutyTimeRepository.cs @@ -1,11 +1,11 @@ using BMA.EHR.Application.Common.Interfaces; using BMA.EHR.Application.Messaging; -using BMA.EHR.Domain.Models.Leave; +using BMA.EHR.Domain.Models.Leave.TimeAttendants; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; -namespace BMA.EHR.Application.Repositories.Leaves +namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants { public class DutyTimeRepository : GenericRepository { @@ -61,6 +61,11 @@ namespace BMA.EHR.Application.Repositories.Leaves return await _dbContext.Set().Where(x => x.IsActive).ToListAsync(); } + public async Task GetDefaultAsync() + { + return await _dbContext.Set().Where(x => x.IsDefault).FirstOrDefaultAsync(); + } + #endregion } } diff --git a/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserTimeStampRepository.cs b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserTimeStampRepository.cs new file mode 100644 index 00000000..9d71ad97 --- /dev/null +++ b/BMA.EHR.Application/Repositories/Leaves/TimeAttendants/UserTimeStampRepository.cs @@ -0,0 +1,71 @@ +using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Application.Messaging; +using BMA.EHR.Domain.Models.Leave.TimeAttendants; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; + +namespace BMA.EHR.Application.Repositories.Leaves.TimeAttendants +{ + public class UserTimeStampRepository : GenericRepository + { + #region " Fields " + + private readonly IApplicationDBContext _dbContext; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly OrganizationCommonRepository _organizationCommonRepository; + private readonly UserProfileRepository _userProfileRepository; + private readonly IConfiguration _configuration; + private readonly EmailSenderService _emailSenderService; + + #endregion + + #region " Constructor and Destuctor " + + public UserTimeStampRepository(IApplicationDBContext dbContext, + IHttpContextAccessor httpContextAccessor, + OrganizationCommonRepository organizationCommonRepository, + UserProfileRepository userProfileRepository, + IConfiguration configuration, + EmailSenderService emailSenderService) : base(dbContext, httpContextAccessor) + { + _dbContext = dbContext; + _httpContextAccessor = httpContextAccessor; + _organizationCommonRepository = organizationCommonRepository; + _userProfileRepository = userProfileRepository; + _configuration = configuration; + _emailSenderService = emailSenderService; + } + + #endregion + + #region " Properties " + + protected Guid UserOrganizationId + { + get + { + if (UserId != null || UserId != "") + return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!)); + else + return Guid.Empty; + } + } + + #endregion + + #region " Methods " + + public async Task GetLastRecord(Guid keycloakId) + { + var data = await _dbContext.Set() + .Where(u => u.KeycloakUserId == keycloakId) + .OrderByDescending(u => u.CheckIn) + .FirstOrDefaultAsync(); + + return data; + } + + #endregion + } +} diff --git a/BMA.EHR.Application/Repositories/MinIOService.cs b/BMA.EHR.Application/Repositories/MinIOService.cs index 34c01048..93ff622e 100644 --- a/BMA.EHR.Application/Repositories/MinIOService.cs +++ b/BMA.EHR.Application/Repositories/MinIOService.cs @@ -315,6 +315,40 @@ namespace BMA.EHR.Application.Repositories } } + public async Task UploadFileAsync(string fileName, string subFolder) + { + try + { + var fileContents = File.ReadAllBytes(fileName); + System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileContents); + //var fileNameWithoutExt = Path.GetFileNameWithoutExtension(fileName); + var fileExt = Path.GetExtension(fileName); + var fileType = MimeTypeMap.GetMimeType(fileExt); + var file_name = Path.GetFileName(fileName); + Console.WriteLine($"{_bucketName}{subFolder}"); + Console.WriteLine(fileName); + Console.WriteLine(file_name); + Console.WriteLine(filestream); + Console.WriteLine(fileType); + + var request = new PutObjectRequest + { + //BucketName = $"{_bucketName}", + BucketName = $"{_bucketName}{subFolder}", + Key = file_name, + InputStream = filestream, + ContentType = fileType, + CannedACL = S3CannedACL.PublicRead + }; + + await _s3Client.PutObjectAsync(request); + } + catch + { + throw; + } + } + public async Task GenerateJsonFile(string json, string path, string fileName) { var tmpDir = Path.Combine("tmp"); diff --git a/BMA.EHR.Domain/Models/Leave/DutyTime.cs b/BMA.EHR.Domain/Models/Leave/TimeAttendants/DutyTime.cs similarity index 96% rename from BMA.EHR.Domain/Models/Leave/DutyTime.cs rename to BMA.EHR.Domain/Models/Leave/TimeAttendants/DutyTime.cs index ea815fde..64a986a0 100644 --- a/BMA.EHR.Domain/Models/Leave/DutyTime.cs +++ b/BMA.EHR.Domain/Models/Leave/TimeAttendants/DutyTime.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; -namespace BMA.EHR.Domain.Models.Leave +namespace BMA.EHR.Domain.Models.Leave.TimeAttendants { public class DutyTime : EntityBase { diff --git a/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs b/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs new file mode 100644 index 00000000..aa650ad4 --- /dev/null +++ b/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs @@ -0,0 +1,44 @@ +using BMA.EHR.Domain.Models.Base; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace BMA.EHR.Domain.Models.Leave.TimeAttendants +{ + public class UserTimeStamp : EntityBase + { + [Required, Comment("รหัส User ของ Keycloak")] + public Guid KeycloakUserId { get; set; } = Guid.Empty; + + [Required, Comment("วัน เวลา เข้างาน")] + public DateTime CheckIn { get; set; } = DateTime.MinValue; + + [Comment("วัน เวลา ออกงาน")] + public DateTime? CheckOut { get; set; } + + [Required, Comment("นำไปประมวลผลแล้วหรือยัง")] + public bool IsProcess { get; set; } = false; + + [Required, Comment("พิกัดละติจูด")] + public double Lat { get; set; } = 0; + + [Required, Comment("พิกัดลองจิจูด")] + public double Lon { get; set; } = 0; + + [Required, Comment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์")] + public string POI { get; set; } = string.Empty; + + [Required, Comment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง")] + public bool IsLocation { get; set; } = true; + + [Comment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่")] + public string? LocationName { get; set; } = string.Empty; + + [Required, Comment("รูปถ่ายสถานที่ checkin/checkout")] + public string ImageUrl { get; set; } = string.Empty; + + [Comment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้)")] + public string? Remark { get; set; } = string.Empty; + + + } +} diff --git a/BMA.EHR.Infrastructure/InfrastructureServiceRegistration.cs b/BMA.EHR.Infrastructure/InfrastructureServiceRegistration.cs index 919c3af1..ae07fa84 100644 --- a/BMA.EHR.Infrastructure/InfrastructureServiceRegistration.cs +++ b/BMA.EHR.Infrastructure/InfrastructureServiceRegistration.cs @@ -9,6 +9,30 @@ namespace BMA.EHR.Infrastructure { public static class InfrastructureServiceRegistration { + public static IServiceCollection AddLeavePersistence(this IServiceCollection services, + IConfiguration configuration) + { + services.AddScoped(provider => provider.GetService()); + + // leave db context + var connectionStringLeave = configuration.GetConnectionString("LeaveConnection"); + + services.AddDbContext(options => + options.UseMySql(connectionStringLeave, ServerVersion.AutoDetect(connectionStringLeave), + b => + { + b.MigrationsAssembly(typeof(LeaveDbContext).Assembly.FullName); + b.MigrationsHistoryTable("__LeaveMigrationsHistory"); + + }), + ServiceLifetime.Transient); + + services.AddScoped(provider => provider.GetService()); + + return services; + } + + public static IServiceCollection AddPersistence(this IServiceCollection services, IConfiguration configuration) { @@ -41,22 +65,7 @@ namespace BMA.EHR.Infrastructure }), ServiceLifetime.Transient); - services.AddScoped(provider => provider.GetService()); - - // leave db context - var connectionStringLeave = configuration.GetConnectionString("LeaveConnection"); - - services.AddDbContext(options => - options.UseMySql(connectionStringLeave, ServerVersion.AutoDetect(connectionStringLeave), - b => - { - b.MigrationsAssembly(typeof(LeaveDbContext).Assembly.FullName); - b.MigrationsHistoryTable("__LeaveMigrationsHistory"); - - }), - ServiceLifetime.Transient); - - services.AddScoped(provider => provider.GetService()); + return services; } diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .Designer.cs new file mode 100644 index 00000000..2344c7db --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .Designer.cs @@ -0,0 +1,180 @@ +// +using System; +using BMA.EHR.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + [DbContext(typeof(LeaveDbContext))] + [Migration("20231110034258_ Add user timestamps ")] + partial class Addusertimestamps + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasComment("คำอธิบาย"); + + b.Property("EndTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงบ่าย"); + + b.Property("EndTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงเช้า"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)") + .HasComment("สถานะการเปิดใช้งาน (เปิด/ปิด)"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)") + .HasComment("สถานะว่ารอบใดเป็นค่า Default ของข้าราชการ (สำหรับทุกคนที่ยังไม่ได้ทำการเลือกรอบ)"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("StartTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงบ่าย"); + + b.Property("StartTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงเช้า"); + + b.HasKey("Id"); + + b.ToTable("DutyTimes"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserTimeStamp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckIn") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา เข้างาน"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("นำไปประมวลผลแล้วหรือยัง"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .cs new file mode 100644 index 00000000..45c4805c --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110034258_ Add user timestamps .cs @@ -0,0 +1,48 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class Addusertimestamps : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserTimeStamps", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, comment: "PrimaryKey", collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false, comment: "สร้างข้อมูลเมื่อ"), + CreatedUserId = table.Column(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่สร้างข้อมูล") + .Annotation("MySql:CharSet", "utf8mb4"), + LastUpdatedAt = table.Column(type: "datetime(6)", nullable: true, comment: "แก้ไขข้อมูลล่าสุดเมื่อ"), + LastUpdateUserId = table.Column(type: "varchar(40)", maxLength: 40, nullable: false, comment: "User Id ที่แก้ไขข้อมูลล่าสุด") + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedFullName = table.Column(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่สร้างข้อมูล") + .Annotation("MySql:CharSet", "utf8mb4"), + LastUpdateFullName = table.Column(type: "varchar(200)", maxLength: 200, nullable: false, comment: "ชื่อ User ที่แก้ไขข้อมูลล่าสุด") + .Annotation("MySql:CharSet", "utf8mb4"), + KeycloakUserId = table.Column(type: "char(36)", nullable: false, comment: "รหัส User ของ Keycloak", collation: "ascii_general_ci"), + CheckIn = table.Column(type: "datetime(6)", nullable: false, comment: "วัน เวลา เข้างาน"), + CheckOut = table.Column(type: "datetime(6)", nullable: true, comment: "วัน เวลา ออกงาน"), + IsProcess = table.Column(type: "tinyint(1)", nullable: false, comment: "นำไปประมวลผลแล้วหรือยัง") + }, + constraints: table => + { + table.PrimaryKey("PK_UserTimeStamps", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserTimeStamps"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .Designer.cs new file mode 100644 index 00000000..9ce73072 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .Designer.cs @@ -0,0 +1,210 @@ +// +using System; +using BMA.EHR.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + [DbContext(typeof(LeaveDbContext))] + [Migration("20231110064104_ update field user timestamps ")] + partial class updatefieldusertimestamps + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasComment("คำอธิบาย"); + + b.Property("EndTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงบ่าย"); + + b.Property("EndTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาออกงานช่วงเช้า"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)") + .HasComment("สถานะการเปิดใช้งาน (เปิด/ปิด)"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)") + .HasComment("สถานะว่ารอบใดเป็นค่า Default ของข้าราชการ (สำหรับทุกคนที่ยังไม่ได้ทำการเลือกรอบ)"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("StartTimeAfternoon") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงบ่าย"); + + b.Property("StartTimeMorning") + .IsRequired() + .HasColumnType("longtext") + .HasComment("เวลาเข้างานช่วงเช้า"); + + b.HasKey("Id"); + + b.ToTable("DutyTimes"); + }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserTimeStamp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckIn") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา เข้างาน"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ checkin/checkout"); + + b.Property("IsLocation") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("นำไปประมวลผลแล้วหรือยัง"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Lat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด"); + + b.Property("LocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่"); + + b.Property("Lon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด"); + + b.Property("POI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์"); + + b.Property("Remark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้)"); + + b.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .cs new file mode 100644 index 00000000..ea26fd00 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231110064104_ update field user timestamps .cs @@ -0,0 +1,102 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class updatefieldusertimestamps : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImageUrl", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "รูปถ่ายสถานที่ checkin/checkout") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "IsLocation", + table: "UserTimeStamps", + type: "tinyint(1)", + nullable: false, + defaultValue: false, + comment: "true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง"); + + migrationBuilder.AddColumn( + name: "Lat", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดละติจูด"); + + migrationBuilder.AddColumn( + name: "LocationName", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Lon", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดลองจิจูด"); + + migrationBuilder.AddColumn( + name: "POI", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Remark", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้)") + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ImageUrl", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "IsLocation", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "Lat", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "LocationName", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "Lon", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "POI", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "Remark", + table: "UserTimeStamps"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs index 489d2a29..35dc067e 100644 --- a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .HasAnnotation("ProductVersion", "7.0.9") .HasAnnotation("Relational:MaxIdentifierLength", 64); - modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.DutyTime", b => + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.DutyTime", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -103,6 +103,104 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb b.ToTable("DutyTimes"); }); + + modelBuilder.Entity("BMA.EHR.Domain.Models.Leave.TimeAttendants.UserTimeStamp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CheckIn") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา เข้างาน"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(104) + .HasComment("ชื่อ User ที่สร้างข้อมูล"); + + b.Property("CreatedUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(101) + .HasComment("User Id ที่สร้างข้อมูล"); + + b.Property("ImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ checkin/checkout"); + + b.Property("IsLocation") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง"); + + b.Property("IsProcess") + .HasColumnType("tinyint(1)") + .HasComment("นำไปประมวลผลแล้วหรือยัง"); + + b.Property("KeycloakUserId") + .HasColumnType("char(36)") + .HasComment("รหัส User ของ Keycloak"); + + b.Property("LastUpdateFullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnOrder(105) + .HasComment("ชื่อ User ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdateUserId") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnOrder(103) + .HasComment("User Id ที่แก้ไขข้อมูลล่าสุด"); + + b.Property("LastUpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(102) + .HasComment("แก้ไขข้อมูลล่าสุดเมื่อ"); + + b.Property("Lat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด"); + + b.Property("LocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่"); + + b.Property("Lon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด"); + + b.Property("POI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์"); + + b.Property("Remark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้)"); + + b.HasKey("Id"); + + b.ToTable("UserTimeStamps"); + }); #pragma warning restore 612, 618 } } diff --git a/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs b/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs index dc369b98..5e2feddc 100644 --- a/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs +++ b/BMA.EHR.Infrastructure/Persistence/LeaveDbContext.cs @@ -1,15 +1,17 @@ using BMA.EHR.Application.Common.Interfaces; -using BMA.EHR.Domain.Models.Leave; +using BMA.EHR.Domain.Models.Leave.TimeAttendants; using Microsoft.EntityFrameworkCore; namespace BMA.EHR.Infrastructure.Persistence { public class LeaveDbContext : DbContext, IApplicationDBContext { - #region " Leave " + #region " Check-In " public DbSet DutyTimes { get; set; } + public DbSet UserTimeStamps { get; set; } + #endregion diff --git a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj index 07f6ffbf..9711cd8c 100644 --- a/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj +++ b/BMA.EHR.Leave.Service/BMA.EHR.Leave.Service.csproj @@ -9,8 +9,13 @@ True . BMA.EHR.Command.Service + $(NoWarn);1591 + + + + $(DockerDefaultDockerfile) diff --git a/BMA.EHR.Leave.Service/Controllers/CheckInController.cs b/BMA.EHR.Leave.Service/Controllers/CheckInController.cs deleted file mode 100644 index 64a50691..00000000 --- a/BMA.EHR.Leave.Service/Controllers/CheckInController.cs +++ /dev/null @@ -1,114 +0,0 @@ -using BMA.EHR.Application.Repositories; -using BMA.EHR.Application.Repositories.Leaves; -using BMA.EHR.Command.Service.DTOs.POI; -using BMA.EHR.Domain.Common; -using BMA.EHR.Infrastructure.Persistence; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -using Swashbuckle.AspNetCore.Annotations; -using System.Security.Claims; - -namespace BMA.EHR.Command.Service.Controllers -{ - [Route("api/v{version:apiVersion}/leave/check-in")] - [ApiVersion("1.0")] - [ApiController] - [Produces("application/json")] - [Authorize] - [SwaggerTag("API ระบบลงเวลาทำงาน")] - public class CheckInController : BaseController - { - #region " Fields " - - private readonly DutyTimeRepository _repository; - 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 CheckInController(DutyTimeRepository repository, - LeaveDbContext context, - IHttpContextAccessor httpContextAccessor, - IWebHostEnvironment hostingEnvironment, - IConfiguration configuration, - UserProfileRepository userProfileRepository) - { - _repository = repository; - _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 Guid OcId - { - get - { - if (UserId != null || UserId != "") - return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!)); - else - return Guid.Empty; - } - } - - #endregion - - #region " Methods " - - [HttpPost("locations")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status401Unauthorized)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - [AllowAnonymous] - public async Task> ListPOIAsync([FromBody] GetPOIDto data) - { - var api_url = $"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={data.Lat},{data.Lon}&types=point_of_interest&radius=100&sensor=false&language=th&key=AIzaSyDXKvpU4hinlCKGOEJUgLDbx9yCSZe3woc"; - - using (var client = new HttpClient()) - { - var req = new HttpRequestMessage(HttpMethod.Get, api_url); - - var res = await client.SendAsync(req); - var result = await res.Content.ReadAsStringAsync(); - var poi_result = JsonConvert.DeserializeObject(result); - - var poi_data = new List(); - - if (poi_result != null) - { - foreach (var r in poi_result.results.Take(5)) - { - poi_data.Add(new POIResultDto - { - Id = r.place_id, - Name = r.name, - Latitude = r.geometry.location.lat, - Longitude = r.geometry.location.lng, - }); - } - } - - return Success(poi_data); - } - } - - #endregion - } -} diff --git a/BMA.EHR.Leave.Service/Controllers/DutyTimeController.cs b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs similarity index 63% rename from BMA.EHR.Leave.Service/Controllers/DutyTimeController.cs rename to BMA.EHR.Leave.Service/Controllers/LeaveController.cs index cf866334..94d89203 100644 --- a/BMA.EHR.Leave.Service/Controllers/DutyTimeController.cs +++ b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs @@ -1,8 +1,10 @@ using BMA.EHR.Application.Repositories; -using BMA.EHR.Application.Repositories.Leaves; +using BMA.EHR.Application.Repositories.Leaves.TimeAttendants; +using BMA.EHR.Command.Service.DTOs.CheckIn; using BMA.EHR.Command.Service.DTOs.DutyTime; using BMA.EHR.Domain.Common; using BMA.EHR.Domain.Models.Leave; +using BMA.EHR.Domain.Models.Leave.TimeAttendants; using BMA.EHR.Domain.Shared; using BMA.EHR.Infrastructure.Persistence; using Microsoft.AspNetCore.Authorization; @@ -12,40 +14,43 @@ using System.Security.Claims; namespace BMA.EHR.Command.Service.Controllers { - [Route("api/v{version:apiVersion}/leave/duty-time")] + [Route("api/v{version:apiVersion}/leave")] [ApiVersion("1.0")] [ApiController] [Produces("application/json")] [Authorize] - [SwaggerTag("API ระบบจัดการรอบการลงเวลาทำงาน")] - public class DutyTimeController : BaseController + [SwaggerTag("API ระบบลงเวลาและการลา")] + public class LeaveController : BaseController { #region " Fields " - private readonly DutyTimeRepository _repository; + private readonly DutyTimeRepository _dutyTimeRepository; private readonly LeaveDbContext _context; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IWebHostEnvironment _hostingEnvironment; private readonly IConfiguration _configuration; private readonly UserProfileRepository _userProfileRepository; + private readonly UserTimeStampRepository _userTimeStampRepository; #endregion #region " Constuctor and Destructor " - public DutyTimeController(DutyTimeRepository repository, + public LeaveController(DutyTimeRepository dutyTimeRepository, LeaveDbContext context, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, - UserProfileRepository userProfileRepository) + UserProfileRepository userProfileRepository, + UserTimeStampRepository userTimeStampRepository) { - _repository = repository; + _dutyTimeRepository = dutyTimeRepository; _context = context; _httpContextAccessor = httpContextAccessor; _hostingEnvironment = hostingEnvironment; _configuration = configuration; _userProfileRepository = userProfileRepository; + _userTimeStampRepository = userTimeStampRepository; } #endregion @@ -73,6 +78,8 @@ namespace BMA.EHR.Command.Service.Controllers #region " Methods " + #region " Duty Time รอบการทำงาน " + /// /// LV1_004 - ข้อมูลทั้งหมดของรอบการปฏิบัติงาน (ADMIN) /// @@ -81,13 +88,13 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำรายการสำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpGet] + [HttpGet("duty-time")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> GetAllAsync() { - var data = await _repository.GetAllAsync(); + var data = await _dutyTimeRepository.GetAllAsync(); return Success(data); } @@ -100,13 +107,13 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำรายการสำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpGet("{id:guid}")] + [HttpGet("duty-time/{id:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> GetByIdAsync(Guid id) { - var data = await _repository.GetByIdAsync(id); + var data = await _dutyTimeRepository.GetByIdAsync(id); return Success(data); } @@ -119,7 +126,7 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำรายการสำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpPost] + [HttpPost("duty-time")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] @@ -141,7 +148,7 @@ namespace BMA.EHR.Command.Service.Controllers throw new Exception(GlobalMessages.StartTimeGreaterEnd); } - var oldData = await _repository.GetAllAsync(); + var oldData = await _dutyTimeRepository.GetAllAsync(); if (oldData == null || oldData.Count == 0) { var inserted = new DutyTime @@ -156,7 +163,7 @@ namespace BMA.EHR.Command.Service.Controllers IsDefault = true, }; - var ret = await _repository.AddAsync(inserted); + var ret = await _dutyTimeRepository.AddAsync(inserted); return Success(ret); } @@ -167,7 +174,7 @@ namespace BMA.EHR.Command.Service.Controllers foreach (var d in oldData) { d.IsDefault = false; - await _repository.UpdateAsync(d); + await _dutyTimeRepository.UpdateAsync(d); } } @@ -183,7 +190,7 @@ namespace BMA.EHR.Command.Service.Controllers IsDefault = data.IsDefault, }; - var ret = await _repository.AddAsync(inserted); + var ret = await _dutyTimeRepository.AddAsync(inserted); return Success(ret); } @@ -198,26 +205,26 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำรายการสำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpPut("{id:guid}")] + [HttpPut("duty-time/{id:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> PutAsync(Guid id, [FromBody] UpdateDutyTimeDto data) { - var oldData = await _repository.GetByIdAsync(id); + var oldData = await _dutyTimeRepository.GetByIdAsync(id); if (oldData == null) { throw new Exception(GlobalMessages.DataNotFound); } else - { - var oldDataList = await _repository.GetAllAsync(); + { + var oldDataList = await _dutyTimeRepository.GetAllAsync(); if (data.IsDefault) { foreach (var d in oldDataList) { d.IsDefault = false; - await _repository.UpdateAsync(d); + await _dutyTimeRepository.UpdateAsync(d); } } @@ -225,7 +232,7 @@ namespace BMA.EHR.Command.Service.Controllers oldData.IsDefault = data.IsDefault; oldData.IsActive = data.IsActive; - await _repository.UpdateAsync(oldData); + await _dutyTimeRepository.UpdateAsync(oldData); return Success(oldData); @@ -241,13 +248,13 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำรายการสำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpDelete("{id:guid}")] + [HttpDelete("duty-time/{id:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> DeleteAsync(Guid id) { - var oldData = await _repository.GetByIdAsync(id); + var oldData = await _dutyTimeRepository.GetByIdAsync(id); if (oldData == null) { throw new Exception(GlobalMessages.DataNotFound); @@ -259,11 +266,87 @@ namespace BMA.EHR.Command.Service.Controllers throw new Exception("ไม่สามารถลบรอบการปฏิบัติงานที่ยังใช้งานอยู่ได้"); } - await _repository.DeleteAsync(oldData); + await _dutyTimeRepository.DeleteAsync(oldData); return Success(); } } + /// + /// LV1_012 - ข้อมูลทั้งหมดของรอบการปฏิบัติงานที่ active (ADMIN) + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("round")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GetAllActiveAsync() + { + var data = await _dutyTimeRepository.GetAllActiveAsync(); + + return Success(data); + } + + #endregion + + #region " Check-In Check-Out ลงเวลา " + + /// + /// LV1_006 - เช็คเวลาต้องลงเวลาเข้าหรือออกงาน (USER) + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("check-time")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CheckTimeAsync() + { + var userId = UserId == null ? Guid.Empty : Guid.Parse(UserId); + var data = await _userTimeStampRepository.GetLastRecord(userId); + + // TODO : รอดุึงรอบที่ผูกกับ user + var duty = await _dutyTimeRepository.GetDefaultAsync(); + CheckInResultDto ret; + + if (data == null) + { + ret = new CheckInResultDto + { + StartTimeMorning = duty == null ? "00:00" : duty.StartTimeMorning, + EndTimeMorning = duty == null ? "00:00" : duty.EndTimeMorning, + StartTimeAfternoon = duty == null ? "00:00" : duty.StartTimeAfternoon, + EndTimeAfternoon = duty == null ? "00:00" : duty.EndTimeAfternoon, + Description = duty == null ? "-" : duty.Description, + CheckInTime = null, + CheckInId = null, + }; + } + else + { + ret = new CheckInResultDto + { + StartTimeMorning = duty == null ? "00:00" : duty.StartTimeMorning, + EndTimeMorning = duty == null ? "00:00" : duty.EndTimeMorning, + StartTimeAfternoon = duty == null ? "00:00" : duty.StartTimeAfternoon, + EndTimeAfternoon = duty == null ? "00:00" : duty.EndTimeAfternoon, + Description = duty == null ? "-" : duty.Description, + CheckInTime = data.CheckIn, + CheckInId = data.CheckOut == null ? null : data.Id, + }; + } + + return Success(ret); + } + + #endregion + #endregion } } diff --git a/BMA.EHR.Leave.Service/Controllers/RoundController.cs b/BMA.EHR.Leave.Service/Controllers/RoundController.cs deleted file mode 100644 index ccaf315f..00000000 --- a/BMA.EHR.Leave.Service/Controllers/RoundController.cs +++ /dev/null @@ -1,94 +0,0 @@ -using BMA.EHR.Application.Repositories; -using BMA.EHR.Application.Repositories.Leaves; -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.Command.Service.Controllers -{ - [Route("api/v{version:apiVersion}/leave/round")] - [ApiVersion("1.0")] - [ApiController] - [Produces("application/json")] - [Authorize] - [SwaggerTag("API ระบบจัดการรอบการลงเวลาทำงาน")] - public class RoundController : BaseController - { - #region " Fields " - - private readonly DutyTimeRepository _repository; - 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 RoundController(DutyTimeRepository repository, - LeaveDbContext context, - IHttpContextAccessor httpContextAccessor, - IWebHostEnvironment hostingEnvironment, - IConfiguration configuration, - UserProfileRepository userProfileRepository) - { - _repository = repository; - _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 Guid OcId - { - get - { - if (UserId != null || UserId != "") - return _userProfileRepository.GetUserOCId(Guid.Parse(UserId!)); - else - return Guid.Empty; - } - } - - #endregion - - #region " Methods " - - /// - /// LV1_012 - ข้อมูลทั้งหมดของรอบการปฏิบัติงานที่ active (ADMIN) - /// - /// - /// - /// เมื่อทำรายการสำเร็จ - /// ไม่ได้ Login เข้าระบบ - /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpGet] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status401Unauthorized)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async Task> GetAllActiveAsync() - { - var data = await _repository.GetAllActiveAsync(); - - return Success(data); - } - - #endregion - } -} diff --git a/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckInResultDto.cs b/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckInResultDto.cs new file mode 100644 index 00000000..74a8bb71 --- /dev/null +++ b/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckInResultDto.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace BMA.EHR.Command.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"; + } +} diff --git a/BMA.EHR.Leave.Service/Program.cs b/BMA.EHR.Leave.Service/Program.cs index a20db411..401f0a46 100644 --- a/BMA.EHR.Leave.Service/Program.cs +++ b/BMA.EHR.Leave.Service/Program.cs @@ -80,6 +80,7 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddApplication(); builder.Services.AddPersistence(builder.Configuration); + builder.Services.AddLeavePersistence(builder.Configuration); builder.Services.AddControllers(options => { diff --git a/BMA.EHR.Leave.Service/appsettings.json b/BMA.EHR.Leave.Service/appsettings.json index d780e018..8555c0d7 100644 --- a/BMA.EHR.Leave.Service/appsettings.json +++ b/BMA.EHR.Leave.Service/appsettings.json @@ -16,7 +16,9 @@ //"DefaultConnection": "User Id=sys;Password=P@ssw0rd;DBA Privilege=SYSDBA;Data Source=localhost:1521/ORCLCDB", "DefaultConnection": "server=192.168.1.9;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.9;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.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.9;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",