分毫不差——项目系统设计与数据库设计

分毫不差. 分毫不差. 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

分毫不差——项目系统设计与数据库设计

img

这个作业属于哪个课程2601_CS_SE_FZU
这个作业要求在哪里团队第三次作业——概要设计与数据库设计
这个作业的目标完成同账的系统设计与数据库设计:体系结构和功能模块层次、E-R 和表、设计类图、安全与权限、改进分析和三个 LLM 设计示例、本次绩效,以及排到 11 月下旬的开发计划。同时交两份说明书、答辩 PPT 和评审表
其他参考文献GB/T 8567—2006《计算机软件文档编制规范》;邹欣《构建之法》第 17 章;UML 类图;数据库表结构设计的几条准则;用户密码加密

华为云团队仓库: 分毫不差

目录

  • 一、体系结构与数据库设计
  • 1.1 三层
  • 1.2 功能模块层次
  • 1.3 账本状态
  • 1.4 E-R
  • 1.5 十三张表
  • 1.6 设计取舍
  • 二、类图与安全权限
  • 2.1 设计类图
  • 2.2 登录凭证和密码
  • 2.3 创建者、普通成员、尚未加入
  • 2.4 为什么划成这样
  • 三、改进分析
  • 3.1 成员上的角色列
  • 3.2 结算批次自己的状态
  • 3.3 收据排序号,以及跨到另一本账
  • 3.4 登录会话还没有落点
  • 3.5 LLM 辅助设计示例 1:正式结算单放哪
  • 第 1 轮:只要三张表的关系
  • 第 2 轮:按拒绝的地方重画
  • 第 3 轮:主键、外键、不许级联删
  • 3.6 LLM 辅助设计示例 2:四种身份放哪一列
  • 第 1 轮:身份分开,不要角色列
  • 第 2 轮:换成脚本里的列名
  • 第 3 轮:只补两格
  • 3.7 LLM 辅助设计示例 3:删消费时图片和账怎么办
  • 第 1 轮:封面、收据、删除、冻结
  • 第 2 轮:按表名把五件事收紧
  • 第 3 轮:只改类型、约束和清理
  • 四、组员分工与工作量比例
  • 4.1 本轮的 8 条任务
  • 4.2 五个维度
  • 4.2.1 记 60 的理由
  • 4.2.2 记 100 的项
  • 4.2.3 解开阻塞,各加 2 分
  • 4.3 个人分
  • 4.4 贡献系数
  • 4.5 本次贡献度
  • 五、开发计划安排
  • 5.1 时间以哪一天为准
  • 5.2 按周的里程碑和产出
  • 5.3 设计收口与落库:10 月 20 日–10 月 26 日
  • 5.4 消费与结算接口:10 月 27 日–11 月 2 日
  • 5.5 Alpha:11 月 3 日–11 月 9 日
  • 5.6 冲刺第一周:11 月 10 日–11 月 16 日
  • 5.7 Beta:11 月 17 日–11 月 23 日
  • 5.8 冲刺收尾:11 月 24 日–11 月 30 日
  • 5.9 一个里程碑怎样算过去
  • 5.10 组队后到冲刺的安排
  • 5.11 分工怎么划
  • 5.12 每人的角色和详细开发部分
  • 5.12.1 风车
  • 5.12.2 饶恩哲
  • 5.12.3 whisper
  • 5.12.4 circlexx
  • 5.12.5 叶银珍
  • 5.12.6 陈林祺
  • 5.12.7 李润君
  • 5.12.8 G_bamboopole
  • 5.13 各周交到谁手里
  • 5.14 里程碑

一、体系结构与数据库设计

同账是一本多人账:谁垫了钱、谁该摊、结束时最少转几笔。这一节写四件事:系统分成哪三层、功能按哪七块切开、十三张表在 E-R 上怎么连、以及这些切法要挡住什么。金额在库里和接口里都是整数分。账本状态只有进行中、结算中、已结清。

鼓山一日用来核对整条路径。四人、三笔消费,合计 30000 分。正式转账 2 笔、共 9000 分。四人净额相加为 0。

1.1 三层

手机负责把表单填对、把结果画出来。允不允许写、金额算成多少,由服务端在锁住这本账之后重算。PostgreSQL 只按参数落行,并守住单行就能看住的约束。

三层是模块化单体,同一次课程项目里只有一个 API 进程。手机拿不到数据库地址。表示层收操作、发 HTTPS、把错误留在当前页。业务层认会话、认成员、认状态,事务从这里开。数据层执行参数化查询和行锁,查询结果回到业务层之后才决定页面上说什么。

img

图2-1 分层架构。自上而下是页面、服务、库。contracts 两边共用字段形状,domain 两边共用整数分、余分和最少转账,这两包不引用 Node、React Native 或库表实体。手机上先看到的预览只供当场看,正式结果以服务端重算为准。

层技术这一层做的事这一层不碰的事
表示层React Native 0.86.3、Expo SDK 57、React 19.2.3页面、面板、本地校验、把错误留在当前页最终权限,数据库模型
业务层Fastify 5.12.7、TypeScript 6.0.3、Zod 4.6.7会话、权限、状态、事务、重新分摊决定页面跳到哪一屏
数据层Drizzle 0.45.4、pg 8.23.1、PostgreSQL 17参数化查询、约束、行锁、bytea 图片业务上允不允许这笔账
共享contracts、domain跨端字段和纯函数Node、React Native、库表实体

一次写入按这个顺序走:

  1. 手机把表单交给 contracts 里的字段形状,金额先在本地看成整数分。
  2. HTTPS 把请求送到 Fastify。Zod 先看格式,会话再看是谁。
  3. 业务层锁住这本账,重查成员和状态,用 domain 再算一遍分摊或结算。正式方案取这次重算的结果。
  4. 同一事务里写消费、分摊、图片关联、版本和幂等结果。失败则整笔回滚,原表单还在。

外面进来的是账号、邀请码、消费表单和已还声明,出去的是账本、余额、结算方案和错误码。顶层数据流只画这些来源和去向,不画页面跳转。

img

图2-5 顶层数据流。成员交账号、邀请码、消费和已还声明,创建者另交邀请管理、正式结算和结清确认,手机系统交选中的图片和扫码内容。系统交回账本、流水、余额、方案、状态和可复制的文字。

进了系统之后,同一批表上有五块加工:

  • 账号与资料读写 users、auth_sessions,并记一条操作摘要。
  • 账本与成员读写 ledgers、ledger_members、invitations。结清和本人归档也落回这里。
  • 消费与分摊读写 expenses、expense_splits,图片内容和收据引用在 image_assets、expense_images。
  • 余额统计只读有效消费、分摊和已登记转账,自己不插行。
  • 结算与归档读写 settlement_batches、settlement_transfers,并把账本状态写回去。

记账、加入、正式结算、登记已还都带幂等键,成功结果和业务写在同一个事务里,落在 idempotency_keys。关键操作另写 operation_logs。账号级日志可以不挂账本。

正式环境是一台演示机。手机只拿公开的 API 地址。Caddy 收 443 并持有证书,Fastify 听内部 3300,PostgreSQL 在私有网络里,数据库端口不发布到公网。数据库口令只在服务端环境里。图片二进制放在库里的 bytea,不另开对象存储。开发机走局域网,库在本机 35432,这一段可以明文。

img

图5-3 部署结构。开发机走局域网和本机 35432,正式库不发布公网端口。

1.2 功能模块层次

七个一级模块,叶子对着 FR01 到 FR30。划分按稳定的业务规则:账号、账本、邀请、消费、余额、结算、个人资料,各有自己的写入对象。页面草稿会改,同学分工也会改,这两样不拿来切模块。图片、审计、幂等给各模块共用,不单列成用户能点开的一级模块。

img

图2-10 功能模块层次。根是同账,下面七块,每块再挂到具体的 FR。余额统计只有查询,没有自己的账本写入。

模块需求服务端目录手机目录读写
账号FR01–FR03 注册、登录、退出api/modules/authmobile/features/authusers、auth_sessions
账本FR04–FR06 创建、列表、详情api/modules/ledgersmobile/features/ledgersledgers、ledger_members
成员邀请FR07–FR11 名单、分享、重置、加入api/modules/invitations账本模块里的邀请页invitations、ledger_members
消费FR12–FR18 记账、分摊、流水、收据api/modules/expenses、imagesmobile/features/expensesexpenses、expense_splits、expense_images、image_assets
余额统计FR19–FR20 余额、支出统计api/modules/insightsmobile/features/insights只读有效消费、分摊和已登记转账
结算FR21–FR27 预览、正式结算、登记、结清、归档api/modules/settlementsmobile/features/settlementssettlement_batches、settlement_transfers;归档写 ledger_members
个人中心FR28–FR30 资料、通知、协议api/modules/usersmobile/features/profile只改本人那一行 users

余额统计自己不写账。协议页不产生业务写接口。支撑能力 audit、shared、images 跟在同一次 service 事务里,不单独给用户一条菜单。

一次请求先落到上表的那个目录,再由该目录里的 service 决定写哪几张表。页面只跟自己的 feature 说话,service 再进 repository。例如新增消费走 expenses,同一事务里写消费、分摊,有收据再写图片关联,并给账本 version 加 1。

鼓山这条路径把七个模块串成一次可检查的运行:

  1. 账号:四人登录。
  2. 账本:创建者创建「鼓山一日」,创建者同时成为第一名成员,状态为进行中。
  3. 邀请:另外三人凭有效码加入。已是成员则返回原来那一行,不追摊加入前的消费。人数含创建者,到 12 为止。
  4. 消费:三笔。小安付食堂 12000 分,四人均分;小白付门票 12000 分,四人均分;小陈付车费 6000 分,只在小安和小陈之间均分。
  5. 余额:总支出 30000 分。小安净额 +3000,小白 +6000,小陈 −3000,小丁 −6000,相加为 0。
  6. 结算:成员可以预览和复制。预览不插结算单。创建者确认后写入正式单,两笔转账共 9000 分,账本进入结算中。
  7. 登记与结清:两笔都登记之后,创建者结清。各人再把自己的账本收进历史,只改本人的 archived_at。

查询每一步都先确认是本账成员。冻结之后再记账,服务端拒绝,原表单留着。普通成员可以预览,正式结算和整本结清只交给创建者。

img

图5-1 运行时模块怎么接上。上表的目录仍是七个,这条链说明鼓山一次活动按什么次序调用它们。查询都先做成员校验。

三条主路径各有一张活动图,看步骤和分支。手机、服务端、数据库各做哪一段,写在对应的图下面。

记账与分摊。 成员在手机上填金额、付款人、参与人和分摊方式。手机先看格式,不合法就停在原字段。提交时带上幂等键。服务端认人之后锁账本,重查权限、状态和版本,再用整数分重算分摊。合计对得上,才在同一事务里写消费、分摊、图片关联、版本、审计和幂等结果。任一步失败就回滚,原表单还在。成功则回到来源流水,并刷新摘要。

img

图2-2 记账与分摊。本地先看格式,服务端锁账本、重算分摊,失败就回滚。

结算。 成员打开预览时,服务端在同一次只读快照里读取账本版本、有效消费和分摊,算出最少转账,把版本和方案返回去,不冻结、不插正式单。创建者确认后另开写事务:锁账本,核对仍是进行中、请求里的版本仍等于 ledgers.version,然后重新汇总、重新求解。有人净额不为 0,就保存转账明细并进入结算中。每人净额都是 0,就保存 0 笔正式单并直接已结清,不生成金额为 0 的转账。核对失败则回滚,页面提示重新打开预览。

img

图2-3 结算。预览不写表。创建者确认后,有非零净额进入结算中,全员净额为 0 则直接已结清。

还款、结清与归档。 钱在系统外转。付款人或创建者在结算中登记一整笔已还,事务里写登记人、时间和说明,剩余净额重算,消费总额不动。全部已登记且逐人剩余净额为 0 之后,创建者再确认结清,账本写成已结清并记下 settled_at。成员本人随后归档,只更新自己那一行的 archived_at。条件不够就停在原页。

img

图2-4 还款、结清与归档。登记已还不改消费总额。归档只写本人那一行。

1.3 账本状态

库存的三个值是 ACTIVE、SETTLING、SETTLED。页面上写成进行中、结算中、已结清。三个值都是字符串,由检查约束卡住,不另建枚举类型。已结清之后没有回到进行中的操作。归档只改成员自己的 archived_at,不推动账本状态。正式结算单自己不存状态,这张单走到哪一步,看所属账本。

从进行中出去有两条路。创建者确认零笔方案,且逐人净额为 0,直接到已结清。创建者确认正式结算,且存在非零净额,进入结算中;付款人或创建者可以反复登记整笔已还,状态仍是结算中。创建者确认结清时,每一笔都已登记,且逐人剩余净额为 0,才到已结清。进行中留在本状态的,是成员记账和创建者管理邀请。已结清留在本状态的,是本人归档和查询历史。

img

图5-2 账本状态。

当前谁、做什么变成拒绝时
进行中成员记账,或创建者管邀请仍是进行中FORBIDDEN、VERSION_CONFLICT
进行中成员预览仍是进行中,不写结算单FORBIDDEN
进行中创建者正式结算,有人净额不为 0结算中FORBIDDEN、VERSION_CONFLICT
进行中创建者确认,每人净额都是 0已结清,0 笔转账同上
结算中付款人或创建者登记一整笔已还仍是结算中FORBIDDEN
结算中创建者结清,每笔已登记且剩余净额为 0已结清OUTSTANDING_TRANSFERS
结算中或已结清再记账、加人、重置邀请状态不动LEDGER_FROZEN
已结清本人归档状态仍是已结清未结清则 LEDGER_STATE_INVALID

鼓山走右边这条:进行中记账,创建者确认后进入结算中,两笔转账登记完,创建者结清。四人净额在确认前已经相加为 0,但逐人并不都是 0,所以不会走左边的零笔分支。

1.4 E-R

实体按稳定的业务对象来划。用户是账号,成员是用户和某一本账的关系。记录人、垫付人、分摊人都引用成员,不引用昵称。消费和成员通过分摊明细形成多对多。图片的二进制和「这一笔用了哪张图」分成两个对象。正式结算单和转账分开。还款是转账上的状态和登记属性,不另建还款实体。会话、幂等、审计是工程上要落下的行。

下面这一张是总体 E-R。账号、成员、消费、结算四块都在上面,基数按鸦爪读。

img

总体 E-R。付款人、收款人、记录人各走自己的外键。临时图片的 ledger_id 可以为空,所以「图片属于账本」是 0..1 对 0..;绑定之后,封面和收据的复合外键才能引用它。

四块在总图上的读法:

  • 账号与账本。 一个用户创建 0 到多本账,并持有 0 到多条会话。成员把用户和账本连起来。退出会话只作废那一行,不删用户。
  • 成员与邀请。 一本账有 1 到 12 名成员,含创建者。邀请记住是哪一名成员发出的。重置后旧行还在,只是写上 revoked_at。有效与否由撤销时间、过期时间和账本状态一起算。
  • 消费、分摊与收据。 一本账有多笔消费。每笔分给 1 到 12 名本账成员。二进制在 image_assets,收据关联只保存这一笔用了哪一张,一笔最多一张。封面可以是预设关键字,也可以是上传图,两列恰好有一个。
  • 结算与转账。 一本账最多一张正式结算单。一张单有 0 到 11 笔转账:12 人时最多 11 笔,全员净额为 0 则 0 笔。登记人可以空着,等到这笔转账记成已还再填。
从到基数含义
用户账本1 对 0..一个人可以创建多本账
账本成员1 对 1..12含创建者,最多 12 人
账本邀请1 对 0..重置后旧码还在,只是写上撤销时间
账本消费1 对 0..一本账有多笔消费
消费分摊明细1 对 1..12每笔至少分给一个人
消费收据关联1 对 0..1最多一张收据
图片收据关联1 对 0..1一张图只挂一笔消费
图片账本封面0..1 对 0..1也可以只用预设封面,不上传
账本正式结算单1 对 0..1一本账最多一张正式单
结算单转账1 对 0..1112 人时最多 11 笔;全零则 0 笔
用户会话1 对 0..每次登录一行,退出不删行

1.5 十三张表

库名 tongzhang,PostgreSQL 17,UTF-8。十三张表里,业务和关联 10 张,会话、幂等、审计 3 张。字段用 snake_case,金额以 _cents 结尾,时间以 _at 结尾,消费日期用 _on。类上的 camelCase 由 mapper 对照过来。主键、外键、唯一约束和检查约束都有名字。字段全文在 同账-建表设计.sql。

表和表之间的外键如下。箭头从引用表指向被引用表,删除和更新都是 RESTRICT。删掉一本账或一名成员,不会把历史消费和转账一起带走。

img

表间关联。财务记录限制删除。能由查询算出来的余额不在这张图里占一张表。

(1) 账号

users 保存登录身份。邮箱去首尾空格后按小写存放,用户名 2 到 30 字。password_hash 只存 Argon2id 编码串。auth_sessions 每次登录一行:token_hash 唯一,expires_at 为创建后 30 天,退出写 revoked_at。原文令牌不在这张表里。

表关键列约束
userspassword_hash、邮箱、用户名邮箱按小写保存;密码只存 Argon2id 编码串
auth_sessionstoken_hash、expires_at、revoked_at摘要唯一;到期和撤销都留在这一行

(2) 账本

ledgers.status 只取三个字符串。version 从 1 起,消费或成员一变就加 1,正式结算拿它和预览时的版本对。封面是 cover_key 与 cover_image_id 恰好一个有值。已结清当且仅当 settled_at 有值。ledger_members 没有角色列,(ledger_id, user_id) 唯一。invitations.code 是六位无歧义字符,全局唯一,有效期晚于创建时间,重置只填撤销时间。

表关键列约束
ledgerscreated_by_user_id、status、version、cover_key、cover_image_id、settled_at状态三值;version 从 1 起;封面两列恰好有一个;已结清当且仅当 settled_at 有值
ledger_membersledger_id、user_id、joined_at、archived_at(ledger_id, user_id) 唯一;没有角色列
invitationscode、expires_at、revoked_at六位无歧义字符,全局唯一;有效期晚于创建时间

(3) 消费

expenses.amount_cents 是 1 到 999999999 的整数分。记录人创建后不改。垫付人可以不出现在分摊明细里。split_mode 取人均、按份、按金额。deleted_at 有值的行退出汇总,行本身还在。expense_splits 的主键是消费加成员,金额允许 0;按份时 shares 为正整数,其余方式为空。外键都带 ledger_id,账本 A 的消费分不到账本 B 的人。

图片单独放。image_assets.kind 是封面或收据,content 为 JPEG 或 PNG 的原始二进制,1 到 1048576 字节,并等于 octet_length(content)。宽、高各 1 到 4096,像素个数用 width::bigint * height 与 16000000 比较。未绑定的图 ledger_id 为空,只清理超过 24 小时仍未绑定的那些。expense_images 以消费为主键,一笔一行,一张图只出现一次。

表关键列约束
expensesrecorder_member_id、payer_member_id、amount_cents、version、deleted_at金额 1 到 999999999 分;记录人创建后不改;软删除不删行
expense_splitsexpense_id、member_id、ledger_id、shares、amount_cents主键是消费加成员;外键都带 ledger_id
image_assetsledger_id 可空、kind、contentCOVER 或 RECEIPT;字节数等于 octet_length(content)
expense_images主键 expense_id、image_id一笔一行;一张图只出现一次

(4) 结算和工程

settlement_batches.ledger_id 唯一,所以一本账只有一张正式单。确认时写入消费总额、转账总额、笔数、来源版本,以及当时每人净额的 jsonb 数组。之后新的消费不再改写这份快照。0 笔时转账总额为 0。settlement_transfers 只存 PENDING 或 PAID。待登记时,登记人、时间、说明都是空;记成已还后三者一起有值。说明最长 200 字。

idempotency_keys 把用户、操作、请求摘要和成功结果放在同一行,和业务写同一个事务。operation_logs 记操作者和可选的账本。这两张表不存密码,也不存令牌原文。

表关键列约束
settlement_batchesledger_id、source_version、两个总额、transfer_count、net_snapshotledger_id 唯一,所以一本账一张正式单;快照是 jsonb 数组;0 笔则转账总额为 0
settlement_transferspayer_member_id、payee_member_id、status、登记三列只存 PENDING / PAID;待登记时登记人、时间、说明都空
idempotency_keys用户、操作、请求摘要、成功结果同一次重试和业务写在同一个事务里
operation_logs操作者、可选的 ledger_id账号级日志可以不挂账本

派生数不进表:总支出、已付、应摊、消费净额、剩余净额、类别占比、预览方案、登记进度。它们在查询时从有效消费和已登记转账算出来。正式结算才把当时的净额写进 net_snapshot。

鼓山落表之后,应当能查出下面这组数。消费三行,金额 12000、12000、6000,分摊合计 30000。正式单一行:消费总额 30000,转账 2 笔、9000 分。转账两行:小陈付给小安 3000,小丁付给小白 6000。

成员已付应摊消费净额
小安120009000+3000
小白120006000+6000
小陈60009000−3000
小丁06000−6000
合计30000300000

两笔都登记之后,逐人剩余净额为 0,总消费仍是 30000 分。对不上这组数,这版表不能当作鼓山验收通过。

1.6 设计取舍

能由消费和已登记转账算出来的数,不另建一张会过期的表。确认过的方案要留下,所以快照是例外。

余额不建表。 总支出、应摊、净额会随每一笔有效消费变化。若再存一份余额,改一笔消费就要改两处。查询时用 paid − shared 得到消费净额,再用已登记转出、转入得到剩余净额。全员合计应为 0;合计为 0 并不表示逐人都是 0。统计消费总额时排除已软删除的行,也排除还款。正式结算把当时的净额写进 net_snapshot,此后这份数组不再跟着新消费改。

标识用 uuid。 昵称会改。历史消费、分摊和转账认的是成员 id 和用户 id。改显示名不影响「这笔是谁记的」。

同账本用复合外键。 分摊、收据、转账都带 ledger_id,外键同时指向本账的消费和本账的成员。只改其中一端会被拒绝。跨账引用在数据库里就过不去,不必等服务端想起来再查一次。

金额用 bigint 分。 接口传整数字符串。12000 表示 120 元。按份或人均时,先做整数除法,余数按余数从大到小逐分送给成员;余数相同,按成员 UUID 字典序升序。10000 分三人均分,结果是 3334、3333、3333,多分的那 1 分给稳定 id 最小的人。相同的人、相同的金额、相同的 id,每次得到相同的结果。按金额不自动调平,调用方给出的非负金额合计必须等于总额。

消费软删除。 只写 expenses.deleted_at。汇总排除它,分摊行和收据关联还在。这样一条删除不会把当时的分摊依据一起清掉。

财务外键 RESTRICT。 删父行会被数据库拒绝。改历史要走软删除、撤销邀请或登记已还,而不是删掉账本或成员。

幂等键与业务同事务。 超时之后用同一个键重试,提交过的那一次把原来的成功结果交回去,不会写出第二笔同样的消费,也不会把登记时间改掉。

取舍落到库里挡住什么
第三范式,快照单独标明余额不建表;net_snapshot 只在正式结算时写改一笔消费后,余额和快照各写各的
标识用 uuid不拿昵称当外键改显示名把历史账连丢
同账本用复合外键(ledger_id, 成员或消费 id)账本 A 的消费分给账本 B 的人
金额用 bigint 分接口传整数字符串浮点元在分摊余数上对不齐
消费软删除只写 deleted_at,汇总排除它删行把分摊和收据一起级联掉
财务外键 RESTRICT删父行会被数据库拒绝用删除账本或成员来改历史
幂等键与业务同事务成功结果和账一起提交超时重试写出第二笔同样的消费

跨行才能知道的规则放在服务端,不写成一条跨表的检查约束。例如分摊合计必须等于消费金额、净额之和必须为 0、结清前每笔都已登记。这些在锁住账本之后、提交之前重算。单行就能看住的,交给检查约束:金额范围、状态取值、封面两列恰好一个、待登记时不能已经写着登记人。

二、类图与安全权限

类名和表名是同一套东西的两种写法。属性用 camelCase,字段用 snake_case,由 mapper 对照。事务放在 service,不放在页面,也不放在 repository。这一节写设计类图怎么对应到表,登录凭证和密码放在哪,三种身份各自能做什么,以及为什么身份要拆开认。

2.1 设计类图

核心类和十三张表一一对应。登记已还不单独建类,记在 SettlementTransfer 上,方法是把这一笔从待登记写成已登记。成员余额不建类,打开余额页时现算。IdempotencyRecord 和 OperationLog 是每次写入都要带上的工程对象,用户能点到的仍是账本、消费和结算。

img

图3-1 核心设计类图。Ledger 到 SettlementBatch 是 1 对 0..1。Expense 上的记录人和垫付人是两条指向 LedgerMember 的线。LedgerMember 没有角色属性。

类上的方法和表上的约束是同一件事的两面。Ledger 是否还能记账,看的是 status。Expense 改完要带上自己的 version,对不上就拒绝。SettlementBatch 没有自己的状态字段,这张单处于什么阶段,看所属账本。创建者必须同时有成员行,由创建账本的那一个事务保证。人数上限和分摊人数在锁内再数一遍。

类对上的表这一版卡住的关系
Userusers创建账本、持有会话、上传图片
AuthSessionauth_sessions一个用户多条会话;退出只作废这一条
Ledgerledgers1 到 12 名成员;正式结算单 0 或 1 张
LedgerMemberledger_members无角色列;archivedAt 只属于这一行
Invitationinvitations账本发出去的每一次邀请都留一行
ExpenseexpensesrecorderMemberId 与 payerMemberId 是两列
ExpenseSplitexpense_splits一笔消费 1 到 12 条
ImageAssetimage_assets封面和收据都从这里取二进制
ExpenseImageexpense_images一笔消费最多一张收据
SettlementBatchsettlement_batches写入后不再按新消费改快照
SettlementTransfersettlement_transfers待登记、已登记,以及登记人、时间、说明

img

图4-1 模块调用。页面进到对应的 service,service 再进表。手机不绕过服务端去写库。一个 feature 只调用自己的模块;结算要读消费,也是结算 service 在服务端读,而不是手机把算好的转账列表送进库。

2.2 登录凭证和密码

密码和会话分开存。原密码、令牌原文不进业务表、日志和幂等响应。库被拷走时,拿到的是不可逆的密码编码和令牌摘要,换不回下一次登录用的原文。

密码。 users.password_hash 只存 Argon2id 编码串。内存 19456 KiB,时间代价 2,并行度 1,16 字节随机盐,输出 32 字节。盐和参数写在编码串里,没有另一把可逆的密码密钥。上线前会量登录耗时,以后只把参数往更慢的方向调。

