using _0_Framework.Application; using AccountManagement.Application.Contracts.Media; using AccountManagement.Domain.MediaAgg; using Company.Domain.EmployeeAgg; using Company.Domain.EmployeeDocumentItemAgg; using Company.Domain.EmployeeDocumentsAgg; using Company.Domain.LeftWorkAgg; using Company.Domain.WorkshopAgg; using CompanyManagment.App.Contracts.EmployeeDocuments; using CompanyManagment.App.Contracts.Workshop; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Transactions; using Microsoft.AspNetCore.Mvc; using CompanyManagment.App.Contracts.SmsResult; using Microsoft.Identity.Client; using static Microsoft.QualityTools.Testing.Fakes.FakesDelegates; using Company.Domain.EmployeeClientTempAgg; namespace CompanyManagment.Application { public class EmployeeDocumentsApplication : IEmployeeDocumentsApplication { private readonly IEmployeeDocumentsRepository _employeeDocumentsRepository; private readonly IEmployeeRepository _employeeRepository; private readonly IWorkshopRepository _workshopRepository; private readonly IWebHostEnvironment _webHostEnvironment; private readonly IMediaRepository _mediaRepository; private readonly ILeftWorkRepository _leftWorkRepository; private readonly IEmployeeDocumentItemRepository _employeeDocumentItemRepository; private readonly IAuthHelper _authHelper; private readonly IEmployeeClientTempRepository _employeeClientTempRepository; private readonly string _basePath; public EmployeeDocumentsApplication(IEmployeeDocumentsRepository employeeDocumentsRepository, IEmployeeRepository employeeRepository, IWorkshopRepository workshopRepository, IWebHostEnvironment webHostEnvironment, IMediaRepository mediaRepository, ILeftWorkRepository leftWorkRepository, IEmployeeDocumentItemRepository employeeDocumentItemRepository, IAuthHelper authHelper, IEmployeeClientTempRepository employeeClientTempRepository) { _employeeDocumentsRepository = employeeDocumentsRepository; _employeeRepository = employeeRepository; _workshopRepository = workshopRepository; _webHostEnvironment = webHostEnvironment; _mediaRepository = mediaRepository; _leftWorkRepository = leftWorkRepository; _employeeDocumentItemRepository = employeeDocumentItemRepository; _authHelper = authHelper; _employeeClientTempRepository = employeeClientTempRepository; _basePath = Path.Combine(_webHostEnvironment.ContentRootPath, "Storage", "EmployeeDocuments"); } /// /// مدارک تا قبل از ثبت کردن می توانند توسط کاربر حذف شوند /// public OperationResult DeleteUnsubmittedDocument(long documentItemId) { OperationResult op = new(); var entity = _employeeDocumentItemRepository.Get(documentItemId); if (entity == null) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); if (entity.DocumentStatus != DocumentStatus.Unsubmitted) return op.Failed("امکان حذف رکورد های ثبت شده وجود ندارد"); DeleteDocumentItemFile(entity.MediaId); _employeeDocumentItemRepository.Remove(entity); _employeeDocumentItemRepository.SaveChanges(); return op.Succcedded(); } /// /// برای افزودن یکباره مدارک در افزودن پرسنل توسط کلاینت /// public OperationResult AddRangeEmployeeDocumentItemsTemp(long workshopId, long employeeId, List command) { OperationResult op = new(); var (uploaderId, uploaderType,roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == employeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == workshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); using var scope = new TransactionScope(); //if record doesn't exist but employee exists and also the workshop, create a new record if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return opCreate; entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopId(employeeId, workshopId); } List newEntities = new(); foreach (var item in command) { DeleteMultipleUnsubmittedDocumentsByLabel(entity, item.Label, uploaderType); var mediaOpResult = UploadDocumentItemFile(item.PictureFile, item.Label.ToString(), $"temp/{workshopId}/{employeeId}"); if (mediaOpResult.IsSuccedded == false) return mediaOpResult; //if the mediaId is already in use in our table return failed if (_employeeDocumentItemRepository.Exists(x => x.MediaId == mediaOpResult.SendId)) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); var newEntity = new EmployeeDocumentItem(workshopId, employeeId, mediaOpResult.SendId, entity.id, item.Label, uploaderId, uploaderType,roleId); newEntities.Add(newEntity); } var currentItems = entity.EmployeeDocumentItemCollection.GroupBy(x => x.DocumentLabel) .Select(x => x.MaxBy(y => y.CreationDate)).Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted); //This can bite! _employeeDocumentItemRepository.RemoveRange(currentItems); _employeeDocumentItemRepository.SaveChanges(); _employeeDocumentItemRepository.AddRange(newEntities); _employeeDocumentItemRepository.SaveChanges(); scope.Complete(); return op.Succcedded(entity.id); } /// ///برای بررسی مدارک فرد پس از هر تایید و رد مدارک توسط ادمین صدا زده میشود، ///می شود True اگر مدارک لازم را داشت یک مقدار در انتیتی ///می شود False در غیر این صورت /// public void CheckEmployeeDocumentsConfirmation(long employeeDocumentId) { var entity = _employeeDocumentsRepository.GetByIdWithItems(employeeDocumentId); entity.UpdateIsConfirmed(); entity.UpdateIsSentToChecker(); _employeeDocumentsRepository.SaveChanges(); } /// /// مدارک تا قبل از ثبت کردن می توانند توسط کاربر حذف شوند /// public OperationResult DeleteEmployeeMultipleUnsubmittedDocumentsByLabel(long workshopId, long employeeId, DocumentItemLabel label) { OperationResult op = new(); var includedEmployeeDocuments = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (includedEmployeeDocuments == null) return op.Failed(ApplicationMessages.RecordNotFound); var items = includedEmployeeDocuments.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && x.DocumentLabel == label).ToList(); var mediaIds = items.Select(x => x.MediaId); if (items.Any()) { DeleteMultipleDocumentItemFiles(mediaIds); _employeeDocumentItemRepository.RemoveRange(items); _employeeDocumentItemRepository.SaveChanges(); } else { return op.Failed(ApplicationMessages.RecordNotFound); } return op.Succcedded(); } /// /// برای حذف فایل های آپلود شده هنگام انصراف /// public OperationResult DeleteUnsubmittedItems(long workshopId, long employeeId) { OperationResult op = new(); (_, UserType userType,_) = _authHelper.GetUserTypeWithId(); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); var items = entity.EmployeeDocumentItemCollection.Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && x.UploaderType == userType).ToList(); if (items.Any()) { _employeeDocumentItemRepository.RemoveRange(items); _employeeDocumentItemRepository.SaveChanges(); try { DeleteMultipleDocumentItemFiles(items.Select(x => x.MediaId)); } catch { // ignored } } return op.Succcedded(); } #region Client Only Methods /// /// افزودن آیتم جدید به مدارک برای کلاینت /// public OperationResult AddEmployeeDocumentItemForClient(AddEmployeeDocumentItem command) { OperationResult op = new(); var (uploaderId, uploaderType, roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == command.EmployeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == command.WorkshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(command.EmployeeId, command.WorkshopId); //if record doesn't exist but employee exists and also the workshop, create a new record if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = command.EmployeeId, WorkshopId = command.WorkshopId }); if (opCreate.IsSuccedded == false) return opCreate; entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopId(command.EmployeeId, command.WorkshopId); } var currentItems = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted) .GroupBy(x => x.DocumentLabel).Select(x => x.OrderByDescending(y => y.CreationDate).First()).ToList(); if (currentItems.Any(x => x.DocumentLabel == command.Label && (x.DocumentStatus == DocumentStatus.SubmittedByClient || x.DocumentStatus == DocumentStatus.SubmittedByAdmin))) return op.Failed("امکان ثبت دوباره مدارک تا بررسی مدارک ثبت شده فعلی وجود ندارد"); DeleteMultipleUnsubmittedDocumentsByLabel(entity, command.Label, uploaderType); var mediaOpResult = UploadDocumentItemFile(command.PictureFile, command.Label.ToString(), $"temp/{command.WorkshopId}/{command.EmployeeId}"); if (mediaOpResult.IsSuccedded == false) return mediaOpResult; //if the mediaId is already in use in our table return failed if (_employeeDocumentItemRepository.Exists(x => x.MediaId == mediaOpResult.SendId)) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); var newEntity = new EmployeeDocumentItem(command.WorkshopId, command.EmployeeId, mediaOpResult.SendId, entity.id, command.Label, uploaderId, uploaderType, roleId); _employeeDocumentItemRepository.Create(newEntity); _employeeDocumentItemRepository.SaveChanges(); return op.Succcedded(entity.id); } /// /// ثبت مدارک توسط کلاینت /// public OperationResult SubmitDocumentItemsByClient(SubmitEmployeeDocuments cmd) { OperationResult op = new(); var entity = _employeeDocumentsRepository.GetByIdWithItems(cmd.EmployeeDocumentsId); var currentDocs = entity.EmployeeDocumentItemCollection.GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)) .ToList(); var (userId, userType,_) = _authHelper.GetUserTypeWithId(); var unsubmittedDocs = currentDocs.Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && x.UploaderType == UserType.Client).ToList(); if (unsubmittedDocs.Any() == false) return op.Succcedded(); foreach (var item in unsubmittedDocs) { item.SubmitByClient(userId, userType); MoveDocumentItemFile(item.MediaId, $"SubmittedByClient/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } if (HasRequiredDocuments(currentDocs, entity.Gender)) entity.UpdateRequiredItemsSubmittedByClient(); _employeeDocumentItemRepository.SaveChanges(); entity.UpdateIsConfirmed(); _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(); } /// /// ثبت مدارک توسط کلاینت برای افزودن پرسنل /// public OperationResult SubmitDocumentItemsByEmployeeIdWorkshopId(long employeeId, long workshopId) { OperationResult op = new(); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); var notRejectedDocs = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Client) .GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)).ToList(); if (!HasRequiredDocuments(notRejectedDocs, entity.Gender)) return op.Failed("مدارک الزامی بارگذاری نشده اند"); var (userId, userType, roleId) = _authHelper.GetUserTypeWithId(); var unsubmittedDocs = notRejectedDocs.Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted).ToList(); if (unsubmittedDocs.Any() == false) return op.Succcedded(); foreach (var item in unsubmittedDocs) { item.SubmitByClient(userId, userType); MoveDocumentItemFile(item.MediaId, $"SubmittedByClient/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } _employeeDocumentItemRepository.SaveChanges(); entity.UpdateIsConfirmed(); _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(); } /// /// برای افزودن یکباره مدارک در افزودن پرسنل توسط کلاینت /// public OperationResult AddRangeEmployeeDocumentItemsByClient(long workshopId, long employeeId, List command) { OperationResult op = new(); var (uploaderId, uploaderType,roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == employeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == workshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); using var scope = new TransactionScope(); //if record doesn't exist but employee exists and also the workshop, create a new record if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return opCreate; entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopId(employeeId, workshopId); } List newEntities = new(); foreach (var item in command) { DeleteMultipleUnsubmittedDocumentsByLabel(entity, item.Label, uploaderType); var mediaOpResult = UploadDocumentItemFile(item.PictureFile, item.Label.ToString(), $"temp/{workshopId}/{employeeId}"); if (mediaOpResult.IsSuccedded == false) return mediaOpResult; //if the mediaId is already in use in our table return failed if (_employeeDocumentItemRepository.Exists(x => x.MediaId == mediaOpResult.SendId)) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); var newEntity = new EmployeeDocumentItem(workshopId, employeeId, mediaOpResult.SendId, entity.id, item.Label, uploaderId, uploaderType, roleId,DocumentStatus.SubmittedByClient); newEntities.Add(newEntity); } var currentItems = entity.EmployeeDocumentItemCollection.GroupBy(x => x.DocumentLabel) .Where(x => command.Any(a => a.Label == x.Key)) .Select(x => x.MaxBy(y => y.CreationDate)); //This can bite! _employeeDocumentItemRepository.RemoveRange(currentItems); _employeeDocumentItemRepository.SaveChanges(); entity.UpdateIsConfirmed(); _employeeDocumentItemRepository.AddRange(newEntities); _employeeDocumentItemRepository.SaveChanges(); SubmitDocumentItemsByEmployeeIdWorkshopId(employeeId, workshopId); scope.Complete(); return op.Succcedded(entity.id); } ///// ///// ثبت مدارک توسط کلاینت ///// //public OperationResult SubmitDocumentItemsByClient(SubmitEmployeeDocuments cmd) //{ // OperationResult op = new(); // var entity = _employeeDocumentsRepository.GetByIdWithItems(cmd.EmployeeDocumentsId); // var notRejectedDocs = entity.EmployeeDocumentItemCollection.Where(x => // x.DocumentStatus != DocumentStatus.Rejected && x.DocumentStatus != DocumentStatus.Deleted) // .GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)).ToList(); // //if (!HasRequiredDocuments(notRejectedDocs, entity.Gender)) // // return op.Failed("مدارک الزامی بارگذاری نشده اند"); // var (userId, userType) = _authHelper.GetUserTypeWithId(); // var unsubmittedDocs = notRejectedDocs.Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && // x.UploaderType == UserType.Client).ToList(); // if (unsubmittedDocs.Any() == false) // return op.Succcedded(); // foreach (var item in unsubmittedDocs) // item.Submit(userId, userType); // _employeeDocumentItemRepository.SaveChanges(); // entity.UpdateIsSentToChecker(); // entity.UpdateAreRequiredDocumentsConfirmed(); // _employeeDocumentsRepository.SaveChanges(); // return op.Succcedded(); //} // /// // /// ثبت مدارک توسط کلاینت // /// // public OperationResult SubmitDocumentItemsByEmployeeIdWorkshopId(long employeeId, long workshopId) // { // OperationResult op = new(); // var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); // var notRejectedDocs = entity.EmployeeDocumentItemCollection.Where(x => // x.DocumentStatus != DocumentStatus.Rejected && x.DocumentStatus != DocumentStatus.Deleted) // .GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)).ToList(); // if (!HasRequiredDocuments(notRejectedDocs, entity.Gender)) // return op.Failed("مدارک الزامی بارگذاری نشده اند"); // var unsubmittedDocs = notRejectedDocs.Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted).ToList(); // if (unsubmittedDocs.Any() == false) // return op.Succcedded(); // foreach (var item in unsubmittedDocs) // item.Submit(userId, userType); // _employeeDocumentItemRepository.SaveChanges(); // entity.UpdateIsSentToChecker(); // entity.UpdateAreRequiredDocumentsConfirmed(); // _employeeDocumentsRepository.SaveChanges(); // return op.Succcedded(); // } // /// // /// ادمین unsubmitted دریافت جزییات مدارک پرسنل برای کلاینت بدون مدارک // /// /// public EmployeeDocumentsViewModel GetDetailsForClient(long employeeId, long workshopId) { var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (!_employeeRepository.Exists(x => x.id == employeeId)) return new(); if (!_workshopRepository.Exists(x => x.id == workshopId)) return new(); //if entity is null but employee exists, make a new empty entity for it if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return new(); return new EmployeeDocumentsViewModel() { EmployeeId = employeeId }; } List currentConfirmedDocuments = entity.EmployeeDocumentItemCollection .Where(x => x.UploaderType == UserType.Client || x.DocumentStatus != DocumentStatus.Unsubmitted) .GroupBy(x => x.DocumentLabel) .Select(x => x.MaxBy(y => y.CreationDate)).ToList(); var medias = _mediaRepository .GetMedias(currentConfirmedDocuments.Select(x => x.MediaId) .ToList()); var employee = _employeeRepository.Get(entity.EmployeeId); var result = new EmployeeDocumentsViewModel() { Id = entity.id, MilitaryServiceCard = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.MilitaryServiceCard), EducationalDegree = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.EducationalDegree), IdCardPage1 = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.IdCardPage1), IdCardPage2 = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.IdCardPage2), IdCardPage3 = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.IdCardPage3), IdCardPage4 = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.IdCardPage4), NationalCardFront = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.NationalCardFront), NationalCardRear = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.NationalCardRear), EmployeePicture = GetItemFromCollectionByLabel(currentConfirmedDocuments, medias, DocumentItemLabel.EmployeePicture), EmployeeFullName = employee.FullName, WorkshopId = workshopId, EmployeeId = entity.EmployeeId, Gender = employee.Gender, NationalCode = employee.NationalCode, EmployeeFName = employee.FName, EmployeeLName = employee.LName, Nationality = employee.Nationality, IdNumber = employee.IdNumber, FatherName = employee.FatherName, DateOfBirth = employee.DateOfBirth.ToFarsi(), MaritalStatus = employee.MaritalStatus, MilitaryServiceStatus = employee.MilitaryService, SubmittedItemsCount = currentConfirmedDocuments.Count(x => x.DocumentStatus == DocumentStatus.SubmittedByAdmin || x.DocumentStatus == DocumentStatus.SubmittedByClient), IsSentToChecker = entity.IsSentToChecker }; result.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(result.EmployeePicture.PicturePath); result.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage1.PicturePath); result.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage2.PicturePath); result.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage3.PicturePath); result.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage4.PicturePath); result.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(result.NationalCardFront.PicturePath); result.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(result.NationalCardRear.PicturePath); result.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(result.MilitaryServiceCard.PicturePath); return result; } /// /// جستجوی مجموعه مدارک بر اساس کارگاه /// /// مد تعیین کننده فیلتر افراد فعال است، سه حالت دارد: همه، فقط فعال، فقط غیر فعال public List SearchForClient(SearchEmployeeDocuments cmd, EmployeeDocumentSearchMode mode = EmployeeDocumentSearchMode.ActiveEmployees) { #region Create EmployeeDocuments Record For Newly Added Employees var existingEmployeesWithDocs = _employeeDocumentsRepository.GetEmployeeIds(cmd.WorkshopId); var existingEmployeeIds = _leftWorkRepository.GetAllEmployeeIdsInWorkshop(cmd.WorkshopId); var newEmployeeIds = existingEmployeeIds.Except(existingEmployeesWithDocs).ToList(); if (newEmployeeIds.Any()) { List employees = _employeeRepository.GetRangeByIds(newEmployeeIds).Select(x => new EmployeeDocuments(x.id, cmd.WorkshopId, x.Gender)).ToList(); _employeeDocumentsRepository.AddRange(employees); _employeeDocumentsRepository.SaveChanges(); } #endregion cmd.Mode = mode; var result = _employeeDocumentsRepository.SearchForClient(cmd); result.ForEach(x => { x.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(x.EmployeePicture.PicturePath); x.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage1.PicturePath); x.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage2.PicturePath); x.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage3.PicturePath); x.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage4.PicturePath); x.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardFront.PicturePath); x.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardRear.PicturePath); x.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(x.MilitaryServiceCard.PicturePath); }); return result; } public Task> GetClientRejectedDocumentForClient(long workshopId, long accountId) { return _employeeDocumentsRepository.GetClientRejectedDocumentForClient(workshopId, accountId); } #endregion #region Admin Only Methods /// ///حذف آیتم ثبت شده توسط کلاینت برای ادمین /// public OperationResult RemoveClientDocumentItemsByAdminTemp(long workshopId, long employeeId, DocumentItemLabel label) { OperationResult op = new(); var (uploaderId, uploaderType, roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == employeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == workshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (entity == null) { return op.Failed("خطای سیستمی"); } var currentItems = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Admin) .GroupBy(x => x.DocumentLabel).Select(x => x.OrderByDescending(y => y.CreationDate).First()).ToList(); if (currentItems.Any(x => label == x.DocumentLabel && x.DocumentStatus == DocumentStatus.SubmittedByAdmin)) return op.Failed("امکان ثبت دوباره مدارک تا بررسی مدارک ثبت شده فعلی وجود ندارد"); var targetEntites = currentItems.Where(x => label == x.DocumentLabel && x.DocumentStatus == DocumentStatus.SubmittedByClient).ToList(); //if the given label is uploaded by user, move it and soft delete it if (targetEntites.Any()) { foreach (var clientUploadedItem in targetEntites) { clientUploadedItem.Delete(uploaderId, uploaderType); MoveDocumentItemFile(clientUploadedItem.MediaId, $"Deleted/{clientUploadedItem.EmployeeDocuments.WorkshopId}/{clientUploadedItem.EmployeeDocuments.EmployeeId}"); } } DeleteMultipleUnsubmittedDocumentsByLabel(entity, label, uploaderType); _employeeDocumentItemRepository.SaveChanges(); return op.Succcedded(); } /// ///حذف آیتم ثبت شده توسط کلاینت برای ادمین /// public OperationResult RemoveClientDocumentItemsByAdmin(long workshopId, long employeeId, List labels) { OperationResult op = new(); var (uploaderId, uploaderType,roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == employeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == workshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (entity == null) { return op.Failed("خطای سیستمی"); } var currentItems = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Admin) .GroupBy(x => x.DocumentLabel).Select(x => x.OrderByDescending(y => y.CreationDate).First()).ToList(); if (currentItems.Any(x => labels.Contains(x.DocumentLabel) && x.DocumentStatus == DocumentStatus.SubmittedByAdmin)) return op.Failed("امکان ثبت دوباره مدارک تا بررسی مدارک ثبت شده فعلی وجود ندارد"); var targetEntites = currentItems.Where(x => labels.Contains(x.DocumentLabel) && x.DocumentStatus == DocumentStatus.SubmittedByClient).ToList(); //if the given label is uploaded by user, move it and soft delete it if (targetEntites.Any()) { foreach (var clientUploadedItem in targetEntites) { clientUploadedItem.Delete(uploaderId, uploaderType); MoveDocumentItemFile(clientUploadedItem.MediaId, $"Deleted/{clientUploadedItem.EmployeeDocuments.WorkshopId}/{clientUploadedItem.EmployeeDocuments.EmployeeId}"); } _employeeDocumentItemRepository.SaveChanges(); } return op.Succcedded(); } /// /// اضافه کردن آیتم جدید به مدارک برای ادمین /// public OperationResult AddEmployeeDocumentItemForAdmin(AddEmployeeDocumentItem command) { OperationResult op = new(); var (uploaderId, uploaderType, roleId) = _authHelper.GetUserTypeWithId(); //ToDo: add check for leftwork if (!_employeeRepository.Exists(x => x.id == command.EmployeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == command.WorkshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(command.EmployeeId, command.WorkshopId); //if record doesn't exist but employee exists and also the workshop, create a new record if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = command.EmployeeId, WorkshopId = command.WorkshopId }); if (opCreate.IsSuccedded == false) return opCreate; entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopId(command.EmployeeId, command.WorkshopId); } var currentItems = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Admin) .GroupBy(x => x.DocumentLabel).Select(x => x.OrderByDescending(y => y.CreationDate).First()).ToList(); if (currentItems.Any(x => x.DocumentLabel == command.Label && x.DocumentStatus == DocumentStatus.SubmittedByAdmin)) return op.Failed("امکان ثبت دوباره مدارک تا بررسی مدارک ثبت شده فعلی وجود ندارد"); //if a given label is uploaded by user, move it and soft delete it if (currentItems.Any(x => x.DocumentLabel == command.Label && x.DocumentStatus == DocumentStatus.SubmittedByClient)) { var clientUploadedItem = currentItems.First(x => x.DocumentLabel == command.Label && x.DocumentStatus == DocumentStatus.SubmittedByClient); clientUploadedItem.Delete(uploaderId, uploaderType); MoveDocumentItemFile(clientUploadedItem.MediaId, $"Deleted/{clientUploadedItem.EmployeeDocuments.WorkshopId}/{clientUploadedItem.EmployeeDocuments.EmployeeId}"); } DeleteMultipleUnsubmittedDocumentsByLabel(entity, command.Label, uploaderType); var mediaOpResult = UploadDocumentItemFile(command.PictureFile, command.Label.ToString(), $"temp/{command.WorkshopId}/{command.EmployeeId}"); if (mediaOpResult.IsSuccedded == false) return mediaOpResult; //if the mediaId is already in use in our table return failed if (_employeeDocumentItemRepository.Exists(x => x.MediaId == mediaOpResult.SendId)) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); var newEntity = new EmployeeDocumentItem(command.WorkshopId, command.EmployeeId, mediaOpResult.SendId, entity.id, command.Label, uploaderId, uploaderType, roleId); _employeeDocumentItemRepository.Create(newEntity); _employeeDocumentItemRepository.SaveChanges(); return op.Succcedded(entity.id); } /// /// ثبت مدارک توسط ادمین /// public OperationResult SubmitDocumentItemsByAdmin(SubmitEmployeeDocuments cmd) { OperationResult op = new(); var entity = _employeeDocumentsRepository.GetByIdWithItems(cmd.EmployeeDocumentsId); var currentDocs = entity.EmployeeDocumentItemCollection.Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Admin) .GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)).ToList(); //if (!HasRequiredDocuments(notRejectedDocs, entity.Gender)) // return op.Failed("مدارک الزامی بارگذاری نشده اند"); var (userId, operatorType, _) = _authHelper.GetUserTypeWithId(); var adminUnsubmittedDocs = currentDocs.Where(x => x.DocumentStatus == DocumentStatus.SubmittedByClient || (x.DocumentStatus == DocumentStatus.Unsubmitted && x.UploaderType == UserType.Admin)).ToList(); //if (!HasRequiredDocuments(currentDocs, entity.Gender)) // return op.Failed("مدارک الزامی بارگذاری نشده اند"); if (adminUnsubmittedDocs.Any() == false) return op.Succcedded(); foreach (var item in adminUnsubmittedDocs) { item.SubmitByAdmin(userId, operatorType); MoveDocumentItemFile(item.MediaId, $"SubmittedByAdmin/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } _employeeDocumentItemRepository.SaveChanges(); entity.UpdateRequiredItemsSubmittedByClient(); entity.UpdateIsSentToChecker(); entity.UpdateIsConfirmed(); _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(); } /// /// ثبت مدارک توسط ادمین، در این متد مدارک الزامی اعتبار سنجی دارند /// public OperationResult SubmitDocumentItemsByAdminInWorkFlow(SubmitEmployeeDocuments cmd) { OperationResult op = new(); var entity = _employeeDocumentsRepository.GetByIdWithItems(cmd.EmployeeDocumentsId); var currentDocs = entity.EmployeeDocumentItemCollection.Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted || x.UploaderType == UserType.Admin) .GroupBy(x => x.DocumentLabel).Select(x => x.MaxBy(y => y.CreationDate)).ToList(); //if (!HasRequiredDocuments(notRejectedDocs, entity.Gender)) // return op.Failed("مدارک الزامی بارگذاری نشده اند"); var (userId, operatorType, _) = _authHelper.GetUserTypeWithId(); var adminUnsubmittedDocs = currentDocs.Where(x => x.DocumentStatus == DocumentStatus.SubmittedByClient || (x.DocumentStatus == DocumentStatus.Unsubmitted && x.UploaderType == UserType.Admin)).ToList(); if (!HasRequiredDocuments(currentDocs, entity.Gender)) return op.Failed("مدارک الزامی بارگذاری نشده اند"); if (adminUnsubmittedDocs.Any() == false) return op.Succcedded(); foreach (var item in adminUnsubmittedDocs) { item.SubmitByAdmin(userId, operatorType); MoveDocumentItemFile(item.MediaId, $"SubmittedByAdmin/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } _employeeDocumentItemRepository.SaveChanges(); entity.UpdateRequiredItemsSubmittedByClient(); entity.UpdateIsSentToChecker(); entity.UpdateIsConfirmed(); _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(); } /// /// کلاینت unsubmitted دریافت جزییات مدارک پرسنل برای ادمین بدون مدارک /// public EmployeeDocumentsViewModel GetDetailsForAdmin(long employeeId, long workshopId) { var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (!_employeeRepository.Exists(x => x.id == employeeId)) return new(); if (!_workshopRepository.Exists(x => x.id == workshopId)) return new(); //if entity is null but employee exists, make a new empty entity for it if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return new(); return new EmployeeDocumentsViewModel() { EmployeeId = employeeId }; } List currentDocuments = entity.EmployeeDocumentItemCollection .Where(x => x.UploaderType == UserType.Admin || x.DocumentStatus != DocumentStatus.Unsubmitted) .GroupBy(x => x.DocumentLabel) .Select(x => x.MaxBy(y => y.CreationDate)).ToList(); var medias = _mediaRepository .GetMedias(currentDocuments.Select(x => x.MediaId) .ToList()); var employee = _employeeRepository.Get(entity.EmployeeId); var result = new EmployeeDocumentsViewModel() { Id = entity.id, MilitaryServiceCard = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.MilitaryServiceCard), EducationalDegree = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.EducationalDegree), IdCardPage1 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage1), IdCardPage2 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage2), IdCardPage3 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage3), IdCardPage4 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage4), NationalCardFront = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.NationalCardFront), NationalCardRear = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.NationalCardRear), EmployeePicture = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.EmployeePicture), EmployeeFullName = employee.FullName, WorkshopId = workshopId, EmployeeId = entity.EmployeeId, Gender = employee.Gender, NationalCode = employee.NationalCode, EmployeeFName = employee.FName, EmployeeLName = employee.LName, Nationality = employee.Nationality, IdNumber = employee.IdNumber, FatherName = employee.FatherName, DateOfBirth = employee.DateOfBirth.ToFarsi(), MaritalStatus = employee.MaritalStatus, MilitaryServiceStatus = employee.MilitaryService, }; result.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(result.EmployeePicture.PicturePath); result.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage1.PicturePath); result.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage2.PicturePath); result.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage3.PicturePath); result.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(result.IdCardPage4.PicturePath); result.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(result.NationalCardFront.PicturePath); result.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(result.NationalCardRear.PicturePath); result.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(result.MilitaryServiceCard.PicturePath); return result; } /// /// جستجوی مجموعه مدارک بر اساس کارگاه برای ادمین /// مد تعیین کننده فیلتر افراد فعال است، سه حالت دارد: همه، فقط فعال، فقط غیر فعال public List SearchForAdmin(SearchEmployeeDocuments cmd, EmployeeDocumentSearchMode mode = EmployeeDocumentSearchMode.ActiveEmployees) { #region Create EmployeeDocuments Record For Newly Added Employees var existingEmployeesWithDocs = _employeeDocumentsRepository.GetEmployeeIds(cmd.WorkshopId); var existingEmployeeIds = _leftWorkRepository.GetAllEmployeeIdsInWorkshop(cmd.WorkshopId); var newEmployeeIds = existingEmployeeIds.Except(existingEmployeesWithDocs).ToList(); if (newEmployeeIds.Any()) { List employees = _employeeRepository.GetRangeByIds(newEmployeeIds).Select(x => new EmployeeDocuments(x.id, cmd.WorkshopId, x.Gender)).ToList(); _employeeDocumentsRepository.AddRange(employees); _employeeDocumentsRepository.SaveChanges(); } #endregion cmd.Mode = mode; var result = _employeeDocumentsRepository.SearchForAdmin(cmd); result.ForEach(x => { var requiredDocuments = EmployeeDocumentRequiredItems.GetByGender(x.Gender); x.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(x.EmployeePicture.PicturePath); x.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage1.PicturePath); x.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage2.PicturePath); x.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage3.PicturePath); x.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage4.PicturePath); x.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardFront.PicturePath); x.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardRear.PicturePath); x.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(x.MilitaryServiceCard.PicturePath); x.RequiredDocuments = requiredDocuments; x.RequiredDocumentsUploaded = x.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(y => y.PropertyType == typeof(EmployeeDocumentItemViewModel)) .Select(y => y.GetValue(x) as EmployeeDocumentItemViewModel).Where(y => y != null && !string.IsNullOrWhiteSpace(y.PicturePath) && (y.Status is DocumentStatus.Confirmed or DocumentStatus.SubmittedByAdmin)).Select(y => y.DocumentItemLabel).ToList(); }); return result; } /// /// مجموعه مدارک بر اساس کارگاه برای کارپوشه ادمین public List GetByWorkshopIdWithItemsForAdminWorkFlow(long workshopId) { #region Create EmployeeDocuments Record For Newly Added Employees var existingEmployeesWithDocs = _employeeDocumentsRepository.GetEmployeeIds(workshopId); var existingEmployeeIds = _leftWorkRepository.GetAllEmployeeIdsInWorkshop(workshopId); var newEmployeeIds = existingEmployeeIds.Except(existingEmployeesWithDocs).ToList(); if (newEmployeeIds.Any()) { List employees = _employeeRepository.GetRangeByIds(newEmployeeIds).Select(x => new EmployeeDocuments(x.id, workshopId, x.Gender)).ToList(); _employeeDocumentsRepository.AddRange(employees); _employeeDocumentsRepository.SaveChanges(); } #endregion var result = _employeeDocumentsRepository.GetByWorkshopIdWithItemsForAdminWorkFlow(workshopId); result.ForEach(x => { var requiredDocuments = EmployeeDocumentRequiredItems.GetByGender(x.Gender); x.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(x.EmployeePicture.PicturePath); x.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage1.PicturePath); x.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage2.PicturePath); x.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage3.PicturePath); x.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage4.PicturePath); x.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardFront.PicturePath); x.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardRear.PicturePath); x.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(x.MilitaryServiceCard.PicturePath); x.RequiredDocuments = requiredDocuments; #region شتر دیدی ندیدی x.RequiredDocumentsUploaded = x.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(y => y.PropertyType == typeof(EmployeeDocumentItemViewModel)) .Select(y => y.GetValue(x) as EmployeeDocumentItemViewModel).Where(y => y != null && !string.IsNullOrWhiteSpace(y.PicturePath) && (y.Status is DocumentStatus.Confirmed or DocumentStatus.SubmittedByAdmin)).Select(y => y.DocumentItemLabel).ToList(); #endregion }); return result; } /// /// دریافت کارگاه های ادمین که نیاز به آپلود مدارک ضروری دارند /// public List GetWorkshopDocumentsAwaitingUploadForAdminWorkFlow(List workshops) { return _employeeDocumentsRepository.GetWorkshopsWithDocumentsAwaitingReviewForAdminWorkFlow(workshops); } /// /// حذف توسط ادمین، مدارک ثبت شده کلاینت نیز میتوانند توسط ادمین پاک شوند /// public OperationResult RemoveByAdmin(long documentItemId) { OperationResult op = new(); var entity = _employeeDocumentItemRepository.Get(documentItemId); (long operatorId, _,_) = _authHelper.GetUserTypeWithId(); if (entity == null) return op.Failed(ApplicationMessages.RecordNotFound); if (entity.DocumentStatus == DocumentStatus.Confirmed || entity.DocumentStatus == DocumentStatus.Rejected || entity.DocumentStatus == DocumentStatus.Deleted) { return op.Failed("شما تنها مجاز به حذف موارد تعیین تکلیف نشده هستید"); } if (entity.UploaderType == UserType.Client) { entity.Delete(operatorId, UserType.Admin); } else { _employeeDocumentItemRepository.Remove(entity); } _employeeDocumentItemRepository.SaveChanges(); return op.Succcedded(); } public async Task GetAdminWorkFlowCountForSubmittedAndRejectedDocuments(List workshopIds) { return await _employeeDocumentsRepository.GetAdminWorkFlowCountForSubmittedAndRejectedDocuments(workshopIds); } public async Task GetAdminWorkFlowCountForNewEmployees(List workshopIds) { return await _employeeDocumentsRepository.GetAdminWorkFlowCountForNewEmployees(workshopIds); } public async Task> GetWorkshopDocumentCreatedEmployeeForAdmin(List workshops, long roleId) { return await _employeeDocumentsRepository.GetWorkshopDocumentCreatedEmployeeForAdmin(workshops, roleId); } public async Task> GetWorkshopDocumentRejectedForAdmin(List workshops, long roleId) { return await _employeeDocumentsRepository.GetWorkshopDocumentRejectedForAdmin(workshops, roleId); } public async Task> GetRejectedItemsByWorkshopIdAndRoleForAdminWorkFlow(long workshopId, long roleId) { return await _employeeDocumentsRepository.GetRejectedItemsByWorkshopIdAndRoleForAdminWorkFlow(workshopId, roleId); } public Task> GetCreatedEmployeesWorkshopDocumentForAdmin( List workshops, long roleId) { return _employeeDocumentsRepository.GetCreatedEmployeesWorkshopDocumentForAdmin(workshops, roleId); } public Task> GetCreatedEmployeesDocumentByWorkshopIdForAdmin(long workshopId) { return _employeeDocumentsRepository.GetCreatedEmployeesDocumentByWorkshopIdForAdmin(workshopId); } public Task> GetClientRejectedDocumentWorkshopsForAdmin( List workshops, long roleId) { return _employeeDocumentsRepository.GetClientRejectedDocumentWorkshopsForAdmin(workshops,roleId); } public Task> GetClientRejectedDocumentByWorkshopIdForAdmin(long workshopId) { return _employeeDocumentsRepository.GetClientRejectedDocumentByWorkshopIdForAdmin(workshopId); } #endregion #region Checker Only Methods /// /// ثبت عملیات چکر /// public OperationResult SubmitCheckerOperation(CheckerDocumentsOperation cmd) { OperationResult op = new(); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(cmd.EmployeeId, cmd.WorkshopId); if (entity == null) return op.Failed(ApplicationMessages.RecordNotFound); foreach (var operation in cmd.Operations) { var item = _employeeDocumentItemRepository.GetWithEmployeeDocumentsByItemId(operation.EmployeeDocumentItemId); if (item == null) { return op.Failed("رکورد مورد نظر یافت نشد"); } (long operatorId, UserType userType,long roleId) = _authHelper.GetUserTypeWithId(); if ((item.DocumentStatus is DocumentStatus.SubmittedByAdmin or DocumentStatus.SubmittedByClient) == false) return op.Failed("امکان بررسی رکورد مورد نظر وجود ندارد"); if (operation.IsConfirmed == false) { if (string.IsNullOrWhiteSpace(operation.Message)) return op.Failed("لطفا علت رد درخواست را پر کنید"); item.Reject(operatorId, operation.Message, userType); MoveDocumentItemFile(item.MediaId, $"Rejected/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } else { item.Confirm(operatorId, userType); MoveDocumentItemFile(item.MediaId, $"Confirmed/{item.EmployeeDocuments.WorkshopId}/{item.EmployeeDocuments.EmployeeId}"); } } entity.UpdateIsConfirmed(); entity.UpdateIsSentToChecker(); if (entity.IsConfirmed) { var clientTemp = _employeeClientTempRepository.GetByEmployeeIdAndWorkshopId(entity.EmployeeId, entity.WorkshopId); var employee = _employeeRepository.Get(entity.EmployeeId); if (clientTemp != null) { employee.EditFromEmployeeClientTemp(clientTemp.MaritalStatus); _employeeClientTempRepository.Remove(clientTemp); } } _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(); } /// /// برای تایید یا رد توسط چکر ،unsubmitted دریافت جزییات مدارک پرسنل، بدون مدارک /// public EmployeeDocumentsViewModel GetDetailsForChecker(long employeeId, long workshopId) { var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); if (!_employeeRepository.Exists(x => x.id == employeeId)) return new(); if (!_workshopRepository.Exists(x => x.id == workshopId)) return new(); //if entity is null but employee exists, make a new empty entity for it if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return new(); return new EmployeeDocumentsViewModel() { EmployeeId = employeeId }; } List currentDocuments = entity.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus != DocumentStatus.Unsubmitted) .GroupBy(x => x.DocumentLabel) .Select(x => x.MaxBy(y => y.CreationDate)) .Where(x => x.DocumentStatus is DocumentStatus.SubmittedByAdmin or DocumentStatus.Confirmed or DocumentStatus.Rejected or DocumentStatus.SubmittedByClient).ToList(); var medias = _mediaRepository .GetMedias(currentDocuments.Select(x => x.MediaId) .ToList()); var employee = _employeeRepository.Get(entity.EmployeeId); var employeeClientTemp = _employeeClientTempRepository.GetByEmployeeIdAndWorkshopId(employeeId, workshopId); return new EmployeeDocumentsViewModel() { Id = entity.id, MilitaryServiceCard = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.MilitaryServiceCard), EducationalDegree = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.EducationalDegree), IdCardPage1 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage1), IdCardPage2 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage2), IdCardPage3 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage3), IdCardPage4 = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.IdCardPage4), NationalCardFront = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.NationalCardFront), NationalCardRear = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.NationalCardRear), EmployeePicture = GetItemFromCollectionByLabel(currentDocuments, medias, DocumentItemLabel.EmployeePicture), EmployeeFullName = employee.FullName, WorkshopId = workshopId, EmployeeId = entity.EmployeeId, Gender = employee.Gender, NationalCode = employee.NationalCode, EmployeeFName = employee.FName, EmployeeLName = employee.LName, Nationality = employee.Nationality, IdNumber = employee.IdNumber, FatherName = employee.FatherName, DateOfBirth = employee.DateOfBirth.ToFarsi(), MaritalStatus = employeeClientTemp == null ? employee.MaritalStatus : employeeClientTemp.MaritalStatus, MilitaryServiceStatus = employee.MilitaryService, SubmittedItemsCount = currentDocuments.Count(x => x.DocumentStatus is DocumentStatus.SubmittedByAdmin or DocumentStatus.SubmittedByClient) }; } /// /// دریافت کارگاه هایی که اقدام به آپلود مدارک کرده اند /// public List GetWorkshopsWithUploadedDocumentsForChecker() { return _employeeDocumentsRepository.GetWorkshopsWithUploadedDocuments(); } /// /// دریافت پرسنلی که اقدام به آپلود مدارک کرده اند /// public List GetByWorkshopIdWithItemsForChecker(long workshopId, bool onlyConfirmed) { var result = _employeeDocumentsRepository.GetByWorkshopIdWithItemsForChecker(workshopId, onlyConfirmed); result.ForEach(x => { x.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(x.EmployeePicture.PicturePath); x.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage1.PicturePath); x.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage2.PicturePath); x.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage3.PicturePath); x.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage4.PicturePath); x.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardFront.PicturePath); x.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardRear.PicturePath); x.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(x.MilitaryServiceCard.PicturePath); }); return result; } /// /// دریافت کارگاه هایی که اقدام به آپلود مدارک "ضروری" کرده اند، برای کارپوشه /// public List GetWorkshopsWithDocumentsAwaitingReviewForCheckerWorkFlow() { return _employeeDocumentsRepository.GetWorkshopsWithDocumentsAwaitingReviewForCheckerWorkFlow(); } /// /// دریافت پرسنلی در کارگاه که مدارک ضروری آن ها آپلود شده ولی تایید یا رد نشده اند، برای کارپوشه /// public List GetDocumentsAwaitingReviewByWorkshopIdForCheckerWorkFlow(long workshopId) { var result = _employeeDocumentsRepository.GetDocumentsAwaitingReviewByWorkshopIdForCheckerWorkFlow(workshopId); result.ForEach(x => { x.EmployeePicture.PicturePath = GetThumbnailPathFromFilePath(x.EmployeePicture.PicturePath); x.IdCardPage1.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage1.PicturePath); x.IdCardPage2.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage2.PicturePath); x.IdCardPage3.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage3.PicturePath); x.IdCardPage4.PicturePath = GetThumbnailPathFromFilePath(x.IdCardPage4.PicturePath); x.NationalCardFront.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardFront.PicturePath); x.NationalCardRear.PicturePath = GetThumbnailPathFromFilePath(x.NationalCardRear.PicturePath); x.MilitaryServiceCard.PicturePath = GetThumbnailPathFromFilePath(x.MilitaryServiceCard.PicturePath); }); return result; } public async Task GetCheckerWorkFlowCount() { return await _employeeDocumentsRepository.GetCheckerWorkFlowCount(); } public OperationResult AddRangeEmployeeDocumentItemsByAdmin(long workshopId, long employeeId, List command) { OperationResult op = new(); var (uploaderId, uploaderType,roleId) = _authHelper.GetUserTypeWithId(); if (!_employeeRepository.Exists(x => x.id == employeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == workshopId)) return op.Failed("کارگاه وجود ندارد"); var entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); using var scope = new TransactionScope(); //if record doesn't exist but employee exists and also the workshop, create a new record if (entity == null) { var opCreate = Create(new CreateEmployeeDocuments() { EmployeeId = employeeId, WorkshopId = workshopId }); if (opCreate.IsSuccedded == false) return opCreate; entity = _employeeDocumentsRepository.GetByEmployeeIdWorkshopIdWithItems(employeeId, workshopId); } List newEntities = new(); foreach (var item in command) { long mediaId = 0; if (item.WithoutPicture) { var employeeDocumentItem = entity.EmployeeDocumentItemCollection.First(x => x.DocumentLabel == item.Label); mediaId = employeeDocumentItem.MediaId; } else { DeleteMultipleUnsubmittedDocumentsByLabel(entity, item.Label, uploaderType); var mediaOpResult = UploadDocumentItemFile(item.PictureFile, item.Label.ToString(), $"temp/{workshopId}/{employeeId}"); if (mediaOpResult.IsSuccedded == false) return mediaOpResult; //if the mediaId is already in use in our table return failed if (_employeeDocumentItemRepository.Exists(x => x.MediaId == mediaOpResult.SendId)) return op.Failed("امکان ثبت رکورد تکراری وجود ندارد"); mediaId = mediaOpResult.SendId; } var newEntity = new EmployeeDocumentItem(workshopId, employeeId, mediaId, entity.id, item.Label, uploaderId, uploaderType,roleId ,DocumentStatus.SubmittedByAdmin); newEntities.Add(newEntity); } var currentItems = entity.EmployeeDocumentItemCollection.GroupBy(x => x.DocumentLabel) .Where(x => command.Any(a => a.Label == x.Key)) .Select(x => x.MaxBy(y => y.CreationDate)); //This can bite! _employeeDocumentItemRepository.RemoveRange(currentItems); _employeeDocumentItemRepository.SaveChanges(); _employeeDocumentItemRepository.AddRange(newEntities); _employeeDocumentItemRepository.SaveChanges(); SubmitDocumentItemsByEmployeeIdWorkshopId(employeeId, workshopId); entity.UpdateIsConfirmed(); entity.UpdateIsSentToChecker(); _employeeDocumentsRepository.SaveChanges(); scope.Complete(); return op.Succcedded(entity.id); } public EmployeeDocumentItemViewModel GetOneDocumentItemDetailsForAdmin(long employeeId, long workshopId,long documentItemId) { var documentItem = _employeeDocumentItemRepository.GetWithEmployeeDocumentsByItemId(documentItemId); var viewModel = new EmployeeDocumentItemViewModel() { CreationDateTime = documentItem.CreationDate, DocumentItemLabel = documentItem.DocumentLabel, EmployeeDocumentsId = documentItem.EmployeeDocumentId, Gender = documentItem.EmployeeDocuments.Gender, Id = documentItem.id, Status = documentItem.DocumentStatus, MediaId = documentItem.MediaId, RejectionMessage = documentItem.RejectionReason, UploaderType = documentItem.UploaderType }; return viewModel; } #endregion #region Private Methods /// /// مدارک ثبت نشده با برچسب داده شده را پاک می کند. هنگامی استفاده می شود که کاربر یک آیتم را آپلود می کند /// private void DeleteMultipleUnsubmittedDocumentsByLabel(EmployeeDocuments includedEmployeeDocuments, DocumentItemLabel label, UserType userType) { var items = includedEmployeeDocuments.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && x.DocumentLabel == label && x.UploaderType == userType).ToList(); var mediaIds = items.Select(x => x.MediaId); if (items.Any()) { DeleteMultipleDocumentItemFiles(mediaIds); _employeeDocumentItemRepository.RemoveRange(items); _employeeDocumentItemRepository.SaveChanges(); } } /// /// مدارک ثبت نشده با برچسب داده شده را پاک می کند. هنگامی استفاده می شود که کاربر یک آیتم را آپلود می کند /// private void DeleteMultipleUnsubmittedDocumentsByLabel(EmployeeDocuments includedEmployeeDocuments, List labels, UserType userType) { var items = includedEmployeeDocuments.EmployeeDocumentItemCollection .Where(x => x.DocumentStatus == DocumentStatus.Unsubmitted && labels.Contains(x.DocumentLabel) && x.UploaderType == userType).ToList(); var mediaIds = items.Select(x => x.MediaId); if (items.Any()) { DeleteMultipleDocumentItemFiles(mediaIds); _employeeDocumentItemRepository.RemoveRange(items); _employeeDocumentItemRepository.SaveChanges(); } } //You don't need this method to be public as it's already called where its necessary private OperationResult Create(CreateEmployeeDocuments command) { OperationResult op = new(); if (!_employeeRepository.Exists(x => x.id == command.EmployeeId)) return op.Failed("پرسنل یافت نشد"); if (!_workshopRepository.Exists(x => x.id == command.WorkshopId)) return op.Failed("کارگاه وجود ندارد"); // اگر در دیتابیس وجود داشت ارور ندهد و عملیاتی انجام ندهد if (_employeeDocumentsRepository.Exists(x => x.EmployeeId == command.EmployeeId && x.WorkshopId == command.WorkshopId)) return op.Succcedded(_employeeDocumentsRepository .GetByEmployeeIdWorkshopId(command.EmployeeId, command.WorkshopId).id); var gender = _employeeRepository.Get(command.EmployeeId).Gender; var entity = new EmployeeDocuments(command.EmployeeId, command.WorkshopId, gender); _employeeDocumentsRepository.Create(entity); _employeeDocumentsRepository.SaveChanges(); return op.Succcedded(entity.id); } /// /// برای حذف فایل مدارک /// private OperationResult DeleteMultipleDocumentItemFiles(IEnumerable mediaIds) { OperationResult op = new(); var medias = _mediaRepository.GetRange(mediaIds); if (medias == null || !medias.Any()) return op.Failed("رسانه مورد نظر یافت نشد"); foreach (var media in medias) { var filePath = media.Path; var thumbnailPath = GetThumbnailPathFromFilePath(filePath); try { if (System.IO.File.Exists(filePath)) System.IO.File.Delete(filePath); if (System.IO.File.Exists(thumbnailPath)) System.IO.File.Delete(thumbnailPath); } catch { // ignored } } _mediaRepository.RemoveRange(medias); _mediaRepository.SaveChanges(); //if (somethingWentWrong) // return op.Failed("خطایی در حذف فایل رخ داده است"); return op.Succcedded(); } /// /// برای حذف فایل یکی از مدارک /// private OperationResult DeleteDocumentItemFile(long mediaId) { OperationResult op = new(); var media = _mediaRepository.Get(mediaId); if (media == null) return op.Failed("رسانه مورد نظر یافت نشد"); var filePath = media.Path; var thumbnailPath = GetThumbnailPathFromFilePath(filePath); try { if (System.IO.File.Exists(filePath)) System.IO.File.Delete(filePath); if (System.IO.File.Exists(thumbnailPath)) System.IO.File.Delete(thumbnailPath); } catch { return op.Failed("خطایی در حذف فایل رخ داده است"); } _mediaRepository.Remove(media.id); _mediaRepository.SaveChanges(); return op.Succcedded(); } /// /// جابجا کردن فایل یکی از مدارک، استفاده شده هنگام تایید و رد /// private OperationResult MoveDocumentItemFile(long mediaId, string newRelativePath) { OperationResult op = new(); var media = _mediaRepository.Get(mediaId); var oldFilePath = media.Path; var oldThumbnailPath = GetThumbnailPathFromFilePath(oldFilePath); var newDirectory = Path.Combine(_basePath, newRelativePath); Directory.CreateDirectory(newDirectory); string newFilePath = Path.Combine(newDirectory, Path.GetFileName(oldFilePath)!); string newThumbnailFilePath = Path.Combine(newDirectory, Path.GetFileName(oldThumbnailPath)); try { System.IO.File.Move(oldFilePath, newFilePath); System.IO.File.Move(oldThumbnailPath, newThumbnailFilePath); } catch { return op.Failed("در جابجایی فایل خطایی رخ داده است"); } media.Edit(newFilePath, media.Type, media.Category); _mediaRepository.SaveChanges(); return op.Succcedded(); } /// /// دریافت فایل و نوشتن آن در مسیر داده شده، و ثبت مدیا /// /// فایل /// برچسب مدارک /// مسیر فایل /// private OperationResult UploadDocumentItemFile(IFormFile file, string label, string relativePath) { OperationResult op = new(); var now = DateTime.Now; PersianCalendar pc = new PersianCalendar(); var yearFa = pc.GetYear(now); var monthFa = pc.GetMonth(now); var dayFa = pc.GetDayOfMonth(now); var ticks = now.Ticks % 864_000_000_000; List allowedExtensions = [".png", ".jpg", ".jpeg"]; var path = Path.Combine(_basePath, relativePath); var fileExtension = Path.GetExtension(file.FileName); if (file.Length > (50 * 1024 * 1024)) return op.Failed("حجم فایل نمی تواند بیشتر از 50 مگابایت باشد"); if (!allowedExtensions.Contains(fileExtension.ToLower())) { var operationMessage = ":فرمت فایل باید یکی از موارد زیر باشد"; operationMessage += "\n"; operationMessage += string.Join(" ", allowedExtensions); return op.Failed(operationMessage); } Directory.CreateDirectory(path); var type = Path.GetExtension(file.FileName); var uniqueFileName = $"{label}-{yearFa}-{monthFa}-{dayFa}-{ticks}{type}"; var filePath = Path.Combine(path, uniqueFileName); using (var fileStream = new FileStream(filePath, FileMode.CreateNew)) { file.CopyTo(fileStream); } #region Thumbnail Creation var uniqueFileNameThumbnail = $"{label}-{yearFa}-{monthFa}-{dayFa}-{ticks}-thumbnail{type}"; var thumbnailFilePath = Path.Combine(path, uniqueFileNameThumbnail); var thumbnail = Tools.ResizeImage(filePath, 150, 150); System.IO.File.WriteAllBytes(thumbnailFilePath, Convert.FromBase64String(thumbnail)); #endregion var mediaEntity = new Media(filePath, type, "فایل", "EmployeeDocuments"); _mediaRepository.Create(mediaEntity); _mediaRepository.SaveChanges(); return op.Succcedded(mediaEntity.id); } //private OperationResult UploadExistingRollCallEmployeePicture(long mediaId, long workshopId, long employeeId) //{ // OperationResult op = new(); // var media = _mediaRepository.Get(mediaId); // if (media == null) // return op.Failed("فایل مورد نظر یافت نشد"); // var path = Path.Combine(_webHostEnvironment.ContentRootPath, "Storage", "EmployeeDocuments", "temp", // $"{workshopId}", $"{employeeId}"); // var uniqueFileName = $"{DocumentItemLabel.EmployeePicture.ToString()}-{Guid.NewGuid()}{media.Type}"; // var newFilePath = Path.Combine(path, uniqueFileName); // try // { // Directory.CreateDirectory(newFilePath); // if (!System.IO.File.Exists(media.Path)) // return op.Failed("فایل مورد نظر یافت نشد"); // System.IO.File.Copy(media.Path, newFilePath); // } // catch // { // return op.Failed("در جابجایی فایل خطایی رخ داده است"); // } // var mediaEntity = new Media(newFilePath, media.Type, "فایل", "EmployeeDocuments"); // _mediaRepository.Create(mediaEntity); // _mediaRepository.SaveChanges(); // return op.Succcedded(mediaEntity.id); //} /// /// متد پر استفاده برای دریافت آخرین مدارک تایید شده فرد /// private static List GetCurrentConfirmedDocuments(EmployeeDocuments entity) { return entity.EmployeeDocumentItemCollection.Where(x => x.DocumentStatus == DocumentStatus.Confirmed) .GroupBy(x => x.DocumentLabel) .Select(x => x.MaxBy(y => y.CreationDate)).ToList(); } /// /// با توجه به جنسیت مدارک لازم را تعیین می کند، مثلا معافیت سربازی برای آقایان /// /// /// "مرد" یا "زن" private bool HasRequiredDocuments(List items, string gender) { List requiredDocuments = EmployeeDocumentRequiredItems.GetByGender(gender); List labels = items.GroupBy(x => x.DocumentLabel) .Select(x => x.Key).ToList(); //if labels has all the required labels if (labels.Count(x => requiredDocuments.Contains(x)) == requiredDocuments.Count()) return true; return false; } //for mapping purposes private static EmployeeDocumentItemViewModel GetItemFromCollectionByLabel(List items, List medias, DocumentItemLabel label) { if (items == null || items.Count == 0) return new(); var item = items.FirstOrDefault(x => x.DocumentLabel == label); if (item == null || item.MediaId == 0) return new(); return new EmployeeDocumentItemViewModel() { DocumentItemLabel = label, Id = item.id, Status = item.DocumentStatus, StatusString = item.DocumentStatus.ToString().ToLower(), PicturePath = medias.FirstOrDefault(x => x.Id == item.MediaId)?.Path ?? "", RejectionMessage = item.RejectionReason, UploaderType = item.UploaderType, MediaId = medias.FirstOrDefault(x => x.Id == item.MediaId)?.Id ?? 0, }; } private static string GetThumbnailPathFromFilePath(string filePath) { return string.IsNullOrWhiteSpace(filePath) ? string.Empty : Path.Combine(Path.GetDirectoryName(filePath)!, Path.GetFileNameWithoutExtension(filePath) + $"-thumbnail{Path.GetExtension(filePath)}"); } #endregion #region Old MEthods ///// ///// تایید یکی از مدارک توسط چکر ///// //public OperationResult ConfirmDocumentItem(ConfirmDocumentItem cmd) //{ // OperationResult op = new(); // EmployeeDocumentItem entity = // _employeeDocumentItemRepository.GetWithEmployeeDocumentsByItemId(cmd.EmployeeDocumentItemId); // if (entity == null) // { // return op.Failed("رکورد مورد نظر یافت نشد"); // } // if (entity.DocumentStatus != DocumentStatus.SubmittedByAdmin) // return op.Failed("امکان بررسی رکورد مورد نظر وجود ندارد"); // (long operatorId, UserType userType) = _authHelper.GetUserTypeWithId(); // entity.Confirm(operatorId, userType); // _employeeDocumentsRepository.SaveChanges(); // CheckEmployeeDocumentsConfirmation(entity.EmployeeDocumentId); // MoveDocumentItemFile(entity.MediaId, // $"Confirmed/{entity.EmployeeDocuments.WorkshopId}/{entity.EmployeeDocuments.EmployeeId}"); // return op.Succcedded(); //} ///// ///// رد یکی از مدارک توسط چکر ///// //public OperationResult RejectDocumentItem(RejectDocumentItem cmd) //{ // OperationResult op = new(); // var entity = _employeeDocumentItemRepository.GetWithEmployeeDocumentsByItemId(cmd.EmployeeDocumentItemId); // if (entity == null) // { // return op.Failed("رکورد مورد نظر یافت نشد"); // } // if (string.IsNullOrWhiteSpace(cmd.Message)) // return op.Failed("لطفا علت رد درخواست را پر کنید"); // (long operatorId, UserType userType) = _authHelper.GetUserTypeWithId(); // if (entity.DocumentStatus != DocumentStatus.SubmittedByAdmin) // return op.Failed("امکان بررسی رکورد مورد نظر وجود ندارد"); // entity.Reject(operatorId, cmd.Message, userType); // _employeeDocumentsRepository.SaveChanges(); // CheckEmployeeDocumentsConfirmation(entity.EmployeeDocumentId); // MoveDocumentItemFile(entity.MediaId, $"Rejected/{entity.EmployeeDocuments.WorkshopId}/{entity.EmployeeDocuments.EmployeeId}"); // return op.Succcedded(); //} #endregion } }