mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
Implemented tax collection for subscriptions (#1017)
* Implemented tax collection for subscriptions * Cleanup for Sales Tax * Cleanup for Sales Tax * Changes a constraint to an index for checking purposes * Added and implemented a ReadById method for TaxRate * Code review fixes for Tax Rate implementation * Code review fixes for Tax Rate implementation * Made the SalesTax migration script rerunnable
This commit is contained in:
@ -14,6 +14,8 @@ namespace Bit.Core.Models.Api
|
||||
[Range(0, 99)]
|
||||
public short? AdditionalStorageGb { get; set; }
|
||||
public bool PremiumAccessAddon { get; set; }
|
||||
public string BillingAddressCountry { get; set; }
|
||||
public string BillingAddressPostalCode { get; set; }
|
||||
|
||||
public OrganizationUpgrade ToOrganizationUpgrade()
|
||||
{
|
||||
@ -23,7 +25,12 @@ namespace Bit.Core.Models.Api
|
||||
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(),
|
||||
BusinessName = BusinessName,
|
||||
Plan = PlanType,
|
||||
PremiumAccessAddon = PremiumAccessAddon
|
||||
PremiumAccessAddon = PremiumAccessAddon,
|
||||
TaxInfo = new TaxInfo()
|
||||
{
|
||||
BillingAddressCountry = BillingAddressCountry,
|
||||
BillingAddressPostalCode = BillingAddressPostalCode
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
29
src/Core/Models/Api/Response/TaxRateResponseModel.cs
Normal file
29
src/Core/Models/Api/Response/TaxRateResponseModel.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class TaxRateResponseModel : ResponseModel
|
||||
{
|
||||
public TaxRateResponseModel(TaxRate taxRate)
|
||||
: base("profile")
|
||||
{
|
||||
if (taxRate == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(taxRate));
|
||||
}
|
||||
|
||||
Id = taxRate.Id;
|
||||
Country = taxRate.Country;
|
||||
State = taxRate.State;
|
||||
PostalCode = taxRate.PostalCode;
|
||||
Rate = taxRate.Rate;
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string State { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public decimal Rate { get; set; }
|
||||
}
|
||||
}
|
@ -9,5 +9,6 @@ namespace Bit.Core.Models.Business
|
||||
public short AdditionalSeats { get; set; }
|
||||
public short AdditionalStorageGb { get; set; }
|
||||
public bool PremiumAccessAddon { get; set; }
|
||||
public TaxInfo TaxInfo { get; set; }
|
||||
}
|
||||
}
|
||||
|
85
src/Core/Models/Business/SubscriptionCreateOptions.cs
Normal file
85
src/Core/Models/Business/SubscriptionCreateOptions.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using Bit.Core.Models.Table;
|
||||
using Stripe;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Core.Models.Business
|
||||
{
|
||||
public class OrganizationSubscriptionOptionsBase : Stripe.SubscriptionCreateOptions
|
||||
{
|
||||
public OrganizationSubscriptionOptionsBase(Organization org, StaticStore.Plan plan, TaxInfo taxInfo, int additionalSeats, int additionalStorageGb, bool premiumAccessAddon)
|
||||
{
|
||||
Items = new List<SubscriptionItemOptions>();
|
||||
Metadata = new Dictionary<string, string>
|
||||
{
|
||||
[org.GatewayIdField()] = org.Id.ToString()
|
||||
};
|
||||
|
||||
if (plan.StripePlanId != null)
|
||||
{
|
||||
Items.Add(new SubscriptionItemOptions
|
||||
{
|
||||
Plan = plan.StripePlanId,
|
||||
Quantity = 1
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalSeats > 0 && plan.StripeSeatPlanId != null)
|
||||
{
|
||||
Items.Add(new SubscriptionItemOptions
|
||||
{
|
||||
Plan = plan.StripeSeatPlanId,
|
||||
Quantity = additionalSeats
|
||||
});
|
||||
}
|
||||
|
||||
if (additionalStorageGb > 0)
|
||||
{
|
||||
Items.Add(new SubscriptionItemOptions
|
||||
{
|
||||
Plan = plan.StripeStoragePlanId,
|
||||
Quantity = additionalStorageGb
|
||||
});
|
||||
}
|
||||
|
||||
if (premiumAccessAddon && plan.StripePremiumAccessPlanId != null)
|
||||
{
|
||||
Items.Add(new SubscriptionItemOptions
|
||||
{
|
||||
Plan = plan.StripePremiumAccessPlanId,
|
||||
Quantity = 1
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(taxInfo?.StripeTaxRateId))
|
||||
{
|
||||
DefaultTaxRates = new List<string>{ taxInfo.StripeTaxRateId };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OrganizationPurchaseSubscriptionOptions : OrganizationSubscriptionOptionsBase
|
||||
{
|
||||
public OrganizationPurchaseSubscriptionOptions(
|
||||
Organization org, StaticStore.Plan plan,
|
||||
TaxInfo taxInfo, int additionalSeats = 0,
|
||||
int additionalStorageGb = 0, bool premiumAccessAddon = false) :
|
||||
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
|
||||
{
|
||||
OffSession = true;
|
||||
TrialPeriodDays = plan.TrialPeriodDays;
|
||||
}
|
||||
}
|
||||
|
||||
public class OrganizationUpgradeSubscriptionOptions : OrganizationSubscriptionOptionsBase
|
||||
{
|
||||
public OrganizationUpgradeSubscriptionOptions(
|
||||
string customerId, Organization org,
|
||||
StaticStore.Plan plan, TaxInfo taxInfo,
|
||||
int additionalSeats = 0, int additionalStorageGb = 0,
|
||||
bool premiumAccessAddon = false) :
|
||||
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
|
||||
{
|
||||
Customer = customerId;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
_taxIdType = null;
|
||||
}
|
||||
}
|
||||
public string StripeTaxRateId { get; set; }
|
||||
public string BillingAddressLine1 { get; set; }
|
||||
public string BillingAddressLine2 { get; set; }
|
||||
public string BillingAddressCity { get; set; }
|
||||
|
18
src/Core/Models/Table/TaxRate.cs
Normal file
18
src/Core/Models/Table/TaxRate.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Bit.Core.Models.Table
|
||||
{
|
||||
public class TaxRate: ITableObject<string>
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string State { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public decimal Rate { get; set; }
|
||||
public bool Active { get; set; }
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
// Id is created by Stripe, should exist before this gets called
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user