会话。 登录成功时生成 256 位随机令牌,原文只这一次返回手机,放在 SecureStore。库里的 auth_sessions.token_hash 是 SHA-256 摘要。expires_at 为创建后 30 天,固定到期,不用 JWT 刷新链。退出成功则写 revoked_at,这一行留着,旧令牌不能再换一条新会话。服务端没确认撤销时,手机提示未退出,并清掉本地凭证。

出现的地方令牌密码
登录或注册的那一次响应原文,仅这一次不回传
手机 SecureStore原文不保存
users.password_hash—Argon2id 编码串
auth_sessions.token_hashSHA-256 摘要—
日志、幂等结果、图片缓存不写不写

邀请码是六位可读字符串,存在 invitations.code,给创建者复制和分享。它能加入一本账,不能代替登录,也不能当成支付凭证。猜码按每人每分钟 30 次封顶,登录按 IP 和规范化账号 15 分钟 10 次封顶。首版限流记在单进程里,进程重启会清零;多实例之前要另做。

传输上,正式环境走 HTTPS,证书在 Caddy。开发时局域网可以明文,数据库口令只放在服务端环境里。业务角色没有建库权限,迁移用单独的角色。图片读取要先过登录和归属,响应带 Cache-Control: no-store,手机不把图片持久缓存。SQL 一律参数绑定,错误响应不带 SQL 和堆栈。

2.3 创建者、普通成员、尚未加入

三种身份都从数据里认,不在成员表上再存一列角色,也不建全局角色表。创建者看 ledgers.created_by_user_id。普通成员看本账有没有自己的成员行。尚未加入就是本账没有这一行。记录人、垫付人、分摊人写在具体一笔消费上,同一个人可以同时占这三种。

img

图2-11 用况关系。未加入者只能注册、登录和凭码加入。创建者的箭头连到邀请和正式结算,同时也连到记账和本人归档。普通成员能记账、预览、登记自己应付的转账,不能重置邀请,也不能整本结清。

  1. 创建者。 ledgers.created_by_user_id 等于当前用户,并且这个人在 ledger_members 里有一行。建账的那个事务里同时写入这第一名成员。能管邀请、改删进行中的任意消费、正式结算和整本结清,也能做普通成员能做的记账、预览、登记自己应付的转账和本人归档。创建者读不到其他账本,也读不到别人的会话。
  2. 普通成员。 本账有成员行,且用户 id 不等于创建者。能记账、查看、预览和复制已经生成的方案。编辑或删除只限于 expenses.recorder_member_id 是自己的那些笔,还要带上这笔消费的 version。登记已还只限于 settlement_transfers.payer_member_id 是自己的那一笔。
  3. 尚未加入。 本账没有成员行。可以注册、登录、改自己的资料,凭有效邀请码看最小预览:账本名、创建者昵称、当前人数、是否已是成员、能否加入。看不到流水、余额、完整名单、收据和结算。未登录者只能碰到注册、登录和公开的健康检查。

记录人、垫付人、分摊人写在具体一笔消费上。

  • 记录人是 expenses.recorder_member_id,创建后不再改。谁能改、谁能删,认的是这一列,再加上是不是创建者。
  • 垫付人是 expenses.payer_member_id,可以不出现在分摊明细里,也不因此获得改删权。
  • 分摊人是 expense_splits 里的一行。同一人可以既记账、又垫钱、又被分到。

「允许」还要满足最后一列。页面上的按钮只决定发不发请求。这张表也不表示手机可以连上数据库。

操作创建者普通成员尚未加入还要满足
查看本账、消费、图片、余额允许允许不允许仅所属账本;图片再查归属
新增消费允许允许不允许进行中
编辑或删除消费允许允许不允许进行中;普通成员仅本人记录,并核对 expenses.version
查看、复制、分享邀请允许不允许不允许进行中;未加入者只能凭码看最小预览
重置邀请允许不允许不允许进行中;旧码写入 revoked_at,新码 7 天
预览结算允许允许不允许进行中;不插入结算单
正式结算允许不允许不允许进行中,且请求里的版本等于 ledgers.version
复制已经生成的方案允许允许不允许进行中复制刚预览的文字;结算中和已结清复制已落库的那一份
登记已还允许允许不允许结算中;普通成员须为该笔付款人;重复登记返回原记录
整本结清允许不允许不允许每笔已登记且剩余净额为 0;全零在正式结算时直接结清
本人归档允许允许不允许已结清;只改本人 archived_at
修改本人资料允许允许允许已登录,只改自己,与在哪本账无关
凭邀请码加入允许允许允许进行中、未满 12 人;已是成员则返回原行,不追摊旧消费

服务端拒绝时用固定错误码,不把 SQL 返回给手机。

  • 非成员,或普通成员改别人记下的消费:FORBIDDEN
  • 冻结后还记账、加人、重置邀请:LEDGER_FROZEN
  • 预览之后账被改过,版本对不上:VERSION_CONFLICT
  • 分摊合计不等于消费金额:SPLIT_SUM_MISMATCH
  • 未结清就归档:LEDGER_STATE_INVALID
  • 转账没登记完就结清:OUTSTANDING_TRANSFERS
  • 第二张收据,或图片不属于本账:RECEIPT_LIMIT、IMAGE_INVALID
  • 金额不是合法的整数分:VALIDATION_ERROR
  • 猜码或登录过频:RATE_LIMITED

2.4 为什么划成这样

写入顺序固定,后一步看到的是前一步锁住之后的行:

  1. 格式。金额必须是合法的整数分字符串。
  2. 会话。认出用户,并确认这条会话没过期、没撤销。
  3. 幂等。同一个键若已经成功,直接交回原来的结果。
  4. 锁账本。锁住之后再数人数,两个人同时加入也过不了 12 人。
  5. 重新查成员和创建者。按钮当时亮着,锁内再读一次。
  6. 状态、版本、金额与关联。消费或成员一变,ledgers.version 就加 1。预览时看到的版本和确认时对不上,正式结算就拒绝。
  7. 提交。失败则整笔回滚。
这样划原因
创建者只认 created_by_user_id邀请、正式结算、结清都要先认出同一个人。成员行负责「在不在这本账」,创建人标识负责「是不是这本账的创建者」
创建者同时是第一名成员创建者也要记账、归档。建账的那个事务里同时写入这第一行
记录人、垫付人、分摊人分三处一笔账里同一个人可以既记、又垫、又被分到。三列各认各的事
尚未加入等于没有成员行最小预览只交账本名、创建者昵称、人数、是否已是成员、能否加入。有了成员行,才进入上面的矩阵
登记已还认转账付款人,不认消费垫付人垫的是当时那一笔消费,还的是结算单上的一笔转账。鼓山里小陈垫的是车费,结算单上小陈要付给小安的是净额 3000 分
按钮和手机预览不算权限锁账本之后再读状态。检查时还在进行中、写入时已经结算中,这一笔就回滚

健壮性上,这些输入在锁内就被挡住,原表单留着:

  • 消费金额从 1 分到 999999999 分。分摊金额可以为 0,合计必须等于这笔消费。
  • 分摊人数 1 到 12,成员不重复,并且都在本账。按份的份数是正整数。
  • 重复加入、重复登记已还,都返回原来的那一行,不改时间、不插第二行。
  • 0 消费或每人净额都是 0 时,预览给出空方案;创建者确认后保存 0 笔正式单并直接结清,不生成 0 元转账。
  • 一次要读好几项合计时,用同一次 SQL 快照。不把这一秒的消费总额和下一秒的净额拼在一起。
  • 已知的业务冲突映射成上面的错误码。未知的约束错误只进内部日志。

三、改进分析

10 月 16 日的需求分析答辩上,老师、助教和其他组没有向同账提问。

现场没有留下问题。组里后来把课程社区里其他组的第二次作业打开看过,看完回到同账自己的稿上:需求规格说明书里的类属性,和这次要写进表的字段,有没有两句不能一起成立。能一起成立的不动。成员余额本来就是查询时算出来的,这一版仍然不建余额表。

下图分四条,每条从左看到右。左边是讨论前写在类上的,右边是收进表里的。

img

3.1 成员上的角色列

问题。

需求规格说明书 3.1.5 里,LedgerMember 带 role,取值是创建者或普通成员。账本上同时有创建人。创建者、记下这笔账的人、垫钱的人、分摊到的人,是四种身份,类图却只给成员准备了一列角色。

改了什么。

ledger_members 去掉角色列,只留账本、用户、加入时间、本人归档时间。创建者改为读取 ledgers.created_by_user_id,并且创建账本时这个人必须同时成为第一条成员。记录人、付款人写在消费上,分摊人写在分摊明细上。权限矩阵仍分创建者、普通成员、尚未加入,服务端查的是创建人标识和有没有成员关系,不读角色列。数据库设计说明书 3.1.1 账本成员,系统设计说明书 8.3、8.4。

为什么改。

重置邀请、正式结算、整本结清都要先认出创建者。角色列和创建人各写一次,两次写入可以不一致,权限矩阵就没有唯一依据。记录人、付款人、分摊人如果也塞进这一列,一笔账里同一个人只能占一种身份,和“谁记的、谁垫的、谁摊的可以不是同一个人”对不上。

3.2 结算批次自己的状态

问题。

需求规格说明书 3.1.4 写账本与批次是 1 对 0..,同一段又写同一本账同时最多一个有效批次。3.1.5 的批次属性里还有 status。账本自己的状态已经是进行中、结算中、已结清。

改了什么。

批次不再存状态。类图里账本到正式结算单改为 0..1,一本账最多一批。账本状态仍只取进行中、结算中、已结清。确认时在同一事务里写入消费总额、转账总额、笔数、每人净额快照和来源版本,之后不按新的消费重算这张方案。每一笔转账自己保留待登记、已登记。预览只返回方案,不插入结算单,也不冻结。全员净额为 0 时,确认后直接已结清,不生成金额为 0 的转账。数据库设计说明书 3.1.1 正式结算单,系统设计说明书图 3-1 与 2.3.2。

为什么改。

预览、冻结、结清如果各写一处状态,批次可以是“结算中”,账本仍是“进行中”,后面的人还能继续记账,正式方案就不是确认时的那一张。0.. 也允许同一本账再插第二张正式批次,收款对象会被重算。待登记和已登记是每一笔转账的事,不是整本账的事,放在批次上会把“这本账冻住了”和“这一笔还了没有”混在一起。

3.3 收据排序号,以及跨到另一本账

问题。

需求规格说明书 3.1.3 已写首版每笔最多一张收据,3.1.5 的 ExpenseImage 仍留着 sortOrder。分摊明细只有消费、成员、份数和金额,没有账本。同一本账的约定写的是“服务端在事务里检查”。

改了什么。

expense_images 去掉 sortOrder,用消费做主键,一笔一行。图片二进制放在单独的 image_assets,消费只存引用。封面允许在账本创建前先上传,创建成功后再绑定。分摊明细、收据关联、结算转账增加 ledger_id,外键同时指向本账的消费和本账的成员,只改其中一端会被拒绝。财务记录使用限制删除。冻结之后消费只读。数据库设计说明书 2.4.1、3.1.1,系统设计说明书 8.5、8.6。

为什么改。

排序号是给多张图排队用的。它还在,实现时就会再加第二张收据。同账只放在程序里,仍可能把账本 A 的消费分给账本 B 的人。封面和收据若塞进消费那一行,删消费时会把图片二进制一起抹掉。

3.4 登录会话还没有落点

问题。

需求规格说明书 2.6 把登录会话的载体留到工程准备再定。类图里没有会话表。业务规则已经要求登录后持有会话,失效后重新登录,退出只清除这一次的本机凭证。密码只要求保存哈希,没有写算法,也没有写令牌原文能不能进库。

改了什么。

新增 auth_sessions。主键 id,user_id 指向用户。手机拿到 256 位随机令牌,库里的 token_hash 只存 SHA-256 摘要。expires_at 为创建后 30 天。退出写 revoked_at,这一行保留。密码在用户表改为 Argon2id。系统设计说明书 8.1、8.2,表在数据库设计说明书 3.1.1。

为什么改。

载体不定,退出就没有一行可以作废。令牌原文若覆写在用户身上,旧凭证清不干净,库备份里还会留下能直接登录的原文。密码若可逆或只做无盐摘要,泄露之后可以还原或直接比对。

3.5 LLM 辅助设计示例 1:正式结算单放哪

模型是腾讯混元 Hy4 preview。只谈 ledgers、settlement_batches、settlement_transfers,不谈最少转账怎么算。落点是 同账-建表设计.sql。截图贴在对应一轮旁边。

第 1 轮:只要三张表的关系

我的提示词(大意,原文见截图)

账本只有进行中、结算中、已结清。预览不能冻账。确认后留下当时每人该收该付。净额全是 0 就直接已结清,不写 0 元转账。转账自己有待登记、已登记。

只回答四件:结算单要不要状态列,一本账几张正式单,冻结哪些字段,预览写不写表。

img

AI 回了什么(摘要)

问到的它的回答
要不要状态列要。open / closed,表示这张单登记完了没有
几张正式单同时 open 最多一张;历史上可以有 N 张,用 settled_through_at 切下一轮
冻结什么DECIMAL,另加币种、名册、凭证
预览写不写不写

账本三个状态改成从结算单推出来。结清后再记消费可以回到进行中。结算中的新消费归到下一轮。

img

我采纳

  • 预览不写正式结算单,也不冻结
  • 确认后的付款人、收款人、金额不改
  • 不插入 0 元转账

