每次例行检查后为每个雇员扣除保险金额

问题描述

这是我的问题的样本数据,

List<EMPINSURED> lstempIns = new List<EMPINSURED>{
    new EMPINSURED{ EmpID = 558,TOTAL_INSURED_AMT = 50000},new EMPINSURED{ EmpID = 559,TOTAL_INSURED_AMT = 75000} 
};

List<EMP_ROUTINE_CHECKUP_HISTORY> lstempRoutineChkHist = new List<EMP_ROUTINE_CHECKUP_HISTORY>{
    new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 1,EmpID = 558,ROUTINE_CHECKUP = 1,CHECK_UP_CHARGE = 20000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 2,EmpID = 559,CHECK_UP_CHARGE = 35000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 3,ROUTINE_CHECKUP = 2,CHECK_UP_CHARGE = 10000},new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 4,new EMP_ROUTINE_CHECKUP_HISTORY{ ID = 5,ROUTINE_CHECKUP = 3,CHECK_UP_CHARGE = 20000}
};

一年中,仅允许员工进行三次例行检查。员工进行例行检查时,必须从总保险金额中扣除其检查费用。对于下一次例行检查,将仅向雇员支付保险总额中剩余金额的检查费用,超过此限额的任何费用,公司将不承担。 因此,用于计算REMAINING AMOUNT的逻辑有点像这样::

    int var = 0;
if(ROUTINE_CHECKUP == 1)
{
    REMAINING_AMOUNT = TOTAL_INSURED_AMT - CHECK_UP_CHARGE;
    var = CHECK_UP_CHARGE;
} 
else if (ROUTINE_CHECKUP == 2)
{
    REMAINING_AMOUNT = TOTAL_INSURED_AMT - (CHECK_UP_CHARGE + var);
    var = CHECK_UP_CHARGE + var;
}
else if (ROUTINE_CHECKUP == 3)
{
    REMAINING_AMOUNT = TOTAL_INSURED_AMT - (CHECK_UP_CHARGE + var);
    var = CHECK_UP_CHARGE + var;
}

如何使用此逻辑开发LINQ查询获取以下报告数据,否则可能会有更好的方法。 请参阅附件中的报告格式图像。

enter image description here

解决方法

使用一些private void flipCoin() { final Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher_background); final ImageView iv = ((ImageView) findViewById(R.id.imageView)); iv.setRotationY(0f); //iv.animate().setDuration(10); iv.animate().rotationY(90f).setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { iv.setImageDrawable(drawable); iv.setRotationY(270f); iv.animate().rotationY(360f).setListener(null); } @Override public void onAnimationCancel(Animator animation) { } }); 扩展方法,您可以将System.Linq字段中的Join列表与lstEmpIns列表中的lstEmpRoutineChkHist列表EmpId转换为具有值,然后使用RoutineCheckup通过OrderBy对结果进行排序。

丑陋的部分是确定RemainingBalance,因为我们必须查找RoutineCheckup小于或等于当前项目的该员工的所有记录,然后将{{1 }},因此我们可以从CheckupCharge中扣除它。可能有更好的方法,但这就是我想出的。

以下是基于您的代码但使用现代命名约定的示例:

RemainingBalance

一些用于生成输出的代码:

var results = empInsureds
    .Join(empRoutineCheckupHistories,emp => emp.EmpId,hist => hist.EmpId,(emp,hist) => new
        {
            emp.EmpId,emp.TotalInsuredAmt,hist.RoutineCheckup,hist.CheckupCharge,RemainingBalance =
                emp.TotalInsuredAmt -
                empRoutineCheckupHistories
                    .Where(h => h.EmpId == hist.EmpId &&
                                h.RoutineCheckup <= hist.RoutineCheckup)
                    .Sum(h => h.CheckupCharge)
        })
    .OrderBy(r => r.RoutineCheckup)
    .ToList();

其中使用了辅助功能:

Console.WindowWidth = 81;

Console.WriteLine(GetRow("EmpID","Total Insured Amt","Routine Checkup","Checkup Charge","Remaining Amount"));

