ondemandDisabled.tsx 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /**
  2. * OnDemandDisabled is a component that displays an error alert when on-demand billing
  3. * has been disabled for an organization due to unpaid invoices.
  4. *
  5. * On-demand billing can be disabled in two places:
  6. * 1. At the subscription level via subscription.flags.ondemand_disabled
  7. * 2. In the current billing history period via billinghistory.ondemand_disabled
  8. *
  9. * When disabled:
  10. * - The organization cannot use on-demand capacity
  11. * - This may impact the organization's ability to accept data into Sentry
  12. * - The user needs to pay outstanding invoices to re-enable on-demand billing
  13. *
  14. * Integration with billing system:
  15. * - The subscription.disable_ondemand() method sets both subscription flag and billing history
  16. * - Re-enabling requires paying outstanding invoices and calling subscription.enable_ondemand()
  17. *
  18. * Component behavior:
  19. * - Renders an error Alert component when conditions are met
  20. * - Provides links to billing receipts and support email
  21. * - Used in both billing overview pages (with and without billing permissions)
  22. *
  23. * @param props.subscription - The organization's subscription object containing:
  24. * - onDemandDisabled: boolean indicating if on-demand billing is disabled
  25. * - onDemandMaxSpend: number indicating maximum on-demand spend limit
  26. * - planTier: string indicating the subscription plan tier
  27. */
  28. import {NavLink} from 'react-router-dom';
  29. import {Alert} from 'sentry/components/core/alert';
  30. import ExternalLink from 'sentry/components/links/externalLink';
  31. import {tct} from 'sentry/locale';
  32. import {PlanTier, type Subscription} from 'getsentry/types';
  33. import {isAmPlan} from 'getsentry/utils/billing';
  34. interface Props {
  35. subscription: Subscription;
  36. }
  37. function OnDemandDisabled({subscription}: Props) {
  38. // Only show the alert if billing is disabled and there's a spend limit configured
  39. if (!(subscription.onDemandDisabled && subscription.onDemandMaxSpend > 0)) {
  40. return null;
  41. }
  42. // Determine the appropriate terminology based on plan tier
  43. const preAM3Tiers = [PlanTier.AM1, PlanTier.AM2];
  44. const isPreAM3Tier = preAM3Tiers.includes(subscription.planTier as PlanTier);
  45. const isAMTier = isAmPlan(subscription.planTier as PlanTier);
  46. // Set display name based on plan tier:
  47. // - "Pay-as-you-go" for AM3+ plans
  48. // - "On-demand" for all other plans (including legacy AM1/AM2)
  49. let name = 'On-demand';
  50. if (isAMTier && !isPreAM3Tier) {
  51. name = 'Pay-as-you-go';
  52. }
  53. return (
  54. <Alert.Container>
  55. <Alert type="error" data-test-id="ondemand-disabled-alert">
  56. <span>
  57. {tct(
  58. "[Name] billing is disabled for your organization due to an unpaid [lowercase_name] invoice. This may impact your organization's ability to accept data into Sentry. [docs_link:Learn more about this process].",
  59. {
  60. Name: name,
  61. lowercase_name: name.toLowerCase(),
  62. docs_link: (
  63. <ExternalLink href="https://sentry.zendesk.com/hc/en-us/articles/23622477256987-We-can-t-pay-our-on-demand-pay-as-you-go-invoice-and-have-an-annual-contract-What-happens" />
  64. ),
  65. }
  66. )}
  67. </span>{' '}
  68. <span>
  69. {tct(
  70. 'Please contact [contact_link:support@sentry.io] to pay [receipts_link:closed/outstanding invoices] to re-enable [lowercase_name] billing.',
  71. {
  72. lowercase_name: name.toLowerCase(),
  73. receipts_link: <NavLink to="/settings/billing/receipts/" />,
  74. contact_link: <a href="mailto:support@sentry.io" />,
  75. }
  76. )}
  77. </span>
  78. </Alert>
  79. </Alert.Container>
  80. );
  81. }
  82. export default OnDemandDisabled;