Files
sryang 577060bc78 chore: 首次簽入 Thinkyu ASP.NET 專案
- 加入 Visual Studio / ASP.NET .gitignore
- 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
2026-09-10 09:42:37 +08:00

457 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Wellan.Common;
using Wellan.Data;
/// <summary>
/// 計算勞保費
/// </summary>
public class Blif : LaborAndHealthFee
{
private int _inWorkDays;
private int _insuranceSalary;
private int _injurySalary;
private decimal _normalPersonalFee;
private decimal _normalCompanyFee;
private decimal _lostJobPersonalFee;
private decimal _lostJobCompanyFee;
private decimal _injuryCompanyFee;
private decimal _disableNormalSupport;
private decimal _disableLostJobSupport;
private decimal _salaryReverseFund;
private double _normalFeeRate;
private double _lostJobFeeRate;
private double _salaryReverseFundRate;
private double _injuryCompanyFeeRate;
// 職災級距表
private Dictionary<DateTime, List<LHFClass>> _bljiAmtData;
public Blif(DateTime aDate) : base(aDate)
{
_bftyp = 1;
_tableName = "BLIF";
}
/// <summary>
/// 普通事故費率
/// </summary>
public double NormalFeeRate
{
get
{
return _normalFeeRate;
}
set
{
_normalFeeRate = value;
}
}
/// <summary>
/// 就業保險費率
/// </summary>
public double LostJobFeeRate
{
get
{
return _lostJobFeeRate;
}
set
{
_lostJobFeeRate = value;
}
}
/// <summary>
/// 工資墊償基金費率
/// </summary>
public double SalaryReverseFundRate
{
get
{
return _salaryReverseFundRate;
}
set
{
_salaryReverseFundRate = value;
}
}
/// <summary>
/// 職災保險費率
/// </summary>
public double InjuryFeeRate
{
get
{
return _injuryCompanyFeeRate;
}
set
{
_injuryCompanyFeeRate = value;
}
}
public LaborInsuranceFee GetFee()
{
LaborInsuranceFee fee = new LaborInsuranceFee();
fee.Init();
fee.InWorkDays = _inWorkDays;
fee.InsuranceSalary = _insuranceSalary;
fee.InjurySalary = _injurySalary;
fee.NormalPersonalFee = _normalPersonalFee;
fee.NormalCompanyFee = _normalCompanyFee;
fee.LostJobPersonalFee = _lostJobPersonalFee;
fee.LostJobCompanyFee = _lostJobCompanyFee;
fee.InjuryCompanyFee = _injuryCompanyFee;
fee.DisableNormalSupport = _disableNormalSupport;
fee.DisableLostJobSupport = _disableLostJobSupport;
fee.SalaryReverseFund = _salaryReverseFund;
return fee;
}
public void Clear()
{
_inWorkDays = 0;
_insuranceSalary = 0;
_injurySalary = 0;
_normalPersonalFee = 0;
_normalCompanyFee = 0;
_lostJobPersonalFee = 0;
_lostJobCompanyFee = 0;
_injuryCompanyFee = 0;
_disableNormalSupport = 0;
_disableLostJobSupport = 0;
_salaryReverseFund = 0;
}
/// <summary>
/// 取得職災級距表
/// </summary>
/// <param name="aDate">日期</param>
private void GetBLJIData(DateTime aDate)
{
if (this._bljiAmtData == null)
_bljiAmtData = new Dictionary<DateTime, List<LHFClass>>();
if (!_bljiAmtData.ContainsKey(aDate))
{
List<LHFClass> _newAmtDataItem = new List<LHFClass>();
// 取得適用級距表版本
DataTable _verData = _query.Select("SELECT * FROM BFDT WHERE BFTYP=4 ORDER BY BFVER");
int version = 0;
foreach (System.Data.DataRow row in _verData.Rows)
{
if (aDate.CompareTo(row["BFSDT"]) >= 0 && (row["BFEDT"] == DBNull.Value || aDate.CompareTo(row["BFEDT"]) <= 0))
{
version = Convert.ToInt32(row["BFVER"]);
break;
}
}
// 取得該版本的級距表
DataTable data = _query.Select(String.Format("SELECT * FROM BLJI WHERE BSVER={0} ORDER BY BSLVL", version));
for (int i = 0; i < data.Rows.Count; i++)
{
_newAmtDataItem.Add(new LHFClass(Convert.ToInt32(data.Rows[i]["BSLOW"]),
Convert.ToInt32(data.Rows[i]["BSHIH"]),
Convert.ToInt32(data.Rows[i]["BSAMT"])));
}
_bljiAmtData.Add(aDate, _newAmtDataItem);
}
}
/// <summary>
/// 取得職災保險投保薪資
/// </summary>
/// <param name="aDate">日期</param>
/// <param name="salary">薪資</param>
/// <returns></returns>
protected double GetBLJIAmt(DateTime aDate, int salary)
{
GetBLJIData(aDate);
double bsamt = 0;
for (int i = 0; i < _amtData[aDate].Count; i++)
{
if (salary >= _amtData[aDate][i].Low && salary <= _amtData[aDate][i].High)
{
bsamt = _amtData[aDate][i].Amt;
break;
}
}
return bsamt;
}
/// <summary>
/// 取得職災保險投保薪資
/// </summary>
/// <param name="salary">薪資</param>
/// <returns></returns>
protected double GetBLJIAmt(int salary)
{
return GetBLJIAmt(_baseDate, salary);
}
/// <summary>
/// 計算並加入一段時間段的勞保費
/// </summary>
/// <param name="salary">投保薪資</param>
/// <param name="startDay">時間段起日</param>
/// <param name="endDay">時間段迄日</param>
/// <param name="goOut">退保</param>
/// <param name="disable">身障補助</param>
/// <param name="hasLIF">有勞保</param>
/// <param name="retired">已領老年給付</param>
/// <param name="over65">超過65歲</param>
/// <param name="employeeType">員工類型</param>
/// <param name="nation">員工國籍 1=本國籍 2=外國籍</param>
/// <param name="thisMonthLaborDays">本段時間勞保出席天數</param>
public void Add(int salary, DateTime startDay, DateTime endDay, bool goOut, string disable,
bool hasLIF, bool retired, bool over65, string employeeType, string nation,
ref int thisMonthLaborDays)
{
// 無勞保,不處理
if (!hasLIF)
return;
// 勞保、勞退計算基準
double bsamt = GetAmont(salary);
double daysRatio = 0;
int days = 0;
int monthEndDay = startDay.AddMonths(1).AddDays(-startDay.Day).Day;
_insuranceSalary = Convert.ToInt32(bsamt);
if (bsamt > 0)
{
// 整月
if (startDay.Day == 1 && endDay.Day == monthEndDay)
{
days = 30;
// 若二月,且退保,要算至月底的實際天數
if (goOut && endDay.Month == 2)
days = monthEndDay;
}
// 非整月
else
{
// 結束日是月底日
if (endDay.Day == monthEndDay)
{
if (startDay.Day == 30 || startDay.Day == 31)
days = 1;
else
days = 30 - startDay.Day + 1;
// 若二月,且退保,要算至月底的實際天數
if (goOut && endDay.Month == 2)
{
days -= (30 - monthEndDay);
}
}
else
// 結束日非月底日
{
days = endDay.Day - startDay.Day + 1;
}
if (days > 30 - thisMonthLaborDays)
days = 30 - thisMonthLaborDays;
}
_inWorkDays += days;
thisMonthLaborDays += days;
daysRatio = Convert.ToDouble(days) / 30d;
decimal _thisNormalPersonalFee = 0;
decimal _thisNormalCompanyFee = 0;
decimal _thisLostJobPersonalFee = 0;
decimal _thisLostJobCompanyFee = 0;
if (!retired)
{
// 員工身份是雇主:
if (employeeType == "1")
{
// 計算普通事故保費
_thisNormalPersonalFee = Convert.ToDecimal(Math.Round(bsamt * _normalFeeRate * daysRatio * 0.2d, 4, MidpointRounding.AwayFromZero));
_thisNormalCompanyFee = Convert.ToDecimal(Math.Round(bsamt * _normalFeeRate * daysRatio * 0.7d, 4, MidpointRounding.AwayFromZero));
// 計算就業保險保費
_thisLostJobPersonalFee = 0;
_thisLostJobCompanyFee = 0;
}
// 員工身份是一般勞工:
else
{
// 計算普通事故保費
_thisNormalPersonalFee = Convert.ToDecimal(Math.Round(bsamt * _normalFeeRate * daysRatio * 0.2d, 4, MidpointRounding.AwayFromZero));
_thisNormalCompanyFee = Convert.ToDecimal(Math.Round(bsamt * _normalFeeRate * daysRatio * 0.7d, 4, MidpointRounding.AwayFromZero));
// 計算就業保險保費,本國籍員工,未滿65歲才需要
if (nation == "1" && !over65)
{
_thisLostJobPersonalFee = Convert.ToDecimal(Math.Round(bsamt * _lostJobFeeRate * daysRatio * 0.2d, 4, MidpointRounding.AwayFromZero));
_thisLostJobCompanyFee = Convert.ToDecimal(Math.Round(bsamt * _lostJobFeeRate * daysRatio * 0.7d, 4, MidpointRounding.AwayFromZero));
}
}
}
_normalPersonalFee += _thisNormalPersonalFee;
_normalCompanyFee += _thisNormalCompanyFee;
_lostJobPersonalFee += _thisLostJobPersonalFee;
_lostJobCompanyFee += _thisLostJobCompanyFee;
// 計算身心障礙補助
switch (disable)
{
case "0": // 無
break;
case "1": // 輕度
_disableNormalSupport = Math.Round((_thisNormalPersonalFee) * 0.25m, MidpointRounding.AwayFromZero);
_disableLostJobSupport = Math.Round((_thisLostJobPersonalFee) * 0.25m, MidpointRounding.AwayFromZero);
break;
case "2": // 中度
_disableNormalSupport = Math.Round((_thisNormalPersonalFee) * 0.5m, MidpointRounding.AwayFromZero);
_disableLostJobSupport = Math.Round((_thisLostJobPersonalFee) * 0.5m, MidpointRounding.AwayFromZero);
break;
case "3": // 重度
case "4": // 極重度
_disableNormalSupport = _thisNormalPersonalFee;
_disableLostJobSupport = _thisLostJobPersonalFee;
break;
}
// 計算職災保險保費
double bljiAmt = GetBLJIAmt(salary);
_injurySalary = Convert.ToInt32(bljiAmt);
_injuryCompanyFee += Convert.ToDecimal(Math.Round(bljiAmt * _injuryCompanyFeeRate * daysRatio, 4, MidpointRounding.AwayFromZero));
// 計算工資墊償基金
// 員工身份是雇主:
if (employeeType == "1")
{
_salaryReverseFund += 0;
}
else
{
_salaryReverseFund += Convert.ToDecimal(Math.Round(bsamt * daysRatio * _salaryReverseFundRate, 4, MidpointRounding.AwayFromZero));
}
}
}
}
/// <summary>
/// 勞保費
/// </summary>
public struct LaborInsuranceFee
{
/// <summary>
/// 到職天數
/// </summary>
public int InWorkDays;
/// <summary>
/// 投保薪資
/// </summary>
public int InsuranceSalary;
/// <summary>
/// 職災投保薪資
/// </summary>
public int InjurySalary;
/// <summary>
/// 普通事故個人保費
/// </summary>
public decimal NormalPersonalFee;
/// <summary>
/// 普通事故公司保費
/// </summary>
public decimal NormalCompanyFee;
/// <summary>
/// 就業保險個人保費
/// </summary>
public decimal LostJobPersonalFee;
/// <summary>
/// 就業保險公司保費
/// </summary>
public decimal LostJobCompanyFee;
/// <summary>
/// 職災保費
/// </summary>
public decimal InjuryCompanyFee;
/// <summary>
/// 身障補助
/// </summary>
public decimal DisableNormalSupport;
/// <summary>
/// 身障補助
/// </summary>
public decimal DisableLostJobSupport;
/// <summary>
/// 工資墊償基金
/// </summary>
public decimal SalaryReverseFund;
public void Init()
{
InWorkDays = 0;
InsuranceSalary = 0;
InjurySalary = 0;
NormalCompanyFee = 0;
NormalPersonalFee = 0;
LostJobCompanyFee = 0;
LostJobPersonalFee = 0;
InjuryCompanyFee = 0;
DisableNormalSupport = 0;
DisableLostJobSupport = 0;
SalaryReverseFund = 0;
}
public void Add(LaborInsuranceFee fee)
{
InWorkDays += fee.InWorkDays;
InsuranceSalary = fee.InsuranceSalary;
InjurySalary = fee.InjurySalary;
NormalCompanyFee += fee.NormalCompanyFee;
NormalPersonalFee += fee.NormalPersonalFee;
LostJobCompanyFee += fee.LostJobCompanyFee;
LostJobPersonalFee += fee.LostJobPersonalFee;
InjuryCompanyFee += fee.InjuryCompanyFee;
DisableNormalSupport += fee.DisableNormalSupport;
DisableLostJobSupport += fee.DisableLostJobSupport;
SalaryReverseFund += fee.SalaryReverseFund;
}
/// <summary>
/// 個人總保費
/// </summary>
public int TotalPersonalFee
{
// { 四捨五入(普通事故) + 四捨五入(就業保險) }
//- { 四捨五入(普通事故減免) + 四捨五入(就業保險減免) }
get
{
return Convert.ToInt32(Math.Round(NormalPersonalFee, MidpointRounding.AwayFromZero))
+ Convert.ToInt32(Math.Round(LostJobPersonalFee, MidpointRounding.AwayFromZero))
- Convert.ToInt32(Math.Round(DisableNormalSupport, MidpointRounding.AwayFromZero))
- Convert.ToInt32(Math.Round(DisableLostJobSupport, MidpointRounding.AwayFromZero));
}
}
}