1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-19 08:30:59 -05:00

[PM-13837] Switch provider price IDs (#5518)

* Add ProviderPriceAdapter

This is a temporary utility that will be used to manage retrieval of provider price IDs until all providers can be migrated to the new price structure.

* Updated ProviderBillingService.ChangePlan

* Update ProviderBillingService.SetupSubscription

* Update ProviderBillingService.UpdateSeatMinimums

* Update ProviderBillingService.CurrySeatScalingUpdate

* Mark StripeProviderPortalSeatPlanId obsolete

* Run dotnet format
This commit is contained in:
Alex Morask
2025-04-03 08:51:09 -04:00
committed by GitHub
parent 1cc854ddb9
commit 282e80ca02
12 changed files with 480 additions and 213 deletions

View File

@ -309,8 +309,7 @@ public class ProviderMigrator(
.SeatMinimum ?? 0;
var updateSeatMinimumsCommand = new UpdateProviderSeatMinimumsCommand(
provider.Id,
provider.GatewaySubscriptionId,
provider,
[
(Plan: PlanType.EnterpriseMonthly, SeatsMinimum: enterpriseSeatMinimum),
(Plan: PlanType.TeamsMonthly, SeatsMinimum: teamsSeatMinimum)

View File

@ -75,6 +75,7 @@ public abstract record Plan
// Seats
public string StripePlanId { get; init; }
public string StripeSeatPlanId { get; init; }
[Obsolete("No longer used to retrieve a provider's price ID. Use ProviderPriceAdapter instead.")]
public string StripeProviderPortalSeatPlanId { get; init; }
public decimal BasePrice { get; init; }
public decimal SeatPrice { get; init; }

View File

@ -1,8 +1,9 @@
using Bit.Core.Billing.Enums;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Billing.Enums;
namespace Bit.Core.Billing.Services.Contracts;
public record ChangeProviderPlanCommand(
Provider Provider,
Guid ProviderPlanId,
PlanType NewPlan,
string GatewaySubscriptionId);
PlanType NewPlan);

View File

@ -1,10 +1,10 @@
using Bit.Core.Billing.Enums;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Billing.Enums;
namespace Bit.Core.Billing.Services.Contracts;
/// <param name="Id">The ID of the provider to update the seat minimums for.</param>
/// <param name="Provider">The provider to update the seat minimums for.</param>
/// <param name="Configuration">The new seat minimums for the provider.</param>
public record UpdateProviderSeatMinimumsCommand(
Guid Id,
string GatewaySubscriptionId,
Provider Provider,
IReadOnlyCollection<(PlanType Plan, int SeatsMinimum)> Configuration);

View File

@ -1,62 +0,0 @@
using Bit.Core.Billing;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Extensions;
using Stripe;
using Plan = Bit.Core.Models.StaticStore.Plan;
namespace Bit.Core.Models.Business;
public class ProviderSubscriptionUpdate : SubscriptionUpdate
{
private readonly string _planId;
private readonly int _previouslyPurchasedSeats;
private readonly int _newlyPurchasedSeats;
protected override List<string> PlanIds => [_planId];
public ProviderSubscriptionUpdate(
Plan plan,
int previouslyPurchasedSeats,
int newlyPurchasedSeats)
{
if (!plan.Type.SupportsConsolidatedBilling())
{
throw new BillingException(
message: $"Cannot create a {nameof(ProviderSubscriptionUpdate)} for {nameof(PlanType)} that doesn't support consolidated billing");
}
_planId = plan.PasswordManager.StripeProviderPortalSeatPlanId;
_previouslyPurchasedSeats = previouslyPurchasedSeats;
_newlyPurchasedSeats = newlyPurchasedSeats;
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
var subscriptionItem = FindSubscriptionItem(subscription, _planId);
return
[
new SubscriptionItemOptions
{
Id = subscriptionItem.Id,
Price = _planId,
Quantity = _previouslyPurchasedSeats
}
];
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var subscriptionItem = FindSubscriptionItem(subscription, _planId);
return
[
new SubscriptionItemOptions
{
Id = subscriptionItem.Id,
Price = _planId,
Quantity = _newlyPurchasedSeats
}
];
}
}

View File

@ -1,5 +1,4 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Billing.Models;
using Bit.Core.Billing.Models.Api.Requests.Accounts;
using Bit.Core.Billing.Models.Api.Requests.Organizations;
@ -25,11 +24,6 @@ public interface IPaymentService
int? newlyPurchasedAdditionalSecretsManagerServiceAccounts,
int newlyPurchasedAdditionalStorage);
Task<string> AdjustSeatsAsync(Organization organization, Plan plan, int additionalSeats);
Task<string> AdjustSeats(
Provider provider,
Plan plan,
int currentlySubscribedSeats,
int newlySubscribedSeats);
Task<string> AdjustSmSeatsAsync(Organization organization, Plan plan, int additionalSeats);
Task<string> AdjustStorageAsync(IStorableSubscriber storableSubscriber, int additionalStorage, string storagePlanId);

View File

@ -1,5 +1,4 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.Billing.Constants;
using Bit.Core.Billing.Extensions;
using Bit.Core.Billing.Models;
@ -251,18 +250,6 @@ public class StripePaymentService : IPaymentService
public Task<string> AdjustSeatsAsync(Organization organization, StaticStore.Plan plan, int additionalSeats) =>
FinalizeSubscriptionChangeAsync(organization, new SeatSubscriptionUpdate(organization, plan, additionalSeats));
public Task<string> AdjustSeats(
Provider provider,
StaticStore.Plan plan,
int currentlySubscribedSeats,
int newlySubscribedSeats)
=> FinalizeSubscriptionChangeAsync(
provider,
new ProviderSubscriptionUpdate(
plan,
currentlySubscribedSeats,
newlySubscribedSeats));
public Task<string> AdjustSmSeatsAsync(Organization organization, StaticStore.Plan plan, int additionalSeats) =>
FinalizeSubscriptionChangeAsync(
organization,