Skip to content

Conversation

@icecrasher321
Copy link
Collaborator

@icecrasher321 icecrasher321 commented Nov 26, 2025

Summary

Must track departed member usage so that is billed by the org.

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Nov 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
docs Skipped Skipped Nov 30, 2025 2:16am

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Nov 26, 2025

Greptile Overview

Greptile Summary

This PR implements tracking of departed member usage for team plans to ensure organizations are properly billed for usage incurred before members leave. Previously, when a member was removed from an organization, their currentPeriodCost was lost, potentially allowing organizations to avoid billing for consumed resources.

Key Changes:

  • Added departedMemberUsage decimal field to the organization table to accumulate usage from removed members
  • Modified member removal endpoint to capture departing member's currentPeriodCost and add it to organization's departedMemberUsage using SQL increment
  • Updated calculateSubscriptionOverage() to include departed member usage when computing team overage charges
  • Added reset logic in invoice webhook to clear departedMemberUsage at the end of each billing period
  • Removed 126 lines of unused code from seat-management.ts (updateOrganizationSeats and validateMemberRemoval functions)

Confidence Score: 4/5

  • This PR is safe to merge with minor concerns around error handling
  • The implementation correctly solves the billing gap by tracking departed member usage. The logic is straightforward: capture usage on removal, include in billing calculations, and reset at period end. The try-catch around usage capture prevents member removal failures. However, the lack of transaction wrapping means there's a small window where a member could be removed but their usage not captured if the update fails (though this is logged). The SQL increment pattern is correct and handles concurrent removals safely.
  • Pay attention to apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts - ensure the non-transactional usage capture approach is acceptable for your use case

Important Files Changed

File Analysis

Filename Score Overview
packages/db/schema.ts 5/5 Added departedMemberUsage decimal field to organization table with default value '0'
apps/sim/app/api/organizations/[id]/members/[memberId]/route.ts 4/5 Added logic to capture departing member's current period usage and accumulate it in organization's departedMemberUsage field before member deletion
apps/sim/lib/billing/core/billing.ts 5/5 Updated team overage calculation to include departed member usage in total team usage before computing overage charges
apps/sim/lib/billing/webhooks/invoices.ts 5/5 Added reset of departedMemberUsage to '0' for team plans when resetting usage at billing period end

Sequence Diagram

sequenceDiagram
    participant Admin as Admin/Owner
    participant API as DELETE /api/organizations/[id]/members/[memberId]
    participant DB as Database
    participant Billing as calculateSubscriptionOverage()
    participant Webhook as Invoice Webhook Handler
    
    Note over Admin,API: Member Removal Flow
    Admin->>API: DELETE request to remove member
    API->>DB: Query member role
    alt is owner
        API-->>Admin: Error: Cannot remove owner
    end
    
    API->>DB: SELECT currentPeriodCost FROM userStats WHERE userId = memberId
    DB-->>API: Return departed member's usage
    
    alt usage > 0
        API->>DB: UPDATE organization SET departedMemberUsage = departedMemberUsage + usage
        DB-->>API: Usage accumulated
    end
    
    API->>DB: DELETE FROM member WHERE userId = memberId
    DB-->>API: Member removed
    API-->>Admin: Success response
    
    Note over Billing,Webhook: Billing Calculation Flow
    Billing->>DB: SELECT userId FROM member WHERE organizationId = orgId
    DB-->>Billing: Return current members
    
    loop For each member
        Billing->>DB: Get member's currentPeriodCost
        DB-->>Billing: Return usage
    end
    
    Billing->>DB: SELECT departedMemberUsage FROM organization
    DB-->>Billing: Return departed member usage
    
    Billing->>Billing: totalUsage = currentMemberUsage + departedMemberUsage
    Billing->>Billing: Calculate overage = max(0, totalUsage - baseSubscriptionAmount)
    
    Note over Webhook: End of Billing Period
    Webhook->>DB: SELECT members for organization
    
    loop For each member
        Webhook->>DB: UPDATE userStats SET currentPeriodCost = '0'
    end
    
    Webhook->>DB: UPDATE organization SET departedMemberUsage = '0'
    DB-->>Webhook: Usage reset for new period
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@icecrasher321 icecrasher321 merged commit fc5f815 into staging Nov 30, 2025
9 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/orgs-leave branch November 30, 2025 22:23
waleedlatif1 added a commit that referenced this pull request Dec 1, 2025
… sendgrid, linkedin, more tools (#2148)

* feat(tools): added smtp, sendgrid, mailgun, linkedin, fixed permissions in context menu (#2133)

* feat(tools): added twilio sendgrid integration

* feat(tools): added smtp, sendgrid, mailgun, fixed permissions in context menu

* added top level mocks for sporadically failing tests

* incr type safety

* fix(team-plans): track departed member usage so value not lost (#2118)

* fix(team-plans): track departed member usage so value not lost

* reset usage to 0 when they leave team

* prep merge with stagig

* regen migrations

* fix org invite + ws selection'

---------

Co-authored-by: Waleed <[email protected]>

* feat(i18n): update translations (#2134)

Co-authored-by: waleedlatif1 <[email protected]>

* feat(creators): add verification for creators (#2135)

* feat(tools): added apify block/tools  (#2136)

* feat(tools): added apify

* cleanup

* feat(i18n): update translations (#2137)

Co-authored-by: waleedlatif1 <[email protected]>

* feat(env): added more optional env var examples (#2138)

* feat(statuspage): added statuspage, updated list of tools in footer, renamed routes (#2139)

* feat(statuspage): added statuspage, updated list of tools in footer, renamed routes

* ack PR comments

* feat(tools): add generic search tool (#2140)

* feat(i18n): update translations (#2141)

* fix(sdks): bump sdk versions (#2142)

* fix(webhooks): count test webhooks towards usage limit (#2143)

* fix(bill): add requestId to webhook processing (#2144)

* improvement(subflow): remove all associated edges when moving a block into a subflow (#2145)

* improvement(subflow): remove all associated edges when moving a block into a subflow

* ack PR comments

* fix(polling): mark webhook failed on webhook trigger errors (#2146)

* fix(deps): declare core transient deps explicitly (#2147)

* fix(deps): declare core transient deps explicitly

* ack PR comments

---------

Co-authored-by: Vikhyath Mondreti <[email protected]>
Co-authored-by: waleedlatif1 <[email protected]>
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.

3 participants