using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using _0_Framework.Application; using _0_Framework.InfraStructure; using AccountManagement.Application.Contracts.Account; using AccountManagement.Application.Contracts.Media; using AccountManagement.Application.Contracts.Ticket; using AccountManagement.Domain.AdminResponseAgg; using AccountManagement.Domain.ClientResponseAgg; using AccountManagement.Domain.ClientResponseMediaAgg; using AccountManagement.Domain.TicketAgg; using Company.Domain.WorkshopAgg; using Microsoft.EntityFrameworkCore; namespace AccountMangement.Infrastructure.EFCore.Repository; public class TicketRepository : RepositoryBase, ITicketRepository { private readonly AccountContext _accountContext; private readonly IAuthHelper _authHelper; private readonly IPasswordHasher _passwordHasher; private readonly IWorkshopRepository _workshopRepository; public TicketRepository(AccountContext accountContext, IAuthHelper authHelper, IPasswordHasher passwordHasher, IWorkshopRepository workshopRepository) : base(accountContext) { _accountContext = accountContext; _authHelper = authHelper; _passwordHasher = passwordHasher; _workshopRepository = workshopRepository; } public List GetAll(TicketSearchModel searchModel) { var query = _accountContext.Tickets.Where(x => !x.IsDeleted).OrderBy(x => x.Status == "بسته شده") .ThenBy(x => x.Status == "پاسخ داده شده") .ThenBy(x => x.Status == "درحال بررسی") .ThenBy(x => "باز") .ThenByDescending(x => new[] { x.ClientResponses.Max(r => r.CreationDate), x.AdminResponses.Max(r => r.CreationDate) }.Max()).Select(x => new TicketViewModel() { Description = x.Description, SenderId = x.SenderId, ContractingPartyName = x.ContractingPartyName, Id = x.id, Title = x.Title, TicketType = x.TicketType, Status = x.Status, CreationDateTimeGr = x.CreationDate, CreationDateTime = x.CreationDate.ToFarsiFull(), TicketNumber = $"TKC_{x.TicketNumber}", WorkshopName = _workshopRepository.Get(x.WorkshopId).WorkshopFullName, HasTask = _accountContext.Tasks.Include(t => t.Assigns) .Any(t => t.TicketId == x.id && t.Assigns.Any(a => !a.IsDone)), WorkshopId = x.WorkshopId, RawTicketNumber = x.TicketNumber }); #region Search if (!string.IsNullOrWhiteSpace(searchModel.Status)) { query = query.Where(x => x.Status == searchModel.Status); } if (!(string.IsNullOrWhiteSpace(searchModel.StartDate) && string.IsNullOrWhiteSpace(searchModel.EndDate))) { if (string.IsNullOrWhiteSpace(searchModel.OneDay)) { var startDate = searchModel.StartDate.ToGeorgianDateTime(); var endDate = searchModel.EndDate.ToGeorgianDateTime(); query = query.Where(x => startDate < x.CreationDateTimeGr && endDate > x.CreationDateTimeGr); } } if (!string.IsNullOrWhiteSpace(searchModel.OneDay)) { var oneDay = searchModel.OneDay.ToGeorgianDateTime(); query = query.Where(x => x.CreationDateTimeGr.Date == oneDay.Date); } if (!string.IsNullOrWhiteSpace(searchModel.GeneralSearch)) { query = query.Where(x => x.Title.Contains(searchModel.GeneralSearch) || x.ContractingPartyName.Contains(searchModel.GeneralSearch) || x.WorkshopName.Contains(searchModel.GeneralSearch)); } if (!string.IsNullOrWhiteSpace(searchModel.OneDay)) { var day = searchModel.OneDay.ToGeorgianDateTime(); query = query.Where(x => x.CreationDateTimeGr.Date == day.Date); } if (!string.IsNullOrWhiteSpace(searchModel.ContractingPartyName)) { query = query.Where(x => x.ContractingPartyName == searchModel.ContractingPartyName.Trim()); } if (searchModel.WorkshopId > 0) { query = query.Where(x => x.WorkshopId == searchModel.WorkshopId); } if (!string.IsNullOrWhiteSpace(searchModel.TicketNumber)) { query = query.Where(x => x.RawTicketNumber == searchModel.TicketNumber); } if (!string.IsNullOrWhiteSpace(searchModel.Status)) { query = query.Where(x => x.Status == searchModel.Status.Trim()); } #endregion return query.Skip(searchModel.PageIndex).Take(30).ToList(); } public List GetDeletedTicket() { var query = _accountContext.Tickets.Where(x => x.IsDeleted).OrderByDescending(x => x.CreationDate).Select(x => new TicketViewModel() { Description = x.Description, SenderId = x.SenderId, ContractingPartyName = x.ContractingPartyName, Id = x.id, Title = x.Title, TicketType = x.TicketType, Status = x.Status, CreationDateTimeGr = x.CreationDate, CreationDateTime = x.CreationDate.ToFarsiFull(), TicketNumber = $"TKC_{x.TicketNumber}", WorkshopName = _workshopRepository.Get(x.WorkshopId).WorkshopFullName, HasTask = _accountContext.Tasks.Include(t => t.Assigns).Any(t => t.TicketId == x.id && t.Assigns.Any(a => !a.IsDone)), WorkshopId = x.WorkshopId, RawTicketNumber = x.TicketNumber }); return query.ToList(); } public List GetTicketsForClients(TicketSearchModel searchModel) { var accountInfo = _authHelper.CurrentAccountInfo(); var workshopSlug = _authHelper.GetWorkshopSlug(); var workshopId = _passwordHasher.SlugDecrypt(workshopSlug); IQueryable query; if (workshopId > 0) { query = _accountContext.Tickets.Where(x => x.SenderId == accountInfo.Id && x.WorkshopId == workshopId); } else { query = _accountContext.Tickets.Where(x => x.SenderId == accountInfo.Id); } if (accountInfo.SubAccountId>0) { query = query.Where(x => x.SubAccountSenderId == accountInfo.SubAccountId); } if (!string.IsNullOrWhiteSpace(searchModel.ContractingPartyName)) { query = query.Where(x => x.ContractingPartyName.Contains(searchModel.ContractingPartyName)); } if (!string.IsNullOrWhiteSpace(searchModel.Status)) { query = query.Where(x => x.Status == searchModel.Status); } if (!(string.IsNullOrWhiteSpace(searchModel.StartDate) && string.IsNullOrWhiteSpace(searchModel.EndDate))) { if (string.IsNullOrWhiteSpace(searchModel.OneDay)) { var startDate = searchModel.StartDate.ToGeorgianDateTime(); var endDate = searchModel.EndDate.ToGeorgianDateTime(); query = query.Where(x => startDate < x.CreationDate && endDate > x.CreationDate); } } if (!string.IsNullOrWhiteSpace(searchModel.GeneralSearch)) { query = query.Where(x => x.Title.Contains(searchModel.GeneralSearch)); } if (!string.IsNullOrWhiteSpace(searchModel.Status)) { query = query.Where(x => x.Status == searchModel.Status); } if (!string.IsNullOrWhiteSpace(searchModel.OneDay)) { var day = searchModel.OneDay.ToGeorgianDateTime(); query = query.Where(x => x.CreationDate.Date == day.Date); } var res = query.OrderBy(x => x.Status.Trim() == "بسته شده").ThenByDescending(x => x.CreationDate).Select(x => new TicketViewModel() { Description = x.Description, SenderId = x.SenderId, ContractingPartyName = x.ContractingPartyName, Id = x.id, Title = x.Title, TicketType = x.TicketType, Status = x.Status, CreationDateTimeGr = x.CreationDate, CreationDateTime = x.CreationDate.ToFarsi(), TicketNumber = $"TKC_{x.TicketNumber}", WorkshopName = _workshopRepository.Get(x.WorkshopId).WorkshopFullName }); return res.Skip(searchModel.PageIndex).Take(30).ToList(); } public void CreateAdminResponse(AdminResponse command) { _accountContext.Add(command); } public void CreateClientResponse(ClientResponse command) { _accountContext.Add(command); } public EditTicket GetDetails(long id) { var entity = _accountContext.Tickets.FirstOrDefault(x => x.id == id); if (entity == null) return null; var senderAccount = _accountContext.Accounts.FirstOrDefault(a => a.id == entity.SenderId); var adminAccount = _accountContext.Accounts.Where(x => x.AdminAreaPermission == "true").AsEnumerable(); var editTicketViewModel = new EditTicket() { ContractingPartyName = entity.ContractingPartyName, Description = entity.Description, Id = entity.id, SenderId = entity.SenderId, Sender = new AccountViewModel() { Id = senderAccount.id, Fullname = senderAccount.Fullname, }, TicketType = entity.TicketType, Title = entity.Title, CreationDateStr = entity.CreationDate.ToFarsi(), MediaViewModels = _accountContext.TicketMedias.Include(z => z.Media).Where(a => a.TicketId == entity.id) .Select(m => new MediaViewModel() { Id = m.Media.id, Path = m.Media.Path, Type = m.Media.Type, Category = m.Media.Category, }).ToList(), ClientResponseViewModels = _accountContext.ClientResponses .Include(x => x.ClientResponseMedias) .ThenInclude(x => x.Media) .Where(x => x.TicketId == entity.id).Select(x => new ClientResponseViewModel() { Response = x.Response, TicketId = x.TicketId, MediaViewModels = x.ClientResponseMedias.Select(m => new MediaViewModel() { Category = m.Media.Category, Path = m.Media.Path, Id = m.Media.id, Type = m.Media.Type, }).ToList(), CreationDate = x.CreationDate, Id = x.id, }).ToList(), AdminResponseViewModels = _accountContext.AdminResponses .Include(x => x.AdminResponseMedias) .ThenInclude(x => x.Media) .Where(x => x.TicketId == entity.id).Select(x => new AdminResponseViewModel() { Response = x.Response, TicketId = x.TicketId, AdminAccountId = x.AdminAccountId, MediaViewModels = x.AdminResponseMedias.Select(m => new MediaViewModel() { Category = m.Media.Category, Path = m.Media.Path, Id = m.Media.id, Type = m.Media.Type, }).ToList(), CreationDate = x.CreationDate, Id = x.id, IsActive = x.IsActiveString, FullName = adminAccount.First(a => a.id == x.AdminAccountId).Fullname }).ToList(), WorkshopId = entity.WorkshopId, TicketNumber = $"TKC_{entity.TicketNumber}", Status = entity.Status, HasTask = _accountContext.Tasks.Any(x => x.TicketId == entity.id), IsDeleted = entity.IsDeleted }; editTicketViewModel.ResponseViewModels = MergeResponses(editTicketViewModel.ClientResponseViewModels, editTicketViewModel.AdminResponseViewModels); return editTicketViewModel; } public EditTicket GetDetailsForClient(long id) { var entity = _accountContext.Tickets.FirstOrDefault(x => x.id == id); if (entity == null) return null; var senderAccount = _accountContext.Accounts.FirstOrDefault(a => a.id == entity.SenderId); var editTicketViewModel = new EditTicket() { ContractingPartyName = entity.ContractingPartyName, Description = entity.Description, Id = entity.id, SenderId = entity.SenderId, Sender = new AccountViewModel() { Id = senderAccount.id, Fullname = senderAccount.Fullname, }, TicketType = entity.TicketType, Title = entity.Title, CreationDateStr = $"{entity.CreationDate.ToFarsi()} {entity.CreationDate.DayOfWeek.DayOfWeeKToPersian()}", MediaViewModels = _accountContext.TicketMedias.Include(z => z.Media).Where(a => a.TicketId == entity.id) .Select(m => new MediaViewModel() { Id = m.Media.id, Path = m.Media.Path, Type = m.Media.Type, Category = m.Media.Category, }).ToList(), ClientResponseViewModels = _accountContext.ClientResponses .Include(x => x.ClientResponseMedias) .ThenInclude(x => x.Media) .Where(x => x.TicketId == entity.id).Select(x => new ClientResponseViewModel() { Response = x.Response, TicketId = x.TicketId, MediaViewModels = x.ClientResponseMedias.Select(m => new MediaViewModel() { Category = m.Media.Category, Path = m.Media.Path, Id = m.Media.id, Type = m.Media.Type, }).ToList(), CreationDate = x.CreationDate, Id = x.id, }).ToList(), AdminResponseViewModels = _accountContext.AdminResponses .Include(x => x.AdminResponseMedias) .ThenInclude(x => x.Media) .Where(x => x.TicketId == entity.id).Select(x => new AdminResponseViewModel() { Response = x.Response, TicketId = x.TicketId, MediaViewModels = x.AdminResponseMedias.Select(m => new MediaViewModel() { Category = m.Media.Category, Path = m.Media.Path, Id = m.Media.id, Type = m.Media.Type, }).ToList(), CreationDate = x.CreationDate, Id = x.id, IsActive = x.IsActiveString }).ToList(), WorkshopId = entity.WorkshopId, TicketNumber = $"TKC_{entity.TicketNumber}", Status = entity.Status }; editTicketViewModel.ResponseViewModels = MergeResponses(editTicketViewModel.ClientResponseViewModels, editTicketViewModel.AdminResponseViewModels); return editTicketViewModel; } public int GetLastTicketNumber() { var res = _accountContext.Tickets.Any(x => x.TicketNumber != null) ? _accountContext.Tickets.Max(x => Convert.ToInt32(x.TicketNumber)) : 0; return res; } public AdminResponse GetAdminResponse(long adminResId) { return _accountContext.AdminResponses.FirstOrDefault(x => x.id == adminResId); } public ClientResponse GetClientResponse(long clientResId) { return _accountContext.ClientResponses.FirstOrDefault(x => x.id == clientResId); } public void RemoveAdminResponse(long adminResId) { var adminRes = _accountContext.AdminResponses.Include(x => x.AdminResponseMedias).ThenInclude(x => x.Media).FirstOrDefault(x => x.id == adminResId); if (adminRes != null) { _accountContext.RemoveRange(adminRes.AdminResponseMedias); _accountContext.Remove(adminRes); } } public TypesCountOfTicketViewModel GetTypesCountOfTicketForAdmin() { var tickets = _accountContext.Tickets.AsQueryable().Where(x=>!x.IsDeleted); return new TypesCountOfTicketViewModel() { All = tickets.Count(), Answered = tickets.Count(x => x.Status == "پاسخ داده شده"), Closed = tickets.Count(x => x.Status == "بسته شده"), Open = tickets.Count(x => x.Status == "باز"), Pending = tickets.Count(x => x.Status == "درحال بررسی") }; } public TypesCountOfTicketViewModel GetTypesCountOfTicketForClient(long workshopId) { var tickets = _accountContext.Tickets.Where(x => x.WorkshopId == workshopId); return new TypesCountOfTicketViewModel() { All = tickets.Count(), Answered = tickets.Count(x => x.Status == "پاسخ داده شده"), Closed = tickets.Count(x => x.Status == "بسته شده"), Open = tickets.Count(x => x.Status == "باز"), Pending = tickets.Count(x => x.Status == "درحال بررسی") }; } public List MergeResponses(List clientResponseList, List adminResponseList) { var list = new List(); var adminList = adminResponseList.Select(x => new Response() { TicketId = x.TicketId, ResponseMessage = x.Response, IsClient = false, IsAdmin = true, IsActive = x.IsActive, FullName = x.FullName, CreationDate = x.CreationDate, CreationDateStr = $"{x.CreationDate.ToFarsi()} {x.CreationDate.DayOfWeek.DayOfWeeKToPersian()} {x.CreationDate.Hour}:{x.CreationDate.Minute}", MediaViewModels = x.MediaViewModels, AdminResponseId = x.Id, AdminAccountId = x.AdminAccountId }).ToList(); var clientList = clientResponseList.Select(x => new Response() { TicketId = x.TicketId, ResponseMessage = x.Response, IsClient = true, IsAdmin = false, CreationDateStr = $"{x.CreationDate.ToFarsi()} {x.CreationDate.DayOfWeek.DayOfWeeKToPersian()} {x.CreationDate.Hour}:{x.CreationDate.Minute}", CreationDate = x.CreationDate, MediaViewModels = x.MediaViewModels, ClientResponseId = x.Id }).ToList(); list.Capacity = (adminList.Count + clientList.Count); list.AddRange(adminList); list.AddRange(clientList); return list.OrderBy(x => x.CreationDate).ToList(); } #region Vafa public int GetAdminTicketsCount() { return _accountContext.Tickets.Count(x => x.Status == "باز"); } #endregion }