1
0
mirror of https://github.com/bitwarden/server synced 2025-12-14 23:33:41 +00:00

Subscription change, invoice process update

This commit is contained in:
Chad Scharf
2020-05-12 12:48:21 -04:00
parent 00af142d63
commit a9a7003bfc
2 changed files with 186 additions and 275 deletions

View File

@@ -333,70 +333,59 @@ namespace Bit.Core.Services
throw new BadRequestException("Subscription not found.");
}
Func<bool, Task<SubscriptionItem>> subUpdateAction = null;
var prorationDate = DateTime.UtcNow;
var seatItem = sub.Items?.Data?.FirstOrDefault(i => i.Plan.Id == plan.StripeSeatPlanId);
var subItemOptions = sub.Items.Where(i => i.Plan.Id != plan.StripeSeatPlanId)
.Select(i => new InvoiceSubscriptionItemOptions
{
Id = i.Id,
Plan = i.Plan.Id,
Quantity = i.Quantity,
}).ToList();
if (additionalSeats > 0 && seatItem == null)
var subResponse = await subscriptionService.UpdateAsync(sub.Id, new SubscriptionUpdateOptions()
{
subItemOptions.Add(new InvoiceSubscriptionItemOptions
Items = new List<SubscriptionItemOptions>()
{
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats,
});
subUpdateAction = (prorate) => subscriptionItemService.CreateAsync(
new SubscriptionItemCreateOptions
new SubscriptionItemOptions()
{
Id = seatItem?.Id,
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats,
Prorate = prorate,
Subscription = sub.Id
});
}
else if (additionalSeats > 0 && seatItem != null)
{
subItemOptions.Add(new InvoiceSubscriptionItemOptions
{
Id = seatItem.Id,
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats,
});
subUpdateAction = (prorate) => subscriptionItemService.UpdateAsync(seatItem.Id,
new SubscriptionItemUpdateOptions
{
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats,
Prorate = prorate
});
}
else if (seatItem != null && additionalSeats == 0)
{
subItemOptions.Add(new InvoiceSubscriptionItemOptions
{
Id = seatItem.Id,
Deleted = true
});
subUpdateAction = (prorate) => subscriptionItemService.DeleteAsync(seatItem.Id,
new SubscriptionItemDeleteOptions());
}
Deleted = (seatItem?.Id != null && additionalSeats == 0) ? true : (bool?)null
}
},
ProrationBehavior = "always_invoice",
PaymentBehavior = "allow_incomplete",
DaysUntilDue = 1,
CollectionMethod = "send_invoice",
ProrationDate = prorationDate,
});
string paymentIntentClientSecret = null;
var invoicedNow = false;
if (additionalSeats > 0)
{
var result = await (_paymentService as StripePaymentService).PreviewUpcomingInvoiceAndPayAsync(
organization, plan.StripeSeatPlanId, subItemOptions, 500);
invoicedNow = result.Item1;
paymentIntentClientSecret = result.Item2;
try
{
paymentIntentClientSecret = await (_paymentService as StripePaymentService)
.PayInvoiceAfterSubscriptionChangeAsync(organization, subResponse?.LatestInvoiceId);
}
catch
{
// Need to revert the subscription
await subscriptionService.UpdateAsync(sub.Id, new SubscriptionUpdateOptions()
{
Items = new List<SubscriptionItemOptions>()
{
new SubscriptionItemOptions()
{
Id = seatItem?.Id,
Plan = plan.StripeSeatPlanId,
Quantity = organization.Seats,
Deleted = (seatItem?.Id == null || organization.Seats == 0) ? true : (bool?)null
}
},
// This proration behavior prevents a false "credit" from
// being applied forward to the next month's invoice
ProrationBehavior = "none",
});
throw;
}
}
await subUpdateAction(!invoicedNow);
organization.Seats = (short?)newSeatTotal;
await ReplaceAndUpdateCache(organization);
return paymentIntentClientSecret;