CEL_Payroll/Payroll.BO/OPI/OpiCalculator.cs

1093 lines
54 KiB
C#
Raw Normal View History

2024-09-17 14:30:13 +06:00
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<Employee> _employees;
private ObjectsTemplate<OPIProcessDetail> _processDetails;
private ObjectsTemplate<OpiParameter> _opiParameters;
private ObjectsTemplate<OpiItem> _opiItems;
private DataSet _dsOPIRegister;
private ObjectsTemplate<ProcessItem> _processItems;
public DateTime _processMonth;
private ObjectsTemplate<OPIProcess> _oOPIProcesss;
private ObjectsTemplate<OPIProcessDetail> _oOPIProcessDetails;
private ObjectsTemplate<OPIProcessDetailItem> _oOPIProcessDetailItems;
private bool isOPISeparateAcountApplicable;
private List<OpiProcessStatus> _processStatuses;
public event ProcessStatus ProcessStatus;
public event ProgressStatus ProgressStatus;
//
public event ErrorMessage ErrorMessage;
public ObjectsTemplate<OPIProcessDetail> OpiProcessDetails
{
get
{
return _processDetails;
}
}
public OpiCalculator()
{
_opiItems = OpiItem.Get();
isOPISeparateAcountApplicable = ConfigurationManager.GetBoolValue("opi", "separateaccount", EnumConfigurationType.Logic);
}
public List<OpiProcessStatus> 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<Employee> Employees
{
get
{
return _employees;
}
}
public string MakeErrorMessage(List<OpiProcessStatus> allerrors)
{
string error = String.Empty;
foreach (OpiProcessStatus item in allerrors)
{
error += item.EmployeeNo + " " + item.Remarks + "\n";
}
return error;
}
//public ObjectsTemplate<OPIProcessDetail> Process(ObjectsTemplate<Employee> employees, DateTime processMonth)
public void Process(ObjectsTemplate<Employee> 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<Employee> 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<OpiProcessStatus>();
_processDetails = new ObjectsTemplate<OPIProcessDetail>();
}
private bool ProcessStartValidation()
{
return false;
}
private void AddEmployeeToProcessDetail()
{
//_processDetails = new ObjectsTemplate<OPIProcessDetail>();
ObjectsTemplate<Branch> 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<EmployeeGradeSalary> 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<EmployeeGradeSalary> 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<OpiParameterIndividual> opiIndividuals = OpiParameterIndividual.Service.Get(
GlobalFunctions.FirstDateOfMonth(_processMonth),
GlobalFunctions.LastDateOfMonth(_processMonth));
OpiParameter paramter = new OpiParameter();
ObjectsTemplate<OpiParameter> parameters;
ObjectsTemplate<ADParameter> adParams = ADParameter.Get(EnumStatus.Active);
ObjectsTemplate<ADParameterEmployee> adParamEmps = ADParameterEmployee.Get(EnumStatus.Active);
ObjectsTemplate<GrossDefination> 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<OpiParameterIndividual> opiIndividuals = OpiParameterIndividual.Service.Get(
GlobalFunctions.FirstDateOfMonth(_processMonth),
GlobalFunctions.LastDateOfMonth(_processMonth));
OpiParameter paramter = new OpiParameter();
ObjectsTemplate<OpiParameter> 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;
}
}
/// <summary>
///
/// </summary>
/// <param name="detail"></param>
/// <param name="gradeSalaries"></param>
/// <param name="parameters"></param>
/// <param name="franctionate"></param>
private void GradeDefinedOpiItem(OPIProcessDetail detail,
ObjectsTemplate<OpiParameter> 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<SalaryMonthly> 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<OpiParameter> parameters, ObjectsTemplate<ADParameter> adParams, ObjectsTemplate<ADParameterEmployee> adParamEmps, ObjectsTemplate<GrossDefination> 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<SalaryMonthly> 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<OpiParameterIndividual> opiIndividuals
, ObjectsTemplate<EmployeeGradeSalary> 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<OpiParameterIndividual> 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<OpiParameterIndividual> opiIndividuals
, ObjectsTemplate<EmployeeGradeSalary> gradeSalaries)
{
// currently we are not provisioning any kind of discontinued employee
// but in future we need this.
double amount = 0;
#region Individual Allowance
List<OpiParameterIndividual> 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
}
}