using HRS.Lib.Comm.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HRS.Lib.Comm.Enums;
using HRS.Lib.Comm.Exceptions;
namespace HRS.Service.BLL.Sys.Bill
{
/// <summary>
/// 计算费用加锁
/// </summary>
public static class BillCalucateFeeBusiness
{
#region Property
// 月账单费用
private static BillLockObject _NewBillMonthlySocial_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _NewBillMonthlySocial = new BillLockObject() { Value = "CalucateFee" };
// 同步政策库信息
private static BillLockObject _PolicyVersionSynchronyNew_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _PolicyVersionSynchronyNew = new BillLockObject() { Value = "PolicyVersionSynchronyNew" };
// 同步参保方案、账户
private static BillLockObject _AccountSolutionSynchronyNew_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _AccountSolutionSynchronyNew = new BillLockObject() { Value = "AccountSolutionSynchronyNew" };
// 变化数据入账单
private static BillLockObject _ChangesToMonthlySocial_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _ChangesToMonthlySocial = new BillLockObject() { Value = "ChangesToMonthlySocial" };
// 非标费用入账单
private static BillLockObject _NonStandChangesToMonthlySocial_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _NonStandChangesToMonthlySocial = new BillLockObject() { Value = "NonStandChangesToMonthlySocial" };
// 疫情算费
private static BillLockObject _AdjustAccountFee_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _AdjustAccountFee = new BillLockObject() { Value = "AdjustAccountFee" };
// 自动雇员内转
private static BillLockObject _AdjustToNewInstByAuto_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _AdjustToNewInstByAuto = new BillLockObject() { Value = "AdjustToNewInstByAuto" };
// 年调基数翻新
private static BillLockObject _YearAdjustToFeedBackNewBase2_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _YearAdjustToFeedBackNewBase2 = new BillLockObject() { Value = "_YearAdjustToFeedBackNewBase2" };
// 政策年调基数翻新
private static BillLockObject _PolicyYearAdjustToDeclareBase_ID = new BillLockObject(); // 单个最新ID
private static BillLockObject _PolicyYearAdjustToDeclareBase = new BillLockObject() { Value = "_PolicyYearAdjustToDeclareBase" };
#endregion
#region 成员方法
/// <summary>
/// 算费加锁功能
/// 单个和全部机构相互锁,如果单个机构算费先一步锁住_PolicyVersionSynchronyNew,
/// 可能导致全部机构算费不执行(因为会尝试等待10s,所以出现概率很小)
/// </summary>
/// <param name="excuteFun"></param>
/// <param name="enu"></param>
/// <param name="date"></param>
/// <param name="institutionId"></param>
/// <returns></returns>
public static bool Lock(Func<DateTime, Guid?, bool> excuteFun, BillLockEnum enu, DateTime date, Guid? institutionId = null)
{
var lockTaken = false; // 单个机构
var lockTakenAll = false; // 所有机构
// 全局变量
var lockObject = GetInstituionLockObj(enu);
var lockObjectAll = GetAllInstituionLockObj(enu);
try
{
if (institutionId.HasValue)
{
// 判断单个是否lcok
Monitor.TryEnter(string.Intern(lockObjectAll.Value + institutionId.Value), ref lockTaken); // string.Intern转换为同一个地址
if (lockTaken)
{
// 判断全部是否lock
Monitor.TryEnter(string.Intern(lockObjectAll.Value), ref lockTakenAll);
if (lockTakenAll)
{
// 全部解锁
Monitor.Exit(string.Intern(lockObjectAll.Value));
lockTakenAll = false;
lockObject.Value = lockObjectAll.Value + institutionId.Value.ToString(); // 单个锁住标志
return excuteFun(date, institutionId); // 执行单个机构
}
else
{
Log4Pack.CurLog.Error(string.Format("因为所有机构正在执行【{1}】,所以当前机构【{0}】未执行", institutionId.Value, enu.GetDescription()));
}
}
else
{
Log4Pack.CurLog.Error(string.Format("因为机构【{0}】正在执行【{1}】,所以当前机构未执行", institutionId.Value, enu.GetDescription()));
}
}
else
{
// 判断全部是否lock
Monitor.TryEnter(string.Intern(lockObjectAll.Value), ref lockTakenAll);
if (lockTakenAll)
{
// 单个可能被lock
if (!string.IsNullOrEmpty(lockObject.Value))
{
// 判断单个有没有被锁(无限期等待)
Monitor.TryEnter(string.Intern(lockObject.Value), -1, ref lockTaken);
if (lockTaken)
{
// 等待单个机构被锁住释放
Monitor.Exit(string.Intern(lockObject.Value));
lockTaken = false;
Thread.Sleep(10000); // 等待10s(确保所有单个机构执行完毕)
return excuteFun(date, institutionId); // 执行全部机构
}
}
else
{
Thread.Sleep(10000); // 等待10s(确保所有单个机构执行完毕)
return excuteFun(date, institutionId);
}
}
else
{
Log4Pack.CurLog.Error(string.Format("因为所有机构正在执行【{0}】,所以所有机构未执行", enu.GetDescription()));
}
}
return true; // 被锁住,退出不执行
}
catch (Exception ex)
{
Log4Pack.CurLog.Error(ex.StackTrace);
var msg = ex.Message;
if (ex.InnerException != null)
{
msg = ex.InnerException.Message;
}
Log4Pack.CurLog.Error("错误明细:" + msg);
return true;
}
finally
{
try
{
if (lockTakenAll)
{
Monitor.Exit(string.Intern(lockObjectAll.Value));
}
if (lockTaken)
{
lockObject.Value = "";
Monitor.Exit(string.Intern(lockObjectAll.Value + institutionId.Value));
}
}
catch (Exception ex)
{
Log4Pack.CurLog.Error(ex.StackTrace);
var msg = ex.Message;
if (ex.InnerException != null)
{
msg = ex.InnerException.Message;
}
Log4Pack.CurLog.Error("错误明细:" + msg);
}
}
}
#endregion
#region 私有方法
/// <summary>
/// 获取所有机构LockObject
/// </summary>
/// <param name="enu"></param>
/// <returns></returns>
private static BillLockObject GetAllInstituionLockObj(BillLockEnum enu)
{
switch (enu)
{
case BillLockEnum.NewBillMonthlySocial:
{
return _NewBillMonthlySocial;
}
case BillLockEnum.PolicyVersionSynchrony:
{
return _PolicyVersionSynchronyNew;
}
case BillLockEnum.AccountSolutionSynchrony:
{
return _AccountSolutionSynchronyNew;
}
case BillLockEnum.ChangesToMonthlySocial:
{
return _ChangesToMonthlySocial;
}
case BillLockEnum.NonStandChangesToMonthlySocial:
{
return _NonStandChangesToMonthlySocial;
}
case BillLockEnum.AdjustAccountFee:
{
return _AdjustAccountFee;
}
case BillLockEnum.AdjustToNewInstByAuto:
{
return _AdjustToNewInstByAuto;
}
case BillLockEnum.YearAdjustToFeedBackNewBase2:
{
return _YearAdjustToFeedBackNewBase2;
}break;
case BillLockEnum.PolicyYearAdjustToDeclareBase:
{
return _PolicyYearAdjustToDeclareBase;
}break;
default:
throw new ShowInfoException("AllLockObjeck枚举不存在");
}
}
/// <summary>
/// 获取单个机构LockObject
/// </summary>
/// <param name="enu"></param>
/// <returns></returns>
private static BillLockObject GetInstituionLockObj(BillLockEnum enu)
{
switch (enu)
{
case BillLockEnum.NewBillMonthlySocial:
{
return _NewBillMonthlySocial_ID;
}
case BillLockEnum.PolicyVersionSynchrony:
{
return _PolicyVersionSynchronyNew_ID;
}
case BillLockEnum.AccountSolutionSynchrony:
{
return _AccountSolutionSynchronyNew_ID;
}
case BillLockEnum.ChangesToMonthlySocial:
{
return _ChangesToMonthlySocial_ID;
}
case BillLockEnum.NonStandChangesToMonthlySocial:
{
return _NonStandChangesToMonthlySocial_ID;
}
case BillLockEnum.AdjustAccountFee:
{
return _AdjustAccountFee_ID;
}
case BillLockEnum.AdjustToNewInstByAuto:
{
return _AdjustToNewInstByAuto_ID;
}
case BillLockEnum.YearAdjustToFeedBackNewBase2:
{
return _YearAdjustToFeedBackNewBase2_ID;
} break;
case BillLockEnum.PolicyYearAdjustToDeclareBase:
{
return _PolicyYearAdjustToDeclareBase_ID;
} break;
default:
throw new ShowInfoException("SingleLockObjeck枚举不存在");
}
}
#endregion
}
#region 辅助类、枚举
/// <summary>
/// 账单参数枚举
/// </summary>
public enum BillLockEnum
{
/// <summary>
/// 月账单作业
/// </summary>
[DefaultValue("0")]
[Description("月账单作业")]
NewBillMonthlySocial = 0,
/// <summary>
/// 同步政策库信息
/// </summary>
[DefaultValue("1")]
[Description("同步政策库信息")]
PolicyVersionSynchrony,
/// <summary>
/// 参保方案,账户变动同步
/// </summary>
[DefaultValue("2")]
[Description("参保方案,账户变动同步")]
AccountSolutionSynchrony,
/// <summary>
/// 变化数据入账单
/// </summary>
[DefaultValue("3")]
[Description("变化数据入账单")]
ChangesToMonthlySocial,
/// <summary>
/// 非标费用入账单
/// </summary>
[DefaultValue("4")]
[Description("非标费用入账单")]
NonStandChangesToMonthlySocial,
/// <summary>
/// 疫情算费
/// </summary>
[DefaultValue("5")]
[Description("疫情算费")]
AdjustAccountFee,
/// <summary>
/// 自动雇员内转
/// </summary>
[DefaultValue("5")]
[Description("自动雇员内转")]
AdjustToNewInstByAuto,
/// <summary>
/// 自动雇员内转
/// </summary>
[DefaultValue("6")]
[Description("年调基数翻新")]
YearAdjustToFeedBackNewBase2,
/// <summary>
/// 自动雇员内转
/// </summary>
[DefaultValue("7")]
[Description("政策库年调基数翻新")]
PolicyYearAdjustToDeclareBase
}
/// <summary>
/// 账单Lock对象
/// </summary>
public class BillLockObject
{
public string Value { get; set; }
}
#endregion
}