Console.WriteLine(new string('-',80));

results.ForEach(r => Console.WriteLine(GetRow($"{r.EmpId}",$"{r.TotalInsuredAmt:C}",$"{r.RoutineCheckup}",$"{r.CheckupCharge:C}",$"{r.RemainingBalance:C}")));

GetKeyFromUser("\nDone! Press any key to exit...");

输出

enter image description here

,

我的建议是,如果源不是IQueryable而是IEnumerable,则使用Queryable.GroupJoin的重载之一,或它的IEnumerable等效项。

使用GroupJoin,您可以获得“所有雇员,每个雇员的零个或多个例行检查”。通过使用参数resultSelector,可以创建所需的输出。

GroupJoin的优势在于,您还将获得到目前为止尚未进行过检查的员工。如果您使用Join,那么您根本不会得到这些雇员。

var employeesWithTheirCheckups = dbContext.Employees.GroupJoin(
    dbContext.RoutineCheckUps,employee => employee.EmpId,// from every Employee take the primary key
    checkup => checkup.EmpId,// from every RoutineCheckup take the foreign key
                                   // to the Employee

    // parameter resultSelector: for every Employee and his zero or more Checkups,// make one new object:
    (employee,checkupsOfThisEmployee) => new
    {
        EmpId = employee.Id,TotalInsuredAmount = employee.TotalInsuredAmount,Checkups = checkupsOfThisEmployee.Select(checkup => new
        {
            RoutineCheckup = checkup.RoutineCheckup,CheckupCharge = checkup.CheckupCharge,// TODO: Remaining Amount   
        })
        .ToList(),});

剩余的检查费用,等于该雇员的总金额减去此“该雇员直到这次检查的总检查费用”。

因此,对于具有RoutineCheckup 2的历史记录,您需要对具有RoutineCheckups

计算方法如下:

var chargedUntilNow = checkupsOfThisEmployee
    .Where(checkupOfThisEmployee => checkupOfThisEmployee <= checkup)
    .Select(checkupOfThisEmployee => checkupOfThisEmployee.CheckUpCharge)
    .Sum();

剩余的是该雇员的总数-chargeUntilNow。

返回GroupJoin:

(employee,checkupsOfThisEmployee) => new
{
    EmpId = employee.Id,Checkups = checkupsOfThisEmployee.Select(checkup => new
    {
        RoutineCheckup = checkup.RoutineCheckup,// remaining is the total of this employee - chargedUntilNow.
        RemainingAmount = employee.TotalInsured -
            checkupsOfThisEmployee
            .Where(checkupOfThisEmployee => checkupOfThisEmployee <= checkup)
            .Select(checkupOfThisEmployee => checkupOfThisEmployee.CheckUpCharge)
            .Sum();
    })
    .ToList(),

结果是所有雇员(当然,只有他的ID和他的总保险金额)的序列,每个雇员的检查次数为零或更多。每个Checkup将具有RoutineCheckup编号,CheckupAmount和RemainingAmount。

好东西:您还将拥有尚未进行检查的员工!

此外:[EmpId,TotalInsuredAmount],每个员工只能转移一次。如果您将使用标准的Join,则每个Checkup将发送相同的[EmpId,TotalInsuredAmount]。

如果要展平,如最终结果一样,请使用SelectMany。继续使用LINQ:

.SelectMany(groupJoinResult,groupJoinResult.Checkups,// parameter resultSelector: take the GroupJoinResult,and each one of its Checkups
// to make one new:
(groupJoinResult,checkupOfThisGroupJoinResult) => new
{
    EmpId = groupJoinResult.EmpId,TotalInsuredAmount = groupJoinResult.TotalInsuredAmount,RoutineCheckUp = checkupOfThisGroupJoinResult.RoutineCheckup,CheckupCharge = checkupOfThisGroupJoinResult.CheckupCharge,RemainingAmount = checkupOfThisGroupJoinResult.RemainingAmount,});

问题是您将失去尚未进行任何检查的Employee。要解决此问题,您必须提供默认值