/// <summary> /// This is option 2 : DEPARTMENT BASED CASH ADVANCE REQUEST /// </summary> /// <param name="pettyCashRequestDto"></param> /// <param name="empCurAvailBal"></param> private async Task DepartmentCashRequest(PettyCashRequestDTO pettyCashRequestDto, Double empCurAvailBal) { //### 1. If Employee Eligible for Cash Claim enter a record and reduce the available amount for next claim #region int reqEmpid = pettyCashRequestDto.EmployeeId; Employee reqEmp = _context.Employees.Find(reqEmpid); int reqApprGroupId = reqEmp.ApprovalGroupId; int reqRoleId = reqEmp.RoleId; int maxApprLevel = _context.ApprovalRoleMaps.Include("ApprovalLevel").Where(a => a.ApprovalGroupId == reqApprGroupId).ToList().Select(x => x.ApprovalLevel).Max(a => a.Level); int reqApprLevel = _context.ApprovalRoleMaps.Include("ApprovalLevel").Where(a => a.ApprovalGroupId == reqApprGroupId && a.RoleId == reqRoleId).Select(x => x.ApprovalLevel).FirstOrDefault().Level; bool isSelfApprovedRequest = false; Double empReqAmount = pettyCashRequestDto.PettyClaimAmount; var curPettyCashBal = _context.EmpCurrentPettyCashBalances.Where(x => x.EmployeeId == reqEmpid).FirstOrDefault(); if (_context.JobRoles.Find(_context.Employees.Find(pettyCashRequestDto.EmployeeId).RoleId).MaxPettyCashAllowed >= empCurAvailBal - empReqAmount) { curPettyCashBal.CurBalance = empCurAvailBal - empReqAmount; } curPettyCashBal.EmployeeId = reqEmpid; curPettyCashBal.UpdatedOn = DateTime.Now; _context.Update(curPettyCashBal); await _context.SaveChangesAsync(); #endregion //##### 2. Adding entry to PettyCashRequest table for record #region var pcrq = new PettyCashRequest() { EmployeeId = reqEmpid, PettyClaimAmount = empReqAmount, CashReqDate = DateTime.Now, PettyClaimRequestDesc = pettyCashRequestDto.PettyClaimRequestDesc, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId, DepartmentId = _context.Employees.Find(reqEmpid).DepartmentId, CurrencyTypeId = pettyCashRequestDto.CurrencyTypeId, ApprovalStatusTypeId = (int)EApprovalStatus.Pending, Comments = "Cash Advance Request in Process!" }; _context.PettyCashRequests.Add(pcrq); await _context.SaveChangesAsync(); //get the saved record Id pettyCashRequestDto.Id = pcrq.Id; #endregion //##### STEP 3. ClaimsApprovalTracker to be updated for all the allowed Approvers ///////////////////////////// Check if self Approved Request ///////////////////////////// //if highest approver is requesting Petty cash request himself if (maxApprLevel == reqApprLevel) { isSelfApprovedRequest = true; } ////////////////////////////////////////////////////////////////////////////////////////// var getEmpClaimApproversAllLevels = _context.ApprovalRoleMaps .Include(a => a.ApprovalLevel) .Where(a => a.ApprovalGroupId == reqApprGroupId) .OrderBy(o => o.ApprovalLevel.Level).ToList(); bool isFirstApprover = true; if (isSelfApprovedRequest) { ClaimApprovalStatusTracker claimAppStatusTrack = new() { EmployeeId = pettyCashRequestDto.EmployeeId, PettyCashRequestId = pettyCashRequestDto.Id, DepartmentId = _context.Employees.Find(pettyCashRequestDto.EmployeeId).DepartmentId, ProjectId = null, SubProjectId = null, WorkTaskId = null, RoleId = _context.Employees.Find(pettyCashRequestDto.EmployeeId).RoleId, ApprovalGroupId = reqApprGroupId, ApprovalLevelId = reqApprLevel, ReqDate = DateTime.Now, FinalApprovedDate = DateTime.Now, ApprovalStatusTypeId = (int)EApprovalStatus.Approved, Comments = "Self Approved Request!" //1-Initiating, 2-Pending, 3-InReview, 4-Approved, 5-Rejected }; _context.ClaimApprovalStatusTrackers.Add(claimAppStatusTrack); pcrq.ApprovalStatusTypeId = (int)EApprovalStatus.Approved; _context.PettyCashRequests.Update(pcrq); await _context.SaveChangesAsync(); } else { foreach (ApprovalRoleMap ApprMap in getEmpClaimApproversAllLevels) { int role_id = ApprMap.RoleId; var approver = _context.Employees.Where(e => e.RoleId == role_id && e.ApprovalGroupId == reqApprGroupId).FirstOrDefault(); if (approver == null) { continue; } int approverLevelid = _context.ApprovalRoleMaps.Where(x => x.RoleId == approver.RoleId && x.ApprovalGroupId == reqApprGroupId).FirstOrDefault().ApprovalLevelId; int approverLevel = _context.ApprovalLevels.Find(approverLevelid).Level; if (reqApprLevel >= approverLevel) { continue; } ClaimApprovalStatusTracker claimAppStatusTrack = new() { EmployeeId = pettyCashRequestDto.EmployeeId, PettyCashRequestId = pettyCashRequestDto.Id, DepartmentId = approver.DepartmentId, ProjectId = null, SubProjectId = null, WorkTaskId = null, RoleId = approver.RoleId, ApprovalGroupId = reqApprGroupId, ApprovalLevelId = ApprMap.ApprovalLevelId, ReqDate = DateTime.Now, FinalApprovedDate = null, ApprovalStatusTypeId = isFirstApprover ? (int)EApprovalStatus.Pending : (int)EApprovalStatus.Initiating, Comments = "Awaiting Approver Action" //1-Initiating, 2-Pending, 3-InReview, 4-Approved, 5-Rejected }; _context.ClaimApprovalStatusTrackers.Add(claimAppStatusTrack); await _context.SaveChangesAsync(); if (isFirstApprover) { //##### 4. Send email to the Approver //#################################### var approverMailAddress = approver.Email; string subject = "Pettycash Request Approval " + pettyCashRequestDto.Id.ToString(); Employee emp = await _context.Employees.FindAsync(pettyCashRequestDto.EmployeeId); var pettycashreq = _context.PettyCashRequests.Find(pettyCashRequestDto.Id); string content = "Petty Cash Approval sought by " + emp.FirstName + "@<br/>Cash Request for the amount of " + pettycashreq.PettyClaimAmount + "@<br/>towards " + pettycashreq.PettyClaimRequestDesc; var messagemail = new Message(new string[] { approverMailAddress }, subject, content); await _emailSender.SendEmailAsync(messagemail); } //first approver will be added as Pending, other approvers will be with In Approval Queue isFirstApprover = false; } } //##### STEP 5. Adding a SINGLE entry in DisbursementsAndClaimsMaster table for records #region DisbursementsAndClaimsMaster disbursementsAndClaimsMaster = new(); disbursementsAndClaimsMaster.EmployeeId = reqEmpid; disbursementsAndClaimsMaster.PettyCashRequestId = pcrq.Id; disbursementsAndClaimsMaster.ExpenseReimburseReqId = null; disbursementsAndClaimsMaster.RequestTypeId = (int)ERequestType.CashAdvance; disbursementsAndClaimsMaster.DepartmentId = _context.Employees.Find(reqEmpid).DepartmentId; disbursementsAndClaimsMaster.ProjectId = null; disbursementsAndClaimsMaster.SubProjectId = null; disbursementsAndClaimsMaster.WorkTaskId = null; disbursementsAndClaimsMaster.RecordDate = DateTime.Now; disbursementsAndClaimsMaster.CurrencyTypeId = pettyCashRequestDto.CurrencyTypeId; disbursementsAndClaimsMaster.ClaimAmount = empReqAmount; disbursementsAndClaimsMaster.CostCenterId = _context.Departments.Find(_context.Employees.Find(reqEmpid).DepartmentId).CostCenterId; disbursementsAndClaimsMaster.ApprovalStatusId = isSelfApprovedRequest ? (int)EApprovalStatus.Approved : (int)EApprovalStatus.Pending; _context.DisbursementsAndClaimsMasters.Add(disbursementsAndClaimsMaster); try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { throw; } #endregion }
/// <summary> /// This is option 2 /// </summary> /// <param name="pettyCashRequestDto"></param> /// <param name="empCurAvailBal"></param> private async Task DepartmentCashRequest(PettyCashRequestDTO pettyCashRequestDto, decimal empCurAvailBal) { #region int empid = pettyCashRequestDto.EmployeeId; decimal empReqAmount = pettyCashRequestDto.PettyClaimAmount; int empApprGroupId = _context.Employees.Find(empid).ApprovalGroupId; //### 1. Employee Eligible for Cash Claim enter a record and reduce the available amount for next claim var curPettyCashBal = _context.EmpCurrentPettyCashBalances.Where(x => x.EmployeeId == empid).FirstOrDefault(); curPettyCashBal.Id = curPettyCashBal.Id; curPettyCashBal.CurBalance = empCurAvailBal - empReqAmount; curPettyCashBal.EmployeeId = empid; _context.Update(curPettyCashBal); await _context.SaveChangesAsync(); #endregion #region //##### 2. Adding entry to PettyCashRequest table for record var pcrq = new PettyCashRequest() { EmployeeId = empid, PettyClaimAmount = empReqAmount, CashReqDate = DateTime.Now, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId }; _context.PettyCashRequests.Add(pcrq); await _context.SaveChangesAsync(); #endregion #region //##### 3. Adding a entry in DisbursementsAndClaimsMaster table for records _context.DisbursementsAndClaimsMasters.Add(new DisbursementsAndClaimsMaster() { EmployeeId = empid, PettyCashRequestId = pcrq.Id, ExpenseReimburseReqId = null, AdvanceOrReimburseId = (int)ClaimType.CashAdvance, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId, RecordDate = DateTime.Now, Amount = empReqAmount, CostCentreId = _context.Departments.Find(_context.Employees.Find(empid).DepartmentId).CostCentreId, ApprovalStatusId = (int)ApprovalStatus.Pending }); await _context.SaveChangesAsync(); #endregion #region //##### 4. ClaimsApprovalTracker to be updated for all the allowed Approvers var getEmpClaimApproversAllLevels = _context.ApprovalRoleMaps.Where(a => a.ApprovalGroupId == empApprGroupId).ToList().OrderBy(a => a.ApprovalLevel); foreach (ApprovalRoleMap ApprMap in getEmpClaimApproversAllLevels) { int role_id = ApprMap.RoleId; var approver = _context.Employees.Where(e => e.RoleId == role_id).FirstOrDefault(); _context.ClaimApprovalStatusTrackers.Add(new ClaimApprovalStatusTracker { EmployeeId = pettyCashRequestDto.EmployeeId, PettyCashRequestId = pettyCashRequestDto.Id, DepartmentId = approver.DepartmentId, ProjectId = null, RoleId = approver.RoleId, ReqDate = DateTime.Now, FinalApprovedDate = null, ApprovalStatusTypeId = (int)ApprovalStatus.Pending //1-Pending, 2-Approved, 3-Rejected }); await _context.SaveChangesAsync(); #endregion //##### 5. Send email to the Approver //#################################### var approverMailAddress = approver.Email; string subject = "Pettycash Request Approval " + pettyCashRequestDto.Id.ToString(); Employee emp = await _context.Employees.FindAsync(pettyCashRequestDto.EmployeeId); var pettycashreq = _context.PettyCashRequests.Find(pettyCashRequestDto.Id); string content = "Petty Cash Approval sought by " + emp.FirstName + "/nCash Request for the amount of " + pettycashreq.PettyClaimAmount + "/ntowards " + pettycashreq.PettyClaimRequestDesc; var messagemail = new Message(new string[] { approverMailAddress }, subject, content); await _emailSender.SendEmailAsync(messagemail); } }
/// <summary> /// This is the option 1 : : PROJECT BASED CASH ADVANCE REQUEST /// </summary> /// <param name="pettyCashRequestDto"></param> /// <param name="empCurAvailBal"></param> private async Task <IActionResult> ProjectCashRequest(PettyCashRequestDTO pettyCashRequestDto, Double empCurAvailBal) { //### 1. If Employee Eligible for Cash Claim enter a record and reduce the available amount for next claim #region int costCenter = _context.Projects.Find(pettyCashRequestDto.ProjectId).CostCenterId; int projManagerid = _context.Projects.Find(pettyCashRequestDto.ProjectId).ProjectManagerId; var approver = _context.Employees.Find(projManagerid); //// int empid = pettyCashRequestDto.EmployeeId; Double empReqAmount = pettyCashRequestDto.PettyClaimAmount; //int empApprGroupId = _context.Employees.Find(empid).ApprovalGroupId; double maxCashAllowedForRole = (_context.JobRoles.Find(_context.Employees.Find(pettyCashRequestDto.EmployeeId).RoleId).MaxPettyCashAllowed); if (pettyCashRequestDto.PettyClaimAmount > maxCashAllowedForRole) { return(Conflict(new RespStatus { Status = "Failure", Message = "Advance Amount is not eligibile" })); } var curPettyCashBal = _context.EmpCurrentPettyCashBalances.Where(x => x.EmployeeId == empid).FirstOrDefault(); curPettyCashBal.Id = curPettyCashBal.Id; curPettyCashBal.CurBalance = empCurAvailBal - empReqAmount <= maxCashAllowedForRole ? empCurAvailBal - empReqAmount : maxCashAllowedForRole; curPettyCashBal.EmployeeId = empid; curPettyCashBal.UpdatedOn = DateTime.Now; _context.Update(curPettyCashBal); await _context.SaveChangesAsync(); #endregion //##### 2. Adding entry to PettyCashRequest table for record #region var pcrq = new PettyCashRequest() { EmployeeId = empid, PettyClaimAmount = empReqAmount, CashReqDate = DateTime.Now, DepartmentId = null, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId, PettyClaimRequestDesc = pettyCashRequestDto.PettyClaimRequestDesc, CurrencyTypeId = pettyCashRequestDto.CurrencyTypeId, ApprovalStatusTypeId = (int)EApprovalStatus.Pending, Comments = "Cash Advance Request in Process!" }; _context.PettyCashRequests.Add(pcrq); await _context.SaveChangesAsync(); pettyCashRequestDto.Id = pcrq.Id; #endregion //##### 3. Add an entry to ClaimApproval Status tracker //get costcenterID based on project #region ///////////////////////////// Check if self Approved Request ///////////////////////////// int maxApprLevel = _context.ApprovalRoleMaps.Max(a => a.ApprovalLevelId); int empApprLevel = _context.ApprovalRoleMaps.Where(a => a.RoleId == _context.Employees.Find(empid).RoleId).FirstOrDefault().Id; bool isSelfApprovedRequest = false; //if highest approver is requesting Petty cash request himself if (maxApprLevel == empApprLevel || projManagerid == empid) { isSelfApprovedRequest = true; } ////////////////////////////////////////////////////////////////////////////////////////// if (isSelfApprovedRequest) { ClaimApprovalStatusTracker claimAppStatusTrack = new() { EmployeeId = pettyCashRequestDto.EmployeeId, PettyCashRequestId = pettyCashRequestDto.Id, DepartmentId = null, ProjManagerId = projManagerid, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId, RoleId = approver.RoleId, // get the next ProjectManager approval. ApprovalGroupId = _context.Employees.Find(pettyCashRequestDto.EmployeeId).ApprovalGroupId, ApprovalLevelId = 2, //empApprLevel or 2 default approval level is 2 for Project based request ReqDate = DateTime.Now, FinalApprovedDate = DateTime.Now, ApprovalStatusTypeId = (int)EApprovalStatus.Approved, //1-Initiating, 2-Pending, 3-InReview, 4-Approved, 5-Rejected Comments = "Self Approved Request!" }; _context.ClaimApprovalStatusTrackers.Add(claimAppStatusTrack); pcrq.ApprovalStatusTypeId = (int)EApprovalStatus.Approved; _context.PettyCashRequests.Update(pcrq); await _context.SaveChangesAsync(); } else { ClaimApprovalStatusTracker claimAppStatusTrack = new() { EmployeeId = pettyCashRequestDto.EmployeeId, PettyCashRequestId = pettyCashRequestDto.Id, DepartmentId = null, ProjManagerId = projManagerid, ProjectId = pettyCashRequestDto.ProjectId, SubProjectId = pettyCashRequestDto.SubProjectId, WorkTaskId = pettyCashRequestDto.WorkTaskId, RoleId = approver.RoleId, // get the next ProjectManager approval. ApprovalGroupId = _context.Employees.Find(pettyCashRequestDto.EmployeeId).ApprovalGroupId, ApprovalLevelId = 2, // default approval level is 2 for Project based request ReqDate = DateTime.Now, FinalApprovedDate = null, ApprovalStatusTypeId = (int)EApprovalStatus.Pending, //1-Initiating, 2-Pending, 3-InReview, 4-Approved, 5-Rejected Comments = "Awaiting Approver Action" }; _context.ClaimApprovalStatusTrackers.Add(claimAppStatusTrack); await _context.SaveChangesAsync(); #endregion //##### 4. Send email to the user //#################################### #region var approverMailAddress = approver.Email; string subject = "Pettycash Request Approval " + pettyCashRequestDto.Id.ToString(); Employee emp = await _context.Employees.FindAsync(pettyCashRequestDto.EmployeeId); var pettycashreq = _context.PettyCashRequests.Find(pettyCashRequestDto.Id); string content = "Petty Cash Approval sought by " + emp.FirstName + "/nCash Request for the amount of " + pettycashreq.PettyClaimAmount + "/ntowards " + pettycashreq.PettyClaimRequestDesc; var messagemail = new Message(new string[] { approverMailAddress }, subject, content); await _emailSender.SendEmailAsync(messagemail); #endregion } //##### 5. Adding a entry in DisbursementsAndClaimsMaster table for records #region DisbursementsAndClaimsMaster disbursementsAndClaimsMaster = new(); disbursementsAndClaimsMaster.EmployeeId = pettyCashRequestDto.EmployeeId; disbursementsAndClaimsMaster.PettyCashRequestId = pettyCashRequestDto.Id; disbursementsAndClaimsMaster.ExpenseReimburseReqId = null; disbursementsAndClaimsMaster.RequestTypeId = (int)ERequestType.CashAdvance; disbursementsAndClaimsMaster.DepartmentId = null; disbursementsAndClaimsMaster.ProjectId = pettyCashRequestDto.ProjectId; disbursementsAndClaimsMaster.SubProjectId = pettyCashRequestDto.SubProjectId; disbursementsAndClaimsMaster.WorkTaskId = pettyCashRequestDto.WorkTaskId; disbursementsAndClaimsMaster.RecordDate = DateTime.Now; disbursementsAndClaimsMaster.CurrencyTypeId = pettyCashRequestDto.CurrencyTypeId; disbursementsAndClaimsMaster.ClaimAmount = pettyCashRequestDto.PettyClaimAmount; disbursementsAndClaimsMaster.AmountToWallet = 0; disbursementsAndClaimsMaster.AmountToCredit = 0; disbursementsAndClaimsMaster.CostCenterId = _context.Projects.Find(pettyCashRequestDto.ProjectId).CostCenterId; disbursementsAndClaimsMaster.ApprovalStatusId = (int)EApprovalStatus.Pending; //1-Initiating, 2-Pending, 3-InReview, 4-Approved, 5-Rejected _context.DisbursementsAndClaimsMasters.Add(disbursementsAndClaimsMaster); try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException ex) { string error = ex.Message; } #endregion return(Ok(new RespStatus { Status = "Success", Message = "Advance Request Created!" })); }