mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 07:36:14 -05:00
[PM-21092] Set tax exemption to reverse charge for non-US business-use customers (#5812)
* Set automatic tax to enabled and tax exempt to reverse where applicable when ff is on * Fix and add tests * Run dotnet format * Run dotnet format * PM-21745: Resolve defect * PM-21770: Resolve defect * Run dotnet format'
This commit is contained in:
@ -3,14 +3,11 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.Billing.Caches;
|
||||
using Bit.Core.Billing.Constants;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Services.Contracts;
|
||||
using Bit.Core.Billing.Services.Implementations;
|
||||
using Bit.Core.Billing.Tax.Models;
|
||||
using Bit.Core.Billing.Tax.Services;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Test.Billing.Tax.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Braintree;
|
||||
@ -195,7 +192,7 @@ public class SubscriberServiceTests
|
||||
|
||||
await stripeAdapter
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.SubscriptionCancelAsync(Arg.Any<string>(), Arg.Any<SubscriptionCancelOptions>()); ;
|
||||
.SubscriptionCancelAsync(Arg.Any<string>(), Arg.Any<SubscriptionCancelOptions>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -1029,7 +1026,7 @@ public class SubscriberServiceTests
|
||||
|
||||
stripeAdapter
|
||||
.PaymentMethodListAutoPagingAsync(Arg.Any<PaymentMethodListOptions>())
|
||||
.Returns(GetPaymentMethodsAsync(new List<Stripe.PaymentMethod>()));
|
||||
.Returns(GetPaymentMethodsAsync(new List<PaymentMethod>()));
|
||||
|
||||
await sutProvider.Sut.RemovePaymentSource(organization);
|
||||
|
||||
@ -1061,7 +1058,7 @@ public class SubscriberServiceTests
|
||||
|
||||
stripeAdapter
|
||||
.PaymentMethodListAutoPagingAsync(Arg.Any<PaymentMethodListOptions>())
|
||||
.Returns(GetPaymentMethodsAsync(new List<Stripe.PaymentMethod>
|
||||
.Returns(GetPaymentMethodsAsync(new List<PaymentMethod>
|
||||
{
|
||||
new ()
|
||||
{
|
||||
@ -1086,8 +1083,8 @@ public class SubscriberServiceTests
|
||||
.PaymentMethodDetachAsync(cardId);
|
||||
}
|
||||
|
||||
private static async IAsyncEnumerable<Stripe.PaymentMethod> GetPaymentMethodsAsync(
|
||||
IEnumerable<Stripe.PaymentMethod> paymentMethods)
|
||||
private static async IAsyncEnumerable<PaymentMethod> GetPaymentMethodsAsync(
|
||||
IEnumerable<PaymentMethod> paymentMethods)
|
||||
{
|
||||
foreach (var paymentMethod in paymentMethods)
|
||||
{
|
||||
@ -1598,14 +1595,22 @@ public class SubscriberServiceTests
|
||||
City = "Example Town",
|
||||
State = "NY"
|
||||
},
|
||||
TaxIds = new StripeList<TaxId> { Data = [new TaxId { Id = "tax_id_1", Type = "us_ein" }] }
|
||||
TaxIds = new StripeList<TaxId> { Data = [new TaxId { Id = "tax_id_1", Type = "us_ein" }] },
|
||||
Subscriptions = new StripeList<Subscription>
|
||||
{
|
||||
Data = [
|
||||
new Subscription
|
||||
{
|
||||
Id = provider.GatewaySubscriptionId,
|
||||
AutomaticTax = new SubscriptionAutomaticTax { Enabled = false }
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
var subscription = new Subscription { Items = new StripeList<SubscriptionItem>() };
|
||||
sutProvider.GetDependency<IStripeAdapter>().SubscriptionGetAsync(Arg.Any<string>())
|
||||
.Returns(subscription);
|
||||
sutProvider.GetDependency<IAutomaticTaxFactory>().CreateAsync(Arg.Any<AutomaticTaxFactoryParameters>())
|
||||
.Returns(new FakeAutomaticTaxStrategy(true));
|
||||
|
||||
await sutProvider.Sut.UpdateTaxInformation(provider, taxInformation);
|
||||
|
||||
@ -1623,6 +1628,98 @@ public class SubscriberServiceTests
|
||||
await stripeAdapter.Received(1).TaxIdCreateAsync(provider.GatewayCustomerId, Arg.Is<TaxIdCreateOptions>(
|
||||
options => options.Type == "us_ein" &&
|
||||
options.Value == taxInformation.TaxId));
|
||||
|
||||
await stripeAdapter.Received(1).SubscriptionUpdateAsync(provider.GatewaySubscriptionId,
|
||||
Arg.Is<SubscriptionUpdateOptions>(options => options.AutomaticTax.Enabled == true));
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task UpdateTaxInformation_NonUser_ReverseCharge_MakesCorrectInvocations(
|
||||
Provider provider,
|
||||
SutProvider<SubscriberService> sutProvider)
|
||||
{
|
||||
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
|
||||
|
||||
var customer = new Customer { Id = provider.GatewayCustomerId, TaxIds = new StripeList<TaxId> { Data = [new TaxId { Id = "tax_id_1", Type = "us_ein" }] } };
|
||||
|
||||
stripeAdapter.CustomerGetAsync(provider.GatewayCustomerId, Arg.Is<CustomerGetOptions>(
|
||||
options => options.Expand.Contains("tax_ids"))).Returns(customer);
|
||||
|
||||
var taxInformation = new TaxInformation(
|
||||
"CA",
|
||||
"12345",
|
||||
"123456789",
|
||||
"us_ein",
|
||||
"123 Example St.",
|
||||
null,
|
||||
"Example Town",
|
||||
"NY");
|
||||
|
||||
sutProvider.GetDependency<IStripeAdapter>()
|
||||
.CustomerUpdateAsync(
|
||||
Arg.Is<string>(p => p == provider.GatewayCustomerId),
|
||||
Arg.Is<CustomerUpdateOptions>(options =>
|
||||
options.Address.Country == "CA" &&
|
||||
options.Address.PostalCode == "12345" &&
|
||||
options.Address.Line1 == "123 Example St." &&
|
||||
options.Address.Line2 == null &&
|
||||
options.Address.City == "Example Town" &&
|
||||
options.Address.State == "NY"))
|
||||
.Returns(new Customer
|
||||
{
|
||||
Id = provider.GatewayCustomerId,
|
||||
Address = new Address
|
||||
{
|
||||
Country = "CA",
|
||||
PostalCode = "12345",
|
||||
Line1 = "123 Example St.",
|
||||
Line2 = null,
|
||||
City = "Example Town",
|
||||
State = "NY"
|
||||
},
|
||||
TaxIds = new StripeList<TaxId> { Data = [new TaxId { Id = "tax_id_1", Type = "us_ein" }] },
|
||||
Subscriptions = new StripeList<Subscription>
|
||||
{
|
||||
Data = [
|
||||
new Subscription
|
||||
{
|
||||
Id = provider.GatewaySubscriptionId,
|
||||
CustomerId = provider.GatewayCustomerId,
|
||||
AutomaticTax = new SubscriptionAutomaticTax { Enabled = false }
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
var subscription = new Subscription { Items = new StripeList<SubscriptionItem>() };
|
||||
sutProvider.GetDependency<IStripeAdapter>().SubscriptionGetAsync(Arg.Any<string>())
|
||||
.Returns(subscription);
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PM21092_SetNonUSBusinessUseToReverseCharge).Returns(true);
|
||||
|
||||
await sutProvider.Sut.UpdateTaxInformation(provider, taxInformation);
|
||||
|
||||
await stripeAdapter.Received(1).CustomerUpdateAsync(provider.GatewayCustomerId, Arg.Is<CustomerUpdateOptions>(
|
||||
options =>
|
||||
options.Address.Country == taxInformation.Country &&
|
||||
options.Address.PostalCode == taxInformation.PostalCode &&
|
||||
options.Address.Line1 == taxInformation.Line1 &&
|
||||
options.Address.Line2 == taxInformation.Line2 &&
|
||||
options.Address.City == taxInformation.City &&
|
||||
options.Address.State == taxInformation.State));
|
||||
|
||||
await stripeAdapter.Received(1).TaxIdDeleteAsync(provider.GatewayCustomerId, "tax_id_1");
|
||||
|
||||
await stripeAdapter.Received(1).TaxIdCreateAsync(provider.GatewayCustomerId, Arg.Is<TaxIdCreateOptions>(
|
||||
options => options.Type == "us_ein" &&
|
||||
options.Value == taxInformation.TaxId));
|
||||
|
||||
await stripeAdapter.Received(1).CustomerUpdateAsync(provider.GatewayCustomerId,
|
||||
Arg.Is<CustomerUpdateOptions>(options => options.TaxExempt == StripeConstants.TaxExempt.Reverse));
|
||||
|
||||
await stripeAdapter.Received(1).SubscriptionUpdateAsync(provider.GatewaySubscriptionId,
|
||||
Arg.Is<SubscriptionUpdateOptions>(options => options.AutomaticTax.Enabled == true));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
Reference in New Issue
Block a user