src/app/services/payment.service.ts
Properties |
ids |
ids:
|
Type : string[]
|
Defined in src/app/services/payment.service.ts:28
|
import { DatePipe } from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { combineLatest } from 'rxjs/observable/combineLatest';
import { catchError, delay, filter, map, tap } from 'rxjs/operators';
import { ERROR_MESSAGE, LOCALE, PAYMENT_API } from '../app.constants';
import {
CreatePaymentRequest,
P2PPaymentModel,
Payment,
Template,
PaymentInFlightResponse,
BankAccount,
} from '../models';
import { DuplicateInfo } from '../models/duplicate-info';
import { AppState } from '../stores/app-state.store';
import { ErrorStore } from '../stores/error.store';
import { AuthService } from './auth.service';
import { DeliveryDateService } from './delivery-date.service';
interface GetPaymentsResponse {
Data: P2PPaymentModel[];
}
interface CreatePaymentsResponse {
ids: string[];
}
@Injectable()
export class PaymentService {
private headers = new HttpHeaders({
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
Expires: '-1',
});
private datePipe = new DatePipe(LOCALE);
private payments: Payment[] = null;
private publisher = new BehaviorSubject<Payment[]>(null);
public payments$ = this.publisher.asObservable();
constructor(
private http: HttpClient,
private errorService: ErrorStore,
private authService: AuthService,
private app: AppState,
private deliveryDateService: DeliveryDateService
) {}
private publish() {
this.publisher.next(this.payments);
}
cachePayment(payment: Payment): void {
const pmt = payment;
pmt.paymentDateFormatted = this.datePipe.transform(new Date(), 'shortDate');
pmt.status = 'InFlight';
this.payments.push(pmt);
this.payments = this.payments.sort((pmt1: Payment, pmt2: Payment) => {
return this.sortByDateThenName(pmt1, pmt2);
});
this.publish();
}
getTemplatesAsPayments(): Observable<P2PPaymentModel[]> {
const url = `${PAYMENT_API}/GetTemplatesAsPayments`;
return this.http.get<GetPaymentsResponse>(url, { headers: this.headers }).pipe(
map((res) => res.Data),
catchError((error) => {
const title = 'Failed To Retrieve Payments';
return this.handleError(error, title);
})
);
}
cancelPayment(id: string): Observable<boolean> {
const url = `${PAYMENT_API}/${id}`;
return this.http.delete(url, { headers: this.headers }).pipe(
delay(5000),
map((res) => {
return true;
}),
catchError((error) => {
const title = 'Failed To Cancel Payment';
return this.handleError(error, title);
})
);
}
dismissPaymentErrorMessage(hash: string): Observable<boolean> {
const url = `${PAYMENT_API}/${hash}`;
return this.http.delete(url, { headers: this.headers }).pipe(
map((res) => {
return true;
}),
catchError((error) => {
const title = 'Failed To Dismiss Payment Error Message';
return this.handleError(error, title);
})
);
}
createPayment(payment: Payment, template: Template): Observable<Payment> {
const request = {
templateId: template.id,
amount: payment.amount,
memo: payment.memo,
name: template.name,
p2PPayToEmailAddress: template.p2PPayToEmailAddress,
p2PPayToPhoneNumber: template.p2PPayToPhoneNumber,
secret: template.secret,
payFromBankAccountDescription: template.payFromBankAccount.accountType,
payFromAccount: template.payFromBankAccount.accountNumber,
defaultContactMethod: template.defaultContactMethod,
} as CreatePaymentRequest;
if (this.app.acknowledgeDuplicate) {
request.duplicateOf = !!this.app.duplicateInfo.paymentId
? this.app.duplicateInfo.paymentId
: `${this.app.duplicateInfo.key}|${this.app.duplicateInfo.hash}`;
}
// Set Up the Feature Flag Here
const url = `${PAYMENT_API}/create`;
return this.http.post<PaymentInFlightResponse>(url, request).pipe(
map((response) => {
const payment = new Payment();
payment.displayName = request.name;
payment.inFlightKey = response.key;
payment.hash = response.hash;
payment.amount = request.amount;
payment.memo = request.memo;
payment.status = 'InFlight'; // todo get text from product
payment.p2PPayToEmailAddress = request.p2PPayToEmailAddress;
payment.p2PPayToPhoneNumber = request.p2PPayToPhoneNumber;
payment.secret = request.secret;
payment.payFromBankAccountDescription = request.payFromBankAccountDescription;
payment.payFromAccount = request.payFromAccount;
payment.defaultContactMethod = request.defaultContactMethod;
// todo store inflight payment dto into session storage for on refresh / leave & return use cases
this.cachePayment(payment);
this.payments = this.payments.sort((pmt1: Payment, pmt2: Payment) => {
return this.sortByDateThenName(pmt1, pmt2);
});
this.publish();
return payment;
}),
catchError((error) => {
const title = 'Failed To Create Payment';
return this.handleError(error, title);
})
);
}
getPayment(id: string): Observable<Payment> {
try {
return this.payments$.pipe(
filter((payments) => payments !== null && payments !== undefined),
map((payments) => {
let found: any;
if (id.length === 36) {
found = payments.filter((p) => p.id === id);
} else {
found = payments.filter((p) => p.hash === id);
}
const match = found.length > 0 ? found[0] : null;
return match;
})
);
} catch (error) {
const title = 'Failed To Retrieve Payment';
return this.handleError(error, title);
}
}
getPayments(useCache = true): Observable<Payment[]> {
if (useCache && this.payments != null) {
return Observable.of(this.payments);
}
const url = `${PAYMENT_API}`;
return this.http.get<Payment[]>(url, { headers: this.headers }).pipe(
tap((payments) =>
payments.forEach((payment) =>
// tslint:disable-next-line:one-line
{
// Sets the payFromAccount Information for UI
let account: BankAccount = new BankAccount();
account.accountNumber = payment.payFromAccount;
account.accountType = payment.payFromBankAccountDescription;
payment.account = account;
// Formats the date to not use local timezone
if (payment.networkSendDate && payment.networkSendDate.length > 0) {
const deliveryDateValue = payment.networkSendDate.toString().split('T');
payment.deliveryDate = deliveryDateValue[0].concat('T01:00:00');
}
}
)
),
map((payments) => {
this.payments = payments.map((payment) => new Payment(payment));
this.publish();
return payments;
}),
catchError((error) => {
const title = 'Failed To Retrieve Payments';
return this.handleError(error, title);
})
);
}
private handleError(error: any, title: string) {
this.errorService.addError(title, ERROR_MESSAGE);
this.errorService.displayErrors();
return Observable.of(null);
}
findDuplicate(): Observable<Payment> {
try {
return combineLatest(this.payments$, this.deliveryDateService.date$).pipe(
filter(([payments, nextBusinessDate]) => !!payments && !!nextBusinessDate),
map(([payments, nextBusinessDate]) => {
const foundPayment = payments
.filter((p) => {
if (p.error && p.error.length > 0) {
return false;
}
if (p.status.toLowerCase() === 'inflight') {
return true;
}
const date1 = new Date(p.paymentDateFormatted);
const date2 = new Date(nextBusinessDate);
return date1.getTime() === date2.getTime(); // use date as ms to compare date strings even if formatted differently s
})
.filter((p) => p.amount === this.app.payment.amount)
.filter((p) => p.payToName === this.app.template.name)
.reduce((x, p) => {
console.log('matched', p);
return p;
}, null); // return only item in the array instead of returning an array
return foundPayment;
})
);
} catch (error) {
const title = 'Failed To Retrieve Payment';
return this.handleError(error, title);
}
}
acknowledgeDuplicate(customerId: string, payment: Payment) {
const info: DuplicateInfo = {};
if (payment.inFlightKey && payment.inFlightKey.length > 0) {
info.hash = payment.hash;
info.key = payment.inFlightKey;
} else {
info.paymentId = payment.id;
}
console.error('acknowleded duplicate of', info);
this.app.acknowledgeDuplicate = true;
this.app.duplicateInfo = info;
}
private sortByDateThenName(pmt1: Payment, pmt2: Payment): number {
let result = this.sortByDateAsc(pmt1, pmt2);
if (result === 0) {
result = this.sortByNameAsc(pmt1, pmt2);
}
return result;
}
private sortByDateAsc(pmt1: Payment, pmt2: Payment): number {
const dt1 = new Date(pmt1.paymentDate);
const dt2 = new Date(pmt2.paymentDate);
if (dt1 > dt2) {
return 1;
}
if (dt1 < dt2) {
return -1;
}
return 0;
}
private sortByNameAsc(pmt1: Payment, pmt2: Payment): number {
const name1 = pmt1.payToName;
const name2 = pmt2.payToName;
if (name1 > name2) {
return 1;
}
if (name1 < name2) {
return -1;
}
return 0;
}
}