fix: convert metered tier upTo from internal to display credits in listPlans (#18108)
## Summary - The `listPlans` GraphQL query was returning metered tier `upTo` values in internal credit units (1000x the display value), causing "Credits by period" and "Credit Plan" dropdowns to show "50M" instead of "50k" - Applied the existing `INTERNAL_CREDITS_PER_DISPLAY_CREDIT` (1000) divisor in `formatBillingDatabasePriceToMeteredPriceDTO`, matching the conversion already used in `getMeteredProductsUsage` resolver - Updated frontend mock data to reflect the corrected display-unit values ## Test plan - [x] Unit tests pass for `format-database-product-to-graphql-dto.util` - [x] Unit tests pass for `metered-credit.service` and `billing-credit-rollover.service` - [ ] Verify billing page shows correct credit amounts (50k, not 50M) for "Credits by period" and "Credit Plan" Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
@@ -58,7 +58,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 999000,
|
||||
unitAmount: null,
|
||||
upTo: 7500000000,
|
||||
upTo: 7500000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -78,7 +78,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 399000,
|
||||
unitAmount: null,
|
||||
upTo: 2600000000,
|
||||
upTo: 2600000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -98,7 +98,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 199000,
|
||||
unitAmount: null,
|
||||
upTo: 1200000000,
|
||||
upTo: 1200000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -118,7 +118,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 99000,
|
||||
unitAmount: null,
|
||||
upTo: 540000000,
|
||||
upTo: 540000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -138,7 +138,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 29000,
|
||||
unitAmount: null,
|
||||
upTo: 130000000,
|
||||
upTo: 130000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -158,7 +158,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 0,
|
||||
unitAmount: null,
|
||||
upTo: 50000000,
|
||||
upTo: 50000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -178,7 +178,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 99900,
|
||||
unitAmount: null,
|
||||
upTo: 700000000,
|
||||
upTo: 700000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -198,7 +198,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 39900,
|
||||
unitAmount: null,
|
||||
upTo: 240000000,
|
||||
upTo: 240000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -218,7 +218,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 19900,
|
||||
unitAmount: null,
|
||||
upTo: 110000000,
|
||||
upTo: 110000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -238,7 +238,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 9900,
|
||||
unitAmount: null,
|
||||
upTo: 50000000,
|
||||
upTo: 50000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -258,7 +258,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 2900,
|
||||
unitAmount: null,
|
||||
upTo: 10000000,
|
||||
upTo: 10000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -278,7 +278,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 0,
|
||||
unitAmount: null,
|
||||
upTo: 5000000,
|
||||
upTo: 5000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -348,7 +348,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 999000,
|
||||
unitAmount: null,
|
||||
upTo: 7500000000,
|
||||
upTo: 7500000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -368,7 +368,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 399000,
|
||||
unitAmount: null,
|
||||
upTo: 2600000000,
|
||||
upTo: 2600000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -388,7 +388,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 199000,
|
||||
unitAmount: null,
|
||||
upTo: 1200000000,
|
||||
upTo: 1200000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -408,7 +408,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 99000,
|
||||
unitAmount: null,
|
||||
upTo: 540000000,
|
||||
upTo: 540000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -428,7 +428,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 29000,
|
||||
unitAmount: null,
|
||||
upTo: 130000000,
|
||||
upTo: 130000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -448,7 +448,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 0,
|
||||
unitAmount: null,
|
||||
upTo: 50000000,
|
||||
upTo: 50000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -468,7 +468,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 99900,
|
||||
unitAmount: null,
|
||||
upTo: 700000000,
|
||||
upTo: 700000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -488,7 +488,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 39900,
|
||||
unitAmount: null,
|
||||
upTo: 240000000,
|
||||
upTo: 240000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -508,7 +508,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 19900,
|
||||
unitAmount: null,
|
||||
upTo: 110000000,
|
||||
upTo: 110000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -528,7 +528,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 9900,
|
||||
unitAmount: null,
|
||||
upTo: 50000000,
|
||||
upTo: 50000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -548,7 +548,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 2900,
|
||||
unitAmount: null,
|
||||
upTo: 10000000,
|
||||
upTo: 10000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
@@ -568,7 +568,7 @@ export const mockBillingPlans = {
|
||||
__typename: 'BillingPriceTier',
|
||||
flatAmount: 0,
|
||||
unitAmount: null,
|
||||
upTo: 5000000,
|
||||
upTo: 5000,
|
||||
},
|
||||
{
|
||||
__typename: 'BillingPriceTier',
|
||||
|
||||
+56
-3
@@ -31,7 +31,11 @@ describe('formatBillingDatabaseProductToGraphqlDTO', () => {
|
||||
{
|
||||
interval: SubscriptionInterval.Month,
|
||||
tiers: [
|
||||
{ up_to: 10, flat_amount: 500, unit_amount: null },
|
||||
{
|
||||
up_to: 10000000,
|
||||
flat_amount: 500,
|
||||
unit_amount: null,
|
||||
},
|
||||
{ up_to: null, flat_amount: null, unit_amount: 0.001 },
|
||||
],
|
||||
stripePriceId: 'price_metered1',
|
||||
@@ -81,7 +85,11 @@ describe('formatBillingDatabaseProductToGraphqlDTO', () => {
|
||||
{
|
||||
interval: SubscriptionInterval.Month,
|
||||
tiers: [
|
||||
{ up_to: 10, flat_amount: 500, unit_amount: null },
|
||||
{
|
||||
up_to: 10000000,
|
||||
flat_amount: 500,
|
||||
unit_amount: null,
|
||||
},
|
||||
{ up_to: null, flat_amount: null, unit_amount: 0.001 },
|
||||
],
|
||||
stripePriceId: 'price_metered1',
|
||||
@@ -91,7 +99,7 @@ describe('formatBillingDatabaseProductToGraphqlDTO', () => {
|
||||
prices: [
|
||||
{
|
||||
tiers: [
|
||||
{ upTo: 10, flatAmount: 500, unitAmount: null },
|
||||
{ upTo: 10000, flatAmount: 500, unitAmount: null },
|
||||
{ upTo: null, flatAmount: null, unitAmount: 0.001 },
|
||||
],
|
||||
recurringInterval: SubscriptionInterval.Month,
|
||||
@@ -103,4 +111,49 @@ describe('formatBillingDatabaseProductToGraphqlDTO', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert internal credits to display credits in metered tier upTo', () => {
|
||||
const mockPlan = {
|
||||
planKey: BillingPlanKey.PRO,
|
||||
licensedProducts: [],
|
||||
meteredProducts: [
|
||||
{
|
||||
id: 'product-2',
|
||||
name: 'Test Metered Product',
|
||||
billingPrices: [
|
||||
{
|
||||
interval: SubscriptionInterval.Month,
|
||||
tiers: [
|
||||
{
|
||||
up_to: 50000000,
|
||||
flat_amount: 0,
|
||||
unit_amount: null,
|
||||
},
|
||||
{
|
||||
up_to: null,
|
||||
flat_amount: null,
|
||||
unit_amount: null,
|
||||
},
|
||||
],
|
||||
stripePriceId: 'price_metered1',
|
||||
priceUsageType: BillingUsageType.METERED,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = formatBillingDatabaseProductToGraphqlDTO(
|
||||
mockPlan as unknown as BillingGetPlanResult,
|
||||
);
|
||||
|
||||
const meteredPrices = result.meteredProducts[0].prices;
|
||||
|
||||
expect(meteredPrices![0].tiers[0]).toEqual(
|
||||
expect.objectContaining({ upTo: 50000 }),
|
||||
);
|
||||
expect(meteredPrices![0].tiers[1]).toEqual(
|
||||
expect.objectContaining({ upTo: null }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import { type BillingPriceEntity } from 'src/engine/core-modules/billing/entitie
|
||||
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/billing-subscription-interval.enum';
|
||||
import { BillingUsageType } from 'src/engine/core-modules/billing/enums/billing-usage-type.enum';
|
||||
import { type BillingGetPlanResult } from 'src/engine/core-modules/billing/types/billing-get-plan-result.type';
|
||||
import { toDisplayCredits } from 'src/engine/core-modules/billing/utils/to-display-credits.util';
|
||||
|
||||
export const formatBillingDatabaseProductToGraphqlDTO = (
|
||||
plan: BillingGetPlanResult,
|
||||
@@ -42,7 +43,7 @@ const formatBillingDatabasePriceToMeteredPriceDTO = (
|
||||
return {
|
||||
tiers:
|
||||
billingPrice?.tiers?.map((tier) => ({
|
||||
upTo: tier.up_to,
|
||||
upTo: tier.up_to !== null ? toDisplayCredits(tier.up_to) : tier.up_to,
|
||||
flatAmount: tier.flat_amount,
|
||||
unitAmount: tier.unit_amount,
|
||||
})) ?? [],
|
||||
|
||||
Reference in New Issue
Block a user