122 lines
3.7 KiB
C#
122 lines
3.7 KiB
C#
|
|
namespace Service.Budget;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 预算明细项计算辅助类
|
|||
|
|
/// 用于计算单个预算项的有效金额(计算用金额)
|
|||
|
|
/// </summary>
|
|||
|
|
public static class BudgetItemCalculator
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 计算预算项的有效金额
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="category">预算类别(收入/支出)</param>
|
|||
|
|
/// <param name="budgetLimit">预算金额</param>
|
|||
|
|
/// <param name="actualAmount">实际金额</param>
|
|||
|
|
/// <param name="isMandatory">是否为硬性消费</param>
|
|||
|
|
/// <param name="isArchived">是否为归档数据</param>
|
|||
|
|
/// <param name="referenceDate">参考日期</param>
|
|||
|
|
/// <param name="periodType">预算周期类型(月度/年度)</param>
|
|||
|
|
/// <returns>有效金额(用于计算的金额)</returns>
|
|||
|
|
public static decimal CalculateEffectiveAmount(
|
|||
|
|
BudgetCategory category,
|
|||
|
|
decimal budgetLimit,
|
|||
|
|
decimal actualAmount,
|
|||
|
|
bool isMandatory,
|
|||
|
|
bool isArchived,
|
|||
|
|
DateTime referenceDate,
|
|||
|
|
BudgetPeriodType periodType)
|
|||
|
|
{
|
|||
|
|
// 归档数据直接返回实际值
|
|||
|
|
if (isArchived)
|
|||
|
|
{
|
|||
|
|
return actualAmount;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 收入:实际>0取实际,否则取预算
|
|||
|
|
if (category == BudgetCategory.Income)
|
|||
|
|
{
|
|||
|
|
return actualAmount > 0 ? actualAmount : budgetLimit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支出(硬性且实际=0):按天数折算
|
|||
|
|
if (category == BudgetCategory.Expense && isMandatory && actualAmount == 0)
|
|||
|
|
{
|
|||
|
|
return CalculateMandatoryAmount(budgetLimit, referenceDate, periodType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支出(普通):取MAX
|
|||
|
|
if (category == BudgetCategory.Expense)
|
|||
|
|
{
|
|||
|
|
return Math.Max(budgetLimit, actualAmount);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return budgetLimit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 计算硬性消费按天数折算的金额
|
|||
|
|
/// </summary>
|
|||
|
|
private static decimal CalculateMandatoryAmount(
|
|||
|
|
decimal limit,
|
|||
|
|
DateTime date,
|
|||
|
|
BudgetPeriodType periodType)
|
|||
|
|
{
|
|||
|
|
if (periodType == BudgetPeriodType.Month)
|
|||
|
|
{
|
|||
|
|
var daysInMonth = DateTime.DaysInMonth(date.Year, date.Month);
|
|||
|
|
return limit / daysInMonth * date.Day;
|
|||
|
|
}
|
|||
|
|
else // Year
|
|||
|
|
{
|
|||
|
|
var daysInYear = DateTime.IsLeapYear(date.Year) ? 366 : 365;
|
|||
|
|
return limit / daysInYear * date.DayOfYear;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 生成计算说明
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="category">预算类别</param>
|
|||
|
|
/// <param name="budgetLimit">预算金额</param>
|
|||
|
|
/// <param name="actualAmount">实际金额</param>
|
|||
|
|
/// <param name="effectiveAmount">有效金额</param>
|
|||
|
|
/// <param name="isMandatory">是否为硬性消费</param>
|
|||
|
|
/// <param name="isArchived">是否为归档数据</param>
|
|||
|
|
/// <returns>计算说明文本</returns>
|
|||
|
|
public static string GenerateCalculationNote(
|
|||
|
|
BudgetCategory category,
|
|||
|
|
decimal budgetLimit,
|
|||
|
|
decimal actualAmount,
|
|||
|
|
decimal effectiveAmount,
|
|||
|
|
bool isMandatory,
|
|||
|
|
bool isArchived)
|
|||
|
|
{
|
|||
|
|
if (isArchived)
|
|||
|
|
{
|
|||
|
|
return "归档实际";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (category == BudgetCategory.Income)
|
|||
|
|
{
|
|||
|
|
return actualAmount > 0 ? "使用实际" : "使用预算";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (category == BudgetCategory.Expense)
|
|||
|
|
{
|
|||
|
|
if (isMandatory && actualAmount == 0)
|
|||
|
|
{
|
|||
|
|
return "按天折算";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (actualAmount > budgetLimit)
|
|||
|
|
{
|
|||
|
|
return "使用实际(超支)";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return effectiveAmount == actualAmount ? "使用实际" : "使用预算";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return "使用预算";
|
|||
|
|
}
|
|||
|
|
}
|