我拒绝

  1. 结算单自己的状态列
  2. 一轮一轮的历史结算单
  3. 小数金额
  4. 用结算单反推账本状态
  5. 结算中继续记账

状态只在账本上。一本账最多一张正式单。金额是整数分。确认后不能再记消费。已结清不回到进行中。

第 2 轮:按拒绝的地方重画

我的提示词(大意,原文见截图)

  1. 表名 ledgers、settlement_batches、settlement_transfers,金额用整数分
  2. 结算单不要状态;ledger_id 唯一,一本账一张
  3. 确认时留下 source_version、两个总额、笔数、net_snapshot
  4. 转账只有 PENDING / PAID
  5. 净额全 0:仍写这一张单,笔数为 0,账本直接 SETTLED

img

AI 回了什么(摘要)

(1) 到 (5) 的关系它跟上了:1 对 0..1,结算单无状态,预览不落库,整数分,PENDING / PAID。

实现另写了一套:

它写成的差在哪
主键 BIGINT后面要改成 uuid
账本上的列叫 source_version乐观锁列不叫这个名字
ON DELETE CASCADE财务行不能级联删
成员外键只指成员表主键没有绑到本账的成员
把 UNIQUE(ledger_id) 叫幂等键这条只表示一本账一张正式单
可以删转账,也可以删空单正常业务不删这些行

它另外问了三句:第二次确认记在哪,禁止新消费要不要触发器,全部 PAID 之后净额是不是必然为 0。

img

我采纳

一本账一张正式单。结算单不设状态。整数分。转账只有待登记和已登记。预览不写表。

我拒绝

BIGINT 主键,级联删除,账本列叫 source_version,唯一约束当成幂等,业务里删除转账行。第二次确认只改 ledgers.status 和 settled_at。不加结算单列,不加触发器。

第 3 轮:主键、外键、不许级联删

我的提示词(大意,原文见截图)

  • 主键改 uuid
  • 账本列名 version;source_version 只保存确认当时的 ledgers.version
  • 外键 ON DELETE RESTRICT
  • 创建人、付款人、收款人、登记人用 (ledger_id, 成员 id) 指向 ledger_members
  • 转账补 created_at;笔数 0 到 11,顺序号 1 到 11
  • 幂等不放在这三张表上

img

AI 回了什么(摘要)

点过名的结构改过来了:UNIQUE(ledger_id)、复合外键、RESTRICT、settled_at 在账本上、结算单写入后不再 UPDATE。唯一约束也不再被叫成幂等键。

约束还松着。它问回五件事,这一轮就停在这里。

稿子里仍这样它问的
net_snapshot 是对象文本
PENDING 仍可带说明,说明 varchar(500)
version 为 BIGINT,默认 0;结清时间只写在说明里成员变动要不要让 version 加 1;11 笔是不是把人数封顶;结清要不要记人
仍允许删转账和空单确认后再插一行,数据库拦不拦;sequence 要不要连续
唯一约束写成 (id, ledger_id)

img

我采纳

uuid。version 与 source_version 分开。复合外键指向本账成员。外键不级联。第二次确认只写 ledgers.status 与 ledgers.settled_at。UNIQUE(ledger_id) 不当作幂等键。

我拒绝 / 我补充

最后一稿留下。下面五处收进 同账-建表设计.sql。

它最后一稿脚本里为什么动
1net_snapshot 对象文本jsonb 数组;0 笔则转账总额为 0;algorithm_version 为 zero-sum-dp-v1对象过不了数组检查;0 笔和总额会各写各的
2PENDING 可以带着登记人;说明 500PENDING 的登记人、时间、说明都空;说明 varchar(200),不是到账证据还没登记,库里却像记过
3version 从 0 起;结清时间只在说明里version 从 1 起,消费或成员一变就加 1;已结清当且仅当 settled_at 有值。结清人就是创建者,不加 settled_by。笔数上限 11,因为一本账最多 12 人快照要和账本版本同一起点;状态和时间不能拆开
4可删转账,空单也可删业务不删这些行。外键 ON DELETE RESTRICT。确认后不再插入、不再删除转账。不加触发器。sequence 由服务端写成 1 到笔数删掉一笔,冻结的笔数和总额对不上
5UNIQUE (id, ledger_id),转账用 (batch_id, ledger_id) 去引用UNIQUE (ledger_id, id),转账按 (ledger_id, batch_id) 引用。成员仍是 (ledger_id, 成员 id) 指向 ledger_members两边列序不一致时,PostgreSQL 建不起这条外键

快照和 0 笔绑在 settlement_batches:

net_snapshot jsonb NOT NULL,
CONSTRAINT ck_settlement_batches_snapshot CHECK (jsonb_typeof(net_snapshot) = 'array'),
CONSTRAINT ck_settlement_batches_zero CHECK ((transfer_count = 0) = (transfer_total_cents = 0))

登记绑在 settlement_transfers。PAID 必须有登记人和时间:

CONSTRAINT ck_settlement_transfers_registration CHECK (
  (status = 'PENDING'
    AND registered_by_member_id IS NULL
    AND registered_at IS NULL
    AND registration_note IS NULL)
  OR (status = 'PAID'
    AND registered_by_member_id IS NOT NULL
    AND registered_at IS NOT NULL))

版本和结清绑在 ledgers:version integer NOT NULL DEFAULT 1,并且 (status = 'SETTLED') = (settled_at IS NOT NULL)。

外键按脚本的列序:

CONSTRAINT uq_settlement_batches_ledger_id_id UNIQUE (ledger_id, id),
FOREIGN KEY (ledger_id, batch_id) REFERENCES settlement_batches (ledger_id, id)
  ON DELETE RESTRICT ON UPDATE RESTRICT

3.6 LLM 辅助设计示例 2:四种身份放哪一列

模型仍是腾讯混元 Hy4 preview,新开一个对话。只问创建者、记录人、垫付人、分摊人落在哪一列,以及权限矩阵。不建角色表,成员表不放角色列。不重做结算单,不写接口代码。落点是系统设计说明书 8.3、8.4,表在 同账-建表设计.sql。截图贴在对应一轮旁边。

第 1 轮:身份分开,不要角色列

我的提示词(大意,原文见截图)

四种身份不要并成一个角色。创建者才能重置邀请、正式结算、整本结清,进行中可以改删任意消费,结算中可以登记任意一笔已还。普通成员只能改删自己记下的消费,只能登记自己应付的转账。垫付人可以不参与分摊。尚未加入的人只能凭有效邀请码看最小预览。归档只影响自己,且必须已结清。

不要全局角色表,成员表不要角色列。回答两件事:五种身份各在哪一列;一张权限矩阵,列是创建者、普通成员、尚未加入。

img

AI 回了什么(摘要)

没有角色表,也没有成员角色列。创建者认账本上的人,同时有一行成员。记录人、垫付人、分摊人分三处,互不排斥。垫付不给改删权。尚未加入就是没有成员行。归档只改自己那一行。这些留下。

列名和四格矩阵没对上:

它写成的差在哪
creator_id、is_archived创建者列是 created_by_user_id;归档只有 archived_at
recorded_by_member_id、settled_by_member_id记录人列是 recorder_member_id;登记人是 registered_by_member_id,状态只存 PENDING / PAID
成员外键只指 member_id要带 ledger_id,避免指到另一本账
普通成员可以查看邀请;预览三种状态都可以邀请只给创建者,且只在进行中;预览只在进行中
正式结算一定进入结算中全员净额为 0 时,这次确认直接已结清
编辑删除不核对 expenses.version要核对这笔消费自己的版本

img

我采纳

  • 不建角色表,成员表不放角色列
  • 创建者只认账本上的创建人,并且必须有成员行
  • 记录人、垫付人、分摊人分开;垫付人可以不在分摊明细里
  • 查看本账在三种状态下都允许,仅限本账成员

我拒绝

错的列名,成员外键不带账本,邀请和预览放得太宽,全员净额为 0 仍要再结清一次,编辑消费不核对版本。

第 2 轮:换成脚本里的列名

我的提示词(大意,原文见截图)

  1. 列名改为 ledgers.created_by_user_id、ledger_members.archived_at、expenses.recorder_member_id、expenses.payer_member_id
  2. expense_splits 主键 (expense_id, member_id),外键都带 ledger_id
  3. 登记已还写 registered_by_member_id、registered_at、registration_note,状态只用 PENDING / PAID
  4. 邀请只给创建者,只在进行中;预览只在进行中;正式结算要核对 ledgers.version;全员净额为 0 直接已结清

img

AI 回了什么(摘要)

列名改过来了。邀请、预览、正式结算、整本结清四格也按上一问收紧了。expenses.version 和 ledgers.version 分开,不共用。

矩阵里还没有两格:结算中和已结清能不能复制已经生成的方案;凭邀请码加入算不算允许。

img

我采纳

列名、复合外键、邀请只在进行中、预览只在进行中、正式结算核对账本版本、全零直接结清。

我拒绝

先不补别的表。下一问只加「复制已经生成的方案」和「凭邀请码加入」。

第 3 轮:只补两格

我的提示词(大意,原文见截图)

  • 复制已经生成的方案:创建者和普通成员在三种状态下都可以。进行中复制刚预览的文字;结算中、已结清复制已经落库的那一份。不重算,不插新预览,不改账本状态。尚未加入不允许。
  • 凭邀请码加入:只在进行中,并且不满 12 人。已经是成员的不另插一行。结算中、已结清不能加入。

img

AI 回了什么(摘要)

上一稿的列名和其余格子没动。两格都加上了。

补上的它的写法
复制已经生成的方案创建者、普通成员三种状态都允许;尚未加入不允许。不重算,不插新预览,不改 ledgers.version
凭邀请码加入尚未加入只在进行中、人数小于 12 时允许。创建者和普通成员两格写成不允许

正文里又写:已经有成员行时不插新行、不报错。加入成功只加一行 ledger_members,不补旧流水,并且「不参与结算计算」。最小预览写成账本名、创建者昵称、人数/上限、邀请码是否有效。

img

我采纳

复制方案与预览分成两格。预览只在进行中,而且会算;复制三种状态都可以,只取已经有的结果。加入不追摊旧消费,结算中和已结清不能加入。

我拒绝 / 我补充

最后一稿留下。交进 8.3、8.4 的是下面两处。

它最后一稿说明书里为什么动
1创建者、普通成员「凭码加入」写成不允许已是本账成员时仍允许调用。按 (ledger_id, user_id) 返回原来那一行,不插新行,也不当错误矩阵上的不允许,和它自己写的「不报错」是两套结果
2加入后不参与结算计算;预览里带人数上限和邀请码是否有效不追摊加入前的消费。之后被写进新消费的分摊,才进入结算。预览成功体是账本名、创建者昵称、当前人数、是否已是成员、能否加入。无效、过期、已撤销不放进成功体新成员若被记进后来的消费,净额里应该有他。邀请码无效是查询失败,不是预览里的一个字段

3.7 LLM 辅助设计示例 3:删消费时图片和账怎么办

模型仍是腾讯混元 Hy4 preview,再新开一个对话。只问图片放哪、收据怎么挂、删除怎么做、冻结后还能改哪几列。不写上传接口,不重做结算单,也不重做权限矩阵。落点是 image_assets、expense_images、expenses.deleted_at,以及系统设计说明书 8.5、8.6。截图贴在对应一轮旁边。

第 1 轮:封面、收据、删除、冻结

我的提示词(大意,原文见截图)

封面要么用预设,要么用自己上传的一张,两套只能取一种。封面可以在账本创建前先上传。一笔消费最多一张收据。二进制不要放在消费行上。删消费不能把金额和结算记录一起抹掉。结算中之后,消费、分摊、成员和已确认的方案都不再改。

回答五件事:图片放哪、收据怎么关联、进行中怎么删消费、结算中和已结清还能改什么、外键怎样拒绝物理删除。

img

AI 回了什么(摘要)

三件事对上了方向。

  1. 二进制不放在消费行上
  2. 收据单独一张关联表,主键就是消费 id,一张图也不能挂到两笔上
  3. 不要排序号;财务外键用 RESTRICT,不用级联

其余和已经定下的表不一致:

它写成的差在哪
图片在对象存储,主键 BIGINT,另有状态机和 upload_token二进制在库里的 bytea;主键是 uuid;未绑定只是 ledger_id 为空
预设封面是图片表里的共享行,封面还可以是 none预设是账本上的 cover_key,和上传封面恰好有一个
分摊行打上 voided,旧图 7 到 30 天后物理删除,结清后用红冲消费只写 deleted_at;分摊行不动;没有红冲表
结算中还能改封面、账本名、备注,还能补收据结算中只改转账登记
用触发器看账本状态来拦删除状态由服务端拒绝,数据库只拦 DELETE 父行

img

我采纳

图片独立成表。收据以消费为主键,不要排序号。外键不级联。

我拒绝

对象存储、状态机、预设封面共享行、分摊作废标记、红冲、触发器,以及冻结后还改封面和收据。

第 2 轮:按表名把五件事收紧

我的提示词(大意,原文见截图)

  • 表用 image_assets、expense_images。ledger_id 可空,kind 取 COVER / RECEIPT,二进制放 content
  • cover_key 与 cover_image_id 恰好一个有值。收据表主键是 expense_id,image_id 唯一
  • 删除只写 expenses.deleted_at。结算中只改转账的登记四列。已结清只写本人 archived_at
  • 外键 ON DELETE RESTRICT。清理只删未绑定且超过 24 小时的图。已经绑上的不要改回空

img

AI 回了什么(摘要)

ledger_id 可空、kind 在图片上、封面两列互斥、收据主键、软删除、冻结后的可写列、RESTRICT,这些都按上一问改了。

