Skip to content

fix(stripe): classify never paid trial orgs#2252

Merged
riderx merged 1 commit into
mainfrom
codex/stripe-never-paid-trial-export
May 12, 2026
Merged

fix(stripe): classify never paid trial orgs#2252
riderx merged 1 commit into
mainfrom
codex/stripe-never-paid-trial-export

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 12, 2026

Summary (AI generated)

  • Updates the Stripe org email export so --status=never_paid means org-linked Stripe customers with no positive paid invoice at all.
  • Keeps paid duration logic based on paid subscription invoice coverage for paid, active, and canceled exports.
  • Clarifies the help text for the never_paid status.

Motivation (AI generated)

The trial churn export should identify org users whose org never paid anything, not customers that merely lack subscription coverage while still having another positive paid invoice.

Business Impact (AI generated)

This makes the CSV reliable for trial-churn outreach and avoids mixing paid customers into the never-paid segment.

Test Plan (AI generated)

  • bunx eslint --no-ignore scripts/export_stripe_six_month_org_emails.ts scripts/stripe_paid_invoice_export_utils.ts
  • bun --bun tsc --noEmit --ignoreConfig --skipLibCheck --allowImportingTsExtensions --moduleResolution bundler --module ESNext --target ESNext scripts/export_stripe_six_month_org_emails.ts scripts/stripe_paid_invoice_export_utils.ts
  • git diff --check
  • bun scripts/export_stripe_six_month_org_emails.ts --help

Summary by CodeRabbit

  • Bug Fixes

    • Improved accuracy in identifying and exporting trial organization data by refining how customer payment history is tracked and categorized.
  • Chores

    • Enhanced internal data structures for better distinction between trial and paid customer statuses during export operations.

Review Change Stack

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

The PR refactors Stripe paid-invoice export filtering by introducing a CustomerPaidCoverageResult interface that bundles both per-customer coverage data and a set of customer IDs with positive paid invoices. The utility function now populates this set during invoice processing, and the consumer script adapts to destructure and use the set for never-paid classification instead of checking coverage maps.

Changes

Stripe Never-Paid Customer Export Filtering

Layer / File(s) Summary
Paid-invoice result structure and tracking
scripts/stripe_paid_invoice_export_utils.ts
CustomerPaidCoverageResult interface exports both a coverage map and a set of customer IDs with positive paid invoices; collectPaidCoverageByCustomerId initializes and populates both fields, recording customer IDs when invoice amounts are greater than zero, and returns the combined result.
Export script adoption of set-based filtering
scripts/export_stripe_six_month_org_emails.ts
CLI help text explicitly documents --status=never_paid for trial orgs with no positive paid invoice; imports are simplified; main function destructures the result to extract both the coverage map and the positive-invoice set; buildNeverPaidCustomerSummaries signature updates to accept the set and use it directly for filtering instead of checking the coverage map.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Cap-go/capgo#2250: Both PRs modify the same Stripe export flow and consolidate export behavior with richer paid-invoice data handling.
  • Cap-go/capgo#2206: Directly related changes to the same Stripe export script and collectPaidCoverageByCustomerId utility with the same CustomerPaidCoverageResult additions.

Poem

🐰 Invoice trails traced with sets so keen,
Positive paid amounts are seen,
Never-paid orgs sorted clean,
Contracts refined, data pristine,
Export scripts dancing in between! 🎪

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: updating the Stripe export logic to correctly classify never-paid trial organizations.
Description check ✅ Passed The pull request description includes a summary of changes, motivation, business impact, and a comprehensive test plan covering linting, type checking, and manual testing of the affected scripts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/stripe-never-paid-trial-export

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 12, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/stripe-never-paid-trial-export (5a28356) with main (39f2c69)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/stripe_paid_invoice_export_utils.ts (1)

185-201: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Broaden the positive-payment scan to catch partially paid invoices.

customerIdsWithPositivePaidInvoices is derived from stripe.invoices.list({ status: 'paid' }), which excludes invoices with partial payments. Per Stripe API documentation, invoices can have amount_paid > 0 while remaining in open status (until fully paid and transitioning to paid). These partially paid open invoices will be missed by the current status filter, incorrectly classifying those customers as never_paid. Collect the positive-payment set from all invoices (or at minimum open invoices), while keeping the paid-coverage logic restricted to paid subscription invoices.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/stripe_paid_invoice_export_utils.ts` around lines 185 - 201, The
current scan sets invoiceListParams.status = 'paid', which misses partially paid
invoices in 'open' state; remove the status filter from invoiceListParams (or
explicitly include open invoices) when building invoiceListParams used by
stripe.invoices.list so that the loop over
stripe.invoices.list(invoiceListParams) sees invoices of all relevant statuses;
keep the existing checks inside the loop (toStripeId(invoice.customer),
shouldIncludeCustomer, and getInvoiceAmountPaid(invoice) > 0 that adds to
customerIdsWithPositivePaidInvoices) unchanged so only invoices with amount_paid
> 0 are counted, and preserve the existing paid-subscription coverage logic
elsewhere that should remain restricted to fully paid invoices.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/stripe_paid_invoice_export_utils.ts`:
- Around line 185-201: The current scan sets invoiceListParams.status = 'paid',
which misses partially paid invoices in 'open' state; remove the status filter
from invoiceListParams (or explicitly include open invoices) when building
invoiceListParams used by stripe.invoices.list so that the loop over
stripe.invoices.list(invoiceListParams) sees invoices of all relevant statuses;
keep the existing checks inside the loop (toStripeId(invoice.customer),
shouldIncludeCustomer, and getInvoiceAmountPaid(invoice) > 0 that adds to
customerIdsWithPositivePaidInvoices) unchanged so only invoices with amount_paid
> 0 are counted, and preserve the existing paid-subscription coverage logic
elsewhere that should remain restricted to fully paid invoices.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2f073c8-0a33-4e63-8e3f-fd87442d4850

📥 Commits

Reviewing files that changed from the base of the PR and between 39f2c69 and 5a28356.

📒 Files selected for processing (2)
  • scripts/export_stripe_six_month_org_emails.ts
  • scripts/stripe_paid_invoice_export_utils.ts

@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit d105b54 into main May 12, 2026
52 of 53 checks passed
@riderx riderx deleted the codex/stripe-never-paid-trial-export branch May 12, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant