From 11e9efd00805235049c77d92acba59d552df16f1 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Tue, 3 Mar 2026 13:42:01 -0500 Subject: [PATCH 01/11] refactor(billing): change billing address request type --- .../Requests/Premium/UpgradePremiumToOrganizationRequest.cs | 2 +- .../Requests/UpgradePremiumToOrganizationRequestTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Api/Billing/Models/Requests/Premium/UpgradePremiumToOrganizationRequest.cs b/src/Api/Billing/Models/Requests/Premium/UpgradePremiumToOrganizationRequest.cs index 00b1da4bba59..835a64e77d4c 100644 --- a/src/Api/Billing/Models/Requests/Premium/UpgradePremiumToOrganizationRequest.cs +++ b/src/Api/Billing/Models/Requests/Premium/UpgradePremiumToOrganizationRequest.cs @@ -18,7 +18,7 @@ public class UpgradePremiumToOrganizationRequest public required ProductTierType TargetProductTierType { get; set; } [Required] - public required MinimalBillingAddressRequest BillingAddress { get; set; } + public required CheckoutBillingAddressRequest BillingAddress { get; set; } private PlanType PlanType { diff --git a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs index 2d3bdb7b1483..121ecf861cb6 100644 --- a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs +++ b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs @@ -19,7 +19,7 @@ public void ToDomain_ValidTierTypes_ReturnsPlanType(ProductTierType tierType, Pl OrganizationName = "Test Organization", Key = "encrypted-key", TargetProductTierType = tierType, - BillingAddress = new MinimalBillingAddressRequest + BillingAddress = new CheckoutBillingAddressRequest { Country = "US", PostalCode = "12345" @@ -48,7 +48,7 @@ public void ToDomain_InvalidTierTypes_ThrowsInvalidOperationException(ProductTie OrganizationName = "Test Organization", Key = "encrypted-key", TargetProductTierType = tierType, - BillingAddress = new MinimalBillingAddressRequest + BillingAddress = new CheckoutBillingAddressRequest { Country = "US", PostalCode = "12345" From 1c66f0ac971a2fa7be45e4a627e0bcd8c746c3c1 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Tue, 3 Mar 2026 13:42:01 -0500 Subject: [PATCH 02/11] feat(billing): add tax id support for international business plans --- ...pgradePremiumToOrganizationRequestTests.cs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs index 121ecf861cb6..357d4e07c5b9 100644 --- a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs +++ b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs @@ -59,4 +59,47 @@ public void ToDomain_InvalidTierTypes_ThrowsInvalidOperationException(ProductTie var exception = Assert.Throws(() => sut.ToDomain()); Assert.Contains($"Cannot upgrade Premium subscription to {tierType} plan", exception.Message); } + + [Theory] + [InlineData(ProductTierType.Teams, PlanType.TeamsAnnually, "DE", "10115", "eu_vat", "DE123456789")] + [InlineData(ProductTierType.Enterprise, PlanType.EnterpriseAnnually, "FR", "75001", "eu_vat", "FR12345678901")] + public void ToDomain_BusinessPlansWithNonUsTaxId_IncludesTaxIdInBillingAddress( + ProductTierType tierType, + PlanType expectedPlanType, + string country, + string postalCode, + string taxIdCode, + string taxIdValue) + { + // Arrange + var sut = new UpgradePremiumToOrganizationRequest + { + OrganizationName = "International Business", + Key = "encrypted-key", + TargetProductTierType = tierType, + BillingAddress = new CheckoutBillingAddressRequest + { + Country = country, + PostalCode = postalCode, + TaxId = new CheckoutBillingAddressRequest.TaxIdRequest + { + Code = taxIdCode, + Value = taxIdValue + } + } + }; + + // Act + var (organizationName, key, planType, billingAddress) = sut.ToDomain(); + + // Assert + Assert.Equal("International Business", organizationName); + Assert.Equal("encrypted-key", key); + Assert.Equal(expectedPlanType, planType); + Assert.Equal(country, billingAddress.Country); + Assert.Equal(postalCode, billingAddress.PostalCode); + Assert.NotNull(billingAddress.TaxId); + Assert.Equal(taxIdCode, billingAddress.TaxId.Code); + Assert.Equal(taxIdValue, billingAddress.TaxId.Value); + } } From d0d664dc791c8919fa4d323a5d89cb560db546d1 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Tue, 3 Mar 2026 13:43:15 -0500 Subject: [PATCH 03/11] feat(billing): add billing address tax id handling --- .../UpgradePremiumToOrganizationCommand.cs | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs index e13f2295255b..a6235e286069 100644 --- a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs +++ b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs @@ -2,8 +2,11 @@ using Bit.Core.Billing.Commands; using Bit.Core.Billing.Constants; using Bit.Core.Billing.Enums; +using Bit.Core.Billing.Payment.Models; using Bit.Core.Billing.Pricing; using Bit.Core.Billing.Services; +using CountryAbbreviations = Bit.Core.Constants.CountryAbbreviations; +using TaxExempt = Bit.Core.Billing.Constants.StripeConstants.TaxExempt; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Repositories; @@ -34,7 +37,7 @@ Task> Run( string organizationName, string key, PlanType targetPlanType, - Payment.Models.BillingAddress billingAddress); + BillingAddress billingAddress); } public class UpgradePremiumToOrganizationCommand( @@ -53,7 +56,7 @@ public Task> Run( string organizationName, string key, PlanType targetPlanType, - Payment.Models.BillingAddress billingAddress) => HandleAsync(async () => + BillingAddress billingAddress) => HandleAsync(async () => { // Validate that the user has an active Premium subscription if (user is not { Premium: true, GatewaySubscriptionId: not null and not "" }) @@ -182,9 +185,16 @@ public Task> Run( { Country = billingAddress.Country, PostalCode = billingAddress.PostalCode - } + }, + TaxExempt = billingAddress.Country != CountryAbbreviations.UnitedStates ? TaxExempt.Reverse : TaxExempt.None }); + // Add tax ID to customer for accurate tax calculation if provided + if (billingAddress.TaxId != null) + { + await AddTaxIdToCustomerAsync(user, billingAddress.TaxId); + } + // Update the subscription in Stripe await stripeAdapter.UpdateSubscriptionAsync(currentSubscription.Id, subscriptionUpdateOptions); @@ -228,4 +238,26 @@ await organizationApiKeyRepository.CreateAsync(new OrganizationApiKey return new None(); }); + + /// + /// Adds a tax ID to the Stripe customer for accurate tax calculation. + /// If the tax ID is a Spanish NIF, also adds the corresponding EU VAT ID. + /// + /// The user whose Stripe customer will be updated with the tax ID. + /// The tax ID to add, including the type and value. + private async Task AddTaxIdToCustomerAsync(User user, TaxID taxId) + { + + await stripeAdapter.CreateTaxIdAsync(user.GatewayCustomerId, + new TaxIdCreateOptions { Type = taxId.Code, Value = taxId.Value }); + + if (taxId.Code == StripeConstants.TaxIdType.SpanishNIF) + { + await stripeAdapter.CreateTaxIdAsync(user.GatewayCustomerId, + new TaxIdCreateOptions + { + Type = StripeConstants.TaxIdType.EUVAT, Value = $"ES{taxId.Value}" + }); + } + } } From 8389b48490d686a851de09f20f6685566e354190 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Tue, 3 Mar 2026 13:43:55 -0500 Subject: [PATCH 04/11] test: add tests for tax id handling during upgrade --- ...pgradePremiumToOrganizationCommandTests.cs | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs index b4fd0e2d21d0..e0d61db580b0 100644 --- a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs +++ b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs @@ -1006,4 +1006,200 @@ await _organizationUserRepository.Received(1).CreateAsync( orgUser.Type == OrganizationUserType.Owner && orgUser.Status == OrganizationUserStatusType.Confirmed)); } + + [Theory, BitAutoData] + public async Task Run_WithNoTaxId_SetsTaxExemptToNone_DoesNotCreateTaxId(User user) + { + // Arrange + user.Premium = true; + user.GatewaySubscriptionId = "sub_123"; + user.GatewayCustomerId = "cus_123"; + + var mockSubscription = new Subscription + { + Id = "sub_123", + Items = new StripeList + { + Data = new List + { + new SubscriptionItem + { + Id = "si_premium", + Price = new Price { Id = "premium-annually" } + } + } + }, + Metadata = new Dictionary() + }; + + var mockPremiumPlans = CreateTestPremiumPlansList(); + var mockPlan = CreateTestPlan(PlanType.TeamsAnnually, stripeSeatPlanId: "teams-seat-annually"); + + _stripeAdapter.GetSubscriptionAsync("sub_123").Returns(mockSubscription); + _pricingClient.ListPremiumPlans().Returns(mockPremiumPlans); + _pricingClient.GetPlanOrThrow(PlanType.TeamsAnnually).Returns(mockPlan); + _stripeAdapter.UpdateSubscriptionAsync(Arg.Any(), Arg.Any()).Returns(mockSubscription); + _stripeAdapter.UpdateCustomerAsync(Arg.Any(), Arg.Any()).Returns(Task.FromResult(new Customer())); + _organizationRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationApiKeyRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationUserRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _applicationCacheService.UpsertOrganizationAbilityAsync(Arg.Any()).Returns(Task.CompletedTask); + _userService.SaveUserAsync(user).Returns(Task.CompletedTask); + + var billingAddress = new Core.Billing.Payment.Models.BillingAddress + { + Country = "US", + PostalCode = "12345", + TaxId = null + }; + + // Act + var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + + // Assert + Assert.True(result.IsT0); + await _stripeAdapter.Received(1).UpdateCustomerAsync( + "cus_123", + Arg.Is(options => + options.TaxExempt == StripeConstants.TaxExempt.None)); + await _stripeAdapter.DidNotReceive().CreateTaxIdAsync(Arg.Any(), Arg.Any()); + } + + [Theory, BitAutoData] + public async Task Run_WithTaxId_SetsTaxExemptToReverse_CreatesOneTaxId(User user) + { + // Arrange + user.Premium = true; + user.GatewaySubscriptionId = "sub_123"; + user.GatewayCustomerId = "cus_123"; + + var mockSubscription = new Subscription + { + Id = "sub_123", + Items = new StripeList + { + Data = new List + { + new SubscriptionItem + { + Id = "si_premium", + Price = new Price { Id = "premium-annually" } + } + } + }, + Metadata = new Dictionary() + }; + + var mockPremiumPlans = CreateTestPremiumPlansList(); + var mockPlan = CreateTestPlan(PlanType.TeamsAnnually, stripeSeatPlanId: "teams-seat-annually"); + + _stripeAdapter.GetSubscriptionAsync("sub_123").Returns(mockSubscription); + _pricingClient.ListPremiumPlans().Returns(mockPremiumPlans); + _pricingClient.GetPlanOrThrow(PlanType.TeamsAnnually).Returns(mockPlan); + _stripeAdapter.UpdateSubscriptionAsync(Arg.Any(), Arg.Any()).Returns(mockSubscription); + _stripeAdapter.UpdateCustomerAsync(Arg.Any(), Arg.Any()).Returns(Task.FromResult(new Customer())); + _stripeAdapter.CreateTaxIdAsync(Arg.Any(), Arg.Any()).Returns(new TaxId()); + _organizationRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationApiKeyRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationUserRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _applicationCacheService.UpsertOrganizationAbilityAsync(Arg.Any()).Returns(Task.CompletedTask); + _userService.SaveUserAsync(user).Returns(Task.CompletedTask); + + var billingAddress = new Core.Billing.Payment.Models.BillingAddress + { + Country = "DE", + PostalCode = "10115", + TaxId = new Core.Billing.Payment.Models.TaxID("eu_vat", "DE123456789") + }; + + // Act + var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + + // Assert + Assert.True(result.IsT0); + await _stripeAdapter.Received(1).UpdateCustomerAsync( + "cus_123", + Arg.Is(options => + options.TaxExempt == StripeConstants.TaxExempt.Reverse)); + await _stripeAdapter.Received(1).CreateTaxIdAsync( + "cus_123", + Arg.Is(options => + options.Type == "eu_vat" && + options.Value == "DE123456789")); + } + + [Theory, BitAutoData] + public async Task Run_WithSpanishNIF_SetsTaxExemptToReverse_CreatesBothSpanishNIFAndEUVAT(User user) + { + // Arrange + user.Premium = true; + user.GatewaySubscriptionId = "sub_123"; + user.GatewayCustomerId = "cus_123"; + + var mockSubscription = new Subscription + { + Id = "sub_123", + Items = new StripeList + { + Data = new List + { + new SubscriptionItem + { + Id = "si_premium", + Price = new Price { Id = "premium-annually" } + } + } + }, + Metadata = new Dictionary() + }; + + var mockPremiumPlans = CreateTestPremiumPlansList(); + var mockPlan = CreateTestPlan(PlanType.TeamsAnnually, stripeSeatPlanId: "teams-seat-annually"); + + _stripeAdapter.GetSubscriptionAsync("sub_123").Returns(mockSubscription); + _pricingClient.ListPremiumPlans().Returns(mockPremiumPlans); + _pricingClient.GetPlanOrThrow(PlanType.TeamsAnnually).Returns(mockPlan); + _stripeAdapter.UpdateSubscriptionAsync(Arg.Any(), Arg.Any()).Returns(mockSubscription); + _stripeAdapter.UpdateCustomerAsync(Arg.Any(), Arg.Any()).Returns(Task.FromResult(new Customer())); + _stripeAdapter.CreateTaxIdAsync(Arg.Any(), Arg.Any()).Returns(new TaxId()); + _organizationRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationApiKeyRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _organizationUserRepository.CreateAsync(Arg.Any()).Returns(callInfo => Task.FromResult(callInfo.Arg())); + _applicationCacheService.UpsertOrganizationAbilityAsync(Arg.Any()).Returns(Task.CompletedTask); + _userService.SaveUserAsync(user).Returns(Task.CompletedTask); + + var billingAddress = new Core.Billing.Payment.Models.BillingAddress + { + Country = "ES", + PostalCode = "28001", + TaxId = new Core.Billing.Payment.Models.TaxID(StripeConstants.TaxIdType.SpanishNIF, "A12345678") + }; + + // Act + var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + + // Assert + Assert.True(result.IsT0); + + await _stripeAdapter.Received(1).UpdateCustomerAsync( + "cus_123", + Arg.Is(options => + options.TaxExempt == StripeConstants.TaxExempt.Reverse)); + + // Verify Spanish NIF was created + await _stripeAdapter.Received(1).CreateTaxIdAsync( + "cus_123", + Arg.Is(options => + options.Type == StripeConstants.TaxIdType.SpanishNIF && + options.Value == "A12345678")); + + // Verify EU VAT was created with ES prefix + await _stripeAdapter.Received(1).CreateTaxIdAsync( + "cus_123", + Arg.Is(options => + options.Type == StripeConstants.TaxIdType.EUVAT && + options.Value == "ESA12345678")); + + + } } From 4f799ae3dfb7ed55dd18f099603c13b73d7bcad1 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Tue, 3 Mar 2026 14:18:40 -0500 Subject: [PATCH 05/11] fix(billing): run dotnet format --- .../Commands/UpgradePremiumToOrganizationCommand.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs index a6235e286069..1c3a8ddb931d 100644 --- a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs +++ b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs @@ -5,8 +5,6 @@ using Bit.Core.Billing.Payment.Models; using Bit.Core.Billing.Pricing; using Bit.Core.Billing.Services; -using CountryAbbreviations = Bit.Core.Constants.CountryAbbreviations; -using TaxExempt = Bit.Core.Billing.Constants.StripeConstants.TaxExempt; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Repositories; @@ -15,6 +13,8 @@ using Microsoft.Extensions.Logging; using OneOf.Types; using Stripe; +using CountryAbbreviations = Bit.Core.Constants.CountryAbbreviations; +using TaxExempt = Bit.Core.Billing.Constants.StripeConstants.TaxExempt; namespace Bit.Core.Billing.Premium.Commands; /// @@ -256,7 +256,8 @@ await stripeAdapter.CreateTaxIdAsync(user.GatewayCustomerId, await stripeAdapter.CreateTaxIdAsync(user.GatewayCustomerId, new TaxIdCreateOptions { - Type = StripeConstants.TaxIdType.EUVAT, Value = $"ES{taxId.Value}" + Type = StripeConstants.TaxIdType.EUVAT, + Value = $"ES{taxId.Value}" }); } } From 25738f0fc76dda1bda9c38cb90dc3457d045e8ea Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 10:22:33 -0500 Subject: [PATCH 06/11] fix(billing): remove extra line --- .../Premium/Commands/UpgradePremiumToOrganizationCommand.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs index 1c3a8ddb931d..1a8b872ba77a 100644 --- a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs +++ b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs @@ -247,7 +247,6 @@ await organizationApiKeyRepository.CreateAsync(new OrganizationApiKey /// The tax ID to add, including the type and value. private async Task AddTaxIdToCustomerAsync(User user, TaxID taxId) { - await stripeAdapter.CreateTaxIdAsync(user.GatewayCustomerId, new TaxIdCreateOptions { Type = taxId.Code, Value = taxId.Value }); From b359e4f8cecac34e1d7703b74c2726d80c970556 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 16:58:23 -0500 Subject: [PATCH 07/11] fix(billing): modify return type of HandleAsync --- .../Premium/Commands/UpgradePremiumToOrganizationCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs index 0806924ca32b..64f3a5654b22 100644 --- a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs +++ b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs @@ -68,7 +68,7 @@ public Task> Run( string encryptedPrivateKey, string? collectionName, PlanType targetPlanType, - BillingAddress billingAddress) => HandleAsync(async () => + BillingAddress billingAddress) => HandleAsync(async () => { // Validate that the user has an active Premium subscription if (user is not { Premium: true, GatewaySubscriptionId: not null and not "" }) From 590c05598b73f66fc7296efb9006c06714ea38ec Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 16:58:23 -0500 Subject: [PATCH 08/11] test(billing): update tests to reflect updated command signature --- .../Commands/UpgradePremiumToOrganizationCommandTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs index 53fa5c118155..81ec3b81b292 100644 --- a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs +++ b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs @@ -1246,7 +1246,7 @@ public async Task Run_WithNoTaxId_SetsTaxExemptToNone_DoesNotCreateTaxId(User us }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); @@ -1305,7 +1305,7 @@ public async Task Run_WithTaxId_SetsTaxExemptToReverse_CreatesOneTaxId(User user }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); @@ -1368,7 +1368,7 @@ public async Task Run_WithSpanishNIF_SetsTaxExemptToReverse_CreatesBothSpanishNI }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); From 507bf44b92296fa11e10204890d60c8375a2c6c4 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 17:05:39 -0500 Subject: [PATCH 09/11] fix(billing): run dotnet format --- .../Commands/UpgradePremiumToOrganizationCommand.cs | 2 +- .../Commands/UpgradePremiumToOrganizationCommandTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs index 64f3a5654b22..156474092439 100644 --- a/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs +++ b/src/Core/Billing/Premium/Commands/UpgradePremiumToOrganizationCommand.cs @@ -1,4 +1,4 @@ -using Bit.Core.AdminConsole.Entities; +using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Commands; using Bit.Core.Billing.Constants; using Bit.Core.Billing.Enums; diff --git a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs index 81ec3b81b292..1cf63c578675 100644 --- a/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs +++ b/test/Core.Test/Billing/Premium/Commands/UpgradePremiumToOrganizationCommandTests.cs @@ -1,4 +1,4 @@ -using Bit.Core.AdminConsole.Entities; +using Bit.Core.AdminConsole.Entities; using Bit.Core.Billing.Constants; using Bit.Core.Billing.Enums; using Bit.Core.Billing.Premium.Commands; @@ -1246,7 +1246,7 @@ public async Task Run_WithNoTaxId_SetsTaxExemptToNone_DoesNotCreateTaxId(User us }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key", "Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); @@ -1305,7 +1305,7 @@ public async Task Run_WithTaxId_SetsTaxExemptToReverse_CreatesOneTaxId(User user }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key", "Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); @@ -1368,7 +1368,7 @@ public async Task Run_WithSpanishNIF_SetsTaxExemptToReverse_CreatesBothSpanishNI }; // Act - var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key","Default Collection", PlanType.TeamsAnnually, billingAddress); + var result = await _command.Run(user, "My Organization", "encrypted-key", "public-key", "encrypted-private-key", "Default Collection", PlanType.TeamsAnnually, billingAddress); // Assert Assert.True(result.IsT0); From ef14e351c9dcd282243f39a6b0524757ddf69729 Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 17:26:07 -0500 Subject: [PATCH 10/11] tests(billing): fix tests --- .../Requests/UpgradePremiumToOrganizationRequestTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs index 051fa3056b0b..e924c7454c20 100644 --- a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs +++ b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs @@ -85,6 +85,9 @@ public void ToDomain_BusinessPlansWithNonUsTaxId_IncludesTaxIdInBillingAddress( OrganizationName = "International Business", Key = "encrypted-key", TargetProductTierType = tierType, + PublicKey = "public-key", + EncryptedPrivateKey = "encrypted-private-key", + CollectionName = "Default Collection", BillingAddress = new CheckoutBillingAddressRequest { Country = country, @@ -98,12 +101,14 @@ public void ToDomain_BusinessPlansWithNonUsTaxId_IncludesTaxIdInBillingAddress( }; // Act - var (organizationName, key, planType, billingAddress) = sut.ToDomain(); + var (organizationName, key, publicKey, encryptedPrivateKey, collectionName, planType, billingAddress) = sut.ToDomain(); // Assert Assert.Equal("International Business", organizationName); Assert.Equal("encrypted-key", key); - Assert.Equal(expectedPlanType, planType); + Assert.Equal("public-key", publicKey); + Assert.Equal("encrypted-private-key", encryptedPrivateKey); + Assert.Equal("Default Collection", collectionName); Assert.Equal(expectedPlanType, planType); Assert.Equal(country, billingAddress.Country); Assert.Equal(postalCode, billingAddress.PostalCode); Assert.NotNull(billingAddress.TaxId); From f3dc91af7c266ea6378e50932249beb8e1416f6b Mon Sep 17 00:00:00 2001 From: Stephon Brown Date: Wed, 4 Mar 2026 17:40:32 -0500 Subject: [PATCH 11/11] test(billing): format --- .../Requests/UpgradePremiumToOrganizationRequestTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs index e924c7454c20..d43084cdf710 100644 --- a/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs +++ b/test/Api.Test/Billing/Models/Requests/UpgradePremiumToOrganizationRequestTests.cs @@ -108,7 +108,8 @@ public void ToDomain_BusinessPlansWithNonUsTaxId_IncludesTaxIdInBillingAddress( Assert.Equal("encrypted-key", key); Assert.Equal("public-key", publicKey); Assert.Equal("encrypted-private-key", encryptedPrivateKey); - Assert.Equal("Default Collection", collectionName); Assert.Equal(expectedPlanType, planType); + Assert.Equal("Default Collection", collectionName); + Assert.Equal(expectedPlanType, planType); Assert.Equal(country, billingAddress.Country); Assert.Equal(postalCode, billingAddress.PostalCode); Assert.NotNull(billingAddress.TaxId);