billing - check date to avoid mixing transactions in same invoice
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -862,13 +862,22 @@ export default class StripeBillingIntegration extends BillingIntegration {
};
}
- private async _getLatestDraftInvoice(customerID: string): Promise<Stripe.Invoice> {
+ private async _getLatestDraftInvoiceOfTheMonth(customerID: string): Promise<Stripe.Invoice> {
+ // Fetch the invoice list - c.f.: https://stripe.com/docs/api/invoices/list
+ // The invoices are returned sorted by creation date, with the most recent ones appearing first.
const list = await this.stripe.invoices.list({
customer: customerID,
status: BillingInvoiceStatus.DRAFT,
limit: 1
});
- return !Utils.isEmptyArray((list.data)) ? list.data[0] : null;
+ const latestDraftInvoice = !Utils.isEmptyArray((list.data)) ? list.data[0] : null;
+ // Check for the date
+ // We do not want to mix in the same invoice charging sessions from different months
+ if (latestDraftInvoice && moment.unix(latestDraftInvoice.created).isSame(moment(), 'month')) {
+ return latestDraftInvoice;
+ }
+ // The latest DRAFT invoice is too old - don't reuse it!
+ return null;
}
public async billTransaction(transaction: Transaction): Promise<BillingDataTransactionStop> {
@@ -941,8 +950,17 @@ export default class StripeBillingIntegration extends BillingIntegration {
const userID: string = user.id;
const customerID: string = user.billingData?.customerID;
// Check whether a DRAFT invoice can be used
- let stripeInvoice = await this._getLatestDraftInvoice(customerID);
- // Let's create an invoice item (could be a pending one when the stripeInvoice does not yet exist)
+ let stripeInvoice: Stripe.Invoice;
+ if (this.settings.billing?.immediateBillingAllowed) {
+ // immediateBillingAllowed is ON - we want an invoice per transaction
+ // Because of some STRIPE constraints the invoice creation must be postpone!
+ stripeInvoice = null;
+ } else {
+ // immediateBillingAllowed is OFF - let's add to the latest DRAFT invoice (if any)
+ stripeInvoice = await this._getLatestDraftInvoiceOfTheMonth(customerID);
+ }
+ // Let's create an invoice item
+ // When the stripeInvoice is null a pending item is created
const invoiceItemParameters: Stripe.InvoiceItemCreateParams = this._buildInvoiceItemParameters(customerID, billingInvoiceItem, stripeInvoice?.id);
const stripeInvoiceItem = await this._createStripeInvoiceItem(invoiceItemParameters, this.buildIdemPotencyKey(idemPotencyKey, true));
if (!stripeInvoiceItem) {
@@ -956,7 +974,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
});
}
if (!stripeInvoice) {
- // Let's create a new draft invoice (if none has been found)
+ // Let's create a new DRAFT invoice (if none has been found)
stripeInvoice = await this._createStripeInvoice(customerID, userID, this.buildIdemPotencyKey(idemPotencyKey));
}
let operationResult: BillingOperationResult;

billing - check date to avoid mixing transactions in same invoice