645 lines
23 KiB
C#
645 lines
23 KiB
C#
using System;
|
|
using System.Data;
|
|
using Ease.Core.Model;
|
|
using Ease.Core.DataAccess;
|
|
using Ease.Core;
|
|
using System.Collections.Generic;
|
|
using Ease.Core.Utility;
|
|
using System.Configuration;
|
|
using System.Data.SqlClient;
|
|
using HRM.BO;
|
|
using System.Linq;
|
|
|
|
namespace HRM.DA
|
|
{
|
|
#region FSTran Service
|
|
|
|
public class FSTranService : ServiceTemplate, IFSTranService
|
|
{
|
|
#region Private functions and declaration
|
|
|
|
#endregion
|
|
|
|
public FSTranService()
|
|
{
|
|
}
|
|
|
|
private void MapObject(FSTran oFSTran, DataReader oReader)
|
|
{
|
|
base.SetObjectID(oFSTran, (oReader.GetInt32("FSTranID").Value));
|
|
oFSTran.ChangeTaxAmount = oReader.GetDouble("ChangeTaxAmount").Value;
|
|
oFSTran.EmployeeID = oReader.GetInt32("EmployeeID").Value;
|
|
oFSTran.LastSalaryPaidMonth = oReader.GetDateTime("LastSalaryPaidMonth");
|
|
oFSTran.NetAmount = oReader.GetDouble("NetAmount").Value;
|
|
oFSTran.NoticeDate = oReader.GetDateTime("NoticeDate",DateTime.MinValue);
|
|
oFSTran.Remarks = oReader.GetString("Remarks");
|
|
oFSTran.SettlementDate = oReader.GetDateTime("SettlementDate").Value;
|
|
oFSTran.TaxAmount = oReader.GetDouble("TaxAmount").Value;
|
|
oFSTran.ChangeTaxAmount = oReader.GetDouble("ChangeTaxAmount").Value;
|
|
oFSTran.CreatedBy = oReader.GetInt32("CreatedBy").Value;
|
|
oFSTran.CreatedDate = oReader.GetDateTime("CREATIONDATE").HasValue
|
|
? oReader.GetDateTime("CREATIONDATE").Value
|
|
: DateTime.MinValue;
|
|
oFSTran.ModifiedBy = oReader.GetInt32("ModifiedBy");
|
|
oFSTran.ModifiedDate = oReader.GetDateTime("ModifiedDate").HasValue
|
|
? oReader.GetDateTime("ModifiedDate").Value
|
|
: (DateTime?)null;
|
|
oFSTran.ShortNoticePeriod = oReader.GetInt32("ShortNoticePeriod").Value;
|
|
oFSTran.DiscontinueDate = oReader.GetDateTime("DiscontinueDate").Value;
|
|
oFSTran.EmployeeNo = oReader.GetString("EmployeeNo", true, string.Empty);
|
|
oFSTran.EmployeeName = oReader.GetString("EmployeeName", true, string.Empty);
|
|
|
|
this.SetObjectState(oFSTran, Ease.Core.ObjectState.Saved);
|
|
}
|
|
|
|
protected override T CreateObject<T>(DataReader oReader)
|
|
{
|
|
FSTran oFSTran = new FSTran();
|
|
MapObject(oFSTran, oReader);
|
|
return oFSTran as T;
|
|
}
|
|
|
|
protected FSTran CreateObject(DataReader oReader)
|
|
{
|
|
FSTran oFSTran = new FSTran();
|
|
MapObject(oFSTran, oReader);
|
|
return oFSTran;
|
|
}
|
|
|
|
#region Service implementation
|
|
|
|
public FSTran Get(int id)
|
|
{
|
|
FSTran oFSTran = new FSTran();
|
|
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
DataReader oreader = new DataReader(FSTranDA.Get(tc, id));
|
|
if (oreader.Read())
|
|
{
|
|
oFSTran = this.CreateObject<FSTran>(oreader);
|
|
}
|
|
|
|
oreader.Close();
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
return oFSTran;
|
|
}
|
|
|
|
|
|
public List<IncomeTax> CalculateTax(FSTran otran, int userID, int payrolltypeid)
|
|
{
|
|
try
|
|
{
|
|
Employee oEmp = new EmployeeService().Get(otran.EmployeeID);
|
|
if (oEmp != null )
|
|
{
|
|
double TaxAmount = 0.0;
|
|
List<IncomeTax> oincomeTaxes = new List<IncomeTax>();
|
|
List<ADParameter> oADParameters = new List<ADParameter>();
|
|
List<ADParameter> oADDeductParameters = new List<ADParameter>();
|
|
List<ADParameter> oADEmpParameters = new List<ADParameter>();
|
|
List<ADParameterEmployee> adParamEmps = new List<ADParameterEmployee>();
|
|
oADParameters = new ADParameterService().Get((int) oEmp.GradeID, EnumEntitleType.Grade, EnumAllowOrDeduct.Allowance, oEmp.PayrollTypeID);
|
|
oADDeductParameters = new ADParameterService().Get((int)oEmp.GradeID, EnumEntitleType.Grade, EnumAllowOrDeduct.Deduction, oEmp.PayrollTypeID);
|
|
adParamEmps = new ADParameterEmployeeService().GetByEmployee(oEmp.ID, EnumAllowOrDeduct.Allowance, EnumADEmpType.AppliedToIndividual);
|
|
foreach (ADParameterEmployee oADEmp in adParamEmps)
|
|
{
|
|
ADParameter oa = new ADParameter();
|
|
oa = new ADParameterService().Get(oADEmp.ADParameterID, payrolltypeid);
|
|
oADEmpParameters.Add(oa);
|
|
}
|
|
foreach (ADParameter oAD in oADDeductParameters)
|
|
oADParameters.Add(oAD);
|
|
foreach (ADParameter oAD in oADEmpParameters)
|
|
oADParameters.Add(oAD);
|
|
List<TaxRawItem> otaxRawItems = new List<TaxRawItem>();
|
|
enumIncomeTaxItemType eTaxItemType = enumIncomeTaxItemType.None;
|
|
int nTaxItemID = 0;
|
|
TaxRawItem taxRawItem;
|
|
foreach (FSTranDetail od in otran.Details)
|
|
{
|
|
if (od.ItemCode == EnumFSItemCode.Provision)
|
|
continue;
|
|
if (od.AmountType == EnumValueType.Amount)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.None;
|
|
if (od.ItemCode == EnumFSItemCode.Gratuity || od.ItemCode == EnumFSItemCode.Loan)
|
|
continue;
|
|
if (od.ItemCode == EnumFSItemCode.Leave)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Earned_Leave;
|
|
nTaxItemID = (int)EnumIncomeTaxItemGroup.Earned_Leave;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.PF || od.ItemCode == EnumFSItemCode.CPF)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.PF;
|
|
nTaxItemID = (int)EnumIncomeTaxItemGroup.Company_Contri_PF;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.Gross && od.Description == "Basic")
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Basic_Salary;
|
|
nTaxItemID = (int)EnumIncomeTaxItemGroup.Basic_Salary;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.Gross && od.Side == EnumSide.Add)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Allowance;
|
|
nTaxItemID = (int) od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.Gross && od.Side == EnumSide.Deduct)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Deduction;
|
|
nTaxItemID = (int)od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.FractionateSalary && od.Description == "Basic")
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Basic_Salary;
|
|
nTaxItemID = (int)EnumIncomeTaxItemGroup.Basic_Salary;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.FractionateSalary && od.Side == EnumSide.Add)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Allowance;
|
|
nTaxItemID = (int) od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.FractionateSalary && od.Side == EnumSide.Deduct)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Deduction;
|
|
nTaxItemID = (int) od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.Bonus)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.Bonus;
|
|
nTaxItemID =(int) od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.OT)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.OT;
|
|
nTaxItemID =(int) od.ItemID;
|
|
}
|
|
else if (od.ItemCode == EnumFSItemCode.Other)
|
|
{
|
|
eTaxItemType = enumIncomeTaxItemType.FinalSettlement;
|
|
nTaxItemID =(int) od.ItemID;
|
|
}
|
|
ADParameter oADParameter = new ADParameter();
|
|
|
|
oADParameter = oADParameters.Find(delegate (ADParameter t) { return t.AllowDeductID == od.ItemID; });
|
|
|
|
//if (oADParameter == null)
|
|
//continue;
|
|
if (oADParameter != null)
|
|
{
|
|
if (oADParameter.IsTaxable == true)
|
|
{
|
|
taxRawItem = new TaxRawItem();
|
|
taxRawItem = TaxRawItem.Create(od.Description, od.ChangedValue, eTaxItemType, nTaxItemID);
|
|
|
|
otaxRawItems.Add(taxRawItem);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (od.Description == "Basic")
|
|
{
|
|
taxRawItem = new TaxRawItem();
|
|
taxRawItem = TaxRawItem.Create(od.Description, od.ChangedValue, eTaxItemType, nTaxItemID);
|
|
|
|
otaxRawItems.Add(taxRawItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
PayrollType otype = new PayrollTypeService().Get(payrolltypeid);
|
|
TaxCalculator otaxCal = new TaxCalculator((int)otype.TaxParamID, payrolltypeid);
|
|
|
|
otaxCal.TaxParameter = new TaxParameterService().Get((int)otype.TaxParamID);
|
|
otaxCal.Employee = oEmp;
|
|
oincomeTaxes = otaxCal.CalculateSettlementTax(otaxRawItems);
|
|
otran.IncomeTaxcoll = oincomeTaxes;
|
|
}
|
|
}
|
|
catch (Exception exp)
|
|
{
|
|
throw new Exception(exp.Message);
|
|
}
|
|
|
|
return otran.IncomeTaxcoll;
|
|
}
|
|
|
|
public FSTran GetByEmpdId(int nEmpID)
|
|
{
|
|
FSTran oFSTran = null;
|
|
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
DataReader oreader = new DataReader(FSTranDA.GetByEmpdId(tc, nEmpID));
|
|
if (oreader.Read())
|
|
{
|
|
oFSTran = new FSTran();
|
|
oFSTran = this.CreateObject<FSTran>(oreader);
|
|
}
|
|
oreader.Close();
|
|
if (oFSTran != null)
|
|
{
|
|
oFSTran.Details = new FSTranDetailService().GetDetail(tc, oFSTran.ID);
|
|
}
|
|
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
return oFSTran;
|
|
}
|
|
|
|
public List<FSTran> Get()
|
|
{
|
|
List<FSTran> FSTrans = new List<FSTran>();
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
DataReader dr = new DataReader(FSTranDA.Get(tc));
|
|
FSTrans = this.CreateObjects<FSTran>(dr);
|
|
dr.Close();
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
return FSTrans;
|
|
}
|
|
|
|
public List<FSTran> Get(EnumStatus status)
|
|
{
|
|
List<FSTran> FSTrans = new List<FSTran>();
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
|
|
DataReader dr = new DataReader(FSTranDA.Get(tc, status));
|
|
FSTrans = this.CreateObjects<FSTran>(dr);
|
|
dr.Close();
|
|
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
return FSTrans;
|
|
}
|
|
|
|
public List<FSTran> Get(string sEmpIDs)
|
|
{
|
|
List<FSTran> FSTrans = new List<FSTran>();
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
|
|
DataReader dr = new DataReader(FSTranDA.Get(tc, sEmpIDs));
|
|
FSTrans = this.CreateObjects<FSTran>(dr);
|
|
dr.Close();
|
|
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
|
|
return FSTrans;
|
|
}
|
|
|
|
public List<FSTran> Get(DateTime dFromDate, DateTime dToDate, bool withDetail)
|
|
{
|
|
List<FSTran> FSTrans = new List<FSTran>();
|
|
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
|
|
DataReader dr = new DataReader(FSTranDA.Get(tc, dFromDate, dToDate));
|
|
FSTrans = this.CreateObjects<FSTran>(dr);
|
|
dr.Close();
|
|
|
|
if(withDetail ==true && FSTrans != null)
|
|
{
|
|
List<FSTranDetail> items = new FSTranDetailService().GetDetail(tc, dFromDate, dToDate);
|
|
if(items != null)
|
|
{
|
|
foreach(FSTran item in FSTrans)
|
|
{
|
|
item.Details = items.FindAll(x => x.TranID == item.ID);
|
|
}
|
|
}
|
|
}
|
|
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
|
|
return FSTrans;
|
|
}
|
|
|
|
public List<FSTran> GetByEmpIdForRegEmployee(int empid)
|
|
{
|
|
List<FSTran> FSTrans = new List<FSTran>();
|
|
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
|
|
DataReader dr = new DataReader(FSTranDA.GetByEmpIdForRegEmployee(tc, empid));
|
|
FSTrans = this.CreateObjects<FSTran>(dr);
|
|
dr.Close();
|
|
|
|
if (FSTrans != null)
|
|
{
|
|
List<FSTranDetail> items = new FSTranDetailService().GetDetail(tc, empid);
|
|
if (items != null)
|
|
{
|
|
foreach (FSTran item in FSTrans)
|
|
{
|
|
item.Details = items.FindAll(x => x.TranID == item.ID);
|
|
}
|
|
}
|
|
}
|
|
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
|
|
return FSTrans;
|
|
}
|
|
|
|
|
|
|
|
public DataSet GetEmpPaymentAdvice(int settlementAdviceId)
|
|
{
|
|
DataSet oSalaryMonthlys = new DataSet();
|
|
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin();
|
|
oSalaryMonthlys = FSTranDA.GetEmpPaymentAdvice(tc,settlementAdviceId);
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
|
|
return oSalaryMonthlys;
|
|
}
|
|
|
|
public double GetPFAmount(string sEmployeeNo)
|
|
{
|
|
double amount = 0;
|
|
//####
|
|
//string sConnectionString = ConfigurationSettings.AppSettings["PRconn"];
|
|
//if (sConnectionString.Contains("password"))
|
|
//{
|
|
// int nIndex = sConnectionString.IndexOf("password");
|
|
// string sPassString = sConnectionString.Substring(nIndex, sConnectionString.Length - nIndex);
|
|
// sConnectionString = sConnectionString.Remove(nIndex);
|
|
// nIndex = sPassString.IndexOf("=");
|
|
// string sEncryptedPassword = sPassString.Substring(nIndex + 1, sPassString.Length - nIndex - 1);
|
|
// string sDecryptedPassword = Ease.Core.Utility.Global.CipherFunctions.Decrypt("Cel.Admin", sEncryptedPassword);
|
|
// sConnectionString += "Password=" + sDecryptedPassword;
|
|
//}
|
|
//SqlConnection connection = new SqlConnection(sConnectionString);
|
|
|
|
|
|
//try
|
|
//{
|
|
// connection.Open();
|
|
// amount = FSTranDA.GetPFAmount(connection, sEmployeeNo);
|
|
// connection.Close();
|
|
//}
|
|
//catch (Exception e)
|
|
//{
|
|
// #region Handle Exception
|
|
// throw new ServiceException(e.Message, e);
|
|
// #endregion
|
|
//}
|
|
|
|
return amount;
|
|
}
|
|
|
|
public int Save(FSTran oFSTran)
|
|
{
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin(true);
|
|
//if (oFSTran.IsNew)
|
|
// {
|
|
|
|
if (oFSTran.IsNew)
|
|
{
|
|
int id = tc.GenerateID("FSTran", "FSTranID");
|
|
base.SetObjectID(oFSTran, (id));
|
|
FSTranDA.Insert(tc, oFSTran);
|
|
}
|
|
else
|
|
{
|
|
FSTranDA.Update(tc, oFSTran);
|
|
FSTranDetailDA.Delete(tc, oFSTran.ID);
|
|
|
|
}
|
|
FSTranDetailService fDeailService = new FSTranDetailService();
|
|
foreach (FSTranDetail oItem in oFSTran.Details)
|
|
{
|
|
oItem.TranID = oFSTran.ID;
|
|
//oItem.CreatedBy = oFSTran.CreatedBy;
|
|
//oItem.CreatedDate = oFSTran.CreatedDate;
|
|
//oItem.ModifiedBy = oFSTran.ModifiedBy;
|
|
//oItem.ModifiedDate = oFSTran.ModifiedDate;
|
|
fDeailService.Save(tc, oItem);
|
|
}
|
|
|
|
IncomeTaxService osvr = new IncomeTaxService();
|
|
if (oFSTran.IncomeTaxcoll != null && oFSTran.IncomeTaxcoll.Count > 0)
|
|
osvr.Save(tc, oFSTran.IncomeTaxcoll, EnumIncomeTaxDataFrom.ProcessTempData);
|
|
|
|
|
|
//}
|
|
//else
|
|
//{
|
|
// FSTranDA.Update(tc, oFSTran);
|
|
//}
|
|
if (oFSTran.ResignationReqId > 0 )
|
|
{
|
|
EmpResignationRequest orc = new ResignationRequestService().Get(tc, oFSTran.ResignationReqId);
|
|
if (orc.WFStatus == EnumResignStatus.Clearance_initiated)
|
|
{
|
|
if (oFSTran.IsSubmit == true && oFSTran.EssEntryEmpID != null)
|
|
{
|
|
SettlementClearanceDA.UpdateSettlementClearance(tc, (int)oFSTran.EssEntryEmpID, oFSTran.ResignationReqId);
|
|
}
|
|
|
|
var tempSc = new SettlementClearanceService().GetByResignationRequestId(tc, oFSTran.ResignationReqId);
|
|
if (tempSc != null)
|
|
{
|
|
var isAnyNotCompleted = tempSc.Where(x => x.ResignationRequestID == oFSTran.ResignationReqId
|
|
&& x.SettlementClearanceStatus != EnumSettlementClearanceStatus.Completed).Any();
|
|
if (isAnyNotCompleted == false)
|
|
{
|
|
ResignationRequestDA.UpdateResignationRequestResignStatus(tc, oFSTran.ResignationReqId, EnumResignStatus.Clearance_Done);
|
|
}
|
|
}
|
|
}
|
|
else if(orc.WFStatus == EnumResignStatus.Clearance_Done )
|
|
{
|
|
if(oFSTran.IsSubmit ==true) // forward to next phase
|
|
{
|
|
ResignationRequestDA.UpdateResignationRequestResignStatus(tc, oFSTran.ResignationReqId, EnumResignStatus.Calculation_Done);
|
|
}
|
|
}
|
|
|
|
}
|
|
tc.End();
|
|
|
|
return oFSTran.ID;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|
|
|
|
public void Delete(int id)
|
|
{
|
|
TransactionContext tc = null;
|
|
try
|
|
{
|
|
tc = TransactionContext.Begin(true);
|
|
FSTranDetail oItem = new FSTranDetail();
|
|
FSTranDA.Delete(tc, id);
|
|
tc.End();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
#region Handle Exception
|
|
|
|
if (tc != null)
|
|
tc.HandleError();
|
|
ExceptionLog.Write(e);
|
|
throw new ServiceException(e.Message, e);
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public FSTran GetWithEmpID(int nEmpID)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
}
|
|
|
|
#endregion
|
|
} |