Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/app/billing-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import {
SourceType,
UsageCost,
UsageCostType,
GetLocationBillingOrganizationResponse,
UpdateLocationBillingOrganizationResponse,
ChargeOrganizationResponse,
CreateInvoiceAndChargeImmediatelyResponse,
} from '../gen/app/v1/billing_pb';
import {
BillingClient,
Expand Down Expand Up @@ -74,6 +78,20 @@ const testBillingInfo = {
billingTier: 'platinum',
};

const testLocationBillingOrgResponse = new GetLocationBillingOrganizationResponse({
billingOrganizationId: 'test-billing-org-id',
});

const testUpdateLocationBillingOrgResponse = new UpdateLocationBillingOrganizationResponse({});

const testChargeOrgResponse = new ChargeOrganizationResponse({
invoiceId: 'test-invoice-id',
});

const testCreateInvoiceAndChargeImmediatelyResponse = new CreateInvoiceAndChargeImmediatelyResponse({
invoiceId: 'test-invoice-id',
});

let testGetInvoicePdfStream: WritableIterable<GetInvoicePdfResponse>;

let mockTransport: Transport;
Expand Down Expand Up @@ -118,6 +136,10 @@ describe('BillingClient tests', () => {
getOrgBillingInformation: () => testBillingInfo,
getInvoicesSummary: () => testInvoiceSummary,
getInvoicePdf: () => testGetInvoicePdfStream,
getLocationBillingOrganization: () => testLocationBillingOrgResponse,
updateLocationBillingOrganization: () => testUpdateLocationBillingOrgResponse,
chargeOrganization: () => testChargeOrgResponse,
createInvoiceAndChargeImmediately: () => testCreateInvoiceAndChargeImmediatelyResponse,
});
});
});
Expand Down Expand Up @@ -162,4 +184,43 @@ describe('BillingClient tests', () => {
const array = new Uint8Array([1, 2, 3, 4]);
await expect(promise).resolves.toStrictEqual(array);
});

it('getLocationBillingOrganization', async () => {
const response = await subject().getLocationBillingOrganization('locationId');
expect(response).toEqual(testLocationBillingOrgResponse);
});

it('updateLocationBillingOrganization', async () => {
const response = await subject().updateLocationBillingOrganization(
'locationId',
'billingOrgId'
);
expect(response).toEqual(testUpdateLocationBillingOrgResponse);
});

it('chargeOrganization', async () => {
const response = await subject().chargeOrganization('orgId', 10.0, 1.0, {
description: 'test charge',
orgIdForBranding: 'brandingOrgId',
disableConfirmationEmail: true,
});
expect(response).toEqual(testChargeOrgResponse);

const responseMinimal = await subject().chargeOrganization('orgId', 5.0, 0.5);
expect(responseMinimal).toEqual(testChargeOrgResponse);
});

it('createInvoiceAndChargeImmediately (deprecated)', async () => {
const response = await subject().createInvoiceAndChargeImmediately(
'orgId',
10.0,
1.0,
{
description: 'test invoice',
orgIdForBranding: 'brandingOrgId',
disableConfirmationEmail: true,
}
);
expect(response).toEqual(testCreateInvoiceAndChargeImmediatelyResponse);
});
});
90 changes: 89 additions & 1 deletion src/app/billing-client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import type {
GetLocationBillingOrganizationResponse,
UpdateLocationBillingOrganizationResponse,
ChargeOrganizationResponse
} from '../gen/app/v1/billing_pb';
import { createClient, type Client, type Transport } from '@connectrpc/connect';
import { BillingService } from '../gen/app/v1/billing_connect';
import type { GetCurrentMonthUsageResponse as PBGetCurrentMonthUsageResponse } from '../gen/app/v1/billing_pb';
Expand Down Expand Up @@ -115,6 +120,89 @@ export class BillingClient {
}
return concatArrayU8(chunks);
}

/**
* Get the billing organization for a location.
*
* @param locationId - The location ID.
*/
async getLocationBillingOrganization(locationId: string) {
return this.client.getLocationBillingOrganization({
locationId,
});
}

/**
* Update the billing organization for a location.
*
* @param locationId - The location ID.
* @param billingOrganizationId - The billing organization ID.
*/
async updateLocationBillingOrganization(
locationId: string,
billingOrganizationId: string
) {
return this.client.updateLocationBillingOrganization({
locationId,
billingOrganizationId,
});
}

/**
* Charge an organization on the spot.
*
* @param orgIdToCharge - The organization ID to charge.
* @param subtotal - The subtotal amount to charge.
* @param tax - The tax amount to charge.
* @param options - Optional parameters.
* @param options.description - A description for the charge.
* @param options.orgIdForBranding - The organization ID for branding purposes.
* @param options.disableConfirmationEmail - Whether to disable the confirmation email.
*/
async chargeOrganization(
orgIdToCharge: string,
subtotal: number,
tax: number,
options?: {
description?: string;
orgIdForBranding?: string;
disableConfirmationEmail?: boolean;
}
) {
return this.client.chargeOrganization({
orgIdToCharge,
description: options?.description,
subtotal,
tax,
orgIdForBranding: options?.orgIdForBranding,
disableConfirmationEmail: options?.disableConfirmationEmail ?? false,
});
}

/**
* @deprecated Use {@link BillingClient.chargeOrganization} instead.
* Directly create a flat fee invoice for an organization and charge on the spot.
*
* @param orgIdToCharge - The organization ID to charge.
* @param subtotal - The subtotal amount to charge.
* @param tax - The tax amount to charge.
* @param options - Optional parameters.
* @param options.description - A description for the invoice.
* @param options.orgIdForBranding - The organization ID for branding purposes.
* @param options.disableConfirmationEmail - Whether to disable the confirmation email.
*/
async createInvoiceAndChargeImmediately(
orgIdToCharge: string,
subtotal: number,
tax: number,
options?: {
description?: string;
orgIdForBranding?: string;
disableConfirmationEmail?: boolean;
}
) {
return this.chargeOrganization(orgIdToCharge, subtotal, tax, options);
}
}

const concatArrayU8 = (arrays: Uint8Array[]) => {
Expand All @@ -126,4 +214,4 @@ const concatArrayU8 = (arrays: Uint8Array[]) => {
length += array.length;
}
return result;
};
};
Loading