还差五处:

它仍这样要改成
CREATE TYPE,状态叫 in_progressvarchar 检查约束;状态仍是 ACTIVE / SETTLING / SETTLED
图片没有宽高、类型、摘要补上 mime_type、byte_size、width、height、sha256
收据上再加一列 kind,外键带上它不加这列。用途由服务端在绑定和更换时检查
转账列叫 from_member_id / to_member_idpayer_member_id / payee_member_id
旧图为了回收把 ledger_id 改回空绑过账本的图留在原账本上

img

我采纳

未绑定才能被封面或收据的复合外键用上。更换收据只改 image_id,不删行。不是进行中就拒绝再写 deleted_at,错误码用 LEDGER_FROZEN。

我拒绝

枚举类型、多余的 kind 列、转账列名,以及把已绑定的图改回未绑定再删。

第 3 轮:只改类型、约束和清理

我的提示词(大意,原文见截图)

结构不动。去掉 CREATE TYPE。补上图片的类型、大小、宽高和摘要。收据外键只引用 (ledger_id, id)。转账列改回付款人、收款人。清理语句只删 ledger_id 为空且超过 24 小时的行。

img

AI 回了什么(摘要)

五处都改了。kind、mime_type、大小、宽高、sha256 都有检查约束。封面用 num_nonnulls(cover_key, cover_image_id) = 1。收据表有 created_at,没有排序号,也没有第二列 kind。删除、冻结后可写的列、外键动作和 24 小时清理,与上一问一致。

它另外写了两句脚本里没有的做法:宽高相乘没有先转成 bigint;建议再建视图 v_active_expenses 来排除已删消费。

img

我采纳

图片、收据、软删除、冻结列和 RESTRICT 按这一稿。谁能删消费仍按示例 2:进行中,记录人或创建者,并核对 expenses.version。全员净额为 0 时直接结清,仍按示例 1,这一稿没有改那条路径。

我拒绝 / 我补充

最后一稿留下。交进 同账-建表设计.sql 的是下面两处。

它最后一稿脚本里为什么动
1width * height <= 16000000width::bigint * height <= 16000000,宽和高仍各在 1 到 4096两个 integer 直接相乘,边界上的像素积会溢出
2建议视图 v_active_expenses不建这张视图。列表索引带 WHERE deleted_at IS NULL,汇总自己排除已删消费十三张表不再为一条过滤条件加视图

清理任务只保留这一句:

DELETE FROM image_assets
WHERE ledger_id IS NULL
  AND created_at < now() - interval '24 hours';

四、组员分工与工作量比例

这次是第三次作业,按选题博客里的考核方案算贡献系数。

(1) 不数代码行,不数提交次数,也不看谁先交。
(2) 代码是否完成,以组长风车在群里确认为准。
(3) 文稿和 PPT 以风车确认可以发出为准。

这次要交的是系统设计说明书、数据库设计说明书、答辩 PPT、评审表,以及这篇博客。答辩是 10 月 23 日。

顺序固定。跳过前面的人直接改后面的稿,先在群里说。

  1. 饶恩哲交体系结构、功能模块层次、设计类图,以及 13 张表的字段。类名和表名用同一套。
  2. whisper 把记账、分摊、结算、登记已还写成模块接口和数据流,对上类图和表。
  3. 叶银珍把类图、E-R 图、层次图、泳道图收成同一套符号。两份说明书和 PPT 里的图沿用这一套。
  4. 风车写系统安全和权限:登录凭证、密码不明文、创建者与普通成员的权限矩阵,服务端再校验一遍。然后核对两份说明书是同一套名称。
  5. 陈林祺写引言和设计基线,并把改进分析写明改了哪一节。10 月 16 日需求分析答辩没有提问,改动按需求规格说明书和这一版设计的差别写。
  6. 李润君用鼓山手算核库。13 张表上消费与分摊都是 30000 分,结算 2 笔、共 9000 分。对不上就写成不通过。
  7. circlexx 做答辩 PPT。评审表上的项都要有一页:PPT 质量、功能模块层次、接口、安全与健壮性、E-R 和表结构、存在的问题。8 分钟能讲完。
  8. G_bamboopole 把《系统设计说明书》《数据库设计说明书》《系统设计和数据库设计答辩 PPT》的 PDF 传到华为云约定位置。
  9. 风车把华为云仓库链接和三份 PDF 链接写进博客开头,确认可以发出后再交。

每人在华为云仓库里有一次对得上自己任务编号的提交。

这次作业的交接顺序。前面的人交完,下一个人再改后面的稿。

img

4.1 本轮的 8 条任务

一条任务一个负责人。点数只用 1、2、3、5、8。

难度和时效各两档,相乘,不组成四种情况。本轮全部按时,时效都是 1.00。普通难度 1.00。认领时写明要先验证技术方案的,难度 1.25。

任务得分 = 点数 × 难度 × 时效。

编号学号昵称任务做完的标准点数难度时效任务得分
T1072403123饶恩哲体系结构、类图、E-R 和表层次图、设计类图、13 张表的字段能对上鼓山手算81.251.0010.00
T2102400109circlexx答辩 PPT评审表上的项都有一页,8 分钟能讲完81.001.008.00
T3102400307风车两份说明书收口和权限模块、类、接口、13 张表、权限是同一套名称31.001.003.00
T4102400201陈林祺引言、设计基线和改进不看代码能知道系统怎么设计;改进写明改了哪一节。答辩没有提问31.001.003.00
T5102400103李润君数据库验收和鼓山手算30000 分、结算 2 笔、9000 分,对不上就判不通过31.001.003.00
T6072403324whisper模块接口和数据流记账、分摊、结算、登记已还的接口和 13 张表对得上31.001.003.00
T7102400202G_bamboopole华为云仓库和 PDF两份说明书和答辩 PPT 放在约定位置并能打开31.001.003.00
T8052406103叶银珍图的符号统一类图、E-R、层次图、泳道图是同一套符号31.001.003.00

全组任务得分 = 10 + 8 + 3 + 3 + 3 + 3 + 3 + 3 = 36.00。

本期人均 = 36.00 / 8 = 4.50。一半是 2.25。

规模只看任务得分够不够这条线,不看单笔高低。

  • 达到人均,记 100
  • 达到一半、还没到人均,记 60
  • 不到一半,记 0
昵称任务得分和 4.50 比规模分
饶恩哲10.00达到人均100
circlexx8.00达到人均100
风车3.00过半,未到人均60
陈林祺3.00过半,未到人均60
李润君3.00过半,未到人均60
whisper3.00过半,未到人均60
G_bamboopole3.00过半,未到人均60
叶银珍3.00过半,未到人均60

T1 的难度是 1.25,因为认领时写了要先把类图、13 张表和鼓山手算对上。对上之后规模分到顶仍是 100,不会因为单笔 10 分再往上加。T1、T2 记 8 点,因为本阶段看设计和答辩能不能检查,这两条是关键路径。T3 到 T8 各记 3 点,都过了人均的一半,规模没有人记 0。

4.2 五个维度

交付、协作、规范、文档也只打三档:达标 100,能用但有缺陷 60,打不开或对不上任务 0。60 分写明理由。

学号昵称交付规模协作规范文档
072403123饶恩哲10010010010060
102400109circlexx601006010060
102400307风车10060100100100
102400201陈林祺60606010060
102400103李润君60606010060
072403324whisper60606010060
102400202G_bamboopole6060606060
052406103叶银珍6060606060

4.2.1 记 60 的理由

一项一行。分数仍是 60,只把原来挤在一段里的话拆开。

昵称哪一项理由
饶恩哲文档类图和 13 张表能核对,整份答辩还不能按评审表讲完
circlexx交付答辩页按评审表列了,组长还没确认可以发出
circlexx协作PPT 在,没有留下一条指出哪一页该怎么改的记录
circlexx文档页能看,整份演示还不能按清单讲完
风车规模任务得分 3.00,过了 2.25,没有到 4.50
陈林祺交付引言、设计基线和改进能读,组长还没确认可以发出
陈林祺协作文稿在,没有留下一条指出具体下一句该怎么改的记录
陈林祺文档上次的问题写了,整份答辩还不能按清单讲完
陈林祺规模任务得分 3.00,过了 2.25,没有到 4.50
李润君交付鼓山手算能复算,验收表还没到可以发出的版本
李润君协作例子在,没有留下一条指出哪一张表的哪一列要改的记录
李润君文档30000 分、2 笔、9000 分可以复算,整份演示还不能按清单讲完
李润君规模任务得分 3.00,过了 2.25,没有到 4.50
whisper交付记账、分摊、结算、登记已还的接口写了,还有字段没有和表对死
whisper协作接口写了,没有留下一条指出类图哪一个字段要改的记录
whisper文档数据流可以照着看,整份演示还不能按清单讲完
whisper规模任务得分 3.00,过了 2.25,没有到 4.50
G_bamboopole交付目录写了,华为云上的 PDF 还不是可以发出的终稿
G_bamboopole协作目录在,没有留下一条指出哪个文件该放到哪的记录
G_bamboopole规范还没有对上任务编号的提交
G_bamboopole文档链接位置能看,演示还不能按清单讲完
G_bamboopole规模任务得分 3.00,过了 2.25,没有到 4.50
叶银珍交付类图、E-R、层次图、泳道图已经是一套符号,还有一张图没有套完
叶银珍协作符号在,没有留下一条指出哪一张图偏离了这套符号的记录
叶银珍规范图的符号还没有对上任务编号的仓库提交
叶银珍文档主图能看,整份演示还不能按清单讲完
叶银珍规模任务得分 3.00,过了 2.25,没有到 4.50

4.2.2 记 100 的项

谁哪些是 100因为
饶恩哲交付、规模、协作、规范层次图、设计类图、13 张表能和鼓山手算对上,任务编号也对得上
circlexx规模、规范任务得分 8.00,到了 4.50;PPT 的页和评审表条目、任务编号对得上
陈林祺、李润君、whisper规范各自那一块的章节、手算例子、接口和任务编号对得上
风车交付、协作、规范、文档两份说明书收成同一套名称,八条任务也在这张表里

4.2.3 解开阻塞,各加 2 分

昵称加分做了什么
陈林祺+2把上次需求分析答辩的问题写成可以落到具体章节的条目,解开了改进分析没法落笔的阻塞
李润君+2鼓山手算核到 13 张表,是当时别人接不了的验证
whisper+2模块接口把类图和表的字段对齐,解开了对不上的阻塞

4.3 个人分

R = 0.35 × 交付 + 0.25 × 规模 + 0.20 × 协作 + 0.12 × 规范 + 0.08 × 文档。

昵称计算五项结果加 2 分后过程分
饶恩哲0.35×100 + 0.25×100 + 0.20×100 + 0.12×100 + 0.08×60 = 35 + 25 + 20 + 12 + 4.896.8不加96
circlexx0.35×60 + 0.25×100 + 0.20×60 + 0.12×100 + 0.08×60 = 21 + 25 + 12 + 12 + 4.874.8不加74
风车0.35×100 + 0.25×60 + 0.20×100 + 0.12×100 + 0.08×100 = 35 + 15 + 20 + 12 + 890不加90
陈林祺0.35×60 + 0.25×60 + 0.20×60 + 0.12×100 + 0.08×60 = 21 + 15 + 12 + 12 + 4.864.866.866
李润君0.35×60 + 0.25×60 + 0.20×60 + 0.12×100 + 0.08×60 = 21 + 15 + 12 + 12 + 4.864.866.866
whisper0.35×60 + 0.25×60 + 0.20×60 + 0.12×100 + 0.08×60 = 21 + 15 + 12 + 12 + 4.864.866.866
G_bamboopole0.35×60 + 0.25×60 + 0.20×60 + 0.12×60 + 0.08×60 = 21 + 15 + 12 + 7.2 + 4.860不加60
叶银珍0.35×60 + 0.25×60 + 0.20×60 + 0.12×60 + 0.08×60 = 21 + 15 + 12 + 7.2 + 4.860不加60

饶恩哲的五项结果是 96.8,circlexx 是 74.8,都比过程分多 0.8。陈林祺、李润君、whisper 加完 2 分是 66.8,也比 66 多 0.8。这 0.8 不进入过程分。风车的 90、G_bamboopole 的 60、叶银珍的 60 没有这 0.8。

过程分之和 = 96 + 74 + 90 + 66 + 66 + 66 + 60 + 60 = 578。这组数留作本轮过程记录。折小组分不用这 578。

本轮计入 W 的份额按角色定。组长风车 17,主程序饶恩哲 16,答辩汇报 circlexx 13,陈林祺 12,G_bamboopole 11.2,文档李润君 10,功能 whisper 10,功能叶银珍 10。

17 + 16 + 13 + 12 + 11.2 + 10 + 10 + 10 = 99.2。

4.4 贡献系数

W = 这个人的份额 / 99.2。

  • 先得到百分数,再保留两位。
  • 两位之后加起来要是 100%。
  • 小数部分从大到小,每个加 0.01,直到补齐。
  • 小数相同,按封面学号从小到大。
学号计算未补余数贡献度
10240030717 / 99.2 = 17.137097%17.14%17.14%
07240312316 / 99.2 = 16.129032%16.13%16.13%
10240010913 / 99.2 = 13.104839%13.10%13.10%
10240020112 / 99.2 = 12.096774%12.10%12.10%
10240020211.2 / 99.2 = 11.290323%11.29%11.29%
10240010310 / 99.2 = 10.080645%10.08%10.08%
07240332410 / 99.2 = 10.080645%10.08%10.08%
05240610310 / 99.2 = 10.080645%10.08%10.08%

