Merge pull request #21957 from overleaf/ls-compute-immediate-charge-for-subscription-update

compute immediate charge for subscription update

GitOrigin-RevId: 4e5162660b26e6e9db69827a59aa8e0048fa7d5d
This commit is contained in:
Liangjun Song
2024-11-22 09:05:12 +00:00
committed by Copybot
parent 583923a4d0
commit ac8d8d6edc
6 changed files with 120 additions and 14 deletions
@@ -14,6 +14,7 @@ const {
CreditCardPaymentMethod,
RecurlyAddOn,
RecurlyPlan,
RecurlyImmediateCharge,
} = require('./RecurlyEntities')
/**
@@ -315,21 +316,42 @@ function subscriptionChangeFromApi(subscription, subscriptionChange) {
subscriptionAddOnFromApi
)
let immediateCharge =
subscriptionChange.invoiceCollection?.chargeInvoice?.total ?? 0
for (const creditInvoice of subscriptionChange.invoiceCollection
?.creditInvoices ?? []) {
// The credit invoice totals are already negative
immediateCharge += creditInvoice.total ?? 0
}
return new RecurlySubscriptionChange({
subscription,
nextPlanCode: subscriptionChange.plan.code,
nextPlanName: subscriptionChange.plan.name,
nextPlanPrice: subscriptionChange.unitAmount,
nextAddOns,
immediateCharge,
immediateCharge: computeImmediateCharge(subscriptionChange),
})
}
/**
* Compute immediate charge based on invoice collection
*
* @param {recurly.SubscriptionChange} subscriptionChange - the subscription change returned from the API
* @return {RecurlyImmediateCharge}
*/
function computeImmediateCharge(subscriptionChange) {
const roundToTwoDecimal = (/** @type {number} */ num) =>
Math.round(num * 100) / 100
let subtotal =
subscriptionChange.invoiceCollection?.chargeInvoice?.subtotal ?? 0
let tax = subscriptionChange.invoiceCollection?.chargeInvoice?.tax ?? 0
let total = subscriptionChange.invoiceCollection?.chargeInvoice?.total ?? 0
for (const creditInvoice of subscriptionChange.invoiceCollection
?.creditInvoices ?? []) {
// The credit invoice numbers are already negative
subtotal = roundToTwoDecimal(subtotal + (creditInvoice.subtotal ?? 0))
total = roundToTwoDecimal(total + (creditInvoice.total ?? 0))
// Tax rate can be different in credit invoice if a user relocates
tax = roundToTwoDecimal(tax + (creditInvoice.tax ?? 0))
}
return new RecurlyImmediateCharge({
subtotal,
total,
tax,
})
}
@@ -252,7 +252,7 @@ class RecurlySubscriptionChange {
* @param {string} props.nextPlanName
* @param {number} props.nextPlanPrice
* @param {RecurlySubscriptionAddOn[]} props.nextAddOns
* @param {number} [props.immediateCharge]
* @param {RecurlyImmediateCharge} [props.immediateCharge]
*/
constructor(props) {
this.subscription = props.subscription
@@ -260,7 +260,9 @@ class RecurlySubscriptionChange {
this.nextPlanName = props.nextPlanName
this.nextPlanPrice = props.nextPlanPrice
this.nextAddOns = props.nextAddOns
this.immediateCharge = props.immediateCharge ?? 0
this.immediateCharge =
props.immediateCharge ??
new RecurlyImmediateCharge({ subtotal: 0, tax: 0, total: 0 })
this.subtotal = this.nextPlanPrice
for (const addOn of this.nextAddOns) {
@@ -299,6 +301,20 @@ class CreditCardPaymentMethod {
}
}
class RecurlyImmediateCharge {
/**
* @param {object} props
* @param {number} props.subtotal
* @param {number} props.tax
* @param {number} props.total
*/
constructor(props) {
this.subtotal = props.subtotal
this.tax = props.tax
this.total = props.total
}
}
/**
* An add-on configuration, independent of any subscription
*/
@@ -350,4 +366,5 @@ module.exports = {
RecurlyAddOn,
RecurlyPlan,
isStandaloneAiAddOnPlanCode,
RecurlyImmediateCharge,
}
@@ -915,7 +915,7 @@ function makeChangePreview(
return {
change: subscriptionChangeDescription,
currency: subscription.currency,
immediateCharge: subscriptionChange.immediateCharge,
immediateCharge: { ...subscriptionChange.immediateCharge },
paymentMethod: paymentMethod.toString(),
nextPlan: {
annual: nextPlan.annual ?? false,
@@ -966,6 +966,7 @@ module.exports = {
previewAddonPurchase: expressify(previewAddonPurchase),
purchaseAddon,
removeAddon,
makeChangePreview,
promises: {
getRecommendedCurrency: _getRecommendedCurrency,
getLatamCountryBannerDetails,