mirror of
https://github.com/bitwarden/browser
synced 2024-12-17 20:04:06 +01:00
Implemented tax collection for subscriptions (#723)
* Implemented tax collection for subscriptions * Cleanup for Sales Tax * Code review fixes for Tax Rate implementation * Code review fixes for Tax Rate implementation
This commit is contained in:
parent
512b9e0a92
commit
7c4d0a15dd
@ -206,16 +206,22 @@
|
||||
</label>
|
||||
</div>
|
||||
<hr class="my-3">
|
||||
<div class="text-lg">
|
||||
<strong>{{'total' | i18n}}:</strong> {{subtotal | currency:'USD $'}} /{{selectedPlanInterval | i18n}}
|
||||
<h2 class="spaced-header mb-4">{{ (createOrganization ? 'paymentInformation' : 'billingInformation') | i18n}}</h2>
|
||||
<app-payment *ngIf="createOrganization" [hideCredit]="true"></app-payment>
|
||||
<app-tax-info (onCountryChanged)="changedCountry()"></app-tax-info>
|
||||
<div id="price" class="my-4">
|
||||
<div class="text-muted text-sm">
|
||||
{{ 'planPrice' | i18n }}: {{ subtotal | currency: 'USD $' }}
|
||||
<br />
|
||||
<ng-container>
|
||||
{{ 'estimatedTax' | i18n }}: {{ taxCharges | currency: 'USD $' }}
|
||||
</ng-container>
|
||||
</div>
|
||||
<hr class="my-1 col-3 ml-0">
|
||||
<p class="text-lg"><strong>{{'total' | i18n}}:</strong>
|
||||
{{total | currency:'USD $'}}/{{selectedPlanInterval | i18n}}</p>
|
||||
</div>
|
||||
<ng-container *ngIf="createOrganization">
|
||||
<small
|
||||
class="text-muted font-italic">{{'paymentChargedWithTrial' | i18n : (selectedPlanInterval | i18n) }}</small>
|
||||
<h2 class="spaced-header mb-4">{{'paymentInformation' | i18n}}</h2>
|
||||
<app-payment [hideCredit]="true"></app-payment>
|
||||
<app-tax-info (onCountryChanged)="changedCountry()"></app-tax-info>
|
||||
</ng-container>
|
||||
<small class="text-muted font-italic">{{'paymentChargedWithTrial' | i18n : (selectedPlanInterval | i18n) }}</small>
|
||||
<ng-container *ngIf="!createOrganization">
|
||||
<app-payment [showMethods]="false"></app-payment>
|
||||
</ng-container>
|
||||
|
@ -159,6 +159,16 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
return subTotal;
|
||||
}
|
||||
|
||||
get taxCharges() {
|
||||
return this.taxComponent != null && this.taxComponent.taxRate != null ?
|
||||
(this.taxComponent.taxRate / 100) * this.subtotal :
|
||||
0;
|
||||
}
|
||||
|
||||
get total() {
|
||||
return (this.subtotal + this.taxCharges) || 0;
|
||||
}
|
||||
|
||||
changedProduct() {
|
||||
this.plan = this.selectablePlans[0].type;
|
||||
if (!this.selectedPlan.hasPremiumAccessOption) {
|
||||
@ -278,6 +288,9 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
request.premiumAccessAddon = this.selectedPlan.hasPremiumAccessOption &&
|
||||
this.premiumAccessAddon;
|
||||
request.planType = this.selectedPlan.type;
|
||||
request.billingAddressCountry = this.taxComponent.taxInfo.country;
|
||||
request.billingAddressPostalCode = this.taxComponent.taxInfo.postalCode;
|
||||
|
||||
const result = await this.apiService.postOrganizationUpgrade(this.organizationId, request);
|
||||
if (!result.success && result.paymentIntentClientSecret != null) {
|
||||
await this.paymentComponent.handleStripeCardPayment(result.paymentIntentClientSecret, null);
|
||||
|
@ -7,6 +7,7 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { ApiService } from 'jslib/abstractions/api.service';
|
||||
import { OrganizationTaxInfoUpdateRequest } from 'jslib/models/request/organizationTaxInfoUpdateRequest';
|
||||
import { TaxInfoUpdateRequest } from 'jslib/models/request/taxInfoUpdateRequest';
|
||||
import { TaxRateResponse } from 'jslib/models/response/taxRateResponse';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tax-info',
|
||||
@ -28,6 +29,8 @@ export class TaxInfoComponent {
|
||||
includeTaxId: false,
|
||||
};
|
||||
|
||||
taxRates: TaxRateResponse[];
|
||||
|
||||
private pristine: any = {
|
||||
taxId: null,
|
||||
line1: null,
|
||||
@ -77,9 +80,22 @@ export class TaxInfoComponent {
|
||||
this.onCountryChanged.emit();
|
||||
}
|
||||
});
|
||||
|
||||
const taxRates = await this.apiService.getTaxRates();
|
||||
this.taxRates = taxRates.data;
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
get taxRate() {
|
||||
if (this.taxRates != null) {
|
||||
const localTaxRate = this.taxRates.find(x =>
|
||||
x.country === this.taxInfo.country &&
|
||||
x.postalCode === this.taxInfo.postalCode
|
||||
);
|
||||
return localTaxRate?.rate ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
getTaxInfoRequest(): TaxInfoUpdateRequest {
|
||||
if (this.organizationId) {
|
||||
const request = new OrganizationTaxInfoUpdateRequest();
|
||||
|
@ -1662,6 +1662,9 @@
|
||||
"paymentInformation": {
|
||||
"message": "Payment Information"
|
||||
},
|
||||
"billingInformation": {
|
||||
"message": "Billing Information"
|
||||
},
|
||||
"creditCard": {
|
||||
"message": "Credit Card"
|
||||
},
|
||||
@ -3355,5 +3358,11 @@
|
||||
"noSendsInList": {
|
||||
"message": "There are no Sends to list.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"planPrice": {
|
||||
"message": "Plan price"
|
||||
},
|
||||
"estimatedTax": {
|
||||
"message": "Estimated tax"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user