Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ORV2-1679 - Update payment methods for refund and payment on frontend #767

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { AutoMap } from '@automapper/classes';
import { ApiProperty } from '@nestjs/swagger';
import { TransactionType } from '../../../../common/enum/transaction-type.enum';
import { PaymentMethodType } from 'src/common/enum/payment-method-type.enum';
import { PaymentCardType } from 'src/common/enum/payment-card-type.enum';

export class PermitHistoryDto {
@AutoMap()
Expand Down Expand Up @@ -57,10 +59,19 @@ export class PermitHistoryDto {

@AutoMap()
@ApiProperty({
example: 'VI',
description: 'Represents the card type used by a transaction.',
enum: TransactionType,
example: PaymentMethodType.WEB,
description: 'The identifier of the user selected payment method.',
})
paymentMethodTypeCode: PaymentMethodType;

@AutoMap()
@ApiProperty({
enum: PaymentCardType,
example: PaymentCardType.VISA,
description: 'The identifier of the user selected payment type.',
})
pgCardType: string;
paymentCardTypeCode: PaymentCardType;

@AutoMap()
@ApiProperty({
Expand Down
3 changes: 2 additions & 1 deletion backend/vehicles/src/modules/permit/permit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ export class PermitService {
transactionTypeId: permitTransaction.transaction.transactionTypeId,
pgPaymentMethod: permitTransaction.transaction.pgPaymentMethod,
pgTransactionId: permitTransaction.transaction.pgTransactionId,
pgCardType: permitTransaction.transaction.pgCardType,
paymentCardTypeCode: permitTransaction.transaction.paymentCardTypeCode,
paymentMethodTypeCode: permitTransaction.transaction.paymentMethodTypeCode,
commentUsername: permit.createdUser,
permitId: +permit.permitId,
transactionSubmitDate:
Expand Down
93 changes: 61 additions & 32 deletions frontend/src/common/types/paymentMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
export const PAYMENT_METHOD_TYPE_CODE = {
CASH: "CASH",
CHEQUE: "CHEQUE",
CREDIT_ACCOUNT: "ACCOUNT",
ACCOUNT: "ACCOUNT",
GA: "GA",
ICEPAY: "ICEPAY",
POS: "POS",
Expand All @@ -23,7 +23,7 @@ export type PaymentMethodTypeCode =
export const PAYMENT_METHOD_TYPE_DISPLAY = {
CASH: "Cash",
CHEQUE: "Cheque",
CREDIT_ACCOUNT: "Credit Account",
ACCOUNT: "Credit Account",
GA: "GA Payment",
ICEPAY: "IcePay",
POS: "PoS",
Expand All @@ -37,12 +37,12 @@ export type PaymentMethodTypeDisplay =
(typeof PAYMENT_METHOD_TYPE_DISPLAY)[keyof typeof PAYMENT_METHOD_TYPE_DISPLAY];

export const PAYMENT_CARD_TYPE_CODE = {
VISA: "VI", // Visa
MASTERCARD: "MC", // MasterCard
AMEX: "AM", // American Express
VISA_DEBIT: "PV", // Visa Debit
MASTERCARD_DEBIT: "MD", // Debit MasterCard
DEBIT: "DB", // Debit
VI: "VI", // Visa
MC: "MC", // MasterCard
AM: "AM", // American Express
PV: "PV", // Visa Debit
MD: "MD", // Debit MasterCard
DB: "DB", // Debit
} as const;

export type PaymentCardTypeCode =
Expand All @@ -52,17 +52,32 @@ export type PaymentCardTypeCode =
* The card types
*/
export const PAYMENT_CARD_TYPE_DISPLAY = {
AMEX: "Amex",
VISA_DEBIT: "Visa (Debit)",
VISA: "Visa",
MASTERCARD: "Mastercard",
MASTERCARD_DEBIT: "Mastercard (Debit)",
DEBIT: "Debit",
AM: "Amex",
PV: "Visa (Debit)",
VI: "Visa",
MC: "Mastercard",
MD: "Mastercard (Debit)",
DB: "Debit",
} as const;

export type PaymentCardTypeDisplay =
(typeof PAYMENT_CARD_TYPE_DISPLAY)[keyof typeof PAYMENT_CARD_TYPE_DISPLAY];

export const PAYMENT_METHODS_WITH_CARD: PaymentMethodTypeCode[] = [
PAYMENT_METHOD_TYPE_CODE.ICEPAY,
PAYMENT_METHOD_TYPE_CODE.WEB,
PAYMENT_METHOD_TYPE_CODE.POS,
];

export type PaymentMethodWithCard = Extract<
PaymentMethodTypeCode,
typeof PAYMENT_METHOD_TYPE_CODE.ICEPAY |
typeof PAYMENT_METHOD_TYPE_CODE.WEB |
typeof PAYMENT_METHOD_TYPE_CODE.POS
>;

export type PaymentMethodDisplayWithCard = typeof PAYMENT_METHOD_TYPE_DISPLAY[PaymentMethodWithCard];

/**
* An object containing the paymentMethodTypeCode and paymentCardTypeCode values.
*/
Expand Down Expand Up @@ -94,74 +109,74 @@ export const CONSOLIDATED_PAYMENT_METHODS: Record<
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.CHEQUE,
},
"Credit Account": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.CREDIT_ACCOUNT,
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ACCOUNT,
},
"GA Payment": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.GA,
},
"IcePay - Amex": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ICEPAY,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AMEX,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AM,
},
"IcePay - Mastercard": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ICEPAY,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MC,
},
"IcePay - Mastercard (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ICEPAY,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MD,
},
"IcePay - Visa": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ICEPAY,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VI,
},
"IcePay - Visa (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.ICEPAY,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.PV,
},
"PoS - Amex": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AMEX,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AM,
},
"PoS - Debit": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.DB,
},
"PoS - Mastercard": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MC,
},
"PoS - Mastercard (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MD,
},
"PoS - Visa": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VI,
},
"PoS - Visa (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.POS,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.PV,
},
"Web - Amex": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AMEX,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.AM,
},
"Web - Mastercard": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MC,
},
"Web - Mastercard (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MASTERCARD_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.MD,
},
"Web - Visa": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VI,
},
"Web - Visa (Debit)": {
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.VISA_DEBIT,
paymentCardTypeCode: PAYMENT_CARD_TYPE_CODE.PV,
},
};

Expand All @@ -174,6 +189,20 @@ export const CONSOLIDATED_PAYMENT_METHODS: Record<
* @returns string
*/
export const getConsolidatedPaymentMethod = (
paymentMethod: Extract<PaymentMethodTypeDisplay, "IcePay" | "Web" | "PoS">,
paymentMethod: PaymentMethodDisplayWithCard,
paymentCard: PaymentCardTypeDisplay,
): string => paymentMethod + " - " + paymentCard;

export const getPaymentMethod = (
paymentMethod: PaymentMethodTypeCode,
paymentCard?: PaymentCardTypeCode | null,
): string => {
if (!paymentCard || !PAYMENT_METHODS_WITH_CARD.includes(paymentMethod)) {
return PAYMENT_METHOD_TYPE_DISPLAY[paymentMethod];
}

return getConsolidatedPaymentMethod(
PAYMENT_METHOD_TYPE_DISPLAY[paymentMethod] as PaymentMethodDisplayWithCard,
PAYMENT_CARD_TYPE_DISPLAY[paymentCard],
);
};
10 changes: 3 additions & 7 deletions frontend/src/features/permits/helpers/payment.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { PayBCPaymentDetails } from "../types/payment";
import { parseRedirectUriPath } from "../pages/Payment/PaymentRedirect";
import {
applyWhenNotNullable,
getDefaultRequiredVal,
} from "../../../common/helpers/util";

import {
BAMBORA_PAYMENT_METHODS,
BamboraPaymentMethod,
CARD_TYPES,
CardType,
} from "../types/PaymentMethod";
import { parseRedirectUriPath } from "../pages/Payment/PaymentRedirect";

