1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-28 17:27:50 +01:00

billing page invoices and transactions

This commit is contained in:
Kyle Spearrin 2019-02-09 00:19:54 -05:00
parent 3432243acb
commit 0220f4519d
6 changed files with 147 additions and 33 deletions

2
jslib

@ -1 +1 @@
Subproject commit cdbe08ae7eb9f0b127ebc2e28de287ff8096aebc
Subproject commit 647b254a71d0af105e1f6f1a1febeb15cd4181fb

View File

@ -173,20 +173,51 @@
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" [organizationId]="organizationId" (onAdjusted)="closePayment(true)"
(onCanceled)="closePayment(false)" *ngIf="showAdjustPayment">
</app-adjust-payment>
<h2 class="spaced-header">{{'charges' | i18n}}</h2>
<p *ngIf="!charges || !charges.length">{{'noCharges' | i18n}}</p>
<table class="table mb-2" *ngIf="charges && charges.length">
<h2 class="spaced-header">{{'invoices' | i18n}}</h2>
<p *ngIf="!invoices || !invoices.length">{{'noInvoices' | i18n}}</p>
<table class="table mb-2" *ngIf="invoices && invoices.length">
<tbody>
<tr *ngFor="let c of charges">
<tr *ngFor="let i of invoices">
<td>{{i.date | date:'mediumDate'}}</td>
<td>
<a href="#" appStopClick (click)="viewInvoice(c)" title="{{'invoice' | i18n}}">
<i class="fa fa-file-pdf-o"></i>
</a>
<a href="{{i.pdfUrl}}" target="_blank" rel="noopener" class="mr-2" title="{{'downloadInvoice' | i18n}}">
<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>{{c.createdDate | date:'mediumDate'}}</td>
<td>{{c.paymentSource ? c.paymentSource.description : '-'}}</td>
<td class="text-capitalize">{{c.status}}</td>
<td [ngClass]="{'text-strike':c.refunded}" title="{{(c.refunded ? 'refunded' : '') | i18n}}">{{c.amount | currency:'$'}}</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>
</tbody>
</table>

View File

@ -20,6 +20,7 @@ import { TokenService } from 'jslib/abstractions/token.service';
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
import { PlanType } from 'jslib/enums/planType';
import { TransactionType } from 'jslib/enums/transactionType';
@Component({
selector: 'app-org-billing',
@ -37,6 +38,7 @@ export class OrganizationBillingComponent implements OnInit {
showUpdateLicense = false;
billing: OrganizationBillingResponse;
paymentMethodType = PaymentMethodType;
transactionType = TransactionType;
selfHosted = false;
verifyAmount1: number;
verifyAmount2: number;
@ -227,12 +229,16 @@ export class OrganizationBillingComponent implements OnInit {
return this.billing != null ? this.billing.upcomingInvoice : null;
}
get paymentSource() {
return this.billing != null ? this.billing.paymentSource : null;
get invoices() {
return this.billing != null ? this.billing.invoices : null;
}
get charges() {
return this.billing != null ? this.billing.charges : null;
get transactions() {
return this.billing != null ? this.billing.transactions : null;
}
get paymentSource() {
return this.billing != null ? this.billing.paymentSource : null;
}
get storagePercentage() {

View File

@ -117,15 +117,51 @@
<app-adjust-payment [currentType]="paymentSource != null ? paymentSource.type : null" (onAdjusted)="closePayment(true)" (onCanceled)="closePayment(false)"
*ngIf="showAdjustPayment">
</app-adjust-payment>
<h2 class="spaced-header">{{'charges' | i18n}}</h2>
<p *ngIf="!charges || !charges.length">{{'noCharges' | i18n}}</p>
<table class="table mb-2" *ngIf="charges && charges.length">
<h2 class="spaced-header">{{'invoices' | i18n}}</h2>
<p *ngIf="!invoices || !invoices.length">{{'noInvoices' | i18n}}</p>
<table class="table mb-2" *ngIf="invoices && invoices.length">
<tbody>
<tr *ngFor="let c of charges">
<td>{{c.createdDate | date:'mediumDate'}}</td>
<td>{{c.paymentSource ? c.paymentSource.description : '-'}}</td>
<td class="text-capitalize">{{c.status}}</td>
<td [ngClass]="{'text-strike':c.refunded}" title="{{(c.refunded ? 'refunded' : '') | i18n}}">{{c.amount | currency:'$'}}</td>
<tr *ngFor="let i of invoices">
<td>{{i.date | date:'mediumDate'}}</td>
<td>
<a href="{{i.pdfUrl}}" target="_blank" rel="noopener" class="mr-2" title="{{'downloadInvoice' | i18n}}">
<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>
</tbody>
</table>

View File

@ -15,6 +15,7 @@ import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { TokenService } from 'jslib/abstractions/token.service';
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
import { TransactionType } from 'jslib/enums/transactionType';
@Component({
selector: 'app-user-billing',
@ -29,6 +30,7 @@ export class UserBillingComponent implements OnInit {
showUpdateLicense = false;
billing: BillingResponse;
paymentMethodType = PaymentMethodType;
transactionType = TransactionType;
selfHosted = false;
cancelPromise: Promise<any>;
@ -164,8 +166,12 @@ export class UserBillingComponent implements OnInit {
return this.billing != null ? this.billing.paymentSource : null;
}
get charges() {
return this.billing != null ? this.billing.charges : null;
get invoices() {
return this.billing != null ? this.billing.invoices : null;
}
get transactions() {
return this.billing != null ? this.billing.transactions : null;
}
get storagePercentage() {

View File

@ -1691,12 +1691,34 @@
"changePaymentMethod": {
"message": "Change Payment Method"
},
"charges": {
"message": "Charges",
"description": "Credit card charges/payments."
"invoices": {
"message": "Invoices"
},
"noCharges": {
"message": "No charges."
"noInvoices": {
"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": {
"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.",
"description": "A billing plan/package. For example: families, teams, enterprise, etc."
},
"invoice": {
"message": "Invoice"
"invoiceNumber": {
"message": "Invoice #$NUMBER$",
"description": "ex. Invoice #79C66F0-0001",
"placeholders": {
"number": {
"content": "$1",
"example": "79C66F0-0001"
}
}
},
"viewInvoice": {
"message": "View Invoice"
},
"downloadInvoice": {
"message": "Download Invoice"
},
"verifyBankAccount": {
"message": "Verify Bank Account"