using System; using System.Collections.Generic; using System.Linq; using System.Text; using Ease.CoreV35; using Ease.CoreV35.Model; using Ease.CoreV35.Caching; using System.Data.Linq.Mapping; using System.Data; namespace Payroll.BO { [Serializable] public class OpiCalculator : OpiExceptionCalculator { private ObjectsTemplate _employees; private ObjectsTemplate _processDetails; private ObjectsTemplate _opiParameters; private ObjectsTemplate _opiItems; private DataSet _dsOPIRegister; private ObjectsTemplate _processItems; public DateTime _processMonth; private ObjectsTemplate _oOPIProcesss; private ObjectsTemplate _oOPIProcessDetails; private ObjectsTemplate _oOPIProcessDetailItems; private bool isOPISeparateAcountApplicable; private List _processStatuses; public event ProcessStatus ProcessStatus; public event ProgressStatus ProgressStatus; // public event ErrorMessage ErrorMessage; public ObjectsTemplate OpiProcessDetails { get { return _processDetails; } } public OpiCalculator() { _opiItems = OpiItem.Get(); isOPISeparateAcountApplicable = ConfigurationManager.GetBoolValue("opi", "separateaccount", EnumConfigurationType.Logic); } public List ErrorList { get { return _processStatuses; } } private void UpdateprocessStatus(string statusString) { if (ProcessStatus != null) ProcessStatus(statusString); } private void UpdateProgressStatus(EnumProcessStatus status) { if (ProgressStatus != null) ProgressStatus(status); } public ObjectsTemplate Employees { get { return _employees; } } public string MakeErrorMessage(List allerrors) { string error = String.Empty; foreach (OpiProcessStatus item in allerrors) { error += item.EmployeeNo + " " + item.Remarks + "\n"; } return error; } //public ObjectsTemplate Process(ObjectsTemplate employees, DateTime processMonth) public void Process(ObjectsTemplate employees, DateTime processMonth) { _employees = employees; _processMonth = processMonth; //_opiItems = OpiItem.Get(); UpdateprocessStatus("Collecting Employee basic information...."); this.Initialize(); this.AddEmployeeToProcessDetail(); if (_processStatuses.Count > 0) return; if (_processStatuses.Count > 0) { string message = MakeErrorMessage(_processStatuses); if (ErrorMessage != null) ErrorMessage(message); return; } UpdateprocessStatus("Calculating basic Salary...."); this.CalculateBasicSalary(); if (_processStatuses.Count > 0) return; UpdateprocessStatus("Calculating Provision items...."); if (_processStatuses.Count > 0) return; this.OPIItems(); this.CalculationException(_processDetails, _processMonth); //return _processDetails; } public void ProcessForLC(ObjectsTemplate employees, DateTime processMonth) { _employees = employees; _processMonth = processMonth; //_opiItems = OpiItem.Get(); UpdateprocessStatus("Collecting Employee basic information...."); this.Initialize(); this.AddEmployeeToProcessDetail(); if (_processStatuses.Count > 0) return; if (_processStatuses.Count > 0) { string message = MakeErrorMessage(_processStatuses); if (ErrorMessage != null) ErrorMessage(message); return; } UpdateprocessStatus("Calculating basic Salary...."); this.CalculateBasicSalary(); if (_processStatuses.Count > 0) return; UpdateprocessStatus("Calculating Provision items...."); if (_processStatuses.Count > 0) return; this.OPIItemsLC(); this.CalculationException(_processDetails, _processMonth); //return _processDetails; } private void Initialize() { _processStatuses = new List(); _processDetails = new ObjectsTemplate(); } private bool ProcessStartValidation() { return false; } private void AddEmployeeToProcessDetail() { //_processDetails = new ObjectsTemplate(); ObjectsTemplate obranches = Branch.Get(EnumStatus.Regardless); UpdateProgressStatus(EnumProcessStatus.Start); foreach (Employee employee in _employees) { if (GlobalFunctions.FirstDateOfMonth(employee.JoiningDate) > GlobalFunctions.FirstDateOfMonth(_processMonth)) { AddProcessStatus(employee, "Employee Joining Date is greater than Process Date"); continue; } UpdateProgressStatus(EnumProcessStatus.PerformStep); this.UpdateprocessStatus(" Collecting information for the employee " + employee.Name + " ( " + employee.EmployeeNo + ")"); OPIProcessDetail procDetail = new OPIProcessDetail(); procDetail.CategoryID = employee.CategoryID; procDetail.EmployeeID = employee.ID; procDetail.Gender = employee.Gender; procDetail.IsConfirmed = employee.IsConfirmed; procDetail.PayrollTypeID = employee.PayrollTypeID; procDetail.PFMemberType = employee.PFMemberType; if (employee.ReligionID.IsUnassigned == true) AddProcessStatus(employee, "Religion not yet assigned"); else procDetail.ReligionID = employee.ReligionID; if (employee.GradeID.IsUnassigned == true) AddProcessStatus(employee, "Grade not yet assigned"); else procDetail.GradeID = employee.GradeID; if (employee.DepartmentID.IsUnassigned == true) AddProcessStatus(employee, "Department not yet assigned"); else procDetail.DepartmentID = employee.DepartmentID; if (employee.DesignationID.IsUnassigned == true) AddProcessStatus(employee, "Designation not yet assigned"); else procDetail.DesignationID = employee.DesignationID; if (employee.LocationID.IsUnassigned == true) AddProcessStatus(employee, "Location not yet assigned"); else procDetail.LocationID = employee.LocationID; if (isOPISeparateAcountApplicable) { if (employee.OutPayPaymentMode == EnumPaymentMode.BankTransfer) { if (employee.OutPayBranchID == null || employee.OutPayBranchID.IsUnassigned) { AddProcessStatus(employee, "Employee payment mode is declared" + " to bank transfer, but no OPI bank/account information found"); } else { procDetail.BranchID = employee.OutPayBranchID; procDetail.AccountNo = employee.OutPayAccountNo; Branch branch = new Branch(); branch = obranches.GetItem(employee.OutPayBranchID); procDetail.BankID = branch.BankID; } //procDetail.BranchID = employee.BranchID; //Branch branch = new Branch(); //branch = obranches.GetItem(employee.BranchID); //procDetail.BankID = branch.BankID; //procDetail.AccountNo = employee.AccountNo; } else { procDetail.BranchID = null; procDetail.BankID = null; } } else { if (employee.PaymentMode == EnumPaymentMode.BankTransfer) { if (employee.BranchID == null || employee.BranchID.IsUnassigned) AddProcessStatus(employee, "Employee payment mode is diclared" + " to bank transfer, but no bank/account information found"); else { procDetail.BranchID = employee.BranchID; procDetail.AccountNo = employee.AccountNo; Branch branch = new Branch(); branch = obranches.GetItem(employee.BranchID); procDetail.BankID = branch.BankID; } //procDetail.BranchID = employee.BranchID; //Branch branch = new Branch(); //branch = obranches.GetItem(employee.BranchID); //procDetail.BankID = branch.BankID; //procDetail.AccountNo = employee.AccountNo; } else { procDetail.BranchID = null; procDetail.BankID = null; } } procDetail.Employee = employee; _processDetails.Add(procDetail); } UpdateProgressStatus(EnumProcessStatus.End); } private void AddProcessStatus(Employee employee, string remarks) { OpiProcessStatus status = new OpiProcessStatus(); status.EmployeeNo = employee.EmployeeNo; status.Name = employee.Name; status.Remarks = remarks; _processStatuses.Add(status); } private void CalculateBasicSalary() { UpdateProgressStatus(EnumProcessStatus.Start); //GetCurrentMonthSalaryItems function return current month's employee grade, salary and effect date. //effect date must sorted, otherwise error will be generated from next function. #region Calculate Normal Salary ObjectsTemplate gradeSalaryItems = EmployeeGradeSalary.Service.GetCurrMonthSalaryItems(SystemInformation.CurrentSysInfo.NextPayProcessDate); foreach (OPIProcessDetail opiProcess in _processDetails) { UpdateProgressStatus(EnumProcessStatus.PerformStep); opiProcess.GradeSalaries = EmployeeGradeSalary.Get(gradeSalaryItems, opiProcess.EmployeeID); if (opiProcess.GradeSalaries.Count == 0) continue; EmployeeGradeSalary.PrepareDataForCurrentSalary(opiProcess.Employee, opiProcess.GradeSalaries); } #endregion Calculate Normal Salary #region calculate arrear amount ObjectsTemplate arrearItems = EmployeeGradeSalary.Service.GetArrearItems(); foreach (OPIProcessDetail opiProcess in _processDetails) opiProcess.ArrearGradeSalaries = EmployeeGradeSalary.Get(arrearItems, opiProcess.EmployeeID); #endregion calculate arrear amount UpdateProgressStatus(EnumProcessStatus.End); } private void OPIItems() { try { UpdateProgressStatus(EnumProcessStatus.Start); _opiParameters = OpiParameter.Get(EnumStatus.Active); if (_opiParameters == null || _opiParameters.Count == 0) return; ObjectsTemplate opiIndividuals = OpiParameterIndividual.Service.Get( GlobalFunctions.FirstDateOfMonth(_processMonth), GlobalFunctions.LastDateOfMonth(_processMonth)); OpiParameter paramter = new OpiParameter(); ObjectsTemplate parameters; ObjectsTemplate adParams = ADParameter.Get(EnumStatus.Active); ObjectsTemplate adParamEmps = ADParameterEmployee.Get(EnumStatus.Active); ObjectsTemplate grossDefinitions = GrossDefination.Get(); foreach (OPIProcessDetail detail in _processDetails) { UpdateProgressStatus(EnumProcessStatus.PerformStep); parameters = paramter.ApplicableParameters(detail.Employee, detail, _opiParameters, detail.GradeSalaries); if (parameters == null) { throw new ServiceException(" Applicable parameter not found for the employee :" + detail.Employee.EmployeeNo + " and Grade:" + detail.Employee.Grade.Code); } this.GradeDefinedOpiItem(detail, parameters,adParams,adParamEmps,grossDefinitions); this.IndividualOpiItem(detail, opiIndividuals, detail.GradeSalaries); } } catch (Exception ex) { throw new ServiceException(ex.Message); } } private void OPIItemsLC() { try { UpdateProgressStatus(EnumProcessStatus.Start); _opiParameters = OpiParameter.Get(EnumStatus.Active); if (_opiParameters == null || _opiParameters.Count == 0) return; ObjectsTemplate opiIndividuals = OpiParameterIndividual.Service.Get( GlobalFunctions.FirstDateOfMonth(_processMonth), GlobalFunctions.LastDateOfMonth(_processMonth)); OpiParameter paramter = new OpiParameter(); ObjectsTemplate parameters; foreach (OPIProcessDetail detail in _processDetails) { UpdateProgressStatus(EnumProcessStatus.PerformStep); parameters = paramter.ApplicableParameters(detail.Employee, detail, _opiParameters,detail.GradeSalaries); if (parameters == null) { throw new ServiceException(" Applicable parameter not found for the employee :" + detail.Employee.EmployeeNo + " and Grade:" + detail.Employee.Grade.Code); } this.GradeDefinedOpiItem(detail , parameters); this.IndividualOpiItemLC(detail, opiIndividuals, detail.GradeSalaries); } } catch (Exception ex) { throw new ServiceException(ex.Message); } } private void Add(OPIProcessDetail processDetail, OPIProcessDetailItem item) { OPIProcessDetailItem existItem = processDetail.OPIProcessDetailItems.Find(delegate(OPIProcessDetailItem fItem) { return fItem.OPIItemID == item.OPIItemID; }); if (existItem == null) { processDetail.OPIProcessDetailItems.Add(item); } else { existItem.NetAmount = GlobalFunctions.Round(existItem.NetAmount + item.NetAmount); existItem.ChangeNetAmount = GlobalFunctions.Round(existItem.ChangeNetAmount + item.ChangeNetAmount); existItem.Description = item.Description; } } /// /// /// /// /// /// /// private void GradeDefinedOpiItem(OPIProcessDetail detail, ObjectsTemplate parameters) { double amount = 0, paidAmount = 0; int paidMonth = 0; double indvAmnt = 0; int nNumOfEmp = 0; foreach (OpiParameter parameter in parameters) { if (parameter.EntitleType != EnumEntitleType.Grade) continue; OPIProcessDetailItem opdItem = new OPIProcessDetailItem(); switch (parameter.OpiPeriodicity) { case EnumOpiPeriodicity.Monthly: if (parameter.IsEarnedBasic == true) { SalaryMonthly omonthlysalary = SalaryMonthly.Get(detail.EmployeeID, _processMonth); if (omonthlysalary != null) { amount = omonthlysalary.GetAmount(EnumSalaryGroup.Gross, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); amount = amount + omonthlysalary.GetAmount(EnumSalaryGroup.Arrear, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); amount = amount - omonthlysalary.GetAmount(EnumSalaryGroup.UnauthLeave, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); } amount = parameter.GetGradeDefinedAmount(detail.Employee, amount, 0, 1); } else { EmployeeGradeSalary.PrepareDataForCurrentSalary(detail.Employee, detail.GradeSalaries); amount = parameter.GetGradeDefinedAmount(detail.Employee, detail.GradeSalaries); foreach (EmployeeGradeSalary arrearItem in detail.ArrearGradeSalaries) { arrearItem.FractionofFromTo = GlobalFunctions.GetFraction(arrearItem.EffectDate, (DateTime)arrearItem.TillDate); amount = amount + parameter.GetGradeDefinedAmount(detail.Employee, arrearItem); amount = amount - OPIProcess.GetAmountOnRange(detail.Employee, arrearItem.EffectDate, (DateTime)arrearItem.TillDate, parameter.OpiItemID.Integer, parameter.ID.Integer); amount = GlobalFunctions.Round(amount); } } if (amount > 0) { opdItem.NetAmount = GlobalFunctions.Round(amount); opdItem.ChangeNetAmount = GlobalFunctions.Round(amount); } else { continue; } break; case EnumOpiPeriodicity.OnceOff: break; case EnumOpiPeriodicity.Annual: // Calculation policy 1: // No_of_paid_month = Jan to Next_Pay_Process_Month // paidAmount= get cumalative amount on month range // net_Amount= amount + {(No_of_paid_month * amount) - paidAmount} //implementing policy 1 //amount = parameter.GetGradeDefinedAmount(detail.Employee, gradeSalaries); double annualAmount = amount; amount = amount / 12; DateTime dFromOpiMonth, dToOpiMonth; dFromOpiMonth = new DateTime(_processMonth.Year, 1, 1); paidMonth = Convert.ToInt32(_processMonth.Date.Month) - 1; if (paidMonth <= 0) dToOpiMonth = new DateTime(_processMonth.Year, dFromOpiMonth.Date.Month, (GlobalFunctions.LastDateOfMonth(dFromOpiMonth)).Date.Day); else dToOpiMonth = new DateTime(_processMonth.Year, paidMonth, 1); paidAmount = GlobalFunctions.Round(OPIProcess.GetPrevMonthAmount(detail.EmployeeID, parameter.OpiItemID, dFromOpiMonth, GlobalFunctions.LastDateOfMonth(dToOpiMonth))); if (_processMonth.Month == 12) { if (detail.Employee.JoiningDate > Ease.CoreV35.Utility.Global.DateFunctions.FirstDateOfYear(dFromOpiMonth)) { int dDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", detail.Employee.JoiningDate, Ease.CoreV35.Utility.Global.DateFunctions.LastDateOfYear(dFromOpiMonth)) + 1; annualAmount = annualAmount / 365 * dDays; if ((annualAmount - paidAmount) > 0) { opdItem.NetAmount = annualAmount - paidAmount; } else { continue; } } else { if ((annualAmount - paidAmount) > 0) { opdItem.NetAmount = annualAmount - paidAmount; } else { continue; } } } else { if (detail.Employee.JoiningDate > Ease.CoreV35.Utility.Global.DateFunctions.FirstDateOfYear(dFromOpiMonth)) { int dDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", detail.Employee.JoiningDate, Ease.CoreV35.Utility.Global.DateFunctions.LastDateOfYear(dFromOpiMonth)) +1; annualAmount = annualAmount / 365 * dDays; amount = annualAmount / ((12 - detail.Employee.JoiningDate.Month) + 1); paidMonth = _processMonth.Month - detail.Employee.JoiningDate.Month; } if ((amount + ((paidMonth * amount) - paidAmount)) > 0) { opdItem.NetAmount = GlobalFunctions.Round(amount + ((paidMonth * amount) - paidAmount)); } else { continue; } } opdItem.ChangeNetAmount = GlobalFunctions.Round(opdItem.NetAmount); // Calculation Policy 2: // rest_of_the_Month= (Next_Pay_Process_Month to Dec) + 1 // net_Amount = (amount * 12)/rest_of_the_Month break; //case EnumOpiPeriodicity.AveragePayment: // //find the number of month specific salary item from salary monthly defined in opi parameter // //DateTime fromDate=null, todate=null; // // create the from and todate by averagemonth // // fromdate should be frist date of month // // todate should be last date of month // // avgmonth=3 and payprocessmonth=jun, frommonth=march todate=may // double salaryPaidAmount = 0; // DateTime dFromDate, dToDate; // dFromDate = GlobalFunctions.FirstDateOfMonth(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.AddMonths((parameter.NoOfMonth) * (-1))); // dToDate = GlobalFunctions.LastDateOfMonth(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.AddMonths(-1)); // dFromDate = GlobalFunctions.FirstDateOfMonth(dFromDate); // SalaryMonthly omonthly = new SalaryMonthly(); // switch (parameter.OpiAvgPayType) // { // case EnumOpiAvgPayType.OT: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Gross, EnumSalaryItemCode.Over_Time_Amount, parameter.OpiAvgPayItemID.Integer); // break; // case EnumOpiAvgPayType.Allowance: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Gross, EnumSalaryItemCode.Allowance, parameter.OpiAvgPayItemID.Integer); // break; // case EnumOpiAvgPayType.Deduction: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Deductions, EnumSalaryItemCode.Deduction, parameter.OpiAvgPayItemID.Integer); // break; // default: // break; // } // amount = 0; // if (parameter.NoOfMonth != 0) // amount = salaryPaidAmount / (double)parameter.NoOfMonth; // opdItem.NetAmount = GlobalFunctions.Round(amount); // opdItem.ChangeNetAmount = opdItem.NetAmount; // break; case EnumOpiPeriodicity.OnAmount: // Number of employee of the parameter selected grade - not applicable employees // if gender applicable then remove other gender // if confirmed checked then remove unconfirmed // nNumOfEmp = parameter.NoOfAplicableEmp; if (nNumOfEmp != 0) indvAmnt = parameter.ProvisionAmount / (double)nNumOfEmp; opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; //case EnumOpiPeriodicity.BonusProvision: // // find the parameter of the bonus by using employee gradid and bonus id // // parameter define the number basic/total Amount will get in a year // // find the bonus paid amount from bonus pay detail // // find the number of item paid for the employee // // (rest of the Item * number of basic) // double annualBonusPaidinYear = BonusProcess.GetBonusAmountWithinYear( // Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate, detail.Employee.ID, parameter.OpiAvgPayItemID.Integer); // int paidItem = BonusProcess.GetForNoOfPaid(_processMonth, parameter.OpiAvgPayItemID.Integer); // double provisionedAmount = GlobalFunctions.Round(OPIProcess.GetPrevMonthAmount(detail.EmployeeID, // parameter.OpiItemID, new DateTime(_processMonth.Year, 1, 1), GlobalFunctions.LastDateOfMonth(_processMonth))); // double willProvision; // if (_processMonth.Month != 12) // { // int restofMonth = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("m", _processMonth, new DateTime(_processMonth.Year, 12, 31)) + 1; // BonusParameter bonusParameter = BonusParameter.GetByBonusID(parameter.OpiAvgPayItemID); // willProvision = annualBonusPaidinYear + ((bonusParameter.NoOfBasic - paidItem) * detail.Employee.BasicSalary ); // willProvision = willProvision - provisionedAmount; // willProvision = willProvision / restofMonth; // } // else // { // willProvision = annualBonusPaidinYear - provisionedAmount; // } // opdItem.NetAmount = GlobalFunctions.Round(willProvision); // opdItem.ChangeNetAmount = GlobalFunctions.Round(willProvision); // break; case EnumOpiPeriodicity.EarnedLeave: // Number of employee of the parameter selected grade - not applicable employees // if gender applicable then remove other gender // if confirmed checked then remove unconfirmed // nNumOfEmp = parameter.NoOfAplicableEmp; if (nNumOfEmp != 0) indvAmnt = ((detail.Employee.BasicSalary / 22) * parameter.FlatAmount) / 12; opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; case EnumOpiPeriodicity.OT: indvAmnt = 0; amount = 0; //Get last 3 MonthEnd overtime ObjectsTemplate omonthlysalarys = SalaryMonthly.GetByDateRange(detail.EmployeeID, _processMonth.AddMonths(-3).AddDays(-4), _processMonth.AddDays(-27)); if (omonthlysalarys != null && omonthlysalarys.Count > 0) { foreach (SalaryMonthly item in omonthlysalarys) { //sum of Last 3 month overtime amount = amount + item.GetAmount(EnumSalaryGroup.Miscellaneous, EnumSalaryItemCode.Over_Time_Amount, (int)EnumSalaryItemCode.Over_Time_Amount); } indvAmnt = amount / omonthlysalarys.Count; } // sum of Last 3 month overtime amount divided by 3 opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; default: break; } //opdItem.NetAmount = Math.Abs(opdItem.NetAmount); //opdItem.ChangeNetAmount = Math.Abs(opdItem.ChangeNetAmount); if (opdItem.NetAmount > 0) { opdItem.NetAmount = opdItem.NetAmount; } else { continue; } if (opdItem.ChangeNetAmount > 0) { opdItem.ChangeNetAmount = opdItem.ChangeNetAmount; } else { continue; } OpiItem opItem = _opiItems.GetItem(parameter.OpiItem.ID); opdItem.Description = opItem.Name; opdItem.OPIItemID = parameter.OpiItemID; opdItem.OPIType = opItem.OpiType; opdItem.Sequence = opItem.Sequence; opdItem.Paramter = parameter; this.Add(detail, opdItem); // add the item in the collection } } private void GradeDefinedOpiItem(OPIProcessDetail detail, ObjectsTemplate parameters, ObjectsTemplate adParams, ObjectsTemplate adParamEmps, ObjectsTemplate grossDefinitions) { double amount = 0, paidAmount = 0; int paidMonth = 0; double indvAmnt = 0; int nNumOfEmp = 0; double nMonthlyGross = 0; double nAnnualGross = 0; foreach (OpiParameter parameter in parameters) { if (parameter.EntitleType != EnumEntitleType.Grade) continue; OPIProcessDetailItem opdItem = new OPIProcessDetailItem(); EmployeeGradeSalary oEmpGradeSal = EmployeeGradeSalary.GetBasicOnDate(detail.EmployeeID, _processMonth); detail.Employee.GradeID = oEmpGradeSal.GradeID; switch (parameter.OpiPeriodicity) { case EnumOpiPeriodicity.Monthly: nMonthlyGross = BonusCalculator.GetMonthlyGrossAmount(detail.Employee, adParams, adParamEmps, grossDefinitions, SystemInformation.CurrentSysInfo.NextPayProcessDate); if (parameter.IsEarnedBasic == true) { SalaryMonthly omonthlysalary = SalaryMonthly.Get(detail.EmployeeID, _processMonth); if (omonthlysalary != null) { amount = omonthlysalary.GetAmount(EnumSalaryGroup.Gross, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); amount = amount + omonthlysalary.GetAmount(EnumSalaryGroup.Arrear, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); amount = amount - omonthlysalary.GetAmount(EnumSalaryGroup.UnauthLeave, EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary); } amount = parameter.GetGradeDefinedAmount(detail.Employee, amount, nMonthlyGross, 1); } else { EmployeeGradeSalary.PrepareDataForCurrentSalary(detail.Employee, detail.GradeSalaries); amount = parameter.GetGradeDefinedAmount(detail.Employee, detail.GradeSalaries,nMonthlyGross); foreach (EmployeeGradeSalary arrearItem in detail.ArrearGradeSalaries) { arrearItem.FractionofFromTo = GlobalFunctions.GetFraction(arrearItem.EffectDate, (DateTime)arrearItem.TillDate); amount = amount + parameter.GetGradeDefinedAmount(detail.Employee, arrearItem); amount = amount - OPIProcess.GetAmountOnRange(detail.Employee, arrearItem.EffectDate, (DateTime)arrearItem.TillDate, parameter.OpiItemID.Integer, parameter.ID.Integer); amount = GlobalFunctions.Round(amount); } } if (amount > 0) { opdItem.NetAmount = GlobalFunctions.Round(amount); opdItem.ChangeNetAmount = GlobalFunctions.Round(amount); } else { continue; } break; case EnumOpiPeriodicity.OnceOff: break; case EnumOpiPeriodicity.KPI: nAnnualGross = BonusCalculator.GetGrossAmount(detail.Employee, adParams, adParamEmps, grossDefinitions, SystemInformation.CurrentSysInfo.NextPayProcessDate,oEmpGradeSal ); amount = 0; amount = (((nAnnualGross * parameter.AnnualGrossPerBand) / 100) * ((nAnnualGross * parameter.PerformanceAchievement) / 100)) / 12; opdItem.NetAmount = GlobalFunctions.Round(amount); opdItem.ChangeNetAmount = GlobalFunctions.Round(amount); break; case EnumOpiPeriodicity.Annual: // Calculation policy 1: // No_of_paid_month = Jan to Next_Pay_Process_Month // paidAmount= get cumalative amount on month range // net_Amount= amount + {(No_of_paid_month * amount) - paidAmount} //implementing policy 1 //amount = parameter.GetGradeDefinedAmount(detail.Employee, gradeSalaries); double annualAmount = nMonthlyGross; amount = amount / 12; DateTime dFromOpiMonth, dToOpiMonth; dFromOpiMonth = new DateTime(_processMonth.Year, 1, 1); paidMonth = Convert.ToInt32(_processMonth.Date.Month) - 1; if (paidMonth <= 0) dToOpiMonth = new DateTime(_processMonth.Year, dFromOpiMonth.Date.Month, (GlobalFunctions.LastDateOfMonth(dFromOpiMonth)).Date.Day); else dToOpiMonth = new DateTime(_processMonth.Year, paidMonth, 1); paidAmount = GlobalFunctions.Round(OPIProcess.GetPrevMonthAmount(detail.EmployeeID, parameter.OpiItemID, dFromOpiMonth, GlobalFunctions.LastDateOfMonth(dToOpiMonth))); if (_processMonth.Month == 12) { if (detail.Employee.JoiningDate > Ease.CoreV35.Utility.Global.DateFunctions.FirstDateOfYear(dFromOpiMonth)) { int dDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", detail.Employee.JoiningDate, Ease.CoreV35.Utility.Global.DateFunctions.LastDateOfYear(dFromOpiMonth)) + 1; annualAmount = annualAmount / 365 * dDays; if ((annualAmount - paidAmount) > 0) { opdItem.NetAmount = annualAmount - paidAmount; } else { continue; } } else { if ((annualAmount - paidAmount) > 0) { opdItem.NetAmount = annualAmount - paidAmount; } else { continue; } } } else { if (detail.Employee.JoiningDate > Ease.CoreV35.Utility.Global.DateFunctions.FirstDateOfYear(dFromOpiMonth)) { int dDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", detail.Employee.JoiningDate, Ease.CoreV35.Utility.Global.DateFunctions.LastDateOfYear(dFromOpiMonth)) + 1; annualAmount = annualAmount / 365 * dDays; amount = annualAmount / ((12 - detail.Employee.JoiningDate.Month) + 1); paidMonth = _processMonth.Month - detail.Employee.JoiningDate.Month; } if ((amount + ((paidMonth * amount) - paidAmount)) > 0) { opdItem.NetAmount = GlobalFunctions.Round(amount + ((paidMonth * amount) - paidAmount)); } else { continue; } } opdItem.ChangeNetAmount = GlobalFunctions.Round(opdItem.NetAmount); // Calculation Policy 2: // rest_of_the_Month= (Next_Pay_Process_Month to Dec) + 1 // net_Amount = (amount * 12)/rest_of_the_Month break; //case EnumOpiPeriodicity.AveragePayment: // //find the number of month specific salary item from salary monthly defined in opi parameter // //DateTime fromDate=null, todate=null; // // create the from and todate by averagemonth // // fromdate should be frist date of month // // todate should be last date of month // // avgmonth=3 and payprocessmonth=jun, frommonth=march todate=may // double salaryPaidAmount = 0; // DateTime dFromDate, dToDate; // dFromDate = GlobalFunctions.FirstDateOfMonth(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.AddMonths((parameter.NoOfMonth) * (-1))); // dToDate = GlobalFunctions.LastDateOfMonth(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.AddMonths(-1)); // dFromDate = GlobalFunctions.FirstDateOfMonth(dFromDate); // SalaryMonthly omonthly = new SalaryMonthly(); // switch (parameter.OpiAvgPayType) // { // case EnumOpiAvgPayType.OT: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Gross, EnumSalaryItemCode.Over_Time_Amount, parameter.OpiAvgPayItemID.Integer); // break; // case EnumOpiAvgPayType.Allowance: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Gross, EnumSalaryItemCode.Allowance, parameter.OpiAvgPayItemID.Integer); // break; // case EnumOpiAvgPayType.Deduction: // salaryPaidAmount = omonthly.GetAmountOnRange(detail.Employee, dFromDate, dToDate, EnumSalaryGroup.Deductions, EnumSalaryItemCode.Deduction, parameter.OpiAvgPayItemID.Integer); // break; // default: // break; // } // amount = 0; // if (parameter.NoOfMonth != 0) // amount = salaryPaidAmount / (double)parameter.NoOfMonth; // opdItem.NetAmount = GlobalFunctions.Round(amount); // opdItem.ChangeNetAmount = opdItem.NetAmount; // break; case EnumOpiPeriodicity.OnAmount: // Number of employee of the parameter selected grade - not applicable employees // if gender applicable then remove other gender // if confirmed checked then remove unconfirmed // nNumOfEmp = parameter.NoOfAplicableEmp; if (nNumOfEmp != 0) indvAmnt = parameter.ProvisionAmount / (double)nNumOfEmp; opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; //case EnumOpiPeriodicity.BonusProvision: // // find the parameter of the bonus by using employee gradid and bonus id // // parameter define the number basic/total Amount will get in a year // // find the bonus paid amount from bonus pay detail // // find the number of item paid for the employee // // (rest of the Item * number of basic) // double annualBonusPaidinYear = BonusProcess.GetBonusAmountWithinYear( // Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate, detail.Employee.ID, parameter.OpiAvgPayItemID.Integer); // int paidItem = BonusProcess.GetForNoOfPaid(_processMonth, parameter.OpiAvgPayItemID.Integer); // double provisionedAmount = GlobalFunctions.Round(OPIProcess.GetPrevMonthAmount(detail.EmployeeID, // parameter.OpiItemID, new DateTime(_processMonth.Year, 1, 1), GlobalFunctions.LastDateOfMonth(_processMonth))); // double willProvision; // if (_processMonth.Month != 12) // { // int restofMonth = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("m", _processMonth, new DateTime(_processMonth.Year, 12, 31)) + 1; // BonusParameter bonusParameter = BonusParameter.GetByBonusID(parameter.OpiAvgPayItemID); // willProvision = annualBonusPaidinYear + ((bonusParameter.NoOfBasic - paidItem) * detail.Employee.BasicSalary ); // willProvision = willProvision - provisionedAmount; // willProvision = willProvision / restofMonth; // } // else // { // willProvision = annualBonusPaidinYear - provisionedAmount; // } // opdItem.NetAmount = GlobalFunctions.Round(willProvision); // opdItem.ChangeNetAmount = GlobalFunctions.Round(willProvision); // break; case EnumOpiPeriodicity.EarnedLeave: // Number of employee of the parameter selected grade - not applicable employees // if gender applicable then remove other gender // if confirmed checked then remove unconfirmed // nNumOfEmp = parameter.NoOfAplicableEmp; if (nNumOfEmp != 0) indvAmnt = ((detail.Employee.BasicSalary / 22) * parameter.FlatAmount) / 12; opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; case EnumOpiPeriodicity.OT: indvAmnt = 0; amount = 0; //Get last 3 MonthEnd overtime ObjectsTemplate omonthlysalarys = SalaryMonthly.GetByDateRange(detail.EmployeeID, _processMonth.AddMonths(-3).AddDays(-4), _processMonth.AddDays(-27)); if (omonthlysalarys != null && omonthlysalarys.Count > 0) { foreach (SalaryMonthly item in omonthlysalarys) { //sum of Last 3 month overtime amount = amount + item.GetAmount(EnumSalaryGroup.Miscellaneous, EnumSalaryItemCode.Over_Time_Amount, (int)EnumSalaryItemCode.Over_Time_Amount); } indvAmnt = amount / omonthlysalarys.Count; } // sum of Last 3 month overtime amount divided by 3 opdItem.NetAmount = GlobalFunctions.Round(indvAmnt); opdItem.ChangeNetAmount = GlobalFunctions.Round(indvAmnt); break; default: break; } //opdItem.NetAmount = Math.Abs(opdItem.NetAmount); //opdItem.ChangeNetAmount = Math.Abs(opdItem.ChangeNetAmount); if (opdItem.NetAmount > 0) { opdItem.NetAmount = opdItem.NetAmount; } else { continue; } if (opdItem.ChangeNetAmount > 0) { opdItem.ChangeNetAmount = opdItem.ChangeNetAmount; } else { continue; } OpiItem opItem = _opiItems.GetItem(parameter.OpiItem.ID); opdItem.Description = opItem.Name; opdItem.OPIItemID = parameter.OpiItemID; opdItem.OPIType = opItem.OpiType; opdItem.Sequence = opItem.Sequence; opdItem.Paramter = parameter; this.Add(detail, opdItem); // add the item in the collection } } public void DeleteOPIProcess(DateTime dOPIMonth) { OPIProcess.Undo(dOPIMonth); } private void IndividualOpiItem(OPIProcessDetail detail, ObjectsTemplate opiIndividuals , ObjectsTemplate gradeSalaries) { // currently we are not provisioning any kind of discontinued employee // but in future we need this. if (detail.Employee.Status != EnumEmployeeStatus.Live) return; double amount=0; #region Individual Allowance List items = opiIndividuals.FindAll(delegate(OpiParameterIndividual item) { return item.EmployeeId.Integer == detail.Employee.ID.Integer && item.IndividualType == EnumOPIIndivdualType.AppliedToIndividual; }); foreach (OpiParameterIndividual item in items) { amount = 0; OpiParameter parameter = _opiParameters.GetItem(item.OpiParameterID); amount = parameter.GetIndividualAmount(detail.Employee, _processMonth, item, detail.Employee.BasicSalary, detail.Employee.GrossSalary); //foreach(EmployeeGradeSalary oItem in gradeSalaries) //{ // amount = amount + parameter.GetIndividualAmount(detail.Employee, _processMonth, item, detail.Employee.BasicSalary, detail.Employee.GrossSalary, oItem.FractionofFromTo); //} OPIProcessDetailItem opdItem = new OPIProcessDetailItem(); if (amount > 0) { opdItem.NetAmount = GlobalFunctions.Round(amount); opdItem.ChangeNetAmount = GlobalFunctions.Round(amount); } else { continue; } opdItem.OPIItemID = parameter.OpiItemID; OpiItem opItem=_opiItems.GetItem(parameter.OpiItem.ID); opdItem.OPIType = opItem.OpiType; opdItem.Sequence = opItem.Sequence; opdItem.Description = opItem.Name; //opdItem.Paramter = parameter;//new this.Add(detail, opdItem); // add the item in the collection } #endregion Individual Allowance } private void IndividualOpiItemLC(OPIProcessDetail detail, ObjectsTemplate opiIndividuals , ObjectsTemplate gradeSalaries) { // currently we are not provisioning any kind of discontinued employee // but in future we need this. double amount = 0; #region Individual Allowance List items = opiIndividuals.FindAll(delegate(OpiParameterIndividual item) { return item.EmployeeId.Integer == detail.Employee.ID.Integer && item.IndividualType == EnumOPIIndivdualType.AppliedToIndividual; }); foreach (OpiParameterIndividual item in items) { amount = 0; OpiParameter parameter = _opiParameters.GetItem(item.OpiParameterID); amount = parameter.GetIndividualAmount(detail.Employee, _processMonth, item, detail.Employee.BasicSalary, detail.Employee.GrossSalary); //foreach(EmployeeGradeSalary oItem in gradeSalaries) //{ // amount = amount + parameter.GetIndividualAmount(detail.Employee, _processMonth, item, detail.Employee.BasicSalary, detail.Employee.GrossSalary, oItem.FractionofFromTo); //} OPIProcessDetailItem opdItem = new OPIProcessDetailItem(); opdItem.NetAmount = GlobalFunctions.Round(amount); opdItem.ChangeNetAmount = GlobalFunctions.Round(amount); opdItem.OPIItemID = parameter.OpiItemID; OpiItem opItem = _opiItems.GetItem(parameter.OpiItem.ID); opdItem.OPIType = opItem.OpiType; opdItem.Sequence = opItem.Sequence; opdItem.Description = opItem.Name; //opdItem.Paramter = parameter;//new this.Add(detail, opdItem); // add the item in the collection } #endregion Individual Allowance } } public class OpiProcessStatus { public OpiProcessStatus() { _employeeNo = ""; _name = ""; _remarks = ""; } #region EmployeeNo : Employee No private string _employeeNo; public string EmployeeNo { get { return _employeeNo; } set { _employeeNo = value; } } #endregion #region Employee Name : Employee Name private string _name; public string Name { get { return _name; } set { _name = value; } } #endregion #region Remaks : Remarks private string _remarks; public string Remarks { get { return _remarks; } set { _remarks = value; } } #endregion } }