|
@@ -9,7 +9,13 @@ using MTWorkHR.Core.Entities;
|
|
|
using System.Linq.Dynamic.Core;
|
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
using MTWorkHR.Infrastructure.Entities;
|
|
|
-
|
|
|
+using System.Linq;
|
|
|
+using MTWorkHR.Core.IDto;
|
|
|
+using MTWorkHR.Core.Entities.User;
|
|
|
+using System.Diagnostics.Contracts;
|
|
|
+using Contract = MTWorkHR.Core.Entities.Contract;
|
|
|
+using MTWorkHR.Infrastructure.Reports;
|
|
|
+using DevExpress.DataProcessing;
|
|
|
namespace MTWorkHR.Application.Services
|
|
|
{
|
|
|
public class ContractService : BaseService<Contract, ContractDto, ContractDto>, IContractService
|
|
@@ -17,18 +23,24 @@ namespace MTWorkHR.Application.Services
|
|
|
private readonly IUnitOfWork _unitOfWork;
|
|
|
private readonly IUserService _userService;
|
|
|
private readonly GlobalInfo _globalInfo;
|
|
|
+ private readonly IFileService _fileService;
|
|
|
+ private readonly IOrderAllocationService _orderAllocationService;
|
|
|
|
|
|
- public ContractService(IUnitOfWork unitOfWork, IUserService userService, GlobalInfo globalInfo) : base(unitOfWork)
|
|
|
+ public ContractService(IUnitOfWork unitOfWork, IUserService userService, GlobalInfo globalInfo, IOrderAllocationService orderAllocationService, IFileService fileService) : base(unitOfWork)
|
|
|
{
|
|
|
_unitOfWork = unitOfWork;
|
|
|
_userService = userService;
|
|
|
_globalInfo = globalInfo;
|
|
|
+ _orderAllocationService = orderAllocationService;
|
|
|
+ _fileService = fileService;
|
|
|
}
|
|
|
|
|
|
public override async Task<ContractDto> GetById(long id)
|
|
|
{
|
|
|
var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(id);
|
|
|
var response = MapperObject.Mapper.Map<ContractDto>(entity);
|
|
|
+ response.WorkingDays = entity.WorkingDays != null ? entity.WorkingDays.Split(",").ToList() : null;
|
|
|
+
|
|
|
return response;
|
|
|
}
|
|
|
|
|
@@ -40,7 +52,7 @@ namespace MTWorkHR.Application.Services
|
|
|
{
|
|
|
throw new AppException(ExceptionEnum.MapperIssue);
|
|
|
}
|
|
|
-
|
|
|
+ entity.WorkingDays = input.WorkingDays!=null? string.Join(",", input.WorkingDays): null;
|
|
|
var team = await _unitOfWork.Contract.AddAsync(entity);
|
|
|
await _unitOfWork.CompleteAsync();
|
|
|
|
|
@@ -64,6 +76,8 @@ namespace MTWorkHR.Application.Services
|
|
|
// var response = Mapper.MapperObject.Mapper.Map<ContractDto>(entity);
|
|
|
// return response;
|
|
|
//}
|
|
|
+
|
|
|
+
|
|
|
public async Task<PagingResultDto<ContractDto>> GetAll(ContractPagingInputDto PagingInputDto)
|
|
|
{
|
|
|
var res = await _unitOfWork.Contract.GetAllWithChildrenAsync();
|
|
@@ -71,13 +85,13 @@ namespace MTWorkHR.Application.Services
|
|
|
|
|
|
if (_globalInfo.UserType != UserTypeEnum.Business)
|
|
|
{
|
|
|
- // query = query.Where(m => m.ContractUsers != null && m.ContractUsers.Count > 0 && m.ContractUsers.Count(u=> u.AssignedUserId == _globalInfo.UserId) > 0);
|
|
|
+ // query = query.Where(m => m.ContractUsers != null && m.ContractUsers.Count > 0 && m.ContractUsers.Count(u=> u.AssignedUserId == _globalInfo.UserId) > 0);
|
|
|
|
|
|
}
|
|
|
if (PagingInputDto.Filter != null)
|
|
|
{
|
|
|
var filter = PagingInputDto.Filter;
|
|
|
- query = query.Where(u => u.JobDescription.Contains(filter));
|
|
|
+ query = query.Where(u => u.JobDescription != null && u.JobDescription.Contains(filter));
|
|
|
}
|
|
|
|
|
|
if (PagingInputDto.ContractStatusId != null)
|
|
@@ -119,6 +133,144 @@ namespace MTWorkHR.Application.Services
|
|
|
return response;
|
|
|
}
|
|
|
|
|
|
+ #region HR data____________________________
|
|
|
+ public async Task<PagingResultDto<ContractAllHRDto>> GetAllForHr(ContractPagingInputDto PagingInputDto)
|
|
|
+ {
|
|
|
+ var res = await _unitOfWork.Contract.GetAllWithChildrenAsync();
|
|
|
+ var query = res.Item1;
|
|
|
+
|
|
|
+ if (_globalInfo.UserType != UserTypeEnum.Business)
|
|
|
+ {
|
|
|
+ // query = query.Where(m => m.ContractUsers != null && m.ContractUsers.Count > 0 && m.ContractUsers.Count(u=> u.AssignedUserId == _globalInfo.UserId) > 0);
|
|
|
+
|
|
|
+ }
|
|
|
+ if (PagingInputDto.Filter != null)
|
|
|
+ {
|
|
|
+ var filter = PagingInputDto.Filter;
|
|
|
+ query = query.Where(u => u.JobDescription.Contains(filter));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (PagingInputDto.ContractStatusId != null)
|
|
|
+ {
|
|
|
+ query = query.Where(u => (int)u.ContractStatusId == PagingInputDto.ContractStatusId);
|
|
|
+ }
|
|
|
+ if (PagingInputDto.ContractTypeId != null)
|
|
|
+ {
|
|
|
+ query = query.Where(u => (int)u.ContractTypeId == PagingInputDto.ContractTypeId);
|
|
|
+ }
|
|
|
+
|
|
|
+ var order = query.OrderBy(PagingInputDto.OrderByField + " " + PagingInputDto.OrderType);
|
|
|
+
|
|
|
+ var page = order.Skip((PagingInputDto.PageNumber * PagingInputDto.PageSize) - PagingInputDto.PageSize).Take(PagingInputDto.PageSize);
|
|
|
+
|
|
|
+ var total = await query.CountAsync();
|
|
|
+
|
|
|
+ var list = MapperObject.Mapper
|
|
|
+ .Map<IList<ContractAllHRDto>>(await page.ToListAsync());
|
|
|
+
|
|
|
+
|
|
|
+ var teamUsersList = await _unitOfWork.TeamUser.GetAllWithChildrenAsync();
|
|
|
+ var vacationAllocations = await _unitOfWork.OrderAllocation.GetAllAsync();
|
|
|
+ foreach (var item in list)
|
|
|
+ {
|
|
|
+ if (item.UserId != null)
|
|
|
+ {
|
|
|
+ var user = await _userService.GetUserWithAttachmentById(item.UserId);
|
|
|
+ if (user != null)
|
|
|
+ {
|
|
|
+ item.EmployeeName = user.FirstName + " " + user.LastName;
|
|
|
+ item.EmployeeEmail = user.Email;
|
|
|
+ //___________Get Teams
|
|
|
+ //var TeamsList = teamUsersList.Item1.Where(t => t.AssignedUserId == item.UserId).Select(t => GlobalInfo.lang == "en" ? t.Team.NameEn : t.Team.NameAr);
|
|
|
+ //item.Teams = TeamsList == null ? "" : string.Join(",", TeamsList);
|
|
|
+ var latestTeam = teamUsersList.Item1.OrderByDescending(a=> a.Id).FirstOrDefault(t => t.AssignedUserId == item.UserId);
|
|
|
+ item.Teams = latestTeam == null ? "" : GlobalInfo.lang == "en" ? latestTeam.Team?.NameEn : latestTeam.Team?.NameAr;
|
|
|
+ //_____________Get vacation balance
|
|
|
+ var remainVacations = vacationAllocations.Item1.FirstOrDefault(t => t.EmployeeId == item.UserId && t.ContractId == item.Id);
|
|
|
+ item.RestVacations = remainVacations == null ? item.VacationDays : remainVacations.NumberOfDays ;
|
|
|
+ item.SpentVacations = item.VacationDays - item.RestVacations;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Filter employees by name if provided
|
|
|
+ if (!string.IsNullOrEmpty(PagingInputDto.UserName))
|
|
|
+ {
|
|
|
+ var filter = PagingInputDto.UserName;
|
|
|
+
|
|
|
+ list = list.Where(u =>
|
|
|
+ (u.EmployeeName != null && u.EmployeeName.Contains(filter))
|
|
|
+ || (u.EmployeeEmail != null && u.EmployeeEmail.Contains(filter))
|
|
|
+ ).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var response = new PagingResultDto<ContractAllHRDto>
|
|
|
+ {
|
|
|
+ Result = list,
|
|
|
+ Total = list.Count
|
|
|
+ };
|
|
|
+
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+ public async Task<ContractHRDto> GetByIdHRDetails(long contractId)
|
|
|
+ {
|
|
|
+ var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(contractId);
|
|
|
+ if (entity != null)
|
|
|
+ {
|
|
|
+ var response = MapperObject.Mapper.Map<ContractHRDto>(entity);
|
|
|
+ response.WorkingDays = entity.WorkingDays != null ? entity.WorkingDays.Split(",").ToList() : null;
|
|
|
+ //--------------------
|
|
|
+ var user = await _userService.GetUserWithAttachmentById(entity.UserId);
|
|
|
+ response.EmployeeName = user.FirstName + " " + user.LastName;
|
|
|
+ response.EmployeeEmail = user.Email;
|
|
|
+ //___________Get Teams
|
|
|
+ var teamUsersList = await _unitOfWork.TeamUser.GetUserTeams(entity.UserId);
|
|
|
+ var teamsList = MapperObject.Mapper.Map<List<TeamDto>>(teamUsersList.Item1);
|
|
|
+
|
|
|
+ response.TeamList = teamsList;
|
|
|
+ //_____________Get vacation balance
|
|
|
+ var vacationAllocations = await _unitOfWork.OrderAllocation.GetUserAllocations(entity.UserId, 1, 1, entity.Id, DateTime.Now.Year);
|
|
|
+ var remainVacations = vacationAllocations;
|
|
|
+ response.RestVacations = remainVacations == null ? entity.VacationDays : remainVacations.NumberOfDays;
|
|
|
+ response.SpentVacations = entity.VacationDays - response.RestVacations;
|
|
|
+ //__-----------Order Requests----
|
|
|
+ var orderRequestsList = await _unitOfWork.OrderRequest.GetAllUserOrdersAsync(entity.UserId, contractId);
|
|
|
+ var vacationsList = orderRequestsList.Item1.Where(o => o.OrderStatus == ApprovalStatusEnum.Approved && o.OrderTypeId == 1 && (o.LeaveTypeId == 1 || o.LeaveTypeId == 2));
|
|
|
+ var orderList = MapperObject.Mapper.Map<List<OrderRequestHRDto>>(vacationsList);
|
|
|
+ response.OrderList = orderList;
|
|
|
+ /////------------------------
|
|
|
+ var invoiceList = await _unitOfWork.Invoice.GetAllUserInvoices(contractId);
|
|
|
+ var Invoices = MapperObject.Mapper.Map<List<InvoiceDto>>(invoiceList.Item1);
|
|
|
+
|
|
|
+ response.InvoiceList = Invoices;
|
|
|
+
|
|
|
+ //------------------
|
|
|
+ if(entity.ContractTypeId == (int)ContractTypeEnum.EmployeeContract)
|
|
|
+ {
|
|
|
+ var lastInvoice = Invoices.LastOrDefault();
|
|
|
+ var diffDate = DateTime.Now.Date - entity.StartDate.Value.Date;
|
|
|
+ if(lastInvoice != null)
|
|
|
+ {
|
|
|
+ if (entity.BillingCycle == "Monthly")
|
|
|
+ response.NextSalaryDate = lastInvoice.InvoiceDate.Value.AddMonths(1);
|
|
|
+ else if (entity.BillingCycle == "Fortnightly")
|
|
|
+ response.NextSalaryDate = lastInvoice.InvoiceDate.Value.AddDays(15);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (entity.BillingCycle == "Monthly")
|
|
|
+ response.NextSalaryDate = entity.StartDate.Value.AddMonths(1);
|
|
|
+ else if(entity.BillingCycle == "Fortnightly")
|
|
|
+ response.NextSalaryDate = entity.StartDate.Value.AddDays(15);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+ return new ContractHRDto();
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
public async Task<bool> ChangeStatus(long contractId, int statusId)
|
|
|
{
|
|
|
var entity = await _unitOfWork.Contract.GetByIdAsync(contractId);
|
|
@@ -129,13 +281,159 @@ namespace MTWorkHR.Application.Services
|
|
|
if (statusId == (int)ContractStatusEnum.Approved)
|
|
|
{
|
|
|
var updatedSuccess = await _userService.Update(entity.UserId, entity.CompanyId);
|
|
|
- if (!updatedSuccess) { result = false; }
|
|
|
+ addVacationAllocation(entity.VacationDays.HasValue ? entity.VacationDays.Value : 0, entity.UserId, contractId);
|
|
|
+ if (!updatedSuccess) {
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
}
|
|
|
- await _unitOfWork.CompleteAsync();
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ private async Task addVacationAllocation(int noVacationDays, string employeeId, long contractId)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ await _orderAllocationService.Create(new OrderAllocationDto { ContractId = contractId, EmployeeId = employeeId, OrderTypeId = 1, LeaveTypeId = 1, NumberOfDays = noVacationDays, Period = DateTime.Now.Year });
|
|
|
+ // var orderTypes = await _unitOfWork.OrderType.GetAllAsync();
|
|
|
+ // var leaveTypes = await _unitOfWork.LeaveType.GetAllAsync();
|
|
|
+ //foreach (var orderType in orderTypes.Item1)
|
|
|
+ //{
|
|
|
+ // foreach (var leaveType in leaveTypes.Item1)
|
|
|
+ // {
|
|
|
+ // if (orderType.Id != 1 && leaveType.Id != 1 && (leaveType.DefaultDays > 0 || orderType.DefaultDays > 0))
|
|
|
+ // {
|
|
|
+ // await _orderAllocationService.Create(new OrderAllocationDto
|
|
|
+ // {
|
|
|
+ // ContractId = contractId,
|
|
|
+ // EmployeeId = employeeId,
|
|
|
+ // OrderTypeId = (int)orderType.Id,
|
|
|
+ // LeaveTypeId = (int)leaveType.Id,
|
|
|
+ // NumberOfDays = leaveType.DefaultDays > 0 ? leaveType.DefaultDays : orderType.DefaultDays,
|
|
|
+ // Period = DateTime.Now.Year
|
|
|
+ // }
|
|
|
+ // );
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ }
|
|
|
+ catch(Exception ex)
|
|
|
+ {
|
|
|
+ throw ;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<ContractDetail> GetByIdReport(long id)
|
|
|
+ {
|
|
|
+ var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(id);
|
|
|
+ var contract = MapperObject.Mapper.Map<ContractDetail>(entity);
|
|
|
+ contract.WorkingDays = entity.WorkingDays;//!= null ? entity.WorkingDays.Split(",").ToList() : null;
|
|
|
+ var user = await _userService.GetUserById(entity.UserId);
|
|
|
+ if (user != null)
|
|
|
+ {
|
|
|
+ contract.EmployeeName = user.FirstName + " " + user.LastName;
|
|
|
+ contract.EmployeeEmail = user.Email;
|
|
|
+ contract.EmployeePassport = user.PassportNumber;
|
|
|
+ contract.EmployeePhone = user.PhoneNumber;
|
|
|
+ contract.EmployeeUniversity = user.UniversityName;
|
|
|
+ contract.AcademicQualification = user.QualificationName;
|
|
|
+ contract.EmployeeJobName = user.JobTitleName;
|
|
|
+ }
|
|
|
+ return contract;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
|
|
|
+ public async Task<AttachmentResponseDto> GenerateContractPdf(string outputPath, long contractId)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var entity = await _unitOfWork.Contract.GetByIdWithAllChildren(contractId);
|
|
|
+
|
|
|
+ var contract = new ContractDetail
|
|
|
+ {
|
|
|
+ StartDate = entity.StartDate,
|
|
|
+ BillingCycle = entity.BillingCycle,
|
|
|
+ ContractDuration = entity.ContractDurationId != null ? ((ContractDurationEnum)entity.ContractDurationId).ToString() : "",
|
|
|
+ ContractStatusId = (ContractStatusEnum)entity.ContractStatusId,
|
|
|
+ FirstPatchAmount = entity.FirstPatchAmount,
|
|
|
+ FirstPatchDateFrom = entity.FirstPatchDateFrom,
|
|
|
+ FirstPatchDateTo = entity.FirstPatchDateTo,
|
|
|
+ LastPatchAmount = entity.LastPatchAmount,
|
|
|
+ LastPatchDateFrom = entity.LastPatchDateFrom,
|
|
|
+ LastPatchDateTo = entity.LastPatchDateTo,
|
|
|
+ JobDescription = entity.JobDescription,
|
|
|
+ JobNumber = entity.JobNumber,
|
|
|
+ Salary = entity.Salary,
|
|
|
+ JobTitleName = entity.JobTitleName,//Specialization = entity.SpecializationId,
|
|
|
+ TrialPeriod = entity.TrialPeriod,
|
|
|
+ VacationDays = entity.VacationDays, //WhoCanTerminateContract = entity.WhoCanTerminateContract,TypeOfWork = entity.TypeOfWork
|
|
|
+ //WhoCanTerminateContractInTrial =
|
|
|
+ WorkCountry = entity.WorkCountryId + "",
|
|
|
+ WorkingHours = entity.WorkingHours + "",
|
|
|
+ ContractTypeId = (ContractTypeEnum)entity.ContractTypeId,
|
|
|
+ Currency = entity.Currency,
|
|
|
+ FixedAllowances = entity.FixedAllowances,
|
|
|
+ ProjectStages = entity.ProjectStages,
|
|
|
+ ContractTasks = entity.ContractTasks,
|
|
|
+ WorkState = entity.WorkStateId + "",
|
|
|
+ WorkingDays = entity.WorkingDays
|
|
|
+ };
|
|
|
+
|
|
|
+ var user = await _userService.GetUserById(entity.UserId);
|
|
|
+ if (user != null)
|
|
|
+ {
|
|
|
+ contract.EmployeeName = user.FirstName + " " + user.LastName;
|
|
|
+ contract.EmployeeEmail = user.Email;
|
|
|
+ contract.EmployeePassport = user.PassportNumber;
|
|
|
+ contract.EmployeePhone = user.PhoneNumber;
|
|
|
+ contract.EmployeeUniversity = user.UniversityName;
|
|
|
+ contract.AcademicQualification = user.QualificationName;
|
|
|
+ contract.EmployeeJobName = user.JobTitleName;
|
|
|
+ contract.EmployeeDateOfBirth = user.DateOfBirth;
|
|
|
+ }
|
|
|
+ var representativeUser = await _userService.GetUserById(entity.CompanyRepresentativeId);
|
|
|
+ if (representativeUser != null)
|
|
|
+ {
|
|
|
+ contract.CompanyRepresentativeName = representativeUser.FirstName + " " + representativeUser.LastName;
|
|
|
+ contract.CompanyRepresentativeEmail = representativeUser.Email;
|
|
|
+ contract.CompanyRepresentativePassport = representativeUser.PassportNumber;
|
|
|
+ contract.CompanyRepresentativePhone = representativeUser.PhoneNumber;
|
|
|
+ contract.CompanyRepresentativePosition = representativeUser.Position ?? "";
|
|
|
+ }
|
|
|
+ var company = await _unitOfWork.Company.GetByIdAsync(entity.CompanyId);
|
|
|
+ if (company != null)
|
|
|
+ {
|
|
|
+ contract.CompanyName = company.CompanyName;
|
|
|
+ contract.CompanyEmail = company.Email;
|
|
|
+ contract.CompanyPhone = company.PhoneNumber;
|
|
|
+ contract.CompanyCR = company.CRNumber;
|
|
|
+ contract.CompanyAddress = company.Address;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var pdfBytes = await new ContractPdfGenerator().GenerateContractPdf(outputPath, contract);
|
|
|
+ // Upload to Azure Blob Storage and return the Blob URL
|
|
|
+ string fileName = $"contract_{Guid.NewGuid()}.pdf";
|
|
|
+ var result = await _fileService.UploadFile(pdfBytes, fileName);
|
|
|
+ entity.FilePath = result.FilePath;
|
|
|
+ await _unitOfWork.CompleteAsync();
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ throw e;
|
|
|
+
|
|
|
+ // _logger.LogError(e, "Failed to generate contract PDF for contractId {ContractId}", contractId);
|
|
|
+ var msg = e.Message;
|
|
|
+ //return new AttachmentResponseDto();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public byte[] generatePdfTest()
|
|
|
+ {
|
|
|
+ var pdfBytes = new ContractPdfGenerator().GeneratePdf();
|
|
|
+ return pdfBytes;
|
|
|
+ }
|
|
|
}
|
|
|
}
|