Skip to content

Commit

Permalink
feat(console): App storage billing - auto top-up
Browse files Browse the repository at this point in the history
  • Loading branch information
Cosmin-Parvulescu authored Feb 28, 2024
1 parent 1d5c138 commit bc668ff
Show file tree
Hide file tree
Showing 37 changed files with 1,008 additions and 171 deletions.
2 changes: 1 addition & 1 deletion apps/console/.dev.vars.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ SECRET_STRIPE_API_KEY = ""
SECRET_STRIPE_WEBHOOK_SECRET = ""
SECRET_STRIPE_PRO_PLAN_ID = ""
SECRET_STRIPE_GROUP_SEAT_PLAN_ID = ""
SECRET_STRIPE_APP_DATA_STORAGE_PRICE_IDS = ""
SECRET_STRIPE_APP_DATA_STORAGE_PRICE_IDS = {"SECRET_STRIPE_APP_DATA_STORAGE_STARTER_PRICE_ID":"","SECRET_STRIPE_APP_DATA_STORAGE_SCALE_PRICE_ID":"","SECRET_STRIPE_APP_DATA_STORAGE_STARTER_TOP_UP_PRICE_ID":"","SECRET_STRIPE_APP_DATA_STORAGE_SCALE_TOP_UP_PRICE_ID":""}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useEffect, useState } from 'react'
import { HiOutlineX } from 'react-icons/hi'
import { InputToggle } from '@proofzero/design-system/src/atoms/form/InputToggle'
import { FaCheck, FaTimes } from 'react-icons/fa'
import { HiExclamationTriangle } from 'react-icons/hi2'

type AppDataStorageModalProps = {
isOpen: boolean
Expand All @@ -17,6 +18,10 @@ type AppDataStorageModalProps = {
topUp?: boolean
currentPrice?: number
clientID: string
reads?: number
writes?: number
readTopUp?: number
writeTopUp?: number
}

const AppDataStorageModal: React.FC<AppDataStorageModalProps> = ({
Expand All @@ -27,6 +32,10 @@ const AppDataStorageModal: React.FC<AppDataStorageModalProps> = ({
topUp = false,
currentPrice = 0,
clientID,
reads,
writes,
readTopUp = 0,
writeTopUp = 0,
}) => {
const [selectedPackage, setSelectedPackage] =
useState<ExternalAppDataPackageType>(
Expand Down Expand Up @@ -57,7 +66,7 @@ const AppDataStorageModal: React.FC<AppDataStorageModalProps> = ({
weight="semibold"
className="text-left text-gray-800"
>
Purchase Entitlement(s)
App Data Storage
</Text>
<button
className="bg-white p-2 rounded-lg text-xl cursor-pointer hover:bg-[#F3F4F6]"
Expand All @@ -75,6 +84,7 @@ const AppDataStorageModal: React.FC<AppDataStorageModalProps> = ({
>
Choose Package
</Text>

<div className="text-left flex flex-row items-center gap-1.5">
<Button
disabled={subscriptionFetcher.state !== 'idle'}
Expand Down Expand Up @@ -111,6 +121,30 @@ const AppDataStorageModal: React.FC<AppDataStorageModalProps> = ({
</div>
</div>

{(reads &&
reads >
ExternalAppDataPackages[selectedPackage].reads + readTopUp) ||
(writes &&
writes >
ExternalAppDataPackages[selectedPackage].writes +
writeTopUp) ? (
<>
<div className="flex flex-row rounded p-4 gap-2 max-w-[724px] bg-orange-50">
<HiExclamationTriangle className="h-5 w-5 text-orange-400" />

<Text
size="sm"
weight="medium"
className="text-left text-orange-600"
>
You are already past usage limits of selected package. You
will be charged a one time top-up fee to enable continued
access to the service within the current billing cycle.
</Text>
</div>
</>
) : null}

<div className="flex flex-col border rounded">
<div className="flex flex-row items-center justify-between px-4 py-2">
<Text size="sm" weight="medium" className="text-gray-800">
Expand Down
2 changes: 1 addition & 1 deletion apps/console/app/components/Billing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import { ToastWithLink } from '@proofzero/design-system/src/atoms/toast/ToastWit
import { HiArrowNarrowRight } from 'react-icons/hi'
import _ from 'lodash'
import iSvg from '@proofzero/design-system/src/atoms/info/i.svg'
import plans, { PlanDetails } from '~/utils/plans'
import { PaymentData, ServicePlanType } from '@proofzero/types/billing'
import { Spinner } from '@proofzero/packages/design-system/src/atoms/spinner/Spinner'
import plans, { PlanDetails } from '@proofzero/utils/billing/plans'

export const PlanFeatures = ({
plan,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import type { IdentityURN } from '@proofzero/urns/identity'
import ContactUs from '../ContactUs'
import { ServicePlanType } from '@proofzero/types/billing'
import { isPlanGuarded } from '~/utils/planGate'
import plans from '~/utils/plans'
import _ from 'lodash'
import { TbLock } from 'react-icons/tb'
import { Button } from '@proofzero/design-system'
import { NavLink } from '@remix-run/react'
import plans from '@proofzero/utils/billing/plans'

type EarlyAccessPanelProps = {
clientID: string
Expand Down
2 changes: 1 addition & 1 deletion apps/console/app/routes/__layout/billing/cancel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
requireJWT,
} from '~/utilities/session.server'

import { voidInvoice } from '~/services/billing/stripe'
import { ToastType } from '@proofzero/design-system/src/atoms/toast'
import { voidInvoice } from '@proofzero/utils/billing/stripe'

export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context }) => {
Expand Down
6 changes: 3 additions & 3 deletions apps/console/app/routes/__layout/billing/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
getAuthzHeaderConditionallyFromToken,
parseJwt,
} from '@proofzero/utils'
import { createCustomer, updateCustomer } from '~/services/billing/stripe'
import { IdentityURN } from '@proofzero/urns/identity'
import { AccountURN } from '@proofzero/urns/account'
import { ToastType } from '@proofzero/design-system/src/atoms/toast'
Expand All @@ -21,6 +20,7 @@ import {
} from '@proofzero/urns/identity-group'
import { BadRequestError, UnauthorizedError } from '@proofzero/errors'
import { IdentityRefURN } from '@proofzero/urns/identity-ref'
import { createCustomer, updateCustomer } from '@proofzero/utils/billing/stripe'

export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context }) => {
Expand Down Expand Up @@ -82,7 +82,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
name,
URN: targetURN,
},
context.env
context.env.SECRET_STRIPE_API_KEY
)

paymentData = {
Expand All @@ -105,7 +105,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
email,
name,
},
context.env
context.env.SECRET_STRIPE_API_KEY
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import _ from 'lodash'
import { process3DSecureCard } from '~/utils/billing'
import { IoWarningOutline } from 'react-icons/io5'
import { ToastWarning } from '@proofzero/design-system/src/atoms/toast/ToastWarning'
import plans from '../../../../utils/plans'
import { ServicePlanType } from '@proofzero/types/billing'
import { PlanCard } from '~/components/Billing'
import {
Expand All @@ -40,6 +39,7 @@ import { ListIdentityGroupsOutput } from '@proofzero/platform/identity/src/jsonr
import { AppLoaderData } from '~/root'
import { GroupSeatingCard } from '~/components/Billing/seating'
import { IdentityGroupURN } from '@proofzero/urns/identity-group'
import plans from '@proofzero/utils/billing/plans'

export const loader = billingLoader
export const action = billingAction
Expand Down
6 changes: 4 additions & 2 deletions apps/console/app/routes/__layout/billing/ops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import createCoreClient, {
CoreClientType,
} from '@proofzero/platform-clients/core'
import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace'
import { reconcileSubscriptions } from '~/services/billing/stripe'
import { PaymentData, ServicePlanType } from '@proofzero/types/billing'
import { IdentityRefURN } from '@proofzero/urns/identity-ref'
import { IdentityURN, IdentityURNSpace } from '@proofzero/urns/identity'
Expand Down Expand Up @@ -39,6 +38,7 @@ import {
getCurrentAndUpcomingInvoices,
} from '~/utils/billing'
import { IDENTITY_GROUP_OPTIONS } from '@proofzero/platform/identity/src/constants'
import { reconcileSubscriptions } from '@proofzero/utils/billing/stripe'

export enum TxProduct {
Entitlements = 'entitlements',
Expand Down Expand Up @@ -346,7 +346,9 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
billingURL: `${context.env.CONSOLE_URL}/billing`,
settingsURL: `${context.env.CONSOLE_URL}`,
},
context.env
context.env.SECRET_STRIPE_API_KEY,
context.env.SECRET_STRIPE_PRO_PLAN_ID,
context.env.SECRET_STRIPE_GROUP_SEAT_PLAN_ID
)
}

Expand Down
4 changes: 2 additions & 2 deletions apps/console/app/routes/__layout/billing/payment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
getAuthzHeaderConditionallyFromToken,
parseJwt,
} from '@proofzero/utils'
import { updatePaymentMethod } from '~/services/billing/stripe'
import { BadRequestError, UnauthorizedError } from '@proofzero/errors'
import {
IdentityGroupURN,
IdentityGroupURNSpace,
} from '@proofzero/urns/identity-group'
import { IdentityURN } from '@proofzero/urns/identity'
import { IdentityRefURN } from '@proofzero/urns/identity-ref'
import { updatePaymentMethod } from '@proofzero/utils/billing/stripe'

export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context }) => {
Expand Down Expand Up @@ -64,7 +64,7 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
customerID,
returnURL,
},
context.env
context.env.SECRET_STRIPE_API_KEY
)
}
)
2 changes: 1 addition & 1 deletion apps/console/app/routes/__layout/billing/personal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
import type { LoaderData as OutletContextData } from '~/root'
import { useEffect, useState } from 'react'
import { Toaster, toast } from '@proofzero/design-system/src/atoms/toast'
import plans from '../../../utils/plans'
import { ToastWithLink } from '@proofzero/design-system/src/atoms/toast/ToastWithLink'
import { Input } from '@proofzero/design-system/src/atoms/form/Input'
import { getEmailIcon } from '@proofzero/utils/getNormalisedConnectedAccounts'
Expand All @@ -40,6 +39,7 @@ import {
loader as billingLoader,
action as billingAction,
} from './ops'
import plans from '@proofzero/utils/billing/plans'

export const loader = billingLoader
export const action = billingAction
Expand Down
4 changes: 2 additions & 2 deletions apps/console/app/routes/__layout/billing/portal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
getAuthzHeaderConditionallyFromToken,
parseJwt,
} from '@proofzero/utils'
import { accessCustomerPortal } from '~/services/billing/stripe'
import { BadRequestError, UnauthorizedError } from '@proofzero/errors'
import {
IdentityGroupURNSpace,
IdentityGroupURN,
} from '@proofzero/urns/identity-group'
import { IdentityURN } from '@proofzero/urns/identity'
import { IdentityRefURN } from '@proofzero/urns/identity-ref'
import { accessCustomerPortal } from '@proofzero/utils/billing/stripe'

export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context }) => {
Expand Down Expand Up @@ -64,7 +64,7 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper(
customerID,
returnURL,
},
context.env
context.env.SECRET_STRIPE_API_KEY
)
}
)
6 changes: 4 additions & 2 deletions apps/console/app/routes/__layout/billing/update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
getAuthzHeaderConditionallyFromToken,
parseJwt,
} from '@proofzero/utils'
import { reconcileSubscriptions } from '~/services/billing/stripe'
import { type IdentityURN } from '@proofzero/urns/identity'
import { ToastType } from '@proofzero/design-system/src/atoms/toast'
import { ServicePlanType } from '@proofzero/types/billing'
Expand All @@ -21,6 +20,7 @@ import {
IdentityGroupURN,
} from '@proofzero/urns/identity-group'
import { IdentityRefURN } from '@proofzero/urns/identity-ref'
import { reconcileSubscriptions } from '@proofzero/utils/billing/stripe'

/**
* WARNING: Here be dragons, and not the cute, cuddly kind! This code runs twice in certain scenarios because when the user
Expand Down Expand Up @@ -82,7 +82,9 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
billingURL: `${context.env.CONSOLE_URL}/billing`,
settingsURL: `${context.env.CONSOLE_URL}`,
},
context.env
context.env.SECRET_STRIPE_API_KEY,
context.env.SECRET_STRIPE_PRO_PLAN_ID,
context.env.SECRET_STRIPE_GROUP_SEAT_PLAN_ID
)

// Then based on reconciled result we update the plan
Expand Down
Loading

0 comments on commit bc668ff

Please sign in to comment.