mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-24 12:06:15 +01:00
billing page invoices and transactions
This commit is contained in:
parent
3432243acb
commit
0220f4519d
2
jslib
2
jslib
@ -1 +1 @@
|
|||||||
Subproject commit cdbe08ae7eb9f0b127ebc2e28de287ff8096aebc
|
Subproject commit 647b254a71d0af105e1f6f1a1febeb15cd4181fb
|
@ -173,20 +173,51 @@
|
|||||||
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" [organizationId]="organizationId" (onAdjusted)="closePayment(true)"
|
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" [organizationId]="organizationId" (onAdjusted)="closePayment(true)"
|
||||||
(onCanceled)="closePayment(false)" *ngIf="showAdjustPayment">
|
(onCanceled)="closePayment(false)" *ngIf="showAdjustPayment">
|
||||||
</app-adjust-payment>
|
</app-adjust-payment>
|
||||||
<h2 class="spaced-header">{{'charges' | i18n}}</h2>
|
<h2 class="spaced-header">{{'invoices' | i18n}}</h2>
|
||||||
<p *ngIf="!charges || !charges.length">{{'noCharges' | i18n}}</p>
|
<p *ngIf="!invoices || !invoices.length">{{'noInvoices' | i18n}}</p>
|
||||||
<table class="table mb-2" *ngIf="charges && charges.length">
|
<table class="table mb-2" *ngIf="invoices && invoices.length">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let c of charges">
|
<tr *ngFor="let i of invoices">
|
||||||
|
<td>{{i.date | date:'mediumDate'}}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" appStopClick (click)="viewInvoice(c)" title="{{'invoice' | i18n}}">
|
<a href="{{i.pdfUrl}}" target="_blank" rel="noopener" class="mr-2" title="{{'downloadInvoice' | i18n}}">
|
||||||
<i class="fa fa-file-pdf-o"></i>
|
<i class="fa fa-file-pdf-o"></i></a>
|
||||||
</a>
|
<a href="{{i.url}}" target="_blank" rel="noopener" title="{{'viewInvoice' | i18n}}">
|
||||||
|
{{'invoiceNumber' | i18n : i.number}}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{c.createdDate | date:'mediumDate'}}</td>
|
<td>{{i.amount | currency:'$'}}</td>
|
||||||
<td>{{c.paymentSource ? c.paymentSource.description : '-'}}</td>
|
<td>
|
||||||
<td class="text-capitalize">{{c.status}}</td>
|
<span *ngIf="i.paid">
|
||||||
<td [ngClass]="{'text-strike':c.refunded}" title="{{(c.refunded ? 'refunded' : '') | i18n}}">{{c.amount | currency:'$'}}</td>
|
<i class="fa fa-check text-success"></i>
|
||||||
|
{{'paid' | i18n}}
|
||||||
|
</span>
|
||||||
|
<span *ngIf="!i.paid">
|
||||||
|
<i class="fa fa-exclamation-circle text-muted"></i>
|
||||||
|
{{'unpaid' | i18n}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h2 class="spaced-header">{{'transactions' | i18n}}</h2>
|
||||||
|
<p *ngIf="!transactions || !transactions.length">{{'noTransactions' | i18n}}</p>
|
||||||
|
<table class="table mb-2" *ngIf="transactions && transactions.length">
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let t of transactions">
|
||||||
|
<td>{{t.createdDate | date:'mediumDate'}}</td>
|
||||||
|
<td>
|
||||||
|
<span *ngIf="t.type === transactionType.Charge">{{'chargeNoun' | i18n}}</span>
|
||||||
|
<span *ngIf="t.type === transactionType.Refund">{{'chargeRefund' | i18n}}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<i class="fa fa-fw"
|
||||||
|
*ngIf="t.type === transactionType.Charge || t.type === transactionType.Refund"
|
||||||
|
[ngClass]="{'fa-credit-card': t.paymentMethodType === paymentMethodType.Card,
|
||||||
|
'fa-university': t.paymentMethodType === paymentMethodType.BankAccount,
|
||||||
|
'fa-paypal text-primary': t.paymentMethodType === paymentMethodType.PayPal}"></i>
|
||||||
|
{{t.details}}
|
||||||
|
</td>
|
||||||
|
<td [ngClass]="{'text-strike': t.refunded}" title="{{(t.refunded ? 'refunded' : '') | i18n}}">{{t.amount | currency:'$'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -20,6 +20,7 @@ import { TokenService } from 'jslib/abstractions/token.service';
|
|||||||
|
|
||||||
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
||||||
import { PlanType } from 'jslib/enums/planType';
|
import { PlanType } from 'jslib/enums/planType';
|
||||||
|
import { TransactionType } from 'jslib/enums/transactionType';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-org-billing',
|
selector: 'app-org-billing',
|
||||||
@ -37,6 +38,7 @@ export class OrganizationBillingComponent implements OnInit {
|
|||||||
showUpdateLicense = false;
|
showUpdateLicense = false;
|
||||||
billing: OrganizationBillingResponse;
|
billing: OrganizationBillingResponse;
|
||||||
paymentMethodType = PaymentMethodType;
|
paymentMethodType = PaymentMethodType;
|
||||||
|
transactionType = TransactionType;
|
||||||
selfHosted = false;
|
selfHosted = false;
|
||||||
verifyAmount1: number;
|
verifyAmount1: number;
|
||||||
verifyAmount2: number;
|
verifyAmount2: number;
|
||||||
@ -227,12 +229,16 @@ export class OrganizationBillingComponent implements OnInit {
|
|||||||
return this.billing != null ? this.billing.upcomingInvoice : null;
|
return this.billing != null ? this.billing.upcomingInvoice : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get paymentSource() {
|
get invoices() {
|
||||||
return this.billing != null ? this.billing.paymentSource : null;
|
return this.billing != null ? this.billing.invoices : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get charges() {
|
get transactions() {
|
||||||
return this.billing != null ? this.billing.charges : null;
|
return this.billing != null ? this.billing.transactions : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get paymentSource() {
|
||||||
|
return this.billing != null ? this.billing.paymentSource : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get storagePercentage() {
|
get storagePercentage() {
|
||||||
|
@ -117,15 +117,51 @@
|
|||||||
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" (onAdjusted)="closePayment(true)" (onCanceled)="closePayment(false)"
|
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" (onAdjusted)="closePayment(true)" (onCanceled)="closePayment(false)"
|
||||||
*ngIf="showAdjustPayment">
|
*ngIf="showAdjustPayment">
|
||||||
</app-adjust-payment>
|
</app-adjust-payment>
|
||||||
<h2 class="spaced-header">{{'charges' | i18n}}</h2>
|
<h2 class="spaced-header">{{'invoices' | i18n}}</h2>
|
||||||
<p *ngIf="!charges || !charges.length">{{'noCharges' | i18n}}</p>
|
<p *ngIf="!invoices || !invoices.length">{{'noInvoices' | i18n}}</p>
|
||||||
<table class="table mb-2" *ngIf="charges && charges.length">
|
<table class="table mb-2" *ngIf="invoices && invoices.length">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let c of charges">
|
<tr *ngFor="let i of invoices">
|
||||||
<td>{{c.createdDate | date:'mediumDate'}}</td>
|
<td>{{i.date | date:'mediumDate'}}</td>
|
||||||
<td>{{c.paymentSource ? c.paymentSource.description : '-'}}</td>
|
<td>
|
||||||
<td class="text-capitalize">{{c.status}}</td>
|
<a href="{{i.pdfUrl}}" target="_blank" rel="noopener" class="mr-2" title="{{'downloadInvoice' | i18n}}">
|
||||||
<td [ngClass]="{'text-strike':c.refunded}" title="{{(c.refunded ? 'refunded' : '') | i18n}}">{{c.amount | currency:'$'}}</td>
|
<i class="fa fa-file-pdf-o"></i></a>
|
||||||
|
<a href="{{i.url}}" target="_blank" rel="noopener" title="{{'viewInvoice' | i18n}}">
|
||||||
|
{{'invoiceNumber' | i18n : i.number}}</a>
|
||||||
|
</td>
|
||||||
|
<td>{{i.amount | currency:'$'}}</td>
|
||||||
|
<td>
|
||||||
|
<span *ngIf="i.paid">
|
||||||
|
<i class="fa fa-check text-success"></i>
|
||||||
|
{{'paid' | i18n}}
|
||||||
|
</span>
|
||||||
|
<span *ngIf="!i.paid">
|
||||||
|
<i class="fa fa-exclamation-circle text-muted"></i>
|
||||||
|
{{'unpaid' | i18n}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h2 class="spaced-header">{{'transactions' | i18n}}</h2>
|
||||||
|
<p *ngIf="!transactions || !transactions.length">{{'noTransactions' | i18n}}</p>
|
||||||
|
<table class="table mb-2" *ngIf="transactions && transactions.length">
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let t of transactions">
|
||||||
|
<td>{{t.createdDate | date:'mediumDate'}}</td>
|
||||||
|
<td>
|
||||||
|
<span *ngIf="t.type === transactionType.Charge">{{'chargeNoun' | i18n}}</span>
|
||||||
|
<span *ngIf="t.type === transactionType.Refund">{{'chargeRefund' | i18n}}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<i class="fa fa-fw"
|
||||||
|
*ngIf="t.type === transactionType.Charge || t.type === transactionType.Refund"
|
||||||
|
[ngClass]="{'fa-credit-card': t.paymentMethodType === paymentMethodType.Card,
|
||||||
|
'fa-university': t.paymentMethodType === paymentMethodType.BankAccount,
|
||||||
|
'fa-paypal text-primary': t.paymentMethodType === paymentMethodType.PayPal}"></i>
|
||||||
|
{{t.details}}
|
||||||
|
</td>
|
||||||
|
<td [ngClass]="{'text-strike': t.refunded}" title="{{(t.refunded ? 'refunded' : '') | i18n}}">{{t.amount | currency:'$'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -15,6 +15,7 @@ import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
|||||||
import { TokenService } from 'jslib/abstractions/token.service';
|
import { TokenService } from 'jslib/abstractions/token.service';
|
||||||
|
|
||||||
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
||||||
|
import { TransactionType } from 'jslib/enums/transactionType';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-billing',
|
selector: 'app-user-billing',
|
||||||
@ -29,6 +30,7 @@ export class UserBillingComponent implements OnInit {
|
|||||||
showUpdateLicense = false;
|
showUpdateLicense = false;
|
||||||
billing: BillingResponse;
|
billing: BillingResponse;
|
||||||
paymentMethodType = PaymentMethodType;
|
paymentMethodType = PaymentMethodType;
|
||||||
|
transactionType = TransactionType;
|
||||||
selfHosted = false;
|
selfHosted = false;
|
||||||
|
|
||||||
cancelPromise: Promise<any>;
|
cancelPromise: Promise<any>;
|
||||||
@ -164,8 +166,12 @@ export class UserBillingComponent implements OnInit {
|
|||||||
return this.billing != null ? this.billing.paymentSource : null;
|
return this.billing != null ? this.billing.paymentSource : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get charges() {
|
get invoices() {
|
||||||
return this.billing != null ? this.billing.charges : null;
|
return this.billing != null ? this.billing.invoices : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get transactions() {
|
||||||
|
return this.billing != null ? this.billing.transactions : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get storagePercentage() {
|
get storagePercentage() {
|
||||||
|
@ -1691,12 +1691,34 @@
|
|||||||
"changePaymentMethod": {
|
"changePaymentMethod": {
|
||||||
"message": "Change Payment Method"
|
"message": "Change Payment Method"
|
||||||
},
|
},
|
||||||
"charges": {
|
"invoices": {
|
||||||
"message": "Charges",
|
"message": "Invoices"
|
||||||
"description": "Credit card charges/payments."
|
|
||||||
},
|
},
|
||||||
"noCharges": {
|
"noInvoices": {
|
||||||
"message": "No charges."
|
"message": "No invoices."
|
||||||
|
},
|
||||||
|
"paid" : {
|
||||||
|
"message": "Paid",
|
||||||
|
"description": "Past tense status of an invoice. ex. Paid or unpaid."
|
||||||
|
},
|
||||||
|
"unpaid" : {
|
||||||
|
"message": "Unpaid",
|
||||||
|
"description": "Past tense status of an invoice. ex. Paid or unpaid."
|
||||||
|
},
|
||||||
|
"transactions": {
|
||||||
|
"message": "Transactions",
|
||||||
|
"description": "Payment/credit transactions."
|
||||||
|
},
|
||||||
|
"noTransactions": {
|
||||||
|
"message": "No transactions."
|
||||||
|
},
|
||||||
|
"chargeNoun": {
|
||||||
|
"message": "Charge",
|
||||||
|
"description": "Noun. A charge from a payment method."
|
||||||
|
},
|
||||||
|
"refundNoun": {
|
||||||
|
"message": "Refund",
|
||||||
|
"description": "Noun. A refunded payment that was charged."
|
||||||
},
|
},
|
||||||
"chargesStatement": {
|
"chargesStatement": {
|
||||||
"message": "Any charges will appear on your statement as $STATEMENT_NAME$.",
|
"message": "Any charges will appear on your statement as $STATEMENT_NAME$.",
|
||||||
@ -2474,8 +2496,21 @@
|
|||||||
"message": "Contact customer support if you would like to change your plan. Please ensure that you have an active payment method added to the account.",
|
"message": "Contact customer support if you would like to change your plan. Please ensure that you have an active payment method added to the account.",
|
||||||
"description": "A billing plan/package. For example: families, teams, enterprise, etc."
|
"description": "A billing plan/package. For example: families, teams, enterprise, etc."
|
||||||
},
|
},
|
||||||
"invoice": {
|
"invoiceNumber": {
|
||||||
"message": "Invoice"
|
"message": "Invoice #$NUMBER$",
|
||||||
|
"description": "ex. Invoice #79C66F0-0001",
|
||||||
|
"placeholders": {
|
||||||
|
"number": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "79C66F0-0001"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"viewInvoice": {
|
||||||
|
"message": "View Invoice"
|
||||||
|
},
|
||||||
|
"downloadInvoice": {
|
||||||
|
"message": "Download Invoice"
|
||||||
},
|
},
|
||||||
"verifyBankAccount": {
|
"verifyBankAccount": {
|
||||||
"message": "Verify Bank Account"
|
"message": "Verify Bank Account"
|
||||||
|
Loading…
Reference in New Issue
Block a user