67.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--新增功能--分摊功能总体设计与业务流程

日常生活里,聚餐 AA、合租水电、团队差旅垫付这类场景非常常见,先由某个人付款,随后再按人头、按比例或按指定金额进行分摊。看似简单,但一旦人数多、账单多、跨时间长,就会出现"谁还欠谁""这笔算没算进去""该提醒谁付款"这样的沟通成本与对账成本。

从这篇文章开始,我们将利用五篇文章来讲解分摊功能的开发。这五篇文章分别是:《分摊功能总体设计与业务流程》、《数据模型与数据库设计》、《 分摊主流程实现》、《结算与记账联动实现》、《提醒系统与定时任务》。本篇为第一篇,《分摊功能总体设计与业务流程》,将介绍分摊功能的总体设计思路与业务流程。

一、需求分析

分摊功能的核心需求是支持用户在不同场景下进行费用分摊,主要包括以下几个方面:

  1. 分摊创建:用户可以创建一个分摊账单,输入总金额、参与人、分摊方式(按人头、按比例、按金额)等信息。
  2. 分摊计算:系统根据用户输入的信息,自动计算每个人应付的金额,并生成分摊明细。
  3. 分摊结算:用户可以查看分摊明细,并进行结算操作,如确认付款、标记已付款等。
  4. 分摊提醒:系统可以根据用户设置的提醒时间,自动提醒用户进行付款或结算操作。
  5. 分摊记录:用户可以查看历史分摊记录,包括已结算和未结算的账单。

二、核心业务流程

在这一部分,我们将介绍分摊功能的核心业务流程,主要包括:创建分摊流程、结算流程、提醒流程。

2.1 创建分摊流程

用户进入分摊创建界面,输入分摊信息,包括总金额、参与人、分摊方式等。系统根据用户输入的信息,自动计算每个人应付的金额,并生成分摊明细。用户可以查看分摊明细,并进行确认操作,完成分摊创建。

创建分摊账目的同时,系统会自动生成支出记账,并写入到对应的账本中。这样用户在查看账本时,就可以看到分摊账目的支出记录。支出记录会包含分摊的总金额、分摊类型、参与人数等关键信息,确保账本的完整性和可追溯性。

参与者的明细会按照用户选定的分摊规则进行计算。分摊规则包括三种方式:按人头均摊、按比例分摊、按指定金额分摊。系统会根据选择的规则精确计算每个参与者的应付金额,并在分摊明细中逐一展示。用户可以在确认前查看详细的计算过程和每个人的应付金额,确保分摊的准确性,然后进行确认操作完成分摊创建。

分摊状态会随着用户的后续操作逐步更新,初始状态为待付款,用户付款后会更新为部分付款或全部付款等状态。系统还会自动记录分摊的创建时间、发起人、参与人列表、分摊方式等基础信息,以及每个参与者的应付金额和付款状态,这些信息将为后续的结算提醒、对账管理和历史查询提供完整的数据支撑。

2.2 结算流程

发起结算,包括付款人、收款人、金额和方式,系统会同步生成记账信息,并写入到对应的收款人账本和付款人账本中,最后更新参与者的结算状态,然后刷新分摊状态。

结算流程是分摊功能的关键环节,当参与者需要偿还欠款时,发起人或相关参与者可以发起结算操作。在发起结算时,需要明确指定付款人、收款人、结算金额以及结算方式(如转账、现金、支付宝等),系统会根据这些信息生成对应的记账数据。

生成的记账信息随后会同步写入到收款人和付款人各自的账本中,确保双方的账务记录保持一致。对于付款人而言,这笔记录会体现为一笔支出或债务清偿;对于收款人来说,则会体现为一笔收入或债权回收。系统会自动匹配分摊单据与结算记账,形成完整的对账链路。

结算完成后,系统会自动更新相关参与者的结算状态,包括已结算、部分结算等状态标记,同时刷新整个分摊账单的聚合状态。当所有参与者都完成结算后,分摊账单的状态会更新为已结清,整个分摊流程也随之闭环。在这个过程中,系统会保留完整的结算履历,包括每笔结算的发起时间、参与方、金额和方式,为后续的对账查询和历史审计提供坚实的数据基础。

2.3 提醒流程

提醒流程是分摊功能的重要辅助机制,用于及时提醒参与者完成付款或结算操作。当分摊账单创建或结算发起后,系统会自动创建提醒记录(SharedExpenseReminder),记录提醒的类型、内容、计划发送时间和当前状态。系统支持多种提醒类型,包括分摊创建提醒、待付款提醒、逾期提醒等,用户可以根据需求灵活配置提醒策略。

提醒的发送采用定时任务机制实现。系统通过后台定时任务 SharedExpenseReminderWatcher 每隔 30 分钟轮询一次,查询所有状态为待发送的提醒记录,并按照计划时间依次发送。任务会根据当前时间与计划时间的匹配情况,决定是否执行提醒发送操作,确保提醒能够按时准确地送达用户。

当提醒发送成功后,系统会进行后续的智能调度处理。如果该提醒记录配置了下一次提醒时间(NextReminderTime),系统会自动创建新的提醒记录用于后续发送;对于逾期类型(Overdue)的提醒,系统也会自动安排下一次提醒,以持续催促参与者完成结算。这样可以确保对于长期未完成的账单,用户能够收到持续的提醒,从而提高结算的及时性。

当提醒发送失败时,系统采用重试机制来保证可靠性。发送失败的提醒记录会在 30 分钟后重新尝试发送,系统会将其状态恢复为待发送(Pending),纳入下一个轮询周期的处理队列中。如果连续重试失败超过一定次数,系统会记录失败日志并标记为异常,管理员可以后续介入处理,确保关键提醒最终能够送达用户。

三、模块边界与服务划分

在这一部分,我们将介绍分摊功能的模块边界与服务划分,明确各个模块的职责和交互关系。

3.1 服务划分

分摊功能涉及多个核心业务环节,因此需要通过服务划分来实现职责分离和模块解耦。根据业务流程的特点,我们将分摊功能划分为三个核心服务模块。

分摊主服务(ISharedExpenseServer / SharedExpenseServerImpl)负责分摊账目的全生命周期管理,包括创建、编辑、删除和查询操作。该服务的核心职责是处理用户输入的分摊信息,进行参与者的同步更新,并与支出记账模块进行联动,确保分摊账目创建时自动生成对应的支出记录。

结算服务(ISharedExpenseSettlementServer / SharedExpenseSettlementServerImpl)专注于分摊结算的业务逻辑实现。该服务负责处理结算流水的创建与管理,与收入记账模块进行联动以确保记账信息的准确性,同时更新参与者的结算状态并刷新整个分摊账单的聚合状态,形成完整的结算链路。

提醒服务(ISharedExpenseReminderServer / SharedExpenseReminderServerImpl)负责分摊提醒的全过程管理。该服务包括提醒记录的创建、状态更新和提醒排期逻辑的处理,与定时任务组件紧密协作,确保提醒能够按时准确地发送给用户,并处理失败重试和后续提醒的自动安排。

3.2 控制器边界

为了清晰地划分 API 入口和用户交互边界,分摊功能提供三个专用控制器。SharedExpenseController 作为分摊主流程的入口,处理用户对分摊账目的创建、编辑、删除和查询请求。SharedExpenseSettlementController 作为结算流程的入口,处理用户发起的结算操作请求。SharedExpenseReminderController 作为提醒流程的入口,处理用户对提醒的配置和管理请求。通过清晰的控制器划分,可以使 API 层次结构更加清晰,便于维护和扩展。

四、数据流与状态流转

在分摊功能的全生命周期中,涉及多个关键实体的状态变化与流转过程。这些状态流转环节紧密关联,共同驱动整个分摊业务的推进,确保数据一致性和业务闭环。

4.1 分摊账目状态流转

分摊账目状态(SharedExpenseStatusEnum)用于表示整个分摊单据的结算进度和完成度。当分摊账目创建完成后,初始状态为未付款(Unpaid) ,表示尚未有任何参与者完成结算。随着参与者陆续完成结算操作,分摊账目的状态会逐步推进。当部分参与者完成结算,但仍有其他参与者未完成时,分摊账目状态转变为部分付款(PartialPayment) 。当所有参与者均完成结算操作后,分摊账目的最终状态为全部付款(All),此时分摊流程完全闭环。

分摊账目状态的刷新触发点位于结算服务层。每当结算服务创建新的结算流水记录后,系统会自动对所有参与者的结算状态进行重新计算,并据此更新整个分摊账目的聚合状态。这种设计确保分摊账目状态始终与实际的结算进度保持同步,避免出现状态滞后或不一致的情况。

复制代码
创建分摊账目
    ↓
Unpaid(未付款)
    ↓
[发起结算] → PartialPayment(部分付款)
    ↓
[继续结算] → [继续结算] → ... → All(全部付款)
4.2 参与者明细状态流转

参与者明细(SharedExpenseParticipant)是分摊账目中最细粒度的数据单元,记录每个参与者的应付金额和结算状态。在创建分摊账目时,系统会根据分摊规则计算出每个参与者的应付金额,并将参与者明细记录持久化至数据库,此时每个参与者的初始状态为未结算

