1
0
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:
Addison Beck
2020-12-04 12:05:16 -05:00
committed by GitHub
parent 9e1bf3d584
commit b877c25234
27 changed files with 1157 additions and 88 deletions

View File

@ -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
}
};
}
}

View 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; }
}
}

View File

@ -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; }
}
}

View 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;
}
}
}

View File

@ -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; }

View 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;
}
}
}