保留两位之后是 17.14 + 16.13 + 13.10 + 12.10 + 11.29 + 10.08 + 10.08 + 10.08 = 100.00%。三个 10.08% 的小数部分相同,这次没有余数要补,不用再按学号加 0.01。

4.5 本次贡献度

学号工作内容贡献度
102400307组长。两份说明书收成同一套:模块、类、接口、13 张表、权限用同一批名称。系统安全和权限矩阵。排期、风险和这次贡献度17.14%
072403123主程序员。体系结构和功能模块层次图;设计类图;E-R 与 13 张表的字段;接口和表对上16.13%
102400109答辩汇报。系统设计和数据库设计答辩 PPT,按评审表讲架构、类图、E-R、接口、权限和开发计划,8 分钟讲完13.10%
102400201引言、设计基线、上次需求分析答辩的改进:评审问题对应到改了哪一节12.10%
102400202华为云仓库。系统设计说明书、数据库设计说明书、答辩 PPT 的 PDF 放在约定位置并能打开11.29%
102400103文档。数据库验收和鼓山手算:消费与分摊 30000 分,结算 2 笔、9000 分,对不上写成不通过10.08%
072403324功能。记账、分摊、结算、登记已还的模块接口和数据流,和类图、表对上10.08%
052406103功能。类图、E-R 图、层次图、泳道图用同一套符号,两份说明书和 PPT 的图样式一致10.08%

17.14 + 16.13 + 13.10 + 12.10 + 11.29 + 10.08 + 10.08 + 10.08 = 100.00%。

五、开发计划安排

组队之后到学期结束,同账按周往前做。每一周写明时间、里程碑、这一周交出来的东西、产品本身要做到哪一步。11 月中下旬是项目冲刺,计划从 11 月 10 日排到 11 月 30 日,盖住中旬的收口和下旬的 Beta、收尾。

八个人,队名分毫不差。产品是同账:一起吃饭、一起出门,记下谁先垫钱、谁该摊,结束时算出最少要转几笔。

选题时技术栈已经定下,后面每一周都沿用这一套。

  • 手机端:React Native、Expo
  • 服务端:Fastify
  • 数据库:PostgreSQL
  • 语言:前后端都写 TypeScript

手机端发出请求,Fastify 处理,PostgreSQL 存账。前后端都写 TypeScript。表示层目录在 mobile/features,业务层目录在 api/modules,金额计算放在共享的 domain,手机上的预览不能代替服务端重算。

选题、原型与需求两周已经过去。这份计划从 10 月 20 日这一周写起,只排同账自己的模块。首版模块仍是账号与登录、账本管理、成员与邀请、消费记录、分摊设置、成员余额、结算与还款、结清与归档,对应 FR01–FR30。排除真实支付、到账校验、离线同步、Web 端、OCR、即时通讯、多币种换算,以及预算、导出、成员移除和取消结算。

编码完成度卡在这些区间:落库这一周 40%–60%,接口这一周 70%–90%。Alpha 之后不再用百分比往上加,改看主路径能不能走通。每一周都用鼓山同一笔账来对。

鼓山一日四名成员,三笔有效消费,库内整数分如下。

成员已付应摊消费净额
小安120009000+3000
小白120006000+6000
小陈60009000−3000
小丁06000−6000
合计30000300000

三笔消费是:小安付食堂 12000 分,四人均分;小白付门票 12000 分,四人均分;小陈付车费 6000 分,只由小安与小陈均分。最少转账两笔,合计 9000 分:小陈付给小安 3000 分,小丁付给小白 6000 分。全员净额加总为 0。对不上这张表,当周里程碑记不通过。

5.1 时间以哪一天为准

10 月 23 日的答辩已经写在这一次作业里。23 日之后按大约七天一周来估。六周的起止都写到日。

助教把截止日期写上作业页面之后,以页面上的时间为准。每一周要做的模块、要交的产出保持不动。

同账从这一周到冲刺结束。10 月 20 日这一周是现在所在的一周,在图的第一格。11 月 10 日起的三周是冲刺,排在第二行。

img

5.2 按周的里程碑和产出

对照表先列结果。里程碑是这一周产品要到达的位置,产出是这一周要交出来、别人打得开的东西。

周里程碑产出同账要做到
10 月 20 日–10 月 26 日设计收口与落库。答辩 10 月 23 日系统设计说明书、数据库设计说明书、答辩 PPT、评审表、这篇博客。测试库迁移能建出 13 张表。鼓山手算表类名与表名一致,金额以分入库。编码 40%–60%。可运行的记账留到下一周
10 月 27 日–11 月 2 日消费与结算接口可用,服务端第一次可访问可访问地址、启动步骤、鼓山账的接口记录(请求、响应、库内行)登录能拿到会话。消费与分摊同一事务写入。结算预览给出两笔转账;正式结算后写入批次和转账,账本进入结算中。编码 70%–90%
11 月 3 日–11 月 9 日Alpha,约 11 月 6 日。自己的手机走通主路径代码规范、测试记录、阶段总结、资源汇总、答辩 PPT、评审表。手机演示录屏或当场操作记录接通账号、建账、六位码邀请、记账、分摊、余额、结算预览与正式结算、还款登记、结清与归档。只演示已经通过的模块
11 月 10 日–11 月 16 日冲刺第一周:主路径收口交接清单、缺陷清单、第二台手机装得上的内部安装包、鼓山回归记录接通扫码加入、按份分摊、按金额分摊、收据、流水筛选。阻断主路径的缺陷清掉。功能集停在 FR01–FR30
11 月 17 日–11 月 23 日Beta 冲刺,约 11 月 20 日前后。地点听老师安排可安装包、可访问接口、用户使用调查、三步验收记录、阶段总结、答辩 PPT、评审表外部用户在自己的设备上独立完成建账、记账、结算预览,得到付款人、收款人与转账金额
11 月 24 日–11 月 30 日冲刺收尾使用调查缺陷清单、修完后的安装包、仍可打开的地址、鼓山收尾回归记录只修挡住上述三步的缺陷。功能集停在 Beta 已验收的范围

11 月中下旬单独列出来。这三周是冲刺,前面三周的接口和 Alpha 是为了让冲刺只收口、只交付。

冲刺周时间里程碑产出验收
第一周11 月 10 日–11 月 16 日,中旬主路径收口,规格内剩余页面接通交接清单、缺陷清单、内部安装包、回归记录第二台手机能登录、建账、记一笔人均消费、打开结算预览。扫码、按份、按金额、收据、筛选有入口
第二周11 月 17 日–11 月 23 日,中下旬之交,约 11 月 20 日答辩Beta 交付外部可安装包、接口地址、用户使用调查、三步验收记录、总结、PPT外部用户独立完成三步,中间没有我们代点。预览里的付款人、收款人、金额与接口一致
第三周11 月 24 日–11 月 30 日,下旬按调查收尾缺陷清单、修完后的包和地址、收尾回归记录鼓山账仍是 30000 分、2 笔、9000 分。挡住三步的项清掉。没有新模块进仓库

下面按周写全。每一节写这一周完成哪些模块、交哪些产出、谁在这一周交什么。

5.3 设计收口与落库:10 月 20 日–10 月 26 日

这是现在所在的一周。答辩在 10 月 23 日。同账这一周把类落到库里。可运行的记账留到 10 月 27 日那一周。

13 张表在测试库建成,类名与表名一致。

表放什么
users账号。密码只存哈希
auth_sessions登录会话
ledgers账本。状态 ACTIVE、SETTLING、SETTLED
ledger_members用户与账本的成员关系
invitations六位邀请码、失效时间
expenses消费。金额是整数分
expense_splits逐人应摊。与消费同一事务
image_assets封面和收据的二进制
expense_images消费与收据的引用。每笔至多一张
settlement_batches正式结算批次。预览不写这张表
settlement_transfers正式转账。鼓山账是 2 行、共 9000 分
idempotency_keys同一次提交不写两遍
operation_logs谁在什么时候改了账

金额以整数分持久化。账本状态在界面上是进行中、结算中、已结清。样本消费从这一周起以数据库记录为准。

这一周的产出:

产出放到哪谁交怎样算交了
系统设计说明书华为云,博客给链接G_bamboopole 上传,风车确认能发出PDF 打得开,模块名和表名与数据库说明书一致
数据库设计说明书同上同上13 张表的字段能对上鼓山手算
答辩 PPT、评审表华为云 / 腾讯文档circlexx 做 PPT,G_bamboopole 传 PDF评审表上的项都有一页,8 分钟能讲完
这篇博客作业页面风车确认后交开头有目录,链接能打开
测试库迁移仓库饶恩哲空库执行后得到上述 13 张表

表结构以 10 月 23 日这版数据库设计说明书为准。后面要加字段,先改说明书再改代码。编码按我们自己的区间,这一周走到 40%–60%。

本周仓库里的分工:饶恩哲交迁移;风车核对状态和权限字段;whisper 核对消费、分摊、批次、转账;陈林祺核对图片两张表;李润君用鼓山四个人的已付、应摊、净额对表,30000 分、2 笔、9000 分对不上就写成不通过。

5.4 消费与结算接口:10 月 27 日–11 月 2 日

设计答辩结束之后的一周。这一周写同账的写入接口,并把服务端部署到一个别人打得开的地址。成员邀请页、还款登记页、归档页可以尚未接通。账要能从接口记进去。

这一周完成的模块:

  • 注册和登录能拿到会话。后面的写接口都带这个会话。退出后原会话失效。
  • 创建账本的人同时成为第一名成员,账本状态为进行中。
  • 消费与分摊在同一事务中提交。分摊有一行没写入,整笔回滚,库里不留半笔消费。
  • 人均、按份由服务端用最大余数法重算。10000 分三人均分得到 3334、3333、3333,余分给成员标识字典序最小的人。按金额不自动抹平,合计不等于总额就拒绝。
  • 结算预览在只读事务里读当前净额,返回最少转账。预览不写 settlement_batches,不把账本改成结算中。全员净额为 0 时返回空方案。
  • 正式结算由创建者发起。同一事务里锁账本、核对版本、重算、写入批次和转账、把状态改为结算中。客户端传来的方案不作数。鼓山账写入两行:小陈付给小安 3000 分,小丁付给小白 6000 分。
  • 正式结算之后,消费的新增、编辑、删除和成员变更变为只读。
  • 封面与收据能入库。收据每笔至多一张。消费只存引用。
  • 服务端完成一次可访问部署。地址写进启动步骤,换一台机器按步骤能打开。

第一次部署放在这一周。地址打不开、步骤缺环境变量,都在这一周解决,不堆到 11 月 20 日前后。页面少几张也可以。编码按我们自己的区间,这一周走到 70%–90%。

这一周的产出:

产出放到哪谁交怎样算交了
可访问地址群里,并写入环境说明饶恩哲给出,G_bamboopole 从另一台机器打开健康检查有响应,未登录写消费被拒绝
启动步骤仓库里的运行说明G_bamboopole按步骤能连上 PostgreSQL 并启动 Fastify
鼓山接口记录验收记录李润君三笔消费合计 30000 分;预览为上述两笔;正式结算后库里 2 行、共 9000 分
说明书修订两份说明书里偏离的那一节陈林祺代码里的字段名和 10 月 23 日的表一致,有偏离就先改说明书

本周接口落到人:饶恩哲接登录并部署;风车接建账和结算后的只读;whisper 接消费事务、余额和最少转账;陈林祺接收据上传。circlexx、叶银珍这一周把对应页面的请求改成打这些接口,页面没接完不影响这一周的里程碑。

5.5 Alpha:11 月 3 日–11 月 9 日

约 11 月 6 日。演示在自己的手机上完成,请求打到 10 月 27 日那一周已经部署的服务端。只演示已经通过的模块。

手机上要接通的路径,按操作顺序:

  1. 注册、登录、退出后再登录,会话仍能恢复。
  2. 创建账本,创建者出现在成员名单里。
  3. 另一名成员用六位码加入。人数含创建者不超过 12。后加入的人不追摊加入前的消费。
  4. 记入鼓山三笔消费。人均由服务端重算。输错金额留在当前页。
  5. 成员余额显示小安 +3000、小白 +6000、小陈 −3000、小丁 −6000,合计 0。
  6. 结算预览给出两笔转账。创建者确认后账本变为结算中,消费页变为只读。
  7. 付款人或创建者登记这两笔已还。登记只改转账状态,不连接真实支付。
  8. 两笔都登记并且逐人剩余净额为 0 之后,创建者执行整本结清。
  9. 成员把自己的账本归档。归档只影响本人列表,不删除账目。

权限由服务端校验。普通成员修改他人消费、重置邀请、执行整本结清,接口返回拒绝。手机上把按钮藏起来,不能代替这一层。收据每笔至多一张。预算、导出、成员移除、取消结算不纳入本阶段。

这一周的产出:

产出谁交怎样算交了
代码规范饶恩哲起草,风车确认目录、分支、金额用整数分、错误留在当前页,写进仓库
测试记录李润君上面 9 步每步有过或不过。不过的写明停在哪一步
阶段总结、资源汇总风车收口写明已通过的模块和尚未接通的页面
答辩 PPT、评审表circlexx只讲测试记录里通过的模块
手机演示叶银珍、circlexx 各自那几页,饶恩哲负责装到自己的手机请求打到已部署的服务端,刷新后鼓山账还在

