using BMA.EHR.Application.Common.Interfaces; using BMA.EHR.Application.Requests.Commands; using BMA.EHR.Application.Responses; using BMA.EHR.Domain.Extensions; 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.Http; using Microsoft.EntityFrameworkCore; using Command = BMA.EHR.Domain.Models.Commands.Core.Command; namespace BMA.EHR.Application.Repositories.Commands { public class CommandRepository : GenericRepository { #region " Fields " private readonly IApplicationDBContext _dbContext; private readonly IHttpContextAccessor _httpContextAccessor; #endregion #region " Constructor and Destuctor " public CommandRepository(IApplicationDBContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor) { _dbContext = dbContext; _httpContextAccessor = httpContextAccessor; } #endregion #region " Methods " #region " Private " private async Task> GetReceiverForByCommndTypeAsync(Command command) { var result = new List(); switch (command.CommandType.CommandCode.Trim().ToUpper()) { case "C-PM-01": case "C-PM-02": case "C-PM-03": result = await GetReceiver01(command); break; default: throw new Exception(GlobalMessages.MethodForCommandTypeNotImplement); } return result; } /// /// C-PM-01 /// /// /// private async Task> GetReceiver01(Command command) { try { var result = new List(); // 1. หารายชื่อที่ถูกเลือกไปแล้ว ในประเภทเดียวกัน var otherCommandReceivers = await _dbContext.Set() .Include(x => x.Command) .ThenInclude(x => x.CommandType) .Where(x => x.Command.CommandType.CommandCode.Trim().ToUpper() == "C-PM-01") .Where(x => x.Id != command.Id) .Select(x => x.CitizenId) .ToListAsync(); // 2. Query var appointPeople = await _dbContext.Set() .Include(x => x.Prefix) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.Organization) //.Where(x => x.OrganizationPosition!.Organization!.Id == command.OwnerGovId) .Where(x => !otherCommandReceivers.Contains(x.CitizenId!)) .Where(x => x.PlacementStatus.Trim().ToUpper() == "PREPARE-CONTAIN") .Where(x => x.Draft! == true) .OrderBy(x => x.ExamNumber) .ToListAsync(); // 3. Create new Record var seq = 1; foreach (var item in appointPeople) { var receiver = new CommandReceiver { Sequence = seq, CitizenId = item.CitizenId!, Prefix = item.Prefix!.Name, FirstName = item.Firstname!, LastName = item.Lastname!, RefPlacementProfileId = item.Id }; seq++; result.Add(receiver); } return result; } catch { throw; } } #endregion #region " Override " public override async Task GetByIdAsync(Guid id) { 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 SaveSelectedReceiverAsync(Guid id, List selected) { try { var command = await _dbContext.Set() .Include(x => x.Receivers) .Include(x => x.CommandType) .FirstOrDefaultAsync(x => x.Id == id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); var appointPeople = await _dbContext.Set() .Include(x => x.Prefix) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.Organization) //.Where(x => x.OrganizationPosition!.Organization!.Id == command.OwnerGovId) .Where(x => selected.Contains(x.Id)) .OrderBy(x => x.ExamNumber) .ToListAsync(); _dbContext.Set().RemoveRange(command.Receivers); await _dbContext.SaveChangesAsync(); var seq = 1; foreach (var item in appointPeople) { var receiver = new CommandReceiver { Sequence = seq, CitizenId = item.CitizenId!, Prefix = item.Prefix!.Name, FirstName = item.Firstname!, LastName = item.Lastname!, RefPlacementProfileId = item.Id }; seq++; command.Receivers.Add(receiver); } await _dbContext.SaveChangesAsync(); } catch { throw; } } public async Task> GetReceiverForCommandAsync(Guid id) { try { var command = await _dbContext.Set() .Include(x => x.Receivers) .Include(x => x.CommandType) .FirstOrDefaultAsync(x => x.Id == id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); else return await GetReceiverForByCommndTypeAsync(command); } catch { throw; } } public async Task> GetReceiverByCommmandIdAsync(Guid Id) { try { // ปรับใหม่ให้อ่านจาก database ล้วนๆ var command = await _dbContext.Set() .Include(x => x.Receivers) .Include(x => x.CommandType) .FirstOrDefaultAsync(x => x.Id == Id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); else { if (command.Receivers != null && command!.Receivers!.Count > 0) { return command.Receivers; } else { // returrn empty list return new List(); } } } catch { throw; } } public async Task DeleteCommandReceiverAsync(Guid personalId) { try { var deleted = await _dbContext.Set() .FirstOrDefaultAsync(x => x.Id == personalId); if (deleted == null) throw new Exception(GlobalMessages.DataNotFound); _dbContext.Set().Remove(deleted); await _dbContext.SaveChangesAsync(); return deleted; } catch { throw; } } 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 { var command = await _dbContext.Set() .Include(x => x.Deployments) .FirstOrDefaultAsync(x => x.Id == id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); else { if (command.Deployments != null || command!.Deployments!.Count > 0) { return command.Deployments; } else { var orgPos = await _dbContext.Set() .Include(x => x.Profile) .ThenInclude(x => x!.Prefix) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.Organization) .ThenInclude(x => x!.OrganizationOrganization) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.PositionMaster) .ThenInclude(x => x!.PositionPath) .Where(x => x.OrganizationPosition!.IsDirector! == true) .Where(x => x.OrganizationPosition!.Organization!.Id == command.OwnerGovId) .FirstOrDefaultAsync(); if (orgPos != null) { if (orgPos.Profile != null) { var dp = new CommandDeployment { Sequence = 1, ReceiveUserId = orgPos!.Profile!.Id!.ToString("D"), CitizenId = orgPos!.Profile!.CitizenId!, Prefix = orgPos!.Profile!.Prefix!.Name, FirstName = orgPos!.Profile!.FirstName!, LastName = orgPos!.Profile!.LastName!, IsSendInbox = true, IsSendMail = true, IsSendNotification = true, OrganizationName = orgPos!.OrganizationPosition!.Organization!.OrganizationOrganization!.Name, PositionName = orgPos!.OrganizationPosition!.PositionMaster!.PositionPath!.Name }; command.Deployments.Add(dp); } await _dbContext.SaveChangesAsync(); } // query for new list return command.Deployments; } } } catch { throw; } } public async Task> GetProfileByOrganizationIdAsync(Guid orgId) { try { var orgProfiles = await _dbContext.Set() .Include(x => x.Profile) .ThenInclude(x => x!.Prefix) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.Organization) .ThenInclude(x => x!.OrganizationOrganization) .Include(x => x.OrganizationPosition) .ThenInclude(x => x!.PositionMaster) .ThenInclude(x => x!.PositionPath) .Where(x => x.OrganizationPosition!.Organization!.Id == orgId) .ToListAsync(); return orgProfiles; } catch { throw; } } public async Task CreateCommandDeploymentAsync(Guid commandId, List deploy) { try { var command = await _dbContext.Set() .Include(x => x.Deployments) .FirstOrDefaultAsync(x => x.Id == commandId); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); else { var lastSeq = 0; var dep = command.Deployments.OrderByDescending(x => x.Sequence).FirstOrDefault(); if (dep == null) lastSeq = 1; else lastSeq = dep.Sequence; foreach (var dep2 in deploy) { dep2.Sequence = lastSeq; lastSeq++; } command.Deployments.AddRange(deploy); await _dbContext.SaveChangesAsync(); } } catch { throw; } } public async Task UpdatCommandDeploymentAsync(List deploys) { try { foreach (var dp in deploys) { var updated = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == dp.Id); if (updated != null) { updated.IsSendMail = dp.IsSendMail; updated.IsSendInbox = dp.IsSendInbox; } } await _dbContext.SaveChangesAsync(); } catch { throw; } } public async Task DeleteCommandDeploymentAsync(Guid id) { try { var deleted = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == id); if (deleted == null) throw new Exception(GlobalMessages.DataNotFound); _dbContext.Set().Remove(deleted); await _dbContext.SaveChangesAsync(); } catch { throw; } } public async Task GetCommandDeploymentById(Guid id) { try { var data = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == id); return data; } catch { throw; } } #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 { var docs = await _dbContext.Set() .Include(x => x.Command) .Include(x => x.Document) .Where(x => x.Command.Id == id) .ToListAsync(); return docs; } catch { throw; } } #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 GetPlacementSalaryAsync(Guid placementProfileId) { try { var placementProfile = await _dbContext.Set() .FirstOrDefaultAsync(p => p.Id == placementProfileId); if (placementProfile == null) throw new Exception($"Invalid placement profile: {placementProfileId}"); return new PlacementSalaryResponse { SalaryAmount = placementProfile.Amount ?? 0, PositionSalaryAmount = placementProfile.PositionSalaryAmount ?? 0, MonthSalaryAmount = placementProfile.MouthSalaryAmount ?? 0 }; } catch { throw; } } 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 #region " Command Info " public async Task GetCommandInfoAsync(Guid id) { try { var command = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); return new CommandInfoResponse { SignDate = command.CommandExcecuteDate.Value, OrderNo = command.CommandNo, OrderYear = command.CommandYear, }; } catch { throw; } } public async Task UpdateCommandInfoAsync(Guid id, string orderNo, string orderYear, DateTime signDate) { try { var command = await _dbContext.Set().FirstOrDefaultAsync(x => x.Id == id); if (command == null) throw new Exception(GlobalMessages.CommandNotFound); command.CommandExcecuteDate = signDate; command.CommandNo = orderNo; command.CommandYear = orderYear; await _dbContext.SaveChangesAsync(); } catch { throw; } } #endregion public async Task GetRootOcIdAsync(Guid ocId) { try { var data = await _dbContext.Set().AsQueryable() //.Include(x => x.OrganizationAgency) //.Include(x => x.OrganizationGovernmentAgency) .FirstOrDefaultAsync(o => o.Id == ocId); if (data == null) throw new Exception(GlobalMessages.OrganizationNotFound); return data.OrganizationAgencyId!.Value; } catch { throw; } } #endregion } }