cswork / 带回家作业全部作业

带回家作业 · 约 3 小时 · 不可用 AI

CSV 账单对账

这是很多团队用来代替电话面试、或在电话面试之后发出的那种带回家作业。预计用时三小时左右。这里没有 AI 结对:请按公司要求不使用 AI 时的方式来做。

需求

财务导出了本月的发票,支付服务商导出了收到的款项。请实现 src/reconcile.py 里的 reconcile(invoices_csv, payments_csv):两个参数都是带表头的 CSV 文件文本。可以在 src/ 下添加任意模块,在 tests/ 下写自己的测试。

列。 发票需要 invoice_id、customer、amount、currency;收款需要 payment_id、invoice_id、amount、currency。表头名去掉首尾空白、忽略大小写后匹配,顺序不限,多余的列忽略。文件缺少必需的列时(空文件就是全缺)抛 ValueError。

行。 每个值先去掉首尾空白。一行在下列情况下被拒绝,原因取第一个符合的:

  1. missing:某个必需的值为空,或者这一行太短、没有这一列;
  2. amount:金额不是"0-9 的 ASCII 数字,可带一个 . 和一到两位小数"(不能带正负号、千位分隔符或货币符号),或者金额为零;
  3. currency:币种不是三个 A-Z 字母(大小写不限,比较时一律转成大写);
  4. duplicate:同一个文件里,前面已经接受的行有相同的 id(发票看 invoice_id,收款看 payment_id)。

被拒绝的行记进 errors,格式是 {'file': 'invoices' 或 'payments', 'line': n, 'reason': ...},n 是这一行在文件里的行号,表头是第 1 行。空行跳过,但仍然占行号。先列发票的错误,每个文件内按行号排序。一行坏数据绝不能让其余的行处理不下去。

匹配。 已接受的收款,如果 invoice_id 对应不上任何已接受的发票,算孤立收款(orphan);如果币种和发票不同,算币种不符(mismatched)。这两种都不计入。其余收款计入对应的发票。金额是钱,要用精确的十进制运算。

结果。

{
    'paid': ['INV-1'],                                  # 计入的收款等于发票金额
    'partial': [{'invoice': 'INV-2', 'due': '50.50'}],  # 少于发票金额,但大于零
    'overpaid': [{'invoice': 'INV-3', 'excess': '0.01'}],
    'unpaid': ['INV-4'],                                # 一分都没有计入
    'orphans': ['P-4'],                                 # 收款 id
    'mismatched': ['P-5'],                              # 收款 id
    'errors': [...],
    'totals': {'USD': {'invoiced': '392.50', 'received': '300.00'}},
}

所有 id 列表都按 id 排序。金额一律写成两位小数。totals 按已接受发票的币种各一项:这些发票的金额合计,以及计入它们的收款合计。

需要交付什么

  • src/ 里的代码,没看过需求的人也能读懂;
  • tests/ 里你自己的测试,覆盖上面的规则,以及真实导出文件里可能出现的脏数据;
  • 在编辑器旁边的说明框里写一份简短的设计说明:怎么运行、你做了哪些假设、有哪些取舍,以及文件有好几 GB 时你会改什么。

隐藏测试会检查上面的规则。运行结束后,可以请 AI 评估代码质量:结构、测试、错误处理和设计说明四项,各按 1 到 4 分打分。

不可用 AI。计时、设计说明和编辑中的代码只保存在这个浏览器里;运行测试时文件会和 AI 辅助轮一样保存在你的运行记录里。

正在打开项目…