Home / Function/ UpcomingInvoice() — supabase Function Reference

UpcomingInvoice() — supabase Function Reference

Architecture documentation for the UpcomingInvoice() function in UpcomingInvoice.tsx from the supabase codebase.

Entity Profile

Dependency Diagram

graph TD
  2c85c7d8_937d_2785_9b6c_5080fa88a0c8["UpcomingInvoice()"]
  33d44cde_fee6_d849_e1fe_792e48dd1fdb["formatUsage()"]
  2c85c7d8_937d_2785_9b6c_5080fa88a0c8 -->|calls| 33d44cde_fee6_d849_e1fe_792e48dd1fdb
  fced348a_ab7f_11cf_18fe_5313984546b4["billingMetricUnit()"]
  2c85c7d8_937d_2785_9b6c_5080fa88a0c8 -->|calls| fced348a_ab7f_11cf_18fe_5313984546b4
  style 2c85c7d8_937d_2785_9b6c_5080fa88a0c8 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/UpcomingInvoice.tsx lines 51–313

const UpcomingInvoice = ({ slug }: UpcomingInvoiceProps) => {
  const {
    data: upcomingInvoice,
    error: error,
    isPending: isLoading,
    isError,
    isSuccess,
  } = useOrgUpcomingInvoiceQuery({ orgSlug: slug })

  // For non-platform customers, compute is broken down per project and contains a breakdown array
  const computeItems =
    upcomingInvoice?.lines?.filter((item) => item.description?.toLowerCase().includes('compute')) ||
    []

  const computeCreditsItem =
    upcomingInvoice?.lines?.find((item) => item.description.startsWith('Compute Credits')) ?? null

  const planItem = upcomingInvoice?.lines?.find((item) =>
    item.description?.toLowerCase().includes('plan')
  )

  const regularComputeItems = computeItems.filter(
    (it) => !it.metadata?.is_branch && !it.metadata?.is_read_replica
  )
  const branchingComputeItems = computeItems.filter((it) => it.metadata?.is_branch)
  const replicaComputeItems = computeItems.filter((it) => it.metadata?.is_read_replica)

  const otherItems =
    upcomingInvoice?.lines
      ?.filter(
        (item) =>
          !item.description?.toLowerCase().includes('compute') &&
          !item.description?.toLowerCase().includes('plan') &&
          item.amount_before_discount > 0
      )
      .sort((a, b) => b.amount_before_discount - a.amount_before_discount) || []

  return (
    <>
      {isLoading && (
        <div className="space-y-2">
          <ShimmeringLoader />
          <ShimmeringLoader className="w-3/4" />
          <ShimmeringLoader className="w-1/2" />
        </div>
      )}

      {isError && <AlertError subject="Failed to retrieve upcoming invoice" error={error} />}

      {isSuccess && (
        <div>
          <div>
            <Table className="w-full text-sm">
              <TableBody>
                <TableRow>
                  <TableCell className="!py-2 px-0">{planItem?.description}</TableCell>
                  <TableCell className="text-right py-2 px-0">
                    {planItem == null ? (
                      '-'
                    ) : (
                      <InvoiceLineItemAmount
                        amount={planItem.amount}
                        amountBeforeDiscount={planItem.amount_before_discount}
                      />
                    )}
                  </TableCell>
                </TableRow>

                {/* Compute section */}
                <ComputeLineItem
                  computeItems={regularComputeItems}
                  title="Compute"
                  computeCredits={computeCreditsItem}
                  tooltip={
                    <p className="prose text-xs">
                      The first project is covered by Compute Credits. Additional projects incur
                      compute costs starting at <span translate="no">$10</span>/month, independent
                      of activity. See{' '}
                      <Link
                        href={`${DOCS_URL}/guides/platform/manage-your-usage/compute`}
                        target="_blank"
                      >
                        docs
                      </Link>
                      .
                    </p>
                  }
                />

                {/* Read Replica compute */}
                <ComputeLineItem
                  title="Replica Compute"
                  computeItems={replicaComputeItems}
                  tooltip={
                    <p className="prose text-xs">
                      Each Read Replica is a dedicated database. You are charged for its resources:
                      Compute, Disk Size, provisioned Disk IOPS, provisioned Disk Throughput, and
                      IPv4. See{' '}
                      <Link
                        href={`${DOCS_URL}/guides/platform/manage-your-usage/read-replicas`}
                        target="_blank"
                      >
                        docs
                      </Link>
                      .
                    </p>
                  }
                />

                {/* Branching compute */}
                {branchingComputeItems.length > 0 && (
                  <TableRow>
                    <TableCell className="py-2 px-0">
                      <div className="flex items-center gap-1">
                        <span>Branching</span>
                        <InfoTooltip className="max-w-sm">
                          <ul className="ml-6 list-disc">
                            {branchingComputeItems
                              .flatMap((it) => it.breakdown)
                              .map((breakdown) => (
                                <li key={`branching-breakdown-${breakdown!.project_ref}`}>
                                  {breakdown!.project_name} ({breakdown!.usage} Hours)
                                </li>
                              ))}
                          </ul>

                          <p className="mt-2">
                            See{' '}
                            <Link
                              className="underline"
                              href={`${DOCS_URL}/guides/platform/manage-your-usage/branching`}
                              target="_blank"
                            >
                              docs
                            </Link>{' '}
                            on how billing for Branching works.
                          </p>
                        </InfoTooltip>
                      </div>
                    </TableCell>
                    <TableCell className="text-right py-2 px-0">
                      <InvoiceLineItemAmount
                        amount={branchingComputeItems.reduce((prev, cur) => prev + cur.amount, 0)}
                        amountBeforeDiscount={branchingComputeItems.reduce(
                          (prev, cur) => prev + (cur.amount_before_discount ?? 0),
                          0
                        )}
                      />
                    </TableCell>
                  </TableRow>
                )}

                {/* Non-compute items */}
                {otherItems.map((item) => (
                  <TableRow key={item.description}>
                    <TableCell className="py-2 px-0">
                      <div className="gap-1 flex items-center">
                        <span>{item.description ?? 'Unknown'}</span>
                        {((item.breakdown && item.breakdown.length > 0) ||
                          item.usage_metric != null) && (
                          <InfoTooltip className="max-w-sm">
                            {item.unit_price_desc && (
                              <p className="mb-2" translate="no">
                                Pricing: {item.unit_price_desc}
                              </p>
                            )}

                            {item.breakdown && item.breakdown.length > 0 && (
                              <>
                                <p>Projects using {item.description}:</p>
                                <ul className="ml-6 list-disc">
                                  {item.breakdown.map((breakdown) => (
                                    <li
                                      key={`${item.description}-breakdown-${breakdown.project_ref}`}
                                    >
                                      <Link
                                        className="underline"
                                        href={`/project/${breakdown.project_ref}`}
                                        target="_blank"
                                      >
                                        {breakdown.project_name}
                                      </Link>{' '}
                                      {item.usage_metric && (
                                        <span>
                                          ({formatUsage(item.usage_metric, breakdown)}{' '}
                                          {billingMetricUnit(item.usage_metric)})
                                        </span>
                                      )}
                                    </li>
                                  ))}
                                </ul>
                              </>
                            )}

                            {item.usage_metric &&
                              usageBillingDocsLink[item.usage_metric] != null && (
                                <p className="mt-2">
                                  See{' '}
                                  <Link
                                    className="underline"
                                    href={usageBillingDocsLink[item.usage_metric]!}
                                    target="_blank"
                                  >
                                    docs
                                  </Link>{' '}
                                  on how billing for {item.description} works and{' '}
                                  <Link className="underline" href={`/organization/${slug}/usage`}>
                                    usage page
                                  </Link>{' '}
                                  for a detailed breakdown.
                                </p>
                              )}
                          </InfoTooltip>
                        )}
                      </div>
                    </TableCell>
                    <TableCell className="text-right py-2 px-0">
                      <InvoiceLineItemAmount
                        amount={item.amount}
                        amountBeforeDiscount={item.amount_before_discount}
                      />
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>

              <TableFooter>
                <TableRow>
                  <TableCell className="font-medium py-2 px-0 flex items-center">
                    <span className="mr-2">Current Costs</span>
                    <InfoTooltip>
                      Costs accumulated from the beginning of the billing cycle up to now.
                    </InfoTooltip>
                  </TableCell>
                  <TableCell className="text-right font-medium py-2 px-0" translate="no">
                    {formatCurrency(upcomingInvoice?.amount_total) ?? '-'}
                  </TableCell>
                </TableRow>

                {upcomingInvoice?.amount_projected && (
                  <TableRow>
                    <TableCell className="font-medium py-2 px-0 flex items-center">
                      <span className="mr-2">Projected Costs</span>
                      <InfoTooltip className="max-w-xs">
                        Projected costs at the end of the billing cycle. Includes predictable costs
                        for Compute Hours, IPv4, Custom Domain and Point-In-Time-Recovery, but no
                        costs for metrics like MAU, storage or function invocations. Final amounts
                        may vary depending on your usage.
                      </InfoTooltip>
                    </TableCell>
                    <TableCell className="text-right font-medium py-2 px-0" translate="no">
                      {formatCurrency(upcomingInvoice.amount_projected) ?? '-'}
                    </TableCell>
                  </TableRow>
                )}
              </TableFooter>
            </Table>
          </div>
        </div>
      )}
    </>
  )
}

Subdomains

Frequently Asked Questions

What does UpcomingInvoice() do?
UpcomingInvoice() is a function in the supabase codebase.
What does UpcomingInvoice() call?
UpcomingInvoice() calls 2 function(s): billingMetricUnit, formatUsage.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free