diff --git a/.github/workflows/build-local.yaml b/.github/workflows/build-local.yaml new file mode 100644 index 00000000..3a06de72 --- /dev/null +++ b/.github/workflows/build-local.yaml @@ -0,0 +1,46 @@ +# use for local build with act +name: build-local +run-name: build-local ${{ github.actor }} +on: + workflow_dispatch: +env: + REGISTRY: docker.frappet.com + IMAGE_NAME: demo/bma-ehr-metadata-service +jobs: + # act workflow_dispatch -W .github/workflows/build-local.yaml --input IMAGE_VER=test-v6.1 + build-local: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # skip Set up QEMU because it fail on act and container + - name: Gen Version + id: gen_ver + run: | + if [[ $GITHUB_REF == 'refs/tags/'* ]]; then + IMAGE_VER='${GITHUB_REF/refs\/tags\//}' + else + IMAGE_VER=${{ github.event.inputs.IMAGE_VER }} + fi + if [[ $IMAGE_VER == '' ]]; then + IMAGE_VER='test-vBeta' + fi + echo '::set-output name=image_ver::'$IMAGE_VER + - name: Test Version + run: | + echo $GITHUB_REF + echo ${{ steps.gen_ver.outputs.image_ver }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + # - name: Login in to registry + # uses: docker/login-action@v2 + # with: + # registry: ${{env.REGISTRY}} + # username: ${{secrets.DOCKER_USER}} + # password: ${{secrets.DOCKER_PASS}} + - name: Build and load local docker image + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64 + load: true + tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest diff --git a/.github/workflows/release_command.yaml b/.github/workflows/release_command.yaml new file mode 100644 index 00000000..37301964 --- /dev/null +++ b/.github/workflows/release_command.yaml @@ -0,0 +1,87 @@ +name: release-dev +run-name: release-dev ${{ github.actor }} +on: + # push: + # tags: + # - 'v[0-9]+.[0-9]+.[0-9]+' + # tags-ignore: + # - '2.*' + # Allow run workflow manually from Action tab + workflow_dispatch: +env: + REGISTRY: docker.frappet.com + IMAGE_NAME: ehr/bma-ehr-command-service + DEPLOY_HOST: frappet.com + COMPOSE_PATH: /home/frappet/docker/bma-ehr-command + TOKEN_LINE: uxuK5hDzS2DsoC5piJBrWRLiz8GgY7iMZZldOWsDDF0 + +jobs: + # act workflow_dispatch -W .github/workflows/release.yaml --input IMAGE_VER=test-v6.1 -s DOCKER_USER=sorawit -s DOCKER_PASS=P@ssword -s SSH_PASSWORD=P@ssw0rd + release-dev: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # skip Set up QEMU because it fail on act and container + - name: Gen Version + id: gen_ver + run: | + if [[ $GITHUB_REF == 'refs/tags/'* ]]; then + IMAGE_VER='${GITHUB_REF/refs\/tags\//}' + else + IMAGE_VER=${{ github.event.inputs.IMAGE_VER }} + fi + if [[ $IMAGE_VER == '' ]]; then + IMAGE_VER='test-vBeta' + fi + echo '::set-output name=image_ver::'$IMAGE_VER + - name: Test Version + run: | + echo $GITHUB_REF + echo ${{ steps.gen_ver.outputs.image_ver }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login in to registry + uses: docker/login-action@v2 + with: + registry: ${{env.REGISTRY}} + username: ${{secrets.DOCKER_USER}} + password: ${{secrets.DOCKER_PASS}} + - name: Build and load local docker image + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64 + file: BMA.EHR.Command.Service/Dockerfile + push: true + tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest + + - name: Reload docker compose + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{env.DEPLOY_HOST}} + username: frappet + password: ${{ secrets.SSH_PASSWORD }} + port: 22 + script: | + cd "${{env.COMPOSE_PATH}}" + docker-compose pull + docker-compose up -d + echo "${{ steps.gen_ver.outputs.image_ver }}"> success + - uses: snow-actions/line-notify@v1.1.0 + if: success() + with: + access_token: ${{ env.TOKEN_LINE }} + message: | + -Success✅✅✅ + Image: ${{env.IMAGE_NAME}} + Version: ${{ github.event.inputs.IMAGE_VER }} + By: ${{secrets.DOCKER_USER}} + - uses: snow-actions/line-notify@v1.1.0 + if: failure() + with: + access_token: ${{ env.TOKEN_LINE }} + message: | + -Failure❌❌❌ + Image: ${{env.IMAGE_NAME}} + Version: ${{ github.event.inputs.IMAGE_VER }} + By: ${{secrets.DOCKER_USER}} diff --git a/BMA.EHR.Application/Common/Interfaces/IApplicationDBContext.cs b/BMA.EHR.Application/Common/Interfaces/IApplicationDBContext.cs index 2422892b..ab32d1af 100644 --- a/BMA.EHR.Application/Common/Interfaces/IApplicationDBContext.cs +++ b/BMA.EHR.Application/Common/Interfaces/IApplicationDBContext.cs @@ -7,6 +7,8 @@ namespace BMA.EHR.Application.Common.Interfaces { DbSet Set() where T : class; + void Attatch(T entity) where T : class; + Task SaveChangesAsync(); } } diff --git a/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs b/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs index d8914f35..2be308d1 100644 --- a/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs +++ b/BMA.EHR.Application/Repositories/Commands/CommandRepository.cs @@ -1,11 +1,14 @@ -using Amazon.S3.Model.Internal.MarshallTransformations; -using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Application.Requests.Commands; using BMA.EHR.Domain.Models.Commands.Core; +using BMA.EHR.Domain.Models.MetaData; using BMA.EHR.Domain.Models.Organizations; using BMA.EHR.Domain.Models.Placement; using BMA.EHR.Domain.Shared; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; +using System.Transactions; using Command = BMA.EHR.Domain.Models.Commands.Core.Command; namespace BMA.EHR.Application.Repositories.Commands @@ -39,11 +42,44 @@ namespace BMA.EHR.Application.Repositories.Commands return await _dbContext.Set() .Include(x => x.Placement) .Include(x => x.CommandType) + .Include(x => x.Documents) + .Include(x => x.Receivers) + .Include(x => x.CommandStatus) .FirstOrDefaultAsync(x => x.Id == id); } + public override async Task> GetAllAsync() + { + return await _dbContext.Set() + .Include(x => x.Placement) + .Include(x => x.CommandType) + .Include(x => x.CommandStatus) + .ToListAsync(); + } + + public override async Task AddAsync(Command command) + { + var status = await _dbContext.Set().FirstOrDefaultAsync(c => c.Sequence == 1); + command.CommandStatus = status!; + _dbContext.Attatch(status!); + + return await base.AddAsync(command); + } + + public override async Task UpdateAsync(Command entity) + { + // attatch + _dbContext.Attatch(entity.CommandStatus); + _dbContext.Attatch(entity.CommandType); + _dbContext.Attatch(entity.Placement); + + return await base.UpdateAsync(entity); + } + #endregion + #region " Command Receiver " + public async Task> GetReceiverByCommmandIdAsync(Guid Id) { try @@ -135,6 +171,89 @@ namespace BMA.EHR.Application.Repositories.Commands } } + public async Task GetCommandReceiverAsync(Guid personalId) + { + try + { + var receiver = await _dbContext.Set() + .FirstOrDefaultAsync(x => x.Id == personalId); + + if (receiver == null) + throw new Exception(GlobalMessages.DataNotFound); + + return receiver; + } + catch + { + throw; + } + + + } + + public async Task SwapReceiverOrderAsync(Guid personalId, string direction) + { + try + { + var current = await _dbContext.Set() + .FirstOrDefaultAsync(x => x.Id == personalId); + + if (current == null) + throw new Exception(GlobalMessages.DataNotFound); + + var currentSeq = current.Sequence; + + switch (direction.Trim().ToLower()) + { + case "up": + { + // get prev record + var prev = await _dbContext.Set() + .OrderByDescending(x => x.Sequence) + .Where(x => x.Sequence < currentSeq) + .Take(1) + .FirstOrDefaultAsync(); + + if (prev != null) + { + var prevSeq = prev.Sequence; + + current.Sequence = prevSeq; + prev.Sequence = currentSeq; + await _dbContext.SaveChangesAsync(); + } + break; + } + case "down": + { + // get next record + var next = await _dbContext.Set() + .OrderBy(x => x.Sequence) + .Where(x => x.Sequence > currentSeq) + .Take(1) + .FirstOrDefaultAsync(); + + if (next != null) + { + var nextSeq = next.Sequence; + + current.Sequence = nextSeq; + next.Sequence = currentSeq; + await _dbContext.SaveChangesAsync(); + } + break; + } + default: throw new Exception("Invalid swap direction!"); + } + } + catch + { + throw; + } + } + + #endregion + public async Task> GetDeploymentByCommandIdAsync(Guid id) { try @@ -314,6 +433,54 @@ namespace BMA.EHR.Application.Repositories.Commands #region " Documents " + public async Task> GetExistDocument(Guid id, string category) + { + try + { + var command = await _dbContext.Set() + .Include(x => x.Documents) + .ThenInclude(x => x.Document) + .FirstOrDefaultAsync(c => c.Id == id); + if (command == null) + throw new Exception(GlobalMessages.CommandNotFound); + + // insert new record to comand Document + var exist = command.Documents.Where(x => x.Category == category).ToList(); + + return exist; + } + catch + { + throw; + } + } + + public async Task UploadDocument(Guid id, string category, CommandDocument document) + { + try + { + var command = await _dbContext.Set().Include(x => x.Documents).FirstOrDefaultAsync(c => c.Id == id); + if (command == null) + throw new Exception(GlobalMessages.CommandNotFound); + + // insert new record to comand Document + var exist = command.Documents.Where(x => x.Category == category).ToList(); + if (exist.Any()) + { + _dbContext.Set().RemoveRange(exist); + await _dbContext.SaveChangesAsync(); + } + + // insert new Record + command.Documents.Add(document); + await _dbContext.SaveChangesAsync(); + } + catch + { + throw; + } + } + public async Task> GetCommandDocumentAsync(Guid id) { try @@ -334,12 +501,116 @@ namespace BMA.EHR.Application.Repositories.Commands #endregion + #region " Change Command Status " + + public async Task GotoNextStateAsync(Guid id) + { + try + { + var command = await _dbContext.Set().Include(c => c.CommandStatus).FirstOrDefaultAsync(x => x.Id == id); + if (command == null) + throw new Exception(GlobalMessages.CommandNotFound); + + var notProcess = new int[] { 4, 5 }; + + if (!notProcess.Contains(command.CommandStatus.Sequence)) + { + var nextStatus = await _dbContext.Set().FirstOrDefaultAsync(c => c.Sequence == command.CommandStatus.Sequence + 1); + command.CommandStatus = nextStatus!; + _dbContext.Attatch(nextStatus!); + await _dbContext.SaveChangesAsync(); + } + } + catch + { + throw; + } + } + + public async Task GotoPrevStateAsync(Guid id) + { + try + { + var command = await _dbContext.Set().Include(c => c.CommandStatus).FirstOrDefaultAsync(x => x.Id == id); + if (command == null) + throw new Exception(GlobalMessages.CommandNotFound); + + var notProcess = new int[] { 1, 5 }; + + if (!notProcess.Contains(command.CommandStatus.Sequence)) + { + var nextStatus = await _dbContext.Set().FirstOrDefaultAsync(c => c.Sequence == command.CommandStatus.Sequence - 1); + command.CommandStatus = nextStatus!; + _dbContext.Attatch(nextStatus!); + await _dbContext.SaveChangesAsync(); + } + } + catch + { + throw; + } + } + + #endregion + + #region " Change Detail Sequence " + + + #endregion + + #region " Placement " + + public async Task UpdatePlacementSalaryAsync(Guid placementProfileId, UpdatePlacementSalaryRequest req) + { + try + { + var placementProfile = await _dbContext.Set() + .FirstOrDefaultAsync(p => p.Id == placementProfileId); + + if (placementProfile == null) + throw new Exception($"Invalid placement profile: {placementProfileId}"); + + placementProfile.Amount = req.SalaryAmount; + placementProfile.PositionSalaryAmount = req.PositionSalaryAmount; + placementProfile.MouthSalaryAmount = req.MonthSalaryAmount; + + await _dbContext.SaveChangesAsync(); + } + catch + { + throw; + } + } + + public async Task> GetPlacementPositionPath(Guid id) + { + try + { + var data = await _dbContext.Set() + .Include(x => x.PositionPath) + .Include(x => x.Placement) + .Where(x => x.Placement!.Id == id) + .Where(x => x.PositionPath != null) + .Select(x => x.PositionPath) + .Distinct() + .ToListAsync(); + + return data!; + } + catch + { + throw; + } + } + + #endregion + public async Task UpdateCommandInfo(Guid id, string orderNo, string orderYear, DateTime signDate) { try { var command = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == id); - if(command == null) + if (command == null) throw new Exception(GlobalMessages.CommandNotFound); command.CommandExcecuteDate = signDate; diff --git a/BMA.EHR.Application/Repositories/GenericRepository.cs b/BMA.EHR.Application/Repositories/GenericRepository.cs index c196430c..f752c581 100644 --- a/BMA.EHR.Application/Repositories/GenericRepository.cs +++ b/BMA.EHR.Application/Repositories/GenericRepository.cs @@ -1,4 +1,5 @@ using BMA.EHR.Application.Common.Interfaces; +using BMA.EHR.Domain.Models.Base; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using System.Security.Claims; @@ -49,12 +50,12 @@ namespace BMA.EHR.Application.Repositories public virtual async Task AddAsync(T entity) { - //if (entity is IAuditableEntity) - //{ - // (entity as IAuditableEntity).CreatedUserId = Guid.Parse(UserId); - // (entity as IAuditableEntity).CreatedUserFullName = FullName; - // (entity as IAuditableEntity).CreatedDate = DateTime.Now; - //} + if (entity is EntityBase) + { + (entity as EntityBase).CreatedUserId = UserId!; + (entity as EntityBase).CreatedFullName = FullName!; + (entity as EntityBase).CreatedAt = DateTime.Now; + } await _dbSet.AddAsync(entity); @@ -65,12 +66,12 @@ namespace BMA.EHR.Application.Repositories public virtual async Task UpdateAsync(T entity) { - //if (entity is IAuditableEntity) - //{ - // (entity as IAuditableEntity).ModifiedUserId = Guid.Parse(UserId); - // (entity as IAuditableEntity).ModifiedUserFullName = FullName; - // (entity as IAuditableEntity).ModifiedDate = DateTime.Now; - //} + if (entity is EntityBase) + { + (entity as EntityBase).LastUpdateUserId = UserId!; + (entity as EntityBase).LastUpdateFullName = FullName!; + (entity as EntityBase).LastUpdatedAt = DateTime.Now; + } _dbSet.Update(entity); await _dbContext.SaveChangesAsync(); diff --git a/BMA.EHR.Application/Requests/Commands/UpdatePlacementSalaryRequest.cs b/BMA.EHR.Application/Requests/Commands/UpdatePlacementSalaryRequest.cs new file mode 100644 index 00000000..2aefb92f --- /dev/null +++ b/BMA.EHR.Application/Requests/Commands/UpdatePlacementSalaryRequest.cs @@ -0,0 +1,11 @@ +namespace BMA.EHR.Application.Requests.Commands +{ + public class UpdatePlacementSalaryRequest + { + public double SalaryAmount { get; set; } = 0; + + public double PositionSalaryAmount { get; set; } = 0; + + public double MonthSalaryAmount { get; set; } = 0; + } +} diff --git a/BMA.EHR.Command.Service/BMA.EHR.Command.Service.csproj b/BMA.EHR.Command.Service/BMA.EHR.Command.Service.csproj index 2a444d61..96d01d2d 100644 --- a/BMA.EHR.Command.Service/BMA.EHR.Command.Service.csproj +++ b/BMA.EHR.Command.Service/BMA.EHR.Command.Service.csproj @@ -39,6 +39,18 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest diff --git a/BMA.EHR.Command.Service/Controllers/OrderController.cs b/BMA.EHR.Command.Service/Controllers/OrderController.cs index 4525fb76..264926fa 100644 --- a/BMA.EHR.Command.Service/Controllers/OrderController.cs +++ b/BMA.EHR.Command.Service/Controllers/OrderController.cs @@ -1,5 +1,7 @@ -using BMA.EHR.Application.Repositories; +using Amazon.S3.Model.Internal.MarshallTransformations; +using BMA.EHR.Application.Repositories; using BMA.EHR.Application.Repositories.Commands; +using BMA.EHR.Application.Requests.Commands; using BMA.EHR.Command.Service.Requests; using BMA.EHR.Domain.Common; using BMA.EHR.Domain.Extensions; @@ -31,6 +33,8 @@ namespace BMA.EHR.Command.Service.Controllers private readonly MinIOService _documentService; private readonly IHttpContextAccessor _httpContextAccessor; private readonly PrefixRepository _prefixRepository; + private readonly CommandTypeRepository _commandTypeRepository; + private readonly CommandStatusRepository _commandStatusRepository; #endregion @@ -41,7 +45,9 @@ namespace BMA.EHR.Command.Service.Controllers ApplicationDBContext context, MinIOService documentService, IHttpContextAccessor httpContextAccessor, - GenericRepository prefixRepository) + PrefixRepository prefixRepository, + CommandTypeRepository commandTypeRepository, + CommandStatusRepository commandStatusRepository) { _repository = repository; _context = context; @@ -49,6 +55,8 @@ namespace BMA.EHR.Command.Service.Controllers _httpContextAccessor = httpContextAccessor; _placementRepository = placementRepository; _prefixRepository = prefixRepository; + _commandTypeRepository = commandTypeRepository; + _commandStatusRepository = commandStatusRepository; } #endregion @@ -68,6 +76,9 @@ namespace BMA.EHR.Command.Service.Controllers /// /// แสดงปีเป็นปีพุทธศักราช โดยดึงจากข้อมูลที่มีในระบบ /// + /// + /// ถ้าไม่มีข้อมูลเลยจะ default ปีปัจจุบันให้ 1 รายการ + /// /// /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ /// ไม่ได้ Login เข้าระบบ @@ -76,22 +87,153 @@ namespace BMA.EHR.Command.Service.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async Task> GetFiscal() + public async Task> GetFiscalAsync() { var data = await _repository.GetAllAsync(); if (data != null) { var _data = data.GroupBy(x => x.CommandYear).Select(x => new { - Id = x.FirstOrDefault().CommandYear, - Name = x.FirstOrDefault().CommandYear + 543, + Id = x.FirstOrDefault().CommandYear.ToInteger().ToCeYear(), + Name = x.FirstOrDefault().CommandYear.ToInteger().ToThaiYear(), }).ToList(); + + if (_data == null || _data.Count == 0) + { + _data!.Add(new + { + Id = DateTime.Now.Year, + Name = DateTime.Now.Year.ToThaiYear() + }); + } + return Success(_data); } return Success(data); } + /// + /// แสดงประเภทคำสั่ง โดยดึงจากข้อมูลที่มีในระบบ + /// + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("order-type")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GetCommandTypeAsync() + { + try + { + var data = (await _commandTypeRepository.GetAllAsync()).OrderBy(x => x.CommandCode); + + return Success(data); + } + catch + { + throw; + } + } + + /// + /// ตรวจสอบความพร้อมในการออกคำสั่ง + /// + /// Record Id ของคำสั่ง + /// + /// ค่า Y = พร้อมออกคำสั่ง, N = ยังไม่พร้อม + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("ready/{orderId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CheckReadyToExcecuteAsync(Guid orderId) + { + try + { + var command = await _repository.GetByIdAsync(orderId); + if (command == null) + throw new Exception(GlobalMessages.CommandNotFound); + + var cover = command.Documents.FirstOrDefault(x => x.Category == GlobalConstants.TYPE_COVER); + var attatchment = command.Documents.FirstOrDefault(x => x.Category == GlobalConstants.TYPE_ATTACHMENT); + + if (command.CommandNo != "" && + command.CommandYear != null && + command.CommandExcecuteDate != null && + cover != null && + attatchment != null) + { + return Success(new { result = "Y" }); + } + else + return Success(new { result = "N" }); + } + catch + { + throw; + } + } + + /// + /// เปลี่ยน status ของคำสั่งไปขั้นตอนถัดไป + /// + /// Record Id ของคำสั่ง + /// + /// ค่า Y = พร้อมออกคำสั่ง, N = ยังไม่พร้อม + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("next/{orderId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GoToNextState(Guid orderId) + { + try + { + await _repository.GotoNextStateAsync(orderId); + return Success(); + } + catch + { + throw; + } + } + + /// + /// เปลี่ยน status ของคำสั่งไปขั้นตอนก่อนหน้า + /// + /// Record Id ของคำสั่ง + /// + /// ค่า Y = พร้อมออกคำสั่ง, N = ยังไม่พร้อม + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("prev/{orderId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GoToPrevState(Guid orderId) + { + try + { + await _repository.GotoPrevStateAsync(orderId); + return Success(); + } + catch + { + throw; + } + } + /// /// PM7-19 : หน้าจอรายการออกคำสั่ง /// @@ -110,6 +252,7 @@ namespace BMA.EHR.Command.Service.Controllers var data = (await _repository.GetAllAsync()) .Select(d => new { + OrderId = d.Id, OrderName = d.CommandSubject, OrderNo = d.CommandNo, FiscalYear = d.CommandYear, @@ -170,7 +313,7 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpGet("{orderId}")] + [HttpGet("detail/{orderId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] @@ -193,7 +336,7 @@ namespace BMA.EHR.Command.Service.Controllers orderBy = data.IssuerOrganizationId, signatoryBy = data.AuthorizedUserFullName, signatoryPosition = data.AuthorizedPosition, - examRound = data.Placement.Round, + examRound = data.Placement.Id, registerPosition = "", conclusionRegisterNo = data.ConclusionRegisterNo, conclusionRegisterDate = data.ConclusionRegisterDate, @@ -217,7 +360,7 @@ namespace BMA.EHR.Command.Service.Controllers /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ /// ไม่ได้ Login เข้าระบบ /// เมื่อเกิดข้อผิดพลาดในการทำงาน - [HttpPost] + [HttpPost("detail")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] @@ -239,7 +382,8 @@ namespace BMA.EHR.Command.Service.Controllers ConclusionRegisterNo = req.conclusionRegisterNo, ConclusionRegisterDate = req.conclusionRegisterDate, ConclusionResultNo = req.conclusionResultNo, - ConclusionResultDate = req.conclusionResultDate + ConclusionResultDate = req.conclusionResultDate, + CommandAffectDate = req.orderDate }; var result = await _repository.AddAsync(inserted); @@ -252,6 +396,57 @@ namespace BMA.EHR.Command.Service.Controllers } } + /// + /// PM7-23 : แก้ไขข้อมูลรายละเอียดการออกคำสั่ง + /// + /// Record Id ของคำสั่ง + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("detail/{orderId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> PutAsync(Guid orderId, [FromBody] CreateCommandRequest req) + { + try + { + var order = await _repository.GetByIdAsync(orderId); + if (order == null) + throw new Exception(GlobalMessages.CommandNotFound); + + var placement = await _placementRepository.GetByIdAsync(req.examRound); + var commandType = await _commandTypeRepository.GetByIdAsync(req.orderTypeValue); + var status = await _commandStatusRepository.GetByIdAsync(order.CommandStatusId); + + order.CommandNo = req.orderNo.ToString(); + order.CommandYear = req.orderYear.ToString(); + order.CommandSubject = req.orderTitle; + order.PositionName = req.registerPosition; + order.CommandType = commandType!; + order.IssuerOrganizationId = req.orderBy; + order.AuthorizedUserFullName = req.signatoryBy; + order.AuthorizedPosition = req.signatoryPosition; + order.Placement = placement!; + order.ConclusionRegisterNo = req.conclusionRegisterNo; + order.ConclusionRegisterDate = req.conclusionRegisterDate; + order.ConclusionResultNo = req.conclusionResultNo; + order.ConclusionResultDate = req.conclusionResultDate; + order.CommandStatus = status!; + order.CommandAffectDate = req.orderDate; + + var result = await _repository.UpdateAsync(order); + + return Success(result); + } + catch + { + throw; + } + } + + /// /// PM7-24 : dropdown รอบการสอบ หน้ารายละเอียดการออกคำสั่ง /// @@ -543,17 +738,17 @@ namespace BMA.EHR.Command.Service.Controllers try { var command = await _repository.GetByIdAsync(orderId); - if(command == null) + if (command == null) throw new Exception(GlobalMessages.CommandNotFound); var documents = await _repository.GetCommandDocumentAsync(orderId); - var cover = documents.Where(x => x.Category.Trim().ToLower() == "cover").FirstOrDefault(); - var attach = documents.Where(x => x.Category.Trim().ToLower() == "attachment").FirstOrDefault(); + var cover = documents.Where(x => x.Category.Trim().ToLower() == GlobalConstants.TYPE_COVER).FirstOrDefault(); + var attach = documents.Where(x => x.Category.Trim().ToLower() == GlobalConstants.TYPE_ATTACHMENT).FirstOrDefault(); var result = new { - orderNo=command.CommandNo, - orderYear=command.CommandYear, + orderNo = command.CommandNo, + orderYear = command.CommandYear, signDate = command.CommandExcecuteDate, orderFileUrl = cover == null ? null : _documentService.ImagesPath(cover.Document.ObjectRefId), attachmentFileUrl = attach == null ? null : _documentService.ImagesPath(attach.Document.ObjectRefId), @@ -567,6 +762,109 @@ namespace BMA.EHR.Command.Service.Controllers } } + + /// + /// PM7-35 : อัปโหลดไฟล์คำสั่ง + /// + /// Record Id ของคำสั่ง + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPost("attachment/order-file/{orderId}"), DisableRequestSizeLimit] + public async Task> UploadCommandCoverAsync(Guid orderId) + { + try + { + // check upload file + if (Request.Form.Files == null || Request.Form.Files.Count == 0) + { + return Error(GlobalMessages.NoFileToUpload); + } + + var file = Request.Form.Files[0]; + + // get exit file + var docs = await _repository.GetExistDocument(orderId, GlobalConstants.TYPE_COVER); + + // delete exist document from s3 + foreach (var doc in docs) + { + await _documentService.DeleteFileAsync(doc.Document.ObjectRefId); + } + + // upload new document to s3 + var cover = await _documentService.UploadFileAsync(file); + + // create new CommandDocumentEntity + var commandDoc = new CommandDocument + { + Category = GlobalConstants.TYPE_COVER, + Document = cover, + }; + + // send to repo to save in database + await _repository.UploadDocument(orderId, GlobalConstants.TYPE_COVER, commandDoc); + + return Success(); + } + catch + { + throw; + } + } + + /// + /// PM7-36 : อัปโหลดไฟล์เอกสารแนบท้าย + /// + /// Record Id ของคำสั่ง + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPost("attachment/file/{orderId}"), DisableRequestSizeLimit] + public async Task> UploadCommandAttachmentAsync(Guid orderId) + { + try + { + // check upload file + if (Request.Form.Files == null || Request.Form.Files.Count == 0) + { + return Error(GlobalMessages.NoFileToUpload); + } + + var file = Request.Form.Files[0]; + + // get exit file + var docs = await _repository.GetExistDocument(orderId, GlobalConstants.TYPE_ATTACHMENT); + + // delete exist document from s3 + foreach (var doc in docs) + { + await _documentService.DeleteFileAsync(doc.Document.ObjectRefId); + } + + // upload new document to s3 + var cover = await _documentService.UploadFileAsync(file); + + // create new CommandDocumentEntity + var commandDoc = new CommandDocument + { + Category = GlobalConstants.TYPE_ATTACHMENT, + Document = cover, + }; + + // send to repo to save in database + await _repository.UploadDocument(orderId, GlobalConstants.TYPE_ATTACHMENT, commandDoc); + + return Success(); + } + catch + { + throw; + } + } + #endregion /// @@ -594,6 +892,81 @@ namespace BMA.EHR.Command.Service.Controllers } } + /// + /// บันทึกข้อมูลเงินเดือนสำหรับผู้บรรจุ + /// + /// Record Id ของผู้รับคำสั่งในบัญชีแนบท้าย + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("salary/{id}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> UpdatePlacementSalaryAsync(Guid personalId, [FromBody] UpdatePlacementSalaryRequest req) + { + try + { + var receiver = await _repository.GetCommandReceiverAsync(personalId); + + if (receiver == null) + throw new Exception(GlobalMessages.DataNotFound); + + await _repository.UpdatePlacementSalaryAsync(personalId, req); + + return Success(); + } + catch + { + throw; + } + } + + /// + /// สลับลำดับข้อมูลในบัญชีแนบท้ายขึ้น + /// + /// Record Id ของผู้รับคำสั่งในบัญชีแนบท้าย + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("swap/up/{personalId}")] + public async Task> SwapUpReceiverOrderAsync(Guid personalId) + { + try + { + await _repository.SwapReceiverOrderAsync(personalId, "up"); + return Success(); + } + catch + { + throw; + } + } + + /// + /// สลับลำดับข้อมูลในบัญชีแนบท้ายลง + /// + /// Record Id ของผู้รับคำสั่งในบัญชีแนบท้าย + /// + /// เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpPut("swap/down/{personalId}")] + public async Task> SwapDownReceiverOrderAsync(Guid personalId) + { + try + { + await _repository.SwapReceiverOrderAsync(personalId, "down"); + return Success(); + } + catch + { + throw; + } + } + #endregion } } diff --git a/BMA.EHR.Command.Service/Requests/CreateCommandRequest.cs b/BMA.EHR.Command.Service/Requests/CreateCommandRequest.cs index 336cd3c4..c14accfd 100644 --- a/BMA.EHR.Command.Service/Requests/CreateCommandRequest.cs +++ b/BMA.EHR.Command.Service/Requests/CreateCommandRequest.cs @@ -10,6 +10,8 @@ public int orderYear { get; set; } + public DateTime orderDate { get; set; } + public Guid orderBy { get; set; } public string signatoryBy { get; set; } diff --git a/BMA.EHR.Domain/Shared/GlobalConstants.cs b/BMA.EHR.Domain/Shared/GlobalConstants.cs new file mode 100644 index 00000000..22ed9b28 --- /dev/null +++ b/BMA.EHR.Domain/Shared/GlobalConstants.cs @@ -0,0 +1,8 @@ +namespace BMA.EHR.Domain.Shared +{ + public class GlobalConstants + { + public static readonly string TYPE_ATTACHMENT = "attachment"; + public static readonly string TYPE_COVER = "cover"; + } +} diff --git a/BMA.EHR.Domain/Shared/GlobalMessages.cs b/BMA.EHR.Domain/Shared/GlobalMessages.cs index 0c5c2e77..81bdf617 100644 --- a/BMA.EHR.Domain/Shared/GlobalMessages.cs +++ b/BMA.EHR.Domain/Shared/GlobalMessages.cs @@ -16,6 +16,8 @@ public static readonly string FileNotFoundOnServer = "ไม่พบไฟล์ในระบบ!!"; + public static readonly string NoFileToUpload = "ไม่พบไฟล์ที่ทำการอัพโหลด!"; + #region " Meta Data " public static readonly string DataExist5 = "เนื่องจากมีการกำหนดวันหยุดในการทำงาน 5 วันอยู่"; diff --git a/BMA.EHR.Infrastructure/Persistence/ApplicationDBContext.cs b/BMA.EHR.Infrastructure/Persistence/ApplicationDBContext.cs index a7dcc838..03f97769 100644 --- a/BMA.EHR.Infrastructure/Persistence/ApplicationDBContext.cs +++ b/BMA.EHR.Infrastructure/Persistence/ApplicationDBContext.cs @@ -317,5 +317,10 @@ namespace BMA.EHR.Infrastructure.Persistence { return base.SaveChangesAsync(); } + + public void Attatch(T entity) where T : class + { + Attach(entity); + } } }