/**
* Extracts PayBCPaymentDetails from the query parameters of a URL.
Expand All @@ -32,10 +31,7 @@ export const getPayBCPaymentDetails = (
avsPostalMatch: getDefaultRequiredVal("", params.get("avsPostalMatch")),
avsProcessed: getDefaultRequiredVal("", params.get("avsProcessed")),
avsResult: getDefaultRequiredVal("", params.get("avsResult")),
cardType: getDefaultRequiredVal(
CARD_TYPES.VI,
params.get("cardType"),
) as CardType,
cardType: getDefaultRequiredVal("", params.get("cardType")),
cvdId: 1, // applyWhenNotNullable((cvdId) => Number(cvdId), params.get("cvdId"), 0),
trnApproved: trnApproved,
messageId: "1", // getDefaultRequiredVal("", params.get("messageId")),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
import { PAYMENT_METHOD_TYPE_CODE } from "../../../../../../common/types/paymentMethods";
import { getDefaultRequiredVal } from "../../../../../../common/helpers/util";
import { TRANSACTION_TYPES } from "../../../../types/payment.d";
import { RefundFormData } from "../../../Refund/types/RefundFormData";
import {
CONSOLIDATED_PAYMENT_METHODS,
PAYMENT_METHOD_TYPE_CODE,
} from "../../../../../../common/types/paymentMethods";

export const mapToAmendRequestData = (
refundData: RefundFormData,
amountToRefund: number,
permitId: string,
) => {
const isZeroAmount = Math.abs(amountToRefund) < 0.000001;

const getRefundMethodType = () => {
if (isZeroAmount) return PAYMENT_METHOD_TYPE_CODE.WEB;

const refundMethodTypeCode = getDefaultRequiredVal(
PAYMENT_METHOD_TYPE_CODE.WEB,
CONSOLIDATED_PAYMENT_METHODS[refundData.refundMethod]?.paymentMethodTypeCode
);

return refundData.shouldUsePrevPaymentMethod ?
refundMethodTypeCode :
PAYMENT_METHOD_TYPE_CODE.CHEQUE;
};

const getRefundCardType = () => {
if (isZeroAmount || !refundData.shouldUsePrevPaymentMethod) {
return undefined;
}

return CONSOLIDATED_PAYMENT_METHODS[refundData.refundMethod]?.paymentCardTypeCode;
};

const reqData = {
transactionTypeId: isZeroAmount ? TRANSACTION_TYPES.Z : TRANSACTION_TYPES.R,
paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB, // hardcoded to "WEB" - Web
paymentMethodTypeCode: getRefundMethodType(),
applicationDetails: [
{
applicationId: permitId,
Expand All @@ -24,13 +50,12 @@ export const mapToAmendRequestData = (
}

return {
...reqData,
pgTransactionId: refundData.transactionId,
pgCardType: refundData.refundCardType
? refundData.refundCardType
: undefined,
pgCardType: getRefundCardType(),
paymentCardTypeCode: getRefundCardType(),
pgPaymentMethod: refundData.refundOnlineMethod
? refundData.refundOnlineMethod
: undefined,
...reqData,
};
};
22 changes: 16 additions & 6 deletions frontend/src/features/permits/pages/Payment/PaymentRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { useEffect, useRef } from "react";
import { Navigate, useSearchParams } from "react-router-dom";

import { getPayBCPaymentDetails } from "../../helpers/payment";
import {
CompleteTransactionRequestData,
PayBCPaymentDetails,
} from "../../types/payment";
import { Loading } from "../../../../common/pages/Loading";
import { useCompleteTransaction, useIssuePermits } from "../../hooks/hooks";
import { getDefaultRequiredVal } from "../../../../common/helpers/util";
import { DATE_FORMATS, toUtc } from "../../../../common/helpers/formatDate";
import { PaymentCardTypeCode } from "../../../../common/types/paymentMethods";
import {
CompleteTransactionRequestData,
PayBCPaymentDetails,
} from "../../types/payment";

const PERMIT_ID_DELIM = ",";
const PATH_DELIM = "?";
Expand Down Expand Up @@ -142,15 +143,24 @@ export const PaymentRedirect = () => {
const mapTransactionDetails = (
paymentResponse: PayBCPaymentDetails,
): CompleteTransactionRequestData => {
return {
const isValidCardType = paymentResponse.cardType !== "";
const transactionDetails = {
pgTransactionId: paymentResponse.trnId,
pgApproved: Number(paymentResponse.trnApproved),
pgAuthCode: paymentResponse.authCode,
pgCardType: paymentResponse.cardType,
pgTransactionDate: toUtc(paymentResponse.trnDate, DATE_FORMATS.ISO8601),
pgCvdId: Number(paymentResponse.cvdId),
pgPaymentMethod: paymentResponse.paymentMethod,
pgMessageId: Number(paymentResponse.messageId),
pgMessageText: paymentResponse.messageText,
};

if (!isValidCardType) {
return transactionDetails;
}

return {
...transactionDetails,
pgCardType: paymentResponse.cardType as PaymentCardTypeCode,
};
};
Loading
Loading