From 8bf646230a90775c61201fb01813fc85a9338a8d Mon Sep 17 00:00:00 2001 From: Suphonchai Phoonsawat Date: Mon, 13 Nov 2023 15:26:14 +0700 Subject: [PATCH] Check in and Check Out --- .../Repositories/MinIOService.cs | 70 ++++- .../Leave/TimeAttendants/UserTimeStamp.cs | 51 +++- ...e field user timestamps (add) .Designer.cs | 240 ++++++++++++++++ ...33_ update field user timestamps (add) .cs | 270 ++++++++++++++++++ .../LeaveDb/LeaveDbContextModelSnapshot.cs | 86 ++++-- .../Controllers/LeaveController.cs | 74 ++++- .../DTOs/CheckIn/CheckTimeDto.cs | 28 ++ 7 files changed, 769 insertions(+), 50 deletions(-) create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .Designer.cs create mode 100644 BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .cs create mode 100644 BMA.EHR.Leave.Service/DTOs/CheckIn/CheckTimeDto.cs diff --git a/BMA.EHR.Application/Repositories/MinIOService.cs b/BMA.EHR.Application/Repositories/MinIOService.cs index 93ff622e..71f6f18a 100644 --- a/BMA.EHR.Application/Repositories/MinIOService.cs +++ b/BMA.EHR.Application/Repositories/MinIOService.cs @@ -12,6 +12,8 @@ using Amazon; using BMA.EHR.Domain.Models.Organizations; using MimeTypes; using Profile = BMA.EHR.Domain.Models.HR.Profile; +using System.IO; +using Amazon.S3.Transfer; namespace BMA.EHR.Application.Repositories { @@ -238,6 +240,42 @@ namespace BMA.EHR.Application.Repositories #endregion + private async Task IsExistBucketAsync(string bucketName) + { + try + { + var response = await _s3Client.ListObjectsV2Async(new ListObjectsV2Request + { + BucketName = bucketName + }); + + return true; + } + catch + { + return false; + } + } + + private async Task CreateBucketAsync(string bucketName) + { + try + { + var request = new PutBucketRequest + { + BucketName = bucketName, + UseClientRegion = true, + }; + + var response = await _s3Client.PutBucketAsync(request); + return response.HttpStatusCode == System.Net.HttpStatusCode.OK; + } + catch + { + return false; + } + } + public List GetAllIdByRoot(Guid? id) { try @@ -315,6 +353,33 @@ namespace BMA.EHR.Application.Repositories } } + public async Task UploadFileAsync(string fileName, MemoryStream fileStream) + { + try + { + //var fileTransferUtility = new TransferUtility(_s3Client); + + var fileExt = Path.GetExtension(fileName); + var fileType = MimeTypeMap.GetMimeType(fileExt); + var file_name = Path.GetFileName(fileName); + + var request = new PutObjectRequest + { + BucketName = _bucketName, + Key = file_name, + InputStream = fileStream, + ContentType = fileType, + CannedACL = S3CannedACL.BucketOwnerFullControl + }; + + await _s3Client.PutObjectAsync(request); + } + catch + { + throw; + } + } + public async Task UploadFileAsync(string fileName, string subFolder) { try @@ -325,11 +390,6 @@ namespace BMA.EHR.Application.Repositories 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 { diff --git a/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs b/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs index aa650ad4..01bcf59e 100644 --- a/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs +++ b/BMA.EHR.Domain/Models/Leave/TimeAttendants/UserTimeStamp.cs @@ -18,27 +18,48 @@ namespace BMA.EHR.Domain.Models.Leave.TimeAttendants [Required, Comment("นำไปประมวลผลแล้วหรือยัง")] public bool IsProcess { get; set; } = false; - [Required, Comment("พิกัดละติจูด")] - public double Lat { get; set; } = 0; + [Required, Comment("พิกัดละติจูด Check-In")] + public double CheckInLat { get; set; } = 0; - [Required, Comment("พิกัดลองจิจูด")] - public double Lon { get; set; } = 0; + [Required, Comment("พิกัดลองจิจูด Check-In")] + public double CheckInLon { get; set; } = 0; - [Required, Comment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์")] - public string POI { get; set; } = string.Empty; + [Required, Comment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In")] + public string CheckInPOI { get; set; } = string.Empty; - [Required, Comment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง")] - public bool IsLocation { get; set; } = true; + [Required, Comment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In")] + public bool IsLocationCheckIn { get; set; } = true; - [Comment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่")] - public string? LocationName { get; set; } = string.Empty; + [Comment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In")] + public string? CheckInLocationName { get; set; } = string.Empty; - [Required, Comment("รูปถ่ายสถานที่ checkin/checkout")] - public string ImageUrl { get; set; } = string.Empty; + [Required, Comment("รูปถ่ายสถานที่ Check-In")] + public string CheckInImageUrl { get; set; } = string.Empty; + + [Comment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In")] + public string? CheckInRemark { get; set; } = string.Empty; + + [Required, Comment("พิกัดละติจูด Check-Out")] + public double CheckOutLat { get; set; } = 0; + + [Required, Comment("พิกัดลองจิจูด Check-Out")] + public double CheckOutLon { get; set; } = 0; + + [Required, Comment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out")] + public string CheckOutPOI { get; set; } = string.Empty; + + [Required, Comment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out")] + public bool IsLocationCheckOut { get; set; } = true; + + [Comment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out")] + public string? CheckOutLocationName { get; set; } = string.Empty; + + [Required, Comment("รูปถ่ายสถานที่ Check-Out")] + public string CheckOutImageUrl { get; set; } = string.Empty; + + [Comment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out")] + public string? CheckOutRemark { get; set; } = string.Empty; - [Comment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้)")] - public string? Remark { get; set; } = string.Empty; - } } diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .Designer.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .Designer.cs new file mode 100644 index 00000000..e3deaf24 --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .Designer.cs @@ -0,0 +1,240 @@ +// +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("20231113082133_ update field user timestamps (add) ")] + partial class updatefieldusertimestampsadd + { + /// + 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("CheckInImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-In"); + + b.Property("CheckInLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-In"); + + b.Property("CheckInLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In"); + + b.Property("CheckInLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-In"); + + b.Property("CheckInPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In"); + + b.Property("CheckInRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In"); + + b.Property("CheckOut") + .HasColumnType("datetime(6)") + .HasComment("วัน เวลา ออกงาน"); + + b.Property("CheckOutImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-Out"); + + b.Property("CheckOutLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-Out"); + + b.Property("CheckOutLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out"); + + b.Property("CheckOutLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-Out"); + + b.Property("CheckOutPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out"); + + b.Property("CheckOutRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out"); + + 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("IsLocationCheckIn") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In"); + + b.Property("IsLocationCheckOut") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out"); + + 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/20231113082133_ update field user timestamps (add) .cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .cs new file mode 100644 index 00000000..45c6563b --- /dev/null +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/20231113082133_ update field user timestamps (add) .cs @@ -0,0 +1,270 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Infrastructure.Migrations.LeaveDb +{ + /// + public partial class updatefieldusertimestampsadd : Migration + { + /// + protected override void Up(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"); + + migrationBuilder.AddColumn( + name: "CheckInImageUrl", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "รูปถ่ายสถานที่ Check-In") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckInLat", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดละติจูด Check-In"); + + migrationBuilder.AddColumn( + name: "CheckInLocationName", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckInLon", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดลองจิจูด Check-In"); + + migrationBuilder.AddColumn( + name: "CheckInPOI", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckInRemark", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckOutImageUrl", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "รูปถ่ายสถานที่ Check-Out") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckOutLat", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดละติจูด Check-Out"); + + migrationBuilder.AddColumn( + name: "CheckOutLocationName", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckOutLon", + table: "UserTimeStamps", + type: "double", + nullable: false, + defaultValue: 0.0, + comment: "พิกัดลองจิจูด Check-Out"); + + migrationBuilder.AddColumn( + name: "CheckOutPOI", + table: "UserTimeStamps", + type: "longtext", + nullable: false, + comment: "ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "CheckOutRemark", + table: "UserTimeStamps", + type: "longtext", + nullable: true, + comment: "ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out") + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "IsLocationCheckIn", + table: "UserTimeStamps", + type: "tinyint(1)", + nullable: false, + defaultValue: false, + comment: "true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In"); + + migrationBuilder.AddColumn( + name: "IsLocationCheckOut", + table: "UserTimeStamps", + type: "tinyint(1)", + nullable: false, + defaultValue: false, + comment: "true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CheckInImageUrl", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckInLat", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckInLocationName", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckInLon", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckInPOI", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckInRemark", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutImageUrl", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutLat", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutLocationName", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutLon", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutPOI", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "CheckOutRemark", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "IsLocationCheckIn", + table: "UserTimeStamps"); + + migrationBuilder.DropColumn( + name: "IsLocationCheckOut", + table: "UserTimeStamps"); + + 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"); + } + } +} diff --git a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs index 35dc067e..38a86d6c 100644 --- a/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs +++ b/BMA.EHR.Infrastructure/Migrations/LeaveDb/LeaveDbContextModelSnapshot.cs @@ -117,10 +117,62 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .HasColumnType("datetime(6)") .HasComment("วัน เวลา เข้างาน"); + b.Property("CheckInImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-In"); + + b.Property("CheckInLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-In"); + + b.Property("CheckInLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-In"); + + b.Property("CheckInLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-In"); + + b.Property("CheckInPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-In"); + + b.Property("CheckInRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-In"); + b.Property("CheckOut") .HasColumnType("datetime(6)") .HasComment("วัน เวลา ออกงาน"); + b.Property("CheckOutImageUrl") + .IsRequired() + .HasColumnType("longtext") + .HasComment("รูปถ่ายสถานที่ Check-Out"); + + b.Property("CheckOutLat") + .HasColumnType("double") + .HasComment("พิกัดละติจูด Check-Out"); + + b.Property("CheckOutLocationName") + .HasColumnType("longtext") + .HasComment("กรณีเลือกนอกสถานที่ตั้ง ต้องระบุข้อมูลชื่อสถานะที่ Check-Out"); + + b.Property("CheckOutLon") + .HasColumnType("double") + .HasComment("พิกัดลองจิจูด Check-Out"); + + b.Property("CheckOutPOI") + .IsRequired() + .HasColumnType("longtext") + .HasComment("ชื่อสถานที่ ได้มาจากระบบ ArcGis ของกองสารสนเทศภูมิศาสตร์ Check-Out"); + + b.Property("CheckOutRemark") + .HasColumnType("longtext") + .HasComment("ข้อความหมายเหตุที่ต้องการระบุเพิ่ม(มีเผื่อไว้อาจไม่ได้ใช้) Check-Out"); + b.Property("CreatedAt") .HasColumnType("datetime(6)") .HasColumnOrder(100) @@ -140,14 +192,13 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .HasColumnOrder(101) .HasComment("User Id ที่สร้างข้อมูล"); - b.Property("ImageUrl") - .IsRequired() - .HasColumnType("longtext") - .HasComment("รูปถ่ายสถานที่ checkin/checkout"); - - b.Property("IsLocation") + b.Property("IsLocationCheckIn") .HasColumnType("tinyint(1)") - .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง"); + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-In"); + + b.Property("IsLocationCheckOut") + .HasColumnType("tinyint(1)") + .HasComment("true คือ ณ สถานที่ตั้ง, false คือ นอกสถานที่ตั้ง Check-Out"); b.Property("IsProcess") .HasColumnType("tinyint(1)") @@ -176,27 +227,6 @@ namespace BMA.EHR.Infrastructure.Migrations.LeaveDb .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"); diff --git a/BMA.EHR.Leave.Service/Controllers/LeaveController.cs b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs index 94d89203..36d4ffb0 100644 --- a/BMA.EHR.Leave.Service/Controllers/LeaveController.cs +++ b/BMA.EHR.Leave.Service/Controllers/LeaveController.cs @@ -3,7 +3,6 @@ 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; @@ -31,6 +30,9 @@ namespace BMA.EHR.Command.Service.Controllers private readonly IConfiguration _configuration; private readonly UserProfileRepository _userProfileRepository; private readonly UserTimeStampRepository _userTimeStampRepository; + private readonly MinIOService _minIOService; + + private readonly string _bucketName = "check-in"; #endregion @@ -42,7 +44,8 @@ namespace BMA.EHR.Command.Service.Controllers IWebHostEnvironment hostingEnvironment, IConfiguration configuration, UserProfileRepository userProfileRepository, - UserTimeStampRepository userTimeStampRepository) + UserTimeStampRepository userTimeStampRepository, + MinIOService minIOService) { _dutyTimeRepository = dutyTimeRepository; _context = context; @@ -51,6 +54,7 @@ namespace BMA.EHR.Command.Service.Controllers _configuration = configuration; _userProfileRepository = userProfileRepository; _userTimeStampRepository = userTimeStampRepository; + _minIOService = minIOService; } #endregion @@ -345,6 +349,72 @@ namespace BMA.EHR.Command.Service.Controllers return Success(ret); } + + /// + /// LV1_005 - ลงเวลาเข้า-ออกงาน (USER) + /// + /// + /// + /// เมื่อทำรายการสำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPost("check-in"), DisableRequestSizeLimit] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CheckInAsync([FromForm] CheckTimeDto data) + { + if (data.Img == null) throw new Exception(GlobalMessages.NoFileToUpload); + var currentDate = DateTime.Now; + + var fileName = $"{_bucketName}/{UserId}/{DateTime.Now.ToString("dd-MM-yyyy")}/{data.Img.FileName}"; + using (var ms = new MemoryStream()) + { + data.Img.CopyTo(ms); + await _minIOService.UploadFileAsync(fileName, ms); + } + + // create check in object + if (data.CheckInId == null) + { + var checkin = new UserTimeStamp + { + KeycloakUserId = UserId != null ? Guid.Parse(UserId) : Guid.Empty, + CheckInLat = data.Lat, + CheckInLon = data.Lon, + IsLocationCheckIn = data.IsLocation, + CheckInLocationName = data.LocationName, + CheckInPOI = data.POI, + CheckInRemark = data.Remark, + CheckInImageUrl = fileName, + CheckIn = currentDate + }; + + await _userTimeStampRepository.AddAsync(checkin); + } + else + { + var checkout = await _userTimeStampRepository.GetByIdAsync(data.CheckInId.Value); + if (checkout != null) + { + checkout.CheckOutLat = data.Lat; + checkout.CheckOutLon = data.Lon; + checkout.IsLocationCheckOut = data.IsLocation; + checkout.CheckOutLocationName = data.LocationName; + checkout.CheckOutPOI = data.POI; + checkout.CheckOutRemark = data.Remark; + checkout.CheckOutImageUrl = fileName; + checkout.CheckOut = currentDate; + } + else + { + throw new Exception(GlobalMessages.DataNotFound); + } + } + + return Success(new { date = currentDate }); + } + #endregion #endregion diff --git a/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckTimeDto.cs b/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckTimeDto.cs new file mode 100644 index 00000000..b5cf8df0 --- /dev/null +++ b/BMA.EHR.Leave.Service/DTOs/CheckIn/CheckTimeDto.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; + +namespace BMA.EHR.Command.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; + } +}