Billing Storage, chaging Tenant ID to object
MODIFY
src/integration/billing/BillingIntegration.ts
src/integration/billing/BillingIntegration.ts
@@ -187,7 +187,7 @@ export default abstract class BillingIntegration {
let skip = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
- const invoices = await BillingStorage.getInvoices(this.tenant.id, filter, { sort, limit, skip });
+ const invoices = await BillingStorage.getInvoices(this.tenant, filter, { sort, limit, skip });
if (Utils.isEmptyArray(invoices.result)) {
break;
}
@@ -398,7 +398,7 @@ export default abstract class BillingIntegration {
}
private async _clearAllInvoiceTestData(): Promise<void> {
- const invoices: DataResult<BillingInvoice> = await BillingStorage.getInvoices(this.tenant.id, { liveMode: false }, Constants.DB_PARAMS_MAX_LIMIT);
+ const invoices: DataResult<BillingInvoice> = await BillingStorage.getInvoices(this.tenant, { liveMode: false }, Constants.DB_PARAMS_MAX_LIMIT);
// Let's now finalize all invoices and attempt to get it paid
for (const invoice of invoices.result) {
try {
@@ -436,7 +436,7 @@ export default abstract class BillingIntegration {
});
}
await this._clearTransactionsTestData(billingInvoice);
- await BillingStorage.deleteInvoice(this.tenant.id, billingInvoice.id);
+ await BillingStorage.deleteInvoice(this.tenant, billingInvoice.id);
}
private async _clearTransactionsTestData(billingInvoice: BillingInvoice): Promise<void> {

MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -302,7 +302,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
}
}
// Get the corresponding BillingInvoice (if any)
- const billingInvoice: BillingInvoice = await BillingStorage.getInvoiceByInvoiceID(this.tenant.id, stripeInvoice.id);
+ const billingInvoice: BillingInvoice = await BillingStorage.getInvoiceByInvoiceID(this.tenant, stripeInvoice.id);
const invoiceToSave: BillingInvoice = {
id: billingInvoice?.id, // ACHTUNG: billingInvoice is null when creating the Billing Invoice
// eslint-disable-next-line id-blacklist
@@ -310,9 +310,9 @@ export default class StripeBillingIntegration extends BillingIntegration {
status: status as BillingInvoiceStatus, payInvoiceUrl,
};
// Let's persist the up-to-date data
- const freshInvoiceId = await BillingStorage.saveInvoice(this.tenant.id, invoiceToSave);
+ const freshInvoiceId = await BillingStorage.saveInvoice(this.tenant, invoiceToSave);
// TODO - perf improvement? - can't we just reuse
- const freshBillingInvoice = await BillingStorage.getInvoice(this.tenant.id, freshInvoiceId);
+ const freshBillingInvoice = await BillingStorage.getInvoice(this.tenant, freshInvoiceId);
return freshBillingInvoice;
}

