feat(nw-registered-agent): emit annualFeeUsd for ChittyFinance cost flow#21
feat(nw-registered-agent): emit annualFeeUsd for ChittyFinance cost flow#21chitcommit wants to merge 1 commit into
Conversation
The nw-registered-agent scraper previously emitted documents + paymentStatus but no monetary amount, so a downstream cost consumer had nothing to book. Add a real annualFeeUsd field, parsed from the account-page text via parseAnnualFee() (anchors on "registered agent"/"annual fee"/"renewal"/ "service fee" + a $amount). Undefined when the portal shows no fee — never coerced to 0, so ChittyFinance's vendor-charge ingest can enforce its required-amount guard honestly. This is the ChittyScrape side of the "ChittyScrape feeds the cost flow" wiring: registered-agent annual fee -> ChittyFinance expense (COA 5050). parseAnnualFee verified against realistic NW strings: extracts $125 / $1,250, returns undefined for fee-less inbox text and for $amounts lacking a fee anchor (no false positives). tsc --noEmit clean. NOTE: the live portal scrape is credential-gated (NW login via ChittyConnect); parseAnnualFee runs over real scraped text at runtime but cannot be exercised end-to-end here without portal creds — flagged as the chico/ChittyConnect follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e2b0cf4555
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const money = /\$\s?([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})?|[0-9]+(?:\.[0-9]{2})?)/; | ||
| for (const rawLine of text.split(/\n|\.|;/)) { |
There was a problem hiding this comment.
Parse full fee amounts before returning
When the portal shows an uncommaed four-digit fee or a fee with cents, this parser can emit a smaller amount than shown: the first regex alternative matches only the prefix of $1000 as $100, and text.split(/\n|\.|;/) splits $125.50 before the cents are parsed. Because annualFeeUsd is consumed as the booked cost amount, these common currency formats would silently understate the charge instead of returning the portal value.
Useful? React with 👍 / 👎.
|
|
||
| // Best-effort parse of the annual fee from the account page text. Undefined | ||
| // when the portal view shows no fee — never coerced to 0. | ||
| const annualFeeUsd = parseAnnualFee(accountData?.bodySnippet || ''); |
There was a problem hiding this comment.
Avoid truncating the text used for fee extraction
This calls the fee parser on bodySnippet, but accountData only stores bodyText.slice(0, 2000). On a logged-in dashboard where navigation, banners, or entity lists push the billing/renewal section past the first 2000 characters, the new annualFeeUsd field will be omitted even though the page contains the fee, causing the downstream cost flow to see an unknown amount. Use the full page text, or a billing-specific extraction, for the new monetary field instead of the display snippet.
Useful? React with 👍 / 👎.
| for (const rawLine of text.split(/\n|\.|;/)) { | ||
| const line = rawLine.trim(); | ||
| if (!anchors.test(line)) continue; | ||
| const m = line.match(money); |
There was a problem hiding this comment.
Match fee labels split from their amounts
This only checks for a dollar amount on the same split segment as the anchor, so common billing layouts such as a table/card with Annual Fee in one cell or line and $125 in the adjacent value cell/line return undefined. Since the scraper now exposes annualFeeUsd for the downstream cost flow, those label/value layouts will look like an unknown fee even though the portal surfaced the amount; the parser should inspect nearby text after an anchor rather than only the current line.
Useful? React with 👍 / 👎.
| */ | ||
| export function parseAnnualFee(text: string): number | undefined { | ||
| if (!text) return undefined; | ||
| const anchors = /(registered\s+agent|annual\s+fee|renewal|service\s+fee|yearly)/i; |
There was a problem hiding this comment.
Require the renewal amount to be for registered-agent service
Because renewal by itself is treated as a fee anchor, any dashboard line such as an annual-report renewal or other renewal notice with a $ amount will be returned as annualFeeUsd before a later registered-agent charge is considered. In accounts with annual report reminders or multiple renewal notices, this can book the wrong vendor-charge amount; the match needs to be scoped to registered-agent/service-fee billing text instead of any renewal line.
Useful? React with 👍 / 👎.
What
The
nw-registered-agentscraper emitted documents + paymentStatus but no monetary amount, so a downstream cost consumer had nothing to book. Add a realannualFeeUsdfield — the ChittyScrape side of the "ChittyScrape feeds the cost flow" wiring (ChittyFinance side: chittyapps/chittyfinance#134).Changes
NWAgentResult.annualFeeUsd?: number— parsed from the account-page text viaparseAnnualFee()(anchors on "registered agent"/"annual fee"/"renewal"/"service fee"/"yearly" + a$amount, thousands-aware).Verification
parseAnnualFeeexercised against realistic NW strings: extracts$125/$1,250, returnsundefinedfor fee-less inbox text and for$amountswith no fee anchor (no false positives).tsc --noEmitclean.Credential-gated follow-up (chico/ChittyConnect)
The live scrape (NW login via ChittyConnect) is credential-gated;
parseAnnualFeeruns over real scraped text at runtime but can't be exercised end-to-end here without portal creds.🤖 Generated with Claude Code