当参与者通过结算流程完成付款后,结算服务会更新对应参与者的结算状态,并记录结算凭证(SettlementId)与生成的会计记账编号(AccountingId)。这使得参与者明细与对应的结算流水和会计凭证之间形成可追溯的关联关系。

若在参与者结算后,发起人或管理员进行分摊账目的编辑或删除操作,系统会同步变更或清理相关的参与者明细数据,确保分摊数据在编辑后仍然保持逻辑一致。

复制代码
分摊创建时
    ↓
参与者明细入库(未结算)
    ↓
[发起结算] → 更新结算凭证与 AccountingId(已结算)
    ↓
[编辑/删除分摊] → 同步变更或清理参与者明细
4.3 结算流水状态

结算流水(SharedExpenseSettlement)作为分摊功能与记账模块的中间桥梁,记录每一笔实际的资金结算过程。结算流水在创建后立即视为已完成状态,这种设计使得结算记录能够立即驱动参与者状态更新和分摊账目状态刷新,确保业务流程的连贯性和实时性。

作为系统的重要审计流水,结算流水具有强的一致性和不可变性特征。一般情况下,结算记录一旦创建即不允许回滚或修改,仅允许追加新的结算记录。这种不可变的设计确保了分摊记录的真实性和可追溯性,便于后续的对账、审计和历史查询。如果确实需要修正错误的结算记录,系统应当通过追加冲销记录的方式来实现,而非直接修改原始记录。

4.4 提醒状态流转

提醒状态(ReminderStatusEnum)管理分摊提醒的整个生命周期。提醒记录创建后初始状态为待发送(Pending) ,此时记录包含提醒的类型、内容、计划发送时间等信息。定时任务组件(SharedExpenseReminderWatcher)每隔 30 分钟轮询一次数据库,查询所有待发送的提醒记录,并根据计划发送时间决定是否执行发送操作。

当提醒成功发送后,提醒状态转变为已发送(Sent)。若该提醒配置了下一次提醒时间,系统会自动创建新的提醒记录用于后续发送;对于逾期类型的提醒,系统也会据此安排持续催促机制。这样可以确保对长期未完成的账单,用户能够收到周期性的提醒。

当提醒发送过程中出现网络故障、服务异常等问题时,发送失败的提醒记录不会立即丢弃,而是采用重试机制保证可靠性。失败的提醒记录会在 30 分钟后自动回到**待发送(Pending)状态,纳入下一个定时任务轮询周期重新处理。如果连续重试失败超过预设的阈值次数,系统会标记为异常(Failed)**状态并记录失败日志,由管理员进行后续的人工介入处理。

当用户阅读提醒或完成相关业务操作后,提醒状态最终转变为已读/已处理(Read/Handled),此时提醒流程完全闭环。

复制代码
创建提醒记录
    ↓
Pending(待发送)
    ↓
[定时任务触发] → Sent(已发送)
                    ↓ [配置下一次] → 自动创建新提醒
    ↓
  [发送失败] → Failed(失败)
    ↓           ↓ [30 分钟后] → 回到 Pending(重试)
    ↓
[用户完成业务] → Read/Handled(已读/已处理)

五、小结

通过对分摊功能的总体设计与业务流程的详细介绍,我们明确了分摊功能的核心需求、关键业务流程、模块边界与服务划分,以及数据流与状态流转的具体细节。这些设计原则和流程框架为后续的具体实现提供了坚实的基础,确保分摊功能能够高效、可靠地满足用户在日常生活中的费用分摊需求。在接下来的文章中,我们将深入探讨数据模型与数据库设计,进一步细化分摊功能的实现细节。

相关推荐
tryCbest5 小时前
Oracle查看存储过程
数据库·oracle
roman_日积跬步-终至千里5 小时前
【MLOps(1)】MLOps 架构总览与全方位基础:从实验室到生产环境的实战指南
架构
咩咩不吃草5 小时前
【MySQL】表和列、增删改查语句及数据类型约束详解
数据库·mysql·语法
不懒不懒5 小时前
【MySQL 实战:从零搭建规范用户表(含完整 SQL 与避坑指南)】
数据库
ID_180079054735 小时前
Python结合淘宝关键词API进行商品价格监控与预警
服务器·数据库·python
数据知道5 小时前
PostgreSQL 故障排查:万字详解如何找出数据库中的死锁
数据库·postgresql
AI_56785 小时前
阿里云OSS成本优化:生命周期规则+分层存储省70%
运维·数据库·人工智能·ai
choke2335 小时前
软件测试任务测试
服务器·数据库·sqlserver
龙山云仓5 小时前
MES系统超融合架构
大数据·数据库·人工智能·sql·机器学习·架构·全文检索