Add promo codes for first payment - #679
Open
alisawavezen12 wants to merge 47 commits into
Open
Conversation
…o code index handling
…ne promo code application and workspace unblocking
…ount based on promo validity
…move unused utils
… promo code processing
… billingNew resolver
…sm in billing logic
…itialization logic
…in CloudPayments integration
…o codes and usages factories
…c to improve clarity and remove deprecated methods
…e related types and logic for clarity
…r improved readability and maintainability
…d usages for consistency
…ocks and utility functions for improved clarity and functionality
…e subscription renewal handling in CloudPayments
…nt amount calculation logic
…ture setup and utility functions for clarity
… documentation for payment processing and subscription renewals
…card-link validation in CloudPayments webhooks
…amount calculation for clarity
…alidation in CloudPayments webhooks
… and clarify subscription renewal pricing in CloudPayments
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep package version 1.6.0 from feat/promo-code. Co-authored-by: Cursor <cursoragent@cursor.com>
neSpecc
approved these changes
Aug 31, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds first-payment promo discounts with server-side validation, CloudPayments integration, usage tracking, and UTM attribution.
Changes:
- Adds promo models, pricing, validation, usage limits, and indexes.
- Integrates discounted charges into GraphQL and CloudPayments.
- Adds extensive unit and integration coverage.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
package.json |
Bumps version and shared types. |
yarn.lock |
Locks updated shared types. |
migrations/20260615140000-add-promo-code-indexes.js |
Adds promo indexes. |
src/index.ts |
Registers promo factories. |
src/types/graphql.ts |
Extends context factories. |
src/models/promoCode.ts |
Defines promo model. |
src/models/promoCodesFactory.ts |
Adds promo lookup factory. |
src/models/promoCodeUsage.ts |
Defines usage model. |
src/models/promoCodeUsagesFactory.ts |
Adds usage persistence. |
src/models/user.ts |
Uses shared UTM type. |
src/models/usersFactory.ts |
Updates UTM typing. |
src/services/promoCodeService.ts |
Implements validation and usage. |
src/utils/promoCodePricing.ts |
Calculates discounted prices. |
src/utils/utm/utm.ts |
Adds UTM sanitization. |
src/utils/checksumService.ts |
Signs promo references. |
src/billing/types/paymentData.ts |
Adds promo payment metadata. |
src/billing/cloudpayments.ts |
Integrates promos into webhooks. |
src/resolvers/billingNew.ts |
Adds promo billing resolvers. |
src/resolvers/user.ts |
Updates signup UTM typing. |
src/directives/requireAdmin.ts |
Supports nested identifiers. |
src/typeDefs/billing.ts |
Exposes promo GraphQL API. |
test/services/promoCodeService.test.ts |
Tests promo service behavior. |
test/utils/utm.test.ts |
Tests UTM sanitization. |
test/billing/cloudpayments.test.ts |
Tests webhook billing flows. |
test/integration/cases/billing/promo.test.ts |
Tests persisted promo payments. |
test/resolvers/billingNew.test.ts |
Tests resolver promo flows. |
test/directives/requireAdmin.test.ts |
Tests nested authorization. |
test/resolvers/project.test.ts |
Updates factory fixtures. |
test/sso/saml/controller.test.ts |
Updates factory fixture. |
test/integrations/github-routes.test.ts |
Updates route fixtures. |
Suppressed comments (1)
src/services/promoCodeService.ts:176
NaNandInfinityboth pass this fixed-price validation and are returned through GraphQL'sIntfield, causing serialization errors rather than the documented promo validation error. Add the same finite-number check already used forminFinalPrice.
if (typeof benefit.amount !== 'number' || benefit.amount < DEFAULT_MIN_FINAL_PRICE) {
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| */ | ||
| const isRightAmount = +body.Amount === plan.monthlyCharge || recurrentPaymentSettings?.startDate; | ||
| const expectedAmount = promoPricing?.finalAmount ?? plan.monthlyCharge; | ||
| const isRightAmount = +body.Amount === expectedAmount || (!data.promo && recurrentPaymentSettings?.startDate); |
Comment on lines
+360
to
+362
| } catch (error) { | ||
| console.error('[Billing / Pay] Failed to record promo usage after plan change', error); | ||
| } |
Comment on lines
+436
to
+440
| const [totalUses, userUsage, workspaceUsage] = await Promise.all([ | ||
| this.factories.promoCodeUsagesFactory.countByPromoCodeId(promoCode._id), | ||
| this.factories.promoCodeUsagesFactory.findByPromoCodeAndUser(promoCode._id, userId), | ||
| this.factories.promoCodeUsagesFactory.findByPromoCodeAndWorkspace(promoCode._id, workspaceId), | ||
| ]); |
| function validateBenefitStructure(benefit: PromoCodeModel['benefit']): void { | ||
| switch (benefit.type) { | ||
| case 'percent_discount': | ||
| if (typeof benefit.percent !== 'number' || benefit.percent <= 0 || benefit.percent > 100) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
percent_discount,fixed_price; other benefit types are rejected).composePaymentreturns the amount to charge now (chargeAmount) and signs onlypromo.idin the checksum; CloudPayments/checkand/payrecompute the price from DB.