Public: anyone can read this; the crew can change it.

Each deal carries the agent's commission rate, like 2.5%, and its page shows the commission it pays at closing, kept off the client timeline #145

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Each deal can now carry the agent's commission rate, and its page shows the commission it pays at closing. The full `bun test` run passed (470 tests) apart from the stale-contract check below, and I re-ran `src/openapi.test.ts` after regenerating `contract/openapi.json` (it passes). The design lint (`scripts/lint-design.ts`) passes. `bun x tsc --noEmit` printed only the tsc help text, so no type c…

shipped production is serving it deploy d2eada7

opened this

Each deal can now carry the agent's commission rate, and its page shows the commission it pays at closing. The full bun test run passed (470 tests) apart from the stale-contract check below, and I re-ran src/openapi.test.ts after regenerating contract/openapi.json (it passes). The design lint (scripts/lint-design.ts) passes. bun x tsc --noEmit printed only the tsc help text, so no type check ran. The repo has no scripts/gate.ts or scripts/fast.ts, and docs/VISION.md isn't in this repo.

  • Storage: a nullable commission_rate column, appended as the last migration in src/db.ts. The CHECK is 0–1000 hundredths of a percent, so 2.5% is stored as 250.
  • Parsing: rate() in src/money.ts takes "2.5" or "2.5%" (0–10, at most two decimals). Anything else gives an invalid result on field commission_rate, which the form turns into a 422 that keeps what was typed. A blank value clears the rate.
  • Amount: commission() in src/money.ts is the one place the dollars are rounded, and percent() formats the rate.
  • Doors:

- The new-deal form and the deal's figures form take the rate. Its field sits under the sale price and earnest money. - createDeal and updateDeal handle it. - The API deal schema, the open and update endpoints, and the MCP open_deal and update_figures tools carry it. - contract/openapi.json is regenerated.

  • Sample deals: they carry rates of 2.5%, 3%, 2.75% and 2.5%.
  • Deal page: it reads "Commission 2.5% · $11,250" when the price is set, and "Commission 2.5%" with "add the price to see the amount" when it isn't.
  • Kept private: I added nothing to the timeline page or the reminders code. The MCP client_timeline tool doesn't return the rate either. A test asserts the timeline output and every draft subject and body contain no "commission", rate or amount.
  • Tests: src/commission.test.ts covers the parse and its refusals, the rounding, create and edit, the 422 keeping the typed value, the page text in all three states, and the timeline and drafts leaving it out.
  • Docs: the README has a new Commission paragraph.
  • Wire format: the API and MCP read and write commission_rate as the stored integer (250), while the HTML forms take percent text. I chose this so reading a deal and writing it back match. A JSON integer is hundredths and a string is a percent.
  • contract.json: unchanged, because the rate is a field of deal.
  • Not done: I didn't add a terminal editor for the rate, matching how the other figures work there. I also didn't mention the rate in docs/TECHNICAL.md.

To try it, open a deal with Commission rate "2.5%" and a price of 450000. Its page shows "Commission 2.5% · $11,250", and the Timeline link shows neither the rate nor the amount.

🤖 Generated with Claude Code

Closes #142

commented

Each deal can now carry the agent's commission rate, and its page shows the commission it pays at closing. The full bun test run passed (470 tests) apart from the stale-contract check below, and I re-ran src/openapi.test.ts after regenerating contract/openapi.json (it passes). The design lint (scripts/lint-design.ts) passes. bun x tsc --noEmit printed only the tsc help text, so no type check ran. The repo has no scripts/gate.ts or scripts/fast.ts, and docs/VISION.md isn't in this repo.

  • Storage: a nullable commission_rate column, appended as the last migration in src/db.ts. The CHECK is 0–1000 hundredths of a percent, so 2.5% is stored as 250.
  • Parsing: rate() in src/money.ts takes "2.5" or "2.5%" (0–10, at most two decimals). Anything else gives an invalid result on field commission_rate, which the form turns into a 422 that keeps what was typed. A blank value clears the rate.
  • Amount: commission() in src/money.ts is the one place the dollars are rounded, and percent() formats the rate.
  • Doors:

- The new-deal form and the deal's figures form take the rate. Its field sits under the sale price and earnest money. - createDeal and updateDeal handle it. - The API deal schema, the open and update endpoints, and the MCP open_deal and update_figures tools carry it. - contract/openapi.json is regenerated.

  • Sample deals: they carry rates of 2.5%, 3%, 2.75% and 2.5%.
  • Deal page: it reads "Commission 2.5% · $11,250" when the price is set, and "Commission 2.5%" with "add the price to see the amount" when it isn't.
  • Kept private: I added nothing to the timeline page or the reminders code. The MCP client_timeline tool doesn't return the rate either. A test asserts the timeline output and every draft subject and body contain no "commission", rate or amount.
  • Tests: src/commission.test.ts covers the parse and its refusals, the rounding, create and edit, the 422 keeping the typed value, the page text in all three states, and the timeline and drafts leaving it out.
  • Docs: the README has a new Commission paragraph.
  • Wire format: the API and MCP read and write commission_rate as the stored integer (250), while the HTML forms take percent text. I chose this so reading a deal and writing it back match. A JSON integer is hundredths and a string is a percent.
  • contract.json: unchanged, because the rate is a field of deal.
  • Not done: I didn't add a terminal editor for the rate, matching how the other figures work there. I also didn't mention the rate in docs/TECHNICAL.md.

To try it, open a deal with Commission rate "2.5%" and a price of 450000. Its page shows "Commission 2.5% · $11,250", and the Timeline link shows neither the rate nor the amount.

🤖 Generated with Claude Code

Approved

Clean. The rate is parsed at the boundary in money.ts and refused as a 422 that keeps what was typed. The amount is rounded once. The deal page, API, MCP, openapi and samples carry it. The timeline and drafts leave it out, and a test asserts that. No contract cell changed. Nit, not blocking: the JSON integer (hundredths) and form text (percent) differ, but both are documented.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs