CEL_Payroll/Payroll.BO/OPI/OPIProcessDetail.cs

821 lines
28 KiB
C#
Raw Permalink 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
{
#region OPIProcessDetail
[Serializable]
public class OPIProcessDetail : BasicBaseObject
{
private ObjectsTemplate<Employee> _employees;
private ObjectsTemplate<OPIProcessDetail> _processDetails;
private ObjectsTemplate<OpiParameter> _opiParameters;
private ObjectsTemplate<OpiItem> _opiItems;
private DataSet _dsOPIRegister;
private ObjectsTemplate<ProcessItem> _processItems;
private List<SalaryProcessStatus> _processStatuses;
public DateTime _processMonth;
public event ProcessStatus ProcessStatus;
public event ProgressStatus ProgressStatus;
#region Cache Store
private static Cache _cache = new Cache(typeof(OPIProcessDetail));
#endregion
#region Constructor
public OPIProcessDetail()
{
_accountNo = string.Empty;
_bankID = null;
_branchID = null;
_categoryID = null;
_departmentID = null;
_designationID = null;
_employeeID = null;
_gender = EnumGender.None;
_gradeID = null;
_isConfirmed = false;
_isFinalize = false;
_locationID = null;
_oPIProcessID = null;
_payrollTypeID = null;
_pfMemberType = EnumPFMembershipType.Live;
_religionID = null;
_remarks = string.Empty;
_oPIProcessDetailItems = null;
_gradeSalaries = null;
_employee = null;
_arreargradeSalaries = null;
_arrearPaidgradeSalaries = null;
}
#endregion
#region Properties
#region AccountNo : string
private string _accountNo;
public string AccountNo
{
get
{
return _accountNo;
}
set
{
base.OnPropertyChange<string>("AccountNo", _accountNo, value);
_accountNo = value;
}
}
#endregion
#region BankID : ID
private ID _bankID;
public ID BankID
{
get
{
return _bankID;
}
set
{
base.OnPropertyChange<ID>("BankID", _bankID, value);
_bankID = value;
}
}
#endregion
#region BranchID : ID
private ID _branchID;
public ID BranchID
{
get
{
return _branchID;
}
set
{
base.OnPropertyChange<ID>("BranchID", _branchID, value);
_branchID = value;
}
}
#endregion
#region CategoryID : ID
private ID _categoryID;
public ID CategoryID
{
get
{
return _categoryID;
}
set
{
base.OnPropertyChange<ID>("CategoryID", _categoryID, value);
_categoryID = value;
}
}
#endregion
#region DepartmentID : ID
private ID _departmentID;
public ID DepartmentID
{
get
{
return _departmentID;
}
set
{
base.OnPropertyChange<ID>("DepartmentID", _departmentID, value);
_departmentID = value;
}
}
#endregion
#region DesignationID : ID
private ID _designationID;
public ID DesignationID
{
get
{
return _designationID;
}
set
{
base.OnPropertyChange<ID>("DesignationID", _designationID, value);
_designationID = value;
}
}
#endregion
#region EmployeeID : ID
private ID _employeeID;
public ID EmployeeID
{
get
{
return _employeeID;
}
set
{
base.OnPropertyChange<ID>("EmployeeID", _employeeID, value);
_employeeID = value;
}
}
#endregion
#region Gender : EnumGender
private EnumGender _gender;
public EnumGender Gender
{
get
{
return _gender;
}
set
{
base.OnPropertyChange<short>("Gender", (short)_gender, (short)value);
_gender = value;
}
}
#endregion
#region GradeID : ID
private ID _gradeID;
public ID GradeID
{
get
{
return _gradeID;
}
set
{
base.OnPropertyChange<ID>("GradeID", _gradeID, value);
_gradeID = value;
}
}
#endregion
#region IsConfirmed : bool
private bool _isConfirmed;
public bool IsConfirmed
{
get
{
return _isConfirmed;
}
set
{
base.OnPropertyChange<bool>("IsConfirmed", _isConfirmed, value);
_isConfirmed = value;
}
}
#endregion
#region IsFinalize : bool
private bool _isFinalize;
public bool IsFinalize
{
get
{
return _isFinalize;
}
set
{
base.OnPropertyChange<bool>("IsFinalize", _isFinalize, value);
_isFinalize = value;
}
}
#endregion
#region LocationID : ID
private ID _locationID;
public ID LocationID
{
get
{
return _locationID;
}
set
{
base.OnPropertyChange<ID>("LocationID", _locationID, value);
_locationID = value;
}
}
#endregion
#region OPIProcessID : ID
private ID _oPIProcessID;
public ID OPIProcessID
{
get
{
return _oPIProcessID;
}
set
{
base.OnPropertyChange<ID>("OPIProcessID", _oPIProcessID, value);
_oPIProcessID = value;
}
}
#endregion
#region PayrollTypeID : ID
private ID _payrollTypeID;
public ID PayrollTypeID
{
get
{
return _payrollTypeID;
}
set
{
base.OnPropertyChange<ID>("PayrollTypeID", _payrollTypeID, value);
_payrollTypeID = value;
}
}
#endregion
#region PFMemberType : EnumPFMembershipType
private EnumPFMembershipType _pfMemberType;
public EnumPFMembershipType PFMemberType
{
get
{
return _pfMemberType;
}
set
{
base.OnPropertyChange<short>("PFMemberType", (short)_pfMemberType, (short)value);
_pfMemberType = value;
}
}
#endregion
#region ReligionID : ID
private ID _religionID;
public ID ReligionID
{
get
{
return _religionID;
}
set
{
base.OnPropertyChange<ID>("ReligionID", _religionID, value);
_religionID = value;
}
}
#endregion
#region Remarks : string
private string _remarks;
public string Remarks
{
get
{
return _remarks;
}
set
{
base.OnPropertyChange<string>("Remarks", _remarks, value);
_remarks = value;
}
}
#endregion
#region OPIProcessDetailItem
private ObjectsTemplate<OPIProcessDetailItem> _oPIProcessDetailItems;
public ObjectsTemplate<OPIProcessDetailItem> OPIProcessDetailItems
{
get
{
//Do not change this property
if (_oPIProcessDetailItems == null )
{
_oPIProcessDetailItems = new ObjectsTemplate<OPIProcessDetailItem>();
}
return this._oPIProcessDetailItems;
}
set
{
_oPIProcessDetailItems = value;
}
}
#endregion
#region Employee : Employee
private Employee _employee;
public Employee Employee
{
get
{
if (_employeeID.Integer > 0 && _employee == null)
{
_employee = new Employee();
_employee = Payroll.BO.Employee.Get(_employeeID);
}
return this._employee;
}
set
{
_employee = value;
}
}
#endregion
#region Grade Salaries : ObjectsTemplate<EmployeeGradeSalary>
private ObjectsTemplate<EmployeeGradeSalary> _gradeSalaries;
public ObjectsTemplate<EmployeeGradeSalary> GradeSalaries
{
get
{
if (_gradeSalaries == null)
{
throw new ServiceException("Grade Salary not yet set");
}
return _gradeSalaries;
}
set
{
_gradeSalaries = value;
}
}
#endregion
#region Arrear Grade Salaries : ObjectsTemplate<EmployeeGradeSalary>
private ObjectsTemplate<EmployeeGradeSalary> _arreargradeSalaries;
public ObjectsTemplate<EmployeeGradeSalary> ArrearGradeSalaries
{
get
{
if (_arreargradeSalaries == null)
{
// throw new ServiceException("Arrear Grade Salary not yet set");
_arreargradeSalaries = new ObjectsTemplate<EmployeeGradeSalary>();
}
return _arreargradeSalaries;
}
set
{
_arreargradeSalaries = value;
}
}
#endregion
#region Arrear Paid Grade Salaries : ObjectsTemplate<EmployeeGradeSalary>
private ObjectsTemplate<EmployeeGradeSalary> _arrearPaidgradeSalaries;
public ObjectsTemplate<EmployeeGradeSalary> ArrearPaidGradeSalaries
{
get
{
if (_arrearPaidgradeSalaries == null)
{
_arrearPaidgradeSalaries = new ObjectsTemplate<EmployeeGradeSalary>();
}
return _arrearPaidgradeSalaries;
}
set
{
_arrearPaidgradeSalaries = value;
}
}
#endregion
#region Service Factory IOPIProcessDetailService : IOPIProcessDetailService
internal static IOPIProcessDetailService Service
{
get
{
return Services.Factory.CreateService<IOPIProcessDetailService>(typeof(IOPIProcessDetailService));
}
}
#endregion
public List<SalaryProcessStatus> Errors
{
get
{
return _processStatuses;
}
}
#endregion
#region Functions
public static OPIProcessDetail Get(ID nOPIProcessDetailID)
{
OPIProcessDetail oOPIProcessDetail = null;
#region Cache Header
oOPIProcessDetail = (OPIProcessDetail)_cache["Get", nOPIProcessDetailID];
if (oOPIProcessDetail != null)
return oOPIProcessDetail;
#endregion
oOPIProcessDetail = OPIProcessDetail.Service.Get(nOPIProcessDetailID);
#region Cache Footer
_cache.Add(oOPIProcessDetail, "Get", nOPIProcessDetailID);
#endregion
return oOPIProcessDetail;
}
public static ObjectsTemplate<OPIProcessDetail> Get()
{
#region Cache Header
ObjectsTemplate<OPIProcessDetail> oOPIProcessDetails = _cache["Get"] as ObjectsTemplate<OPIProcessDetail>;
if (oOPIProcessDetails != null)
return oOPIProcessDetails;
#endregion
try
{
oOPIProcessDetails = Service.Get();
}
catch (ServiceException e)
{
throw new Exception(e.Message, e);
}
#region Cache Footer
_cache.Add(oOPIProcessDetails, "Get");
#endregion
return oOPIProcessDetails;
}
public ID Save()
{
this.SetAuditTrailProperties();
return OPIProcessDetail.Service.Save(this);
}
public void Delete(ID id)
{
OPIProcessDetail.Service.Delete(id);
}
#region ProgressBar
private void UpdateprocessStatus(string statusString)
{
if (ProcessStatus != null) ProcessStatus(statusString);
}
private void UpdateProgressStatus(EnumProcessStatus status)
{
if (ProgressStatus != null) ProgressStatus(status);
}
#endregion
public ObjectsTemplate<OPIProcessDetail> Process(ObjectsTemplate<Employee> employees, DateTime processMonth)
{
//SalaryException oSException = new SalaryException();
_employees = employees;
_processMonth = processMonth;
UpdateprocessStatus("Collecting Employee basic information....");
//this.Initialize();
this.AddEmployeeToProcessDetail();
//if (_processStatuses.Count > 0) return;
UpdateprocessStatus("Calculating Employee basic Salary....");
this.BasicSalary();
UpdateprocessStatus("Calculating Employees benifits and deduction....");
this.OPIItems();
//this.LeavePrepare(oSException.GetEmpLeaveStatus());
return _processDetails;
}
private void AddEmployeeToProcessDetail()
{
_processDetails = new ObjectsTemplate<OPIProcessDetail>();
UpdateProgressStatus(EnumProcessStatus.Start);
foreach (Employee employee in _employees)
{
UpdateProgressStatus(EnumProcessStatus.PerformStep);
GlobalFunctions.UpdateStatus(" 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;
procDetail.ReligionID = employee.ReligionID;
procDetail.GradeID = employee.GradeID;
procDetail.DepartmentID = employee.DepartmentID;
procDetail.DesignationID = employee.DesignationID;
procDetail.LocationID = employee.LocationID;
if (employee.PaymentMode == EnumPaymentMode.BankTransfer)
{
procDetail.BranchID = employee.BranchID;
Branch branch = new Branch();
branch = Branch.Get(employee.BranchID);
procDetail.BankID = branch.BankID;
procDetail.AccountNo = employee.AccountNo;
}
else
{
procDetail.BranchID = ID.FromInteger(0);
procDetail.BankID = ID.FromInteger(0);
}
procDetail.Employee = employee;
_processDetails.Add(procDetail);
}
UpdateProgressStatus(EnumProcessStatus.End);
}
private void AddProcessStatus(Employee employee, string remarks)
{
SalaryProcessStatus status = new SalaryProcessStatus();
status.EmployeeNo = employee.EmployeeNo;
status.Name = employee.Name;
status.Remarks = remarks;
_processStatuses.Add(status);
}
private void BasicSalary()
{
//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 )
{
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);
if (opiProcess.ArrearGradeSalaries.Count > 0)
{
DateTime arrearPaidFrom = opiProcess.ArrearGradeSalaries[0].EffectDate;
opiProcess.ArrearPaidGradeSalaries = EmployeeGradeSalary.Service.GetArrearPaidItems(opiProcess.EmployeeID, arrearPaidFrom);
}
}
#endregion calculate arrear amount
}
private void OPIItems()
{
_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> paramters;
foreach (OPIProcessDetail detail in _processDetails)
{
// Regular Grade defined parameters
paramters = paramter.ApplicableParameters(detail.Employee,
detail, _opiParameters, detail.GradeSalaries);
this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);
// Arrear Grade defined parameters
paramters = paramter.ApplicableParameters(detail.Employee,
detail, _opiParameters, detail.ArrearGradeSalaries);
this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);
// Arrear already paid parameters
paramters = paramter.ApplicableParameters(detail.Employee,
detail, _opiParameters, detail.ArrearPaidGradeSalaries);
this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);
//this.IndividualOpiItem(detail, opiIndividuals);
}
}
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 = existItem.NetAmount + item.NetAmount;
existItem.ChangeNetAmount = existItem.ChangeNetAmount + item.ChangeNetAmount;
existItem.Description = item.Description;
}
}
private void GradeDefinedOpiItem(OPIProcessDetail detail, ObjectsTemplate<EmployeeGradeSalary> gradeSalaries,
ObjectsTemplate<OpiParameter> paramters)
{
double amount = 0, totalAmount = 0, paidAmount = 0, remainingAmount, indvAmnt = 0, fractionAmount = 0;
int totalMonth = 12, paidMonth = 0, remainingMonth = 0;
//int randomEmployee = (new Random()).Next(1, _employees.Count);
int empNumber = 1;
foreach (EmployeeGradeSalary empGradeSalary in gradeSalaries)
{
foreach (OpiParameter parameter in paramters)
{
if (parameter.EntitleType == EnumEntitleType.Grade)
{
//amount = parameter.GetGradeDefinedAmount(detail.Employee, empGradeSalary.BasicSalary, empGradeSalary.GrossSalary);
if (parameter.IsFlatAmount == true) amount = amount * empGradeSalary.FractionofFromTo;
}
else continue;
OPIProcessDetailItem opdItem = new OPIProcessDetailItem();
switch (parameter.OpiPeriodicity)
{
case EnumOpiPeriodicity.Monthly:
opdItem.NetAmount = amount;
opdItem.ChangeNetAmount = amount;
//opdItem.TaxAmount =
break;
case EnumOpiPeriodicity.OnceOff:
opdItem.NetAmount = amount;
opdItem.ChangeNetAmount = amount;
//opdItem.TaxAmount =
break;
case EnumOpiPeriodicity.Annual:
paidMonth = Convert.ToInt32(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.Date.Month);
remainingMonth = totalMonth - (paidMonth);
totalAmount = amount * totalMonth;
paidAmount = paidMonth * amount;
remainingAmount = totalAmount - paidAmount;
opdItem.NetAmount = remainingAmount / remainingMonth;
opdItem.ChangeNetAmount = remainingAmount / remainingMonth;
//opdItem.TaxAmount =
break;
//case EnumOpiPeriodicity.AveragePayment:
// break;
//case EnumOpiPeriodicity.OnAmount:
// indvAmnt = amount / _processDetails.Count;
// fractionAmount = (indvAmnt - Math.Round(indvAmnt, 0)) * _processDetails.Count;
// if (empNumber == gradeSalaries.Count)
// {
// opdItem.NetAmount = Math.Round(indvAmnt, 0) + fractionAmount;
// opdItem.ChangeNetAmount = Math.Round(indvAmnt, 0) + fractionAmount;
// }
// else
// {
// opdItem.NetAmount = Math.Round(indvAmnt, 0);
// opdItem.ChangeNetAmount = Math.Round(indvAmnt, 0);
// }
// //opdItem.TaxAmount =
// break;
default:
break;
}
opdItem.Description = parameter.OpiItem.Name;
opdItem.OPIItemID = parameter.OpiItemID;
opdItem.OPIProcessDetailID = this.ID;
opdItem.OPIType = parameter.OpiItem.OpiType;
_opiItems = OpiItem.Get();
if (_opiItems != null && _opiItems.Count > 0)
opdItem.Sequence = _opiItems.GetItem(parameter.OpiItem.ID).Sequence;
this.Add(detail, opdItem); // add the item in the collection
}
empNumber++;
}
}
private void IndividualOpiItem(OPIProcessDetail detail, ObjectsTemplate<OpiParameterIndividual> opiIndividuals)
{
//double amount = 0;
//EnumSalaryGroup groupCode = EnumSalaryGroup.Gross;
//#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.GrossSalary, detail.GetGrossAmount(EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary));
// EnumSalaryItemCode itemCode = EnumSalaryItemCode.Allowance;
// groupCode = EnumSalaryGroup.Gross;
// if (parameter.AllowOrDeductType == EnumAllowOrDeduct.Deduction)
// {
// itemCode = EnumSalaryItemCode.Deduction;
// groupCode = EnumSalaryGroup.Deductions;
// }
// if (item.Arreartype == EnumArrearType.ToCalculate) groupCode = EnumSalaryGroup.Arrear;
// SalaryMonthlyDetail detail = salary.GetDetail(groupCode, itemCode, parameter.AllowDeductID.Integer);
// if (detail == null)
// detail = this.AddDetail(salary, groupCode, itemCode, parameter.AllowDeductID.Integer, parameter.ID.Integer, parameter.AllowanceDeduction.Name, amount);
// else
// {
// detail.CalculatedAmount = detail.CalculatedAmount + amount;
// detail.CalculatedAmount = GlobalFunctions.Round(detail.CalculatedAmount);
// detail.ChangedAmount = detail.CalculatedAmount;
// }
// detail.Position = item.AllowDeduct.Sequence + 1;
//}
//#endregion Individual Allowance
}
#endregion
public static ObjectsTemplate<OPIProcessDetail> GetDetail(DateTime _SalaryMonth)
{
#region Cache Header
ObjectsTemplate<OPIProcessDetail> oOPIProcessDetails = _cache["Get"] as ObjectsTemplate<OPIProcessDetail>;
if (oOPIProcessDetails != null)
return oOPIProcessDetails;
#endregion
try
{
oOPIProcessDetails = Service.Get(_SalaryMonth);
}
catch (ServiceException e)
{
throw new Exception(e.Message, e);
}
#region Cache Footer
_cache.Add(oOPIProcessDetails, "Get");
#endregion
return oOPIProcessDetails;
}
}
#endregion
#region IOPIProcessDetail Service
public interface IOPIProcessDetailService
{
OPIProcessDetail Get(ID id);
ObjectsTemplate<OPIProcessDetail> Get();
ID Save(OPIProcessDetail item);
void Save(OPIProcess oProcess, ObjectsTemplate<OPIProcessDetail> oPDetails);
void Delete(ID id);
ObjectsTemplate<OPIProcessDetail> Get(DateTime _SalaryMonth);
}
#endregion
}