冲刺还没开始。这一周每个工作日用鼓山账走一遍当天已经接通的步骤,不过的记在当天记录里,第二天先改这一条。

本周页面落到人:circlexx 接通记账、分摊、消费详情、结算预览、登记已还;叶银珍接通建账、成员与六位码邀请、余额展示、结清与归档、个人中心;饶恩哲审查后合并到主分支。扫码、按份、按金额、收据选择、流水筛选若这一周没接通,写进阶段总结,下一周补,不在 Alpha 答辩里演示。

5.6 冲刺第一周:11 月 10 日–11 月 16 日

11 月中旬,冲刺从这里开始。Alpha 已经接通的模块保持能用。这一周做两件事:清掉阻断主路径的缺陷,把规格里还没接通的五张页面补上。

五张页面都在 FR 里:扫码加入是 FR10,按份和按金额是 FR13,收据是 FR18,流水筛选是 FR14。补上它们是完成已经写进说明书的功能。预算、导出、成员移除、取消结算、真实支付、离线同步仍然留在排除项里。

主路径是:登录、建账、邀请加入、记一笔人均消费、看到余额、打开结算预览。预览要给出付款人、收款人和转账金额。这六步有一步在第二台手机上走不通,这一周不算过去。

工作日怎么排:

日期当天完成当天产出负责人
11 月 10 日交接清单:已实现模块、13 张表、尚未接通的页面清单放进仓库风车写,李润君按 Alpha 测试记录核对
11 月 11 日扫码加入能打开加入确认页。二维码载荷按说明书的邀请格式解析第二台手机扫到六位码叶银珍页面,风车接口
11 月 12 日按份、按金额在分摊面板里可选。按份走最大余数法,按金额合计不等就停在当前页鼓山车费那一笔用按金额复算,小安与小陈各 3000 分circlexx 页面,whisper 重算
11 月 13 日记账页能选一张收据。第二张被拒绝。流水能按日期、付款人、类别取交集一笔带收据的消费,刷新后图还在circlexx 选图和筛选,陈林祺图片接口
11 月 14 日内部安装包装到第二台手机,请求打到已部署的服务端安装包放上华为云饶恩哲打包,G_bamboopole 核对下载
11 月 15 日鼓山账从头走到结算预览回归记录:入口、操作、刷新、净额李润君
11 月 16 日四条有不过的,退回模块负责人改完再记一次缺陷清单关闭或写明仍开着风车确认

这一周的产出就是上表最后一列交齐的那些:交接清单、缺陷清单、内部安装包、回归记录。

5.7 Beta:11 月 17 日–11 月 23 日

约 11 月 20 日前后,地点听老师安排。这是冲刺的交付周。

交付可安装的移动端和可访问的接口。外部用户在自己的设备上独立完成三步,中间不需要我们代点。

步骤外部用户自己做屏幕上要出现库里要有
建账登录后创建一个账本账本进入进行中列表,创建者在成员里ledgers 一行,ledger_members 一行,状态 ACTIVE
记账记入一笔消费,选付款人和参与人流水里看得到这笔,输错留在当前页expenses 与 expense_splits 同时在,合计等于总额的分
结算预览打开预览付款人、收款人、转账金额预览不写 settlement_batches。金额与 whisper 的接口一致

演示范围限于已通过验收的模块。正式结算、还款登记、结清与归档若已在 Alpha 通过,可以接着演示;测试记录里没通过的,不放进这一场。真实支付、离线同步、预算、导出、取消结算不进入本阶段。

工作日怎么排:

日期当天完成当天产出负责人
11 月 17 日打出给外部用户安装的包,地址仍是已部署的服务端包和地址放到华为云饶恩哲打包,G_bamboopole 从外部网络下载并打开
11 月 18 日找一名组外用户只做建账。我们不碰他的屏幕三步验收记录的第 1 步李润君在场记录,叶银珍改挡住建账的界面
11 月 19 日同一名用户自己记一笔消费三步验收记录的第 2 步李润君记录,circlexx 改挡住记账的界面
11 月 20 日同一名用户打开结算预览,读出付款人、收款人、金额。答辩按老师安排的时间三步验收记录的第 3 步,答辩 PPT李润君记录,whisper 核对金额,circlexx 讲已通过的页
11 月 21 日把这名用户和其他试用的人的意见收成使用调查用户使用调查风车收口
11 月 22 日调查里挡住三步的项,退回模块负责人当天缺陷清单各模块负责人改自己的目录
11 月 23 日三步再走一遍。鼓山账仍用来核对 30000 分、2 笔、9000 分阶段总结、评审表李润君回归,风车确认可以演示的模块

这一周交出来的是安装包、接口地址、用户使用调查、三步验收记录、阶段总结、答辩 PPT 和评审表。

5.8 冲刺收尾:11 月 24 日–11 月 30 日

Beta 演示之后的一周,仍算冲刺。按用户使用调查里挡住三步的记录改。没挡住建账、记账、结算预览的意见记在调查里,这一周不排进仓库。

日期当天完成当天产出负责人
11 月 24 日把调查拆成「挡住三步」和「其余意见」两列收尾缺陷清单李润君拆,风车确认哪几条要改
11 月 25 日建账、邀请页上的阻断项叶银珍的提交叶银珍
11 月 26 日记账、结算预览上的阻断项circlexx、whisper 各自的提交页面归 circlexx,金额归 whisper
11 月 27 日鼓山账再走一次:30000 分、2 笔、9000 分,净额加总为 0收尾回归记录李润君
11 月 28 日–11 月 29 日安装包和地址保持可下载、可打开G_bamboopole 各打开一次G_bamboopole,打不开退回饶恩哲
11 月 30 日功能集与 Beta 已验收的范围一致,清单里挡住三步的项已关闭修完后的包、仍可访问的地址风车确认

功能集停在 Beta 已验收的范围。这一周没有新的需求编号进入实现。

5.9 一个里程碑怎样算过去

每个里程碑按该周的模块验收。金额以整数分守恒,成员净额加总为 0。

入口可进入,操作完成,刷新后数据仍在,净额仍可查询。四条都对上,才进入下一周。

四条在不同的周,检查的入口不一样。

周入口操作刷新后仍在净额
10 月 20 日–10 月 26 日迁移能在空库建出 13 张表鼓山数额能写入重新查询记录还在按消费和转账算出的净额与手算一致
10 月 27 日–11 月 2 日地址可访问,登录能拿到会话三笔消费和一次预览、一次正式结算调用成功重启服务后再查,行还在预览两笔共 9000 分,全员净额 0
11 月 3 日–11 月 16 日自己的手机或第二台手机进得了页面主路径六步做完杀掉应用再打开,账还在四个人的净额与鼓山表一致
11 月 17 日–11 月 30 日外部用户自己的设备进得了应用建账、记账、结算预览三步独立完成换一次网络再打开,账还在预览金额与接口一致,鼓山回归仍通过

李润君填写这四条。有一条空白或不过,风车不确认进入下一周。

5.10 组队后到冲刺的安排

十月初组队定题之后,同账沿用 React Native、Expo、Fastify、PostgreSQL。10 月 20 日这一周把用户到转账落成 13 张表。10 月 27 日那一周接通消费与结算接口,并完成一次可访问部署。11 月 6 日前后在自己的手机上接通账号到归档。11 月 10 日进入冲刺:中旬收口主路径并接通规格内剩余页面,约 11 月 20 日交出可安装客户端,11 月 24 日那一周按使用调查修挡住三步的缺陷。23 日之后的具体日期以作业页面为准,每周要完成的模块按上面各节执行。

5.11 分工怎么划

一条开发部分只有一个负责人。登录、底部导航、建表、审查和部署归主程序员。页面清单、账本状态和权限归组长。消费金额、分摊和最少转账归服务端账务。手机上的记账和结算页面归移动端账务。账本、邀请、统计、结清页面和界面变量归移动端账本。封面与收据的存取归图片模块。鼓山手算和每周回归归验收。地址、安装包和华为云目录归发布。

合并进主分支之前,饶恩哲审查,风车确认可以合入。李润君对不上鼓山数额,就记不通过,退回该模块的负责人。同一张表的写入不由两个人各写一套。

下图分三块,每块从左看到右。第 1 块是记账时手机把操作交给服务端。第 2 块是代码进主分支:各人提交,饶恩哲审查,风车确认。第 3 块是合入之后:李润君用鼓山账核对,对不上退回第 1 块的负责人;饶恩哲打出地址和安装包,G_bamboopole 从外面打开。

img

img

模块需求服务端目录与负责人手机端目录与负责人
账号FR01–FR03api/modules/auth,饶恩哲mobile/features/auth,饶恩哲
账本FR04–FR06api/modules/ledgers,风车mobile/features/ledgers,叶银珍
成员与邀请FR07–FR11api/modules/invitations,风车邀请页在叶银珍的账本功能里
消费与分摊FR12–FR17api/modules/expenses,whispermobile/features/expenses,circlexx
封面与收据FR18api/modules/images,陈林祺封面在叶银珍的建账页;收据在 circlexx 的记账页。两边只调用图片接口
余额与支出统计FR19–FR20api/modules/insights,whispermobile/features/insights,叶银珍
结算方案、批次与转账FR21–FR25api/modules/settlements,whispermobile/features/settlements,circlexx
冻结、结清、归档FR22、FR26、FR27 的状态风车写在 ledgers结清与归档页面归叶银珍
个人中心FR28–FR30api/modules/users,饶恩哲mobile/features/profile,叶银珍
迁移、审查、部署—饶恩哲安装包由饶恩哲打出
鼓山手算与每周回归—李润君手机上的四条也由李润君记
地址、安装包、华为云—G_bamboopole 归档与核对—

消费与分摊由 whisper 在同一事务里提交。收据文件先经陈林祺的图片接口入库,消费只存引用。结算方案由 whisper 计算并写入批次和转账。账本改为结算中、已结清,以及个人归档时间,由风车写入。预览不写正式表。复制结算方案到剪贴板是 circlexx 的页面动作,不新增服务端写入。

5.12 每人的角色和详细开发部分

下表是分工总表。每一人一行,角色和开发部分都写到目录、需求编号和做完的标准。后面 5.12.1 起按人写每一周交什么。

学号昵称角色负责的详细开发部分做完的标准
102400307风车组长,服务端账本与权限页面清单、排期、合并确认。api/modules/ledgers 与 api/modules/invitations:创建账本、账本列表与详情、成员名单、查看和复制邀请、重置邀请、手输或扫码后的加入确认。账本状态 ACTIVE、SETTLING、SETTLED。正式结算后消费与成员只读。整本结清和本人归档时间写在账本与成员上。权限在服务端再校验:普通成员不能改他人消费,不能重置邀请,不能整本结清。未加入者读不到账目普通成员调用上述接口被拒绝。创建者才能正式结算和整本结清。状态名与 10 月 23 日说明书一致。后加入的成员不追摊旧消费。账本人数含创建者最多 12
072403123饶恩哲主程序员仓库、分支、审查合并。13 张表的迁移。api/modules/auth 与 mobile/features/auth:注册、登录、退出、会话恢复,登录页和底部导航。api/modules/users 的本人资料。idempotency_keys、operation_logs 随业务事务写入。10 月 27 日这周把 Fastify 部署成可访问地址。11 月 14 日打出内部安装包,11 月 17 日打出外部可安装包空库迁移得到 13 张表。登录后请求带会话,退出后原会话失效。密码不明文。第二台手机和外部用户的设备能装上包并打开已部署的服务端。金额算法不写在 auth 和 users 里
072403324whisper服务端账务api/modules/expenses:消费新增、编辑、删除、详情和流水。分摊与消费同一事务,失败整笔回滚。人均与按份用最大余数法,按金额不自动抹平。api/modules/insights:已付、应摊、净额、剩余净额由有效消费和已登记转账派生,不另存一份余额。api/modules/settlements:预览生成最少转账,全员净额为 0 时返回空方案;正式结算把方案写入批次和转账。登记已还只把 settlement_transfers 的状态改为已还鼓山账有效消费 30000 分。预览和正式转账都是小陈→小安 3000 分、小丁→小白 6000 分,共 2 笔、9000 分。刷新后净额仍可查询,全员加总为 0。预览不插入正式批次
102400109circlexx移动端账务mobile/features/expenses 与 mobile/features/settlements:新增和编辑消费、分摊面板、流水和筛选、消费详情、结算预览、结算进度、复制方案、登记已还。金额、参与人、分摊方式提交给 whisper 的接口,页面展示返回值。输错留在当前页。正式结算后这些页按风车返回的状态变为只读预览上的付款人、收款人、金额与接口一致。按份、按金额、筛选在 11 月 13 日前可点。页面不直接写 PostgreSQL,不自己改最终应摊
052406103叶银珍移动端账本与界面颜色、字号、按钮、卡片、底部栏写成同一套变量,用到账本、记账、结算和结清各页。mobile/features/ledgers、insights、profile:账本列表、创建账本、账本详情、成员与邀请、扫码加入、支出统计、结清与个人归档、个人中心。支出统计的数来自 insights,还款不计入支出建账、邀请、看统计、归档都能从底部导航进到对应接口。11 月 11 日前扫码能打开加入确认。界面变量和说明书里的图用同一套名称。不改接口字段,不改金额算法
102400201陈林祺图片与规格对照api/modules/images:封面与收据写入 image_assets,收据经 expense_images 绑定消费。每笔消费至多一张收据,读取要登录并且属于该账本。实现若偏离 10 月 23 日的类图或表,先改说明书里对应的那一节,再允许代码合并第二张收据被拒绝。未加入者取不到图片二进制。说明书、表、接口字段是同一套名称。11 月 13 日前记账页能通过这个接口看到收据
102400103李润君验收鼓山一日按 13 张表和接口复算,每个里程碑填写四条:入口、操作、刷新后仍在、净额可查询。维护同一份种子数额:三笔消费、两笔转账。Beta 在场记录外部用户的三步,用户的手不由我们代替。对不上就写成不通过,退回该模块负责人30000 分、2 笔、9000 分可以复算。净额加总不为 0,或刷新后记录消失,记不通过。六周各有一份验收记录
102400202G_bamboopole发布华为云目录。系统设计说明书、数据库设计说明书、答辩 PPT、安装包、环境说明、每周验收记录放在约定位置。10 月 27 日起核对地址,11 月 14 日起核对安装包能否下载。运行说明写清 Node、PostgreSQL、Expo 的启动顺序。不改业务计算,不改表结构约定位置上的文件能打开。地址打不开或包下不下来,记不通过,退回饶恩哲。Beta 那一周从外部网络下载成功

5.12.1 风车

组长。服务端账本、邀请、状态和权限归这一人。排期以这一节的六周为准,作业页面改了截止日期,风车改日期、不改模块。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日权限矩阵和 ACTIVE、SETTLING、SETTLED 与两份说明书对齐说明书里创建者、普通成员、未加入者各能做的操作是同一张表
10 月 27 日–11 月 2 日创建账本、成员查询。正式结算成功后把消费和成员改为只读普通成员在结算中调用新增消费被拒绝
11 月 3 日–11 月 9 日六位码加入、重置邀请、整本结清、本人归档Alpha 路径第 3、8、9 步的接口通过
11 月 10 日–11 月 16 日扫码查询接口;缺陷按模块退回交接清单、11 月 16 日的确认
11 月 17 日–11 月 23 日收使用调查,圈出挡住三步的项调查定稿,阶段总结里的可演示模块
11 月 24 日–11 月 30 日确认没有新需求编号进入仓库收尾清单上挡住三步的项已关闭

5.12.2 饶恩哲

主程序员。账号、迁移、底部导航、审查和部署归这一人。业务金额的计算留在 whisper 的目录。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日13 张表迁移,空库能建出来迁移文件进入仓库
10 月 27 日–11 月 2 日注册、登录、退出、会话。服务端部署到可访问地址地址和一份能登录的账号
11 月 3 日–11 月 9 日登录页、底部导航、审查合并。代码规范自己的手机能登录并切到账本、记账、结算
11 月 10 日–11 月 16 日内部安装包11 月 14 日第二台手机装上
11 月 17 日–11 月 23 日外部可安装包11 月 17 日包可下载
11 月 24 日–11 月 30 日按收尾清单改 auth 和安装配置里挡住三步的项11 月 30 日的包仍可安装

5.12.3 whisper

服务端账务。消费、分摊、余额、最少转账和登记已还的金额状态归这一人。账本改成结算中由风车在同一事务的后半段写,两人按 10 月 23 日的正式结算顺序接,不各写一套状态。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日消费、分摊、批次、转账的字段与鼓山列对齐字段对照,30000 分和 9000 分对得上
10 月 27 日–11 月 2 日消费事务、预览、正式批次与转账、余额查询鼓山接口记录里的两笔转账
11 月 3 日–11 月 9 日编辑、删除、登记已还。删除用软删除,汇总排除已删消费Alpha 第 4、5、6、7 步的金额通过
11 月 10 日–11 月 16 日按份、按金额的服务端重算。流水筛选条件车费 6000 分按金额各 3000 分
11 月 17 日–11 月 23 日预览接口保持和页面同一套付款人、收款人、金额外部用户读出的数与接口一致
11 月 24 日–11 月 30 日只改挡住预览或记账的计算缺陷11 月 27 日鼓山回归通过

5.12.4 circlexx

移动端账务。记账、分摊、流水、结算预览和登记已还的页面归这一人。最终应摊用接口返回值。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日答辩 PPT 按评审表讲到开发计划这一节8 分钟能讲完的 PPT
10 月 27 日–11 月 2 日记账页改成提交到消费接口,失败留在当前页一笔人均消费能从页面写入
11 月 3 日–11 月 9 日分摊、详情、预览、登记已还接通Alpha 手机路径里记账到登记已还可点
11 月 10 日–11 月 16 日按份、按金额、流水筛选、收据选择11 月 12 日、13 日的页面记录
11 月 17 日–11 月 23 日预览页让外部用户能读出三列:付款人、收款人、金额三步验收的第 2、3 步
11 月 24 日–11 月 30 日调查里记账和预览页面上的阻断项11 月 26 日的提交

5.12.5 叶银珍

移动端账本和界面。建账、邀请、统计、结清、个人中心和全组界面变量归这一人。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日说明书和 PPT 的图保持同一套符号,并列出页面将用的颜色、字号、按钮变量变量名和层次图、泳道图一致
10 月 27 日–11 月 2 日创建账本页打到风车的接口创建一个进行中的账本
11 月 3 日–11 月 9 日列表、详情、六位码邀请、余额与统计展示、结清和归档Alpha 路径里建账、邀请、余额、归档可点
11 月 10 日–11 月 16 日扫码加入11 月 11 日第二台手机扫到加入确认
11 月 17 日–11 月 23 日外部用户建账时卡住的界面三步验收的第 1 步
11 月 24 日–11 月 30 日建账和邀请上的阻断项11 月 25 日的提交

5.12.6 陈林祺

图片和规格对照。封面、收据的存取,以及说明书和代码的字段一致,归这一人。

周这一周写的部分交出的结果
10 月 20 日–10 月 26 日引言、设计基线、image_assets 与 expense_images 的字段两张表和说明书是同一套列名
10 月 27 日–11 月 2 日上传和鉴权读取。收据第二张拒绝未加入者拿不到图
11 月 3 日–11 月 9 日封面能挂在新建账本上账本详情看得到封面或预设封面
11 月 10 日–11 月 16 日和 circlexx 接上记账页的收据选择11 月 13 日刷新后收据还在
11 月 17 日–11 月 23 日代码若因修缺陷偏离表,先改说明书对应节合并前字段名一致
11 月 24 日–11 月 30 日收据挡住记账时才改图片接口没有新的图片种类

5.12.7 李润君

验收。六周用同一笔鼓山账,归这一人记过或不过。

周检查什么交出的结果
10 月 20 日–10 月 26 日13 张表对上已付、应摊、净额手算表。对不上写成不通过
10 月 27 日–11 月 2 日接口记录:30000 分、预览 2 笔、正式 9000 分接口验收记录
11 月 3 日–11 月 9 日手机上 9 步Alpha 测试记录
11 月 10 日–11 月 16 日第二台手机主路径四条11 月 15 日回归记录
11 月 17 日–11 月 23 日外部用户三步,记录时不代点三步验收记录、用户使用调查里的事实部分
11 月 24 日–11 月 30 日收尾回归,并把调查拆成挡住三步和其余意见11 月 24 日清单、11 月 27 日回归

5.12.8 G_bamboopole

发布。华为云上的文件、地址和安装包能不能打开,归这一人核对。

周这一周放上去的怎样算对
10 月 20 日–10 月 26 日两份说明书、答辩 PPT博客里的链接能打开 PDF
10 月 27 日–11 月 2 日地址、启动步骤另一台机器按步骤能打开服务端
11 月 3 日–11 月 9 日代码规范、测试记录、阶段总结、资源汇总目录约定位置上找得到
11 月 10 日–11 月 16 日内部安装包、交接清单11 月 14 日包能下载
11 月 17 日–11 月 23 日外部安装包、使用调查、三步记录、Beta 的 PPT外部网络能下载,链接写进博客或作业页
11 月 24 日–11 月 30 日修完后的包、收尾清单11 月 28 日、29 日各打开一次地址和包

5.13 各周交到谁手里

周主责这一周写进仓库的部分同时要交的记录
10 月 20 日–10 月 26 日饶恩哲13 张表的迁移。风车核对状态与权限,whisper 核对消费、分摊、批次、转账,陈林祺核对图片李润君的鼓山手算。两份说明书和答辩 PPT 由 G_bamboopole 放到华为云
10 月 27 日–11 月 2 日whisper消费与分摊事务、余额、最少转账预览、正式批次与转账。风车接上冻结。陈林祺接上收据。饶恩哲部署并接上登录可访问地址、启动步骤、鼓山接口记录
11 月 3 日–11 月 9 日circlexx、叶银珍circlexx 接通记账到登记已还。叶银珍接通建账、邀请、余额、结清与归档。饶恩哲审查后合并手机主路径记录、代码规范、测试记录、阶段总结
11 月 10 日–11 月 16 日风车叶银珍补扫码。circlexx 补按份、按金额、筛选。陈林祺补收据。饶恩哲打内部包。缺陷退回各模块交接清单、缺陷清单、回归记录
11 月 17 日–11 月 23 日饶恩哲、李润君外部安装包。各人只改自己模块上挡住三步的缺陷。G_bamboopole 从外部网络核对用户使用调查、三步验收记录、阶段总结、答辩 PPT
11 月 24 日–11 月 30 日李润君挡住三步的项退回对应负责人。没有新模块进入仓库收尾缺陷清单、仍可安装的包、仍可打开的地址

5.14 里程碑

每一周写同账这一阶段完成的模块。要交的材料见 5.2 的对照表。

里程碑时间完成的模块
设计收口与落库10 月 20 日–10 月 26 日,答辩 10 月 23 日13 张表落成,类名与表名一致。金额以整数分持久化。账本状态为进行中、结算中、已结清。鼓山手算能对上表:30000 分、2 笔、9000 分。本周交付说明书、PPT 和迁移
消费与结算接口10 月 27 日–11 月 2 日登录可用。消费与分摊同一事务写入,分摊失败则整笔回滚。结算预览给出小陈→小安 3000 分、小丁→小白 6000 分;全员净额为 0 时返回空方案。正式结算后账本进入结算中,消费与成员只读。服务端有一个可访问地址
Alpha11 月 3 日–11 月 9 日,约 11 月 6 日自己的手机接通账号与登录、账本管理、六位码邀请、消费记录、分摊设置、成员余额、结算预览与正式结算、还款登记、整本结清、个人归档。权限由服务端校验。只演示已经通过的模块
冲刺收口11 月 10 日–11 月 16 日交接已实现模块和 13 张表。接通扫码加入、按份分摊、按金额分摊、收据和流水筛选。阻断主路径的缺陷修完。第二台手机能装上内部包
Beta11 月 17 日–11 月 23 日,约 11 月 20 日前后可安装的移动端与可访问的接口。外部用户独立完成账本创建、消费录入和结算预览,得到付款人、收款人与转账金额。演示范围限于已通过验收的模块
冲刺收尾11 月 24 日–11 月 30 日使用调查里挡住上述三步的缺陷修完。功能集保持在 Beta 已验收的范围。安装包和地址仍然可打开
...全文

相关推荐

哈工大理论力学 ① 第七版-绝对正版答案

习题分毫不差

qq_33432897

PJ85718DM+MKV46F256VLH16构建HVAC高稳温度监测系统

温度传感器是工业物联网数据采集的起点,其精度、抗干扰性与通信可靠性直接决定边缘感知质量。基于I²C/SPI接口的高精度数字温度传感器(如PJ85718DM)配合具备FlexIO协议引擎的ARM Cortex-M4微控制器(如MKV46F256VLH16),可实现从物理信号采集、边缘预处理到多协议分发的全链路闭环。该组合突破传统单总线或SMBus方案在HVAC强电磁环境下的稳定性瓶颈,支持Modbus RTU、BACnet MS/TP等工业协议硬件卸载,并通过GND分割、硬件时间戳、专用内存池等工程实践保障本

南门居士-杜锦刚

银行级机器学习系统落地:从模型正确性到系统韧性的工程实践

机器学习模型部署不是算法问题,而是系统工程问题——当模型走出Jupyter Notebook,它必须在真实业务环境中应对数据漂移、依赖失效、流量突增与监管审计等多重挑战。其核心原理在于将‘模型输出正确’升级为‘系统行为可预期、可追溯、可降级’,技术价值体现在保障SLA、满足金融级合规(如可审计性、确定性、人工兜底)并支撑高可用决策服务。典型应用场景包括反欺诈、信贷审批、反洗钱等强耦合、高风险业务系统。本文聚焦银行级ML生产落地中的韧性设计、特征供给分层、司法级日志、漂移检测与模型验证四大实操支柱。

ywx407827531

CC2430无线SoC架构解析:从8051内核到Zigbee协议栈的嵌入式设计

在嵌入式系统与物联网领域,片上系统(SoC)通过将微控制器、射频前端及专用外设集成于单一芯片,实现了硬件的高度协同与功耗优化。其核心原理在于通过统一内存架构、直接内存访问(DMA)及硬件加速模块(如AES协处理器),在资源受限环境下平衡性能与功耗。这种设计为低功耗无线通信(如Zigbee、6LoWPAN)提供了关键技术支撑,广泛应用于智能家居、工业传感等场景。CC2430作为经典范例,其增强型8051内核与射频子系统的深度整合,尤其体现了软硬件协同在实现高效无线节点中的核心价值。

weixin_30363509

MP3按时间分割 破解版 MP3Splitter

MP3分割软件,这款软件是按您需要的时间来分割。每分每秒,分毫不差。都可以分割出来。。呵,这是破解版。。

观赏鱼VS电脑专业
评论
收藏 已收藏
分享
返回顶部