根据时间区间拆分时间节点进行分账操作
最近遇到了一个财务分账逻辑,当时解决的时候感觉有点意思,因为最近比较忙,今天才有时间来写一篇博客文章记录一下,希望能对遇到相关问题的朋友提供一点思路。
业务逻辑:
按时间区间拆分时间节点在每个季度末生成账单。
注:15号及15号之前是当月,15号之后是下个月
比如合同期2023年2月15日到2024年2月15日,金额为1万元
23年1季度触发确认2个月,金额:1666
23年2季度确认3个月,金额:2499
23年3季度3个月,金额:2499
23年4季度3个月,金额:2499
24年1季度1个月,金额:837
金额:金额平摊至每个月,按季度算金额,最后一个月补差额(默认不会出现拆分类型变更的情况)
代码实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
//合同开始时间
DateTime contractStartTime = new DateTime(2023, 12, 16);
//合约期
int contractPeriod = 6;
//如果开始时间是15号后,账期归下个月
if (contractStartTime.Day > 15)
{
contractStartTime= contractStartTime.AddMonths(1);
}
//合同结束时间
DateTime contractEndTime = contractStartTime.AddMonths(contractPeriod);
// 分摊合同金额
AmortizeContract(10000, contractStartTime, contractEndTime);
Console.ReadLine();
}
/// <summary>
/// 计算合同差额
/// </summary>
/// <param name="totalAmount"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
static void AmortizeContract(decimal totalAmount, DateTime startDate, DateTime endDate)
{
int monthNum = GetMonthDifference(startDate, endDate);
decimal monthlyAmount = totalAmount / monthNum;
while (startDate <= endDate)
{
int monthsInQuarter = GetMonthsInQuarter(startDate);
decimal amortizedAmount = (int)monthlyAmount * monthsInQuarter;
if (startDate.AddMonths(monthsInQuarter) > endDate)
{
// 计算最后一个季度的分摊月份和金额
monthsInQuarter = (endDate.Month - startDate.Month) + 1;
amortizedAmount = totalAmount - ((int)monthlyAmount * (monthNum - monthsInQuarter + 1));
Console.WriteLine($"{startDate.Year}年{GetQuarter(startDate)}季度,分摊月份为{monthsInQuarter - 1}个月,分摊金额为{(int)amortizedAmount};");
}
else
{
Console.WriteLine($"{startDate.Year}年{GetQuarter(startDate)}季度,分摊月份为{monthsInQuarter}个月,分摊金额为{(int)amortizedAmount};");
}
startDate = startDate.AddMonths(monthsInQuarter);
}
}
/// <summary>
/// 获取日期月份差额
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
static int GetMonthDifference(DateTime startDate, DateTime endDate)
{
int startMonths = startDate.Year * 12 + startDate.Month;
int endMonths = endDate.Year * 12 + endDate.Month;
return endMonths - startMonths;
}
static int GetMonthsInQuarter(DateTime date)
{
int month = date.Month;
if (month <= 3)
{
return 3 - (month - 1);
}
else if (month <= 6)
{
return 6 - (month - 1);
}
else if (month <= 9)
{
return 9 - (month - 1);
}
else
{
return 12 - (month - 1);
}
}
static int GetQuarter(DateTime date)
{
int month = date.Month;
if (month <= 3)
{
return 1;
}
else if (month <= 6)
{
return 2;
}
else if (month <= 9)
{
return 3;
}
else
{
return 4;
}
}
}
}
效果验证:
1.开始日期十五号及之前
2.开始日期15号之后
3.半年区间15号之后
4.半年区间15号之前
版权声明:
作者:兴兴
文章:根据时间区间拆分时间节点进行分账操作
链接:https://www.networkcabin.com/notes/3373
文章版权归本站所有,未经授权请勿转载。
作者:兴兴
文章:根据时间区间拆分时间节点进行分账操作
链接:https://www.networkcabin.com/notes/3373
文章版权归本站所有,未经授权请勿转载。
THE END