MODIFY
src/integration/billing/stripe/StripeHelpers.ts
src/integration/billing/stripe/StripeHelpers.ts
@@ -42,7 +42,7 @@ export default class StripeHelpers {
session,
lastError: billingError
};
- await BillingStorage.updateInvoiceAdditionalData(tenant.id, billingInvoice, additionalData);
+ await BillingStorage.updateInvoiceAdditionalData(tenant, billingInvoice, additionalData);
}
}

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -278,8 +278,10 @@ export default class BillingService {
}
// Filter
const filteredRequest = BillingSecurity.filterGetInvoicesRequest(req.query);
+ // Fetch tenant for tenant id
+ const tenant = await TenantStorage.getTenant(req.user.tenantID);
// Get invoices
- const invoices = await BillingStorage.getInvoices(req.user.tenantID,
+ const invoices = await BillingStorage.getInvoices(tenant,
{
userIDs: !Authorizations.isAdmin(req.user) ? [req.user.id] : (filteredRequest.UserID ? filteredRequest.UserID.split('|') : null),
invoiceStatus: filteredRequest.Status ? filteredRequest.Status.split('|') as BillingInvoiceStatus[] : null,
@@ -314,8 +316,10 @@ export default class BillingService {
if ((await Authorizations.canListUsers(req.user)).authorized) {
userProject = [ 'userID', 'user.id', 'user.name', 'user.firstName', 'user.email' ];
}
+ // Fetch tenant based on Tenant ID
+ const tenant = await TenantStorage.getTenant(req.user.tenantID);
// Get invoice
- const invoice = await BillingStorage.getInvoice(req.user.tenantID, filteredRequest.ID,
+ const invoice = await BillingStorage.getInvoice(tenant, filteredRequest.ID,
[
'id', 'number', 'status', 'amount', 'createdOn', 'currency', 'downloadable', 'sessions',
...userProject
@@ -644,8 +648,10 @@ export default class BillingService {
Action.DOWNLOAD, Entity.BILLING, MODULE_NAME, 'handleDownloadInvoice');
// Filter
const filteredRequest = BillingSecurity.filterDownloadInvoiceRequest(req.query);
+ // Fetch tenant based on tenant ID
+ const tenant = await TenantStorage.getTenant(req.user.tenantID);
// Get the Invoice
- const billingInvoice = await BillingStorage.getInvoice(req.user.tenantID, filteredRequest.ID);
+ const billingInvoice = await BillingStorage.getInvoice(tenant, filteredRequest.ID);
UtilsService.assertObjectExists(action, billingInvoice, `Invoice ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleDownloadInvoice', req.user);
// Check Auth

MODIFY
src/storage/mongodb/BillingStorage.ts
src/storage/mongodb/BillingStorage.ts
@@ -7,35 +7,36 @@ import DatabaseUtils from './DatabaseUtils';
import DbParams from '../../types/database/DbParams';
import Logging from '../../utils/Logging';
import { ObjectID } from 'mongodb';
+import Tenant from '../../types/Tenant';
import Utils from '../../utils/Utils';
const MODULE_NAME = 'BillingStorage';
export default class BillingStorage {
- public static async getInvoice(tenantID: string, id: string = Constants.UNKNOWN_OBJECT_ID, projectFields?: string[]): Promise<BillingInvoice> {
- const invoicesMDB = await BillingStorage.getInvoices(tenantID, {
+ public static async getInvoice(tenant: Tenant, id: string = Constants.UNKNOWN_OBJECT_ID, projectFields?: string[]): Promise<BillingInvoice> {
+ const invoicesMDB = await BillingStorage.getInvoices(tenant, {
invoiceIDs: [id]
}, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return invoicesMDB.count === 1 ? invoicesMDB.result[0] : null;
}
- public static async getInvoiceByInvoiceID(tenantID: string, id: string): Promise<BillingInvoice> {
- const invoicesMDB = await BillingStorage.getInvoices(tenantID, {
+ public static async getInvoiceByInvoiceID(tenant: Tenant, id: string): Promise<BillingInvoice> {
+ const invoicesMDB = await BillingStorage.getInvoices(tenant, {
billingInvoiceID: id
}, Constants.DB_PARAMS_SINGLE_RECORD);
return invoicesMDB.count === 1 ? invoicesMDB.result[0] : null;
}
- public static async getInvoices(tenantID: string,
+ public static async getInvoices(tenant: Tenant,
params: {
invoiceIDs?: string[]; billingInvoiceID?: string; search?: string; userIDs?: string[]; invoiceStatus?: BillingInvoiceStatus[];
startDateTime?: Date; endDateTime?: Date; liveMode?: boolean
} = {},
dbParams: DbParams, projectFields?: string[]): Promise<DataResult<BillingInvoice>> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getInvoices');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getInvoices');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Clone before updating the values
dbParams = Utils.cloneObject(dbParams);
// Check Limit
@@ -98,12 +99,12 @@ export default class BillingStorage {
aggregation.push({ $limit: Constants.DB_RECORD_COUNT_CEIL });
}
// Count Records
- const invoicesCountMDB = await global.database.getCollection<any>(tenantID, 'invoices')
+ const invoicesCountMDB = await global.database.getCollection<any>(tenant.id, 'invoices')
.aggregate([...aggregation, { $count: 'count' }], { allowDiskUse: true })
.toArray();
// Check if only the total count is requested
if (dbParams.onlyRecordCount) {
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getInvoices', uniqueTimerID, invoicesCountMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getInvoices', uniqueTimerID, invoicesCountMDB);
return {
count: (invoicesCountMDB.length > 0 ? invoicesCountMDB[0].count : 0),
result: []
@@ -128,11 +129,11 @@ export default class BillingStorage {
});
// Add Users
DatabaseUtils.pushUserLookupInAggregation({
- tenantID, aggregation: aggregation, asField: 'user', localField: 'userID',
+ tenantID: tenant.id, aggregation: aggregation, asField: 'user', localField: 'userID',
foreignField: '_id', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
// Add Last Changed / Created
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenant.id, aggregation);
// Handle the ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
// Convert Object ID to string
@@ -140,13 +141,13 @@ export default class BillingStorage {
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
- const invoicesMDB = await global.database.getCollection<BillingInvoice>(tenantID, 'invoices')
+ const invoicesMDB = await global.database.getCollection<BillingInvoice>(tenant.id, 'invoices')
.aggregate(aggregation, {
allowDiskUse: true
})
.toArray();
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'getInvoices', uniqueTimerID, invoicesMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'getInvoices', uniqueTimerID, invoicesMDB);
return {
count: (invoicesCountMDB.length > 0 ?
(invoicesCountMDB[0].count === Constants.DB_RECORD_COUNT_CEIL ? -1 : invoicesCountMDB[0].count) : 0),
@@ -154,9 +155,9 @@ export default class BillingStorage {
};
}
- public static async saveInvoice(tenantID: string, invoiceToSave: BillingInvoice): Promise<string> {
+ public static async saveInvoice(tenant: Tenant, invoiceToSave: BillingInvoice): Promise<string> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveInvoice');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveInvoice');
// Build Request
// Properties to save
const invoiceMDB: any = {
@@ -177,21 +178,21 @@ export default class BillingStorage {
payInvoiceUrl: invoiceToSave.payInvoiceUrl
};
// Modify and return the modified document
- await global.database.getCollection<BillingInvoice>(tenantID, 'invoices').findOneAndUpdate(
+ await global.database.getCollection<BillingInvoice>(tenant.id, 'invoices').findOneAndUpdate(
{ _id: invoiceMDB._id },
{ $set: invoiceMDB },
{ upsert: true, returnDocument: 'after' }
);
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveInvoice', uniqueTimerID, invoiceMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveInvoice', uniqueTimerID, invoiceMDB);
return invoiceMDB._id.toHexString();
}
- public static async updateInvoiceAdditionalData(tenantID: string, invoiceToUpdate: BillingInvoice, additionalData: BillingAdditionalData): Promise<void> {
+ public static async updateInvoiceAdditionalData(tenant: Tenant, invoiceToUpdate: BillingInvoice, additionalData: BillingAdditionalData): Promise<void> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveInvoiceAdditionalData');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'saveInvoiceAdditionalData');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Preserve the previous list of sessions
const sessions: BillingSessionData[] = invoiceToUpdate.sessions || [];
if (additionalData.session) {
@@ -202,34 +203,34 @@ export default class BillingStorage {
sessions,
lastError: additionalData.lastError
};
- await global.database.getCollection(tenantID, 'invoices').findOneAndUpdate(
+ await global.database.getCollection(tenant.id, 'invoices').findOneAndUpdate(
{ '_id': Utils.convertToObjectID(invoiceToUpdate.id) },
{ $set: updatedInvoiceMDB });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveInvoiceAdditionalData', uniqueTimerID, updatedInvoiceMDB);
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveInvoiceAdditionalData', uniqueTimerID, updatedInvoiceMDB);
}
- public static async deleteInvoice(tenantID: string, id: string): Promise<void> {
+ public static async deleteInvoice(tenant: Tenant, id: string): Promise<void> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteInvoice');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteInvoice');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete the Invoice
- await global.database.getCollection<BillingInvoice>(tenantID, 'invoices')
+ await global.database.getCollection<BillingInvoice>(tenant.id, 'invoices')
.findOneAndDelete({ '_id': Utils.convertToObjectID(id) });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteInvoice', uniqueTimerID, { id });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteInvoice', uniqueTimerID, { id });
}
- public static async deleteInvoiceByInvoiceID(tenantID: string, id: string): Promise<void> {
+ public static async deleteInvoiceByInvoiceID(tenant: Tenant, id: string): Promise<void> {
// Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'deleteInvoice');
+ const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'deleteInvoice');
// Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
+ DatabaseUtils.checkTenantObject(tenant);
// Delete the Invoice
- await global.database.getCollection<BillingInvoice>(tenantID, 'invoices')
+ await global.database.getCollection<BillingInvoice>(tenant.id, 'invoices')
.findOneAndDelete({ 'invoiceID': id });
// Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'deleteInvoice', uniqueTimerID, { id });
+ await Logging.traceEnd(tenant.id, MODULE_NAME, 'deleteInvoice', uniqueTimerID, { id });
}
}

MODIFY
test/api/BillingStripeTestData.ts
test/api/BillingStripeTestData.ts
@@ -265,7 +265,7 @@ export default class StripeIntegrationTestData {
public async payDraftInvoice(draftInvoice: { id: string }, paymentShouldFail: boolean): Promise<void> {
const draftInvoiceId = draftInvoice.id;
- let billingInvoice: BillingInvoice = await BillingStorage.getInvoice(this.getTenantID(), draftInvoiceId);
+ let billingInvoice: BillingInvoice = await BillingStorage.getInvoice(this.tenantContext?.getTenant(), draftInvoiceId);
// Let's attempt a payment using the default payment method
billingInvoice = await this.billingImpl.chargeInvoice(billingInvoice);
if (paymentShouldFail) {

Billing Storage, chaging Tenant ID to object