diff --git a/backend/vehicles/src/modules/permit/dto/response/permit-history.dto.ts b/backend/vehicles/src/modules/permit/dto/response/permit-history.dto.ts index e713f93d8..4731fc3a0 100644 --- a/backend/vehicles/src/modules/permit/dto/response/permit-history.dto.ts +++ b/backend/vehicles/src/modules/permit/dto/response/permit-history.dto.ts @@ -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() @@ -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({ diff --git a/backend/vehicles/src/modules/permit/permit.service.ts b/backend/vehicles/src/modules/permit/permit.service.ts index 802623a60..9313de6d0 100644 --- a/backend/vehicles/src/modules/permit/permit.service.ts +++ b/backend/vehicles/src/modules/permit/permit.service.ts @@ -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: diff --git a/frontend/src/common/types/paymentMethods.ts b/frontend/src/common/types/paymentMethods.ts index 64ff9a311..b07725bf2 100644 --- a/frontend/src/common/types/paymentMethods.ts +++ b/frontend/src/common/types/paymentMethods.ts @@ -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", @@ -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", @@ -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 = @@ -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. */ @@ -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, }, }; @@ -174,6 +189,20 @@ export const CONSOLIDATED_PAYMENT_METHODS: Record< * @returns string */ export const getConsolidatedPaymentMethod = ( - paymentMethod: Extract, + 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], + ); +}; diff --git a/frontend/src/features/permits/helpers/payment.ts b/frontend/src/features/permits/helpers/payment.ts index 68ddaf57c..372a32d68 100644 --- a/frontend/src/features/permits/helpers/payment.ts +++ b/frontend/src/features/permits/helpers/payment.ts @@ -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. @@ -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")), diff --git a/frontend/src/features/permits/pages/Amend/components/helpers/mapper.ts b/frontend/src/features/permits/pages/Amend/components/helpers/mapper.ts index 6aa83aa65..f8a9ddd11 100644 --- a/frontend/src/features/permits/pages/Amend/components/helpers/mapper.ts +++ b/frontend/src/features/permits/pages/Amend/components/helpers/mapper.ts @@ -1,6 +1,10 @@ -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, @@ -8,9 +12,31 @@ export const mapToAmendRequestData = ( 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, @@ -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, }; }; diff --git a/frontend/src/features/permits/pages/Payment/PaymentRedirect.tsx b/frontend/src/features/permits/pages/Payment/PaymentRedirect.tsx index 15a0c5524..64ad8dc30 100644 --- a/frontend/src/features/permits/pages/Payment/PaymentRedirect.tsx +++ b/frontend/src/features/permits/pages/Payment/PaymentRedirect.tsx @@ -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 = "?"; @@ -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, + }; }; diff --git a/frontend/src/features/permits/pages/Refund/RefundPage.tsx b/frontend/src/features/permits/pages/Refund/RefundPage.tsx index e90498a98..322c372b9 100644 --- a/frontend/src/features/permits/pages/Refund/RefundPage.tsx +++ b/frontend/src/features/permits/pages/Refund/RefundPage.tsx @@ -16,17 +16,19 @@ import { import "./RefundPage.scss"; import { permitTypeDisplayText } from "../../types/PermitType"; import { RefundFormData } from "./types/RefundFormData"; -import { - REFUND_METHODS, - getRefundMethodByCardType, - refundMethodDisplayText, -} from "../../types/PaymentMethod"; import { requiredMessage } from "../../../../common/helpers/validationMessages"; import { getErrorMessage } from "../../../../common/components/form/CustomFormComponents"; import { PermitHistory } from "../../types/PermitHistory"; import { TransactionHistoryTable } from "./components/TransactionHistoryTable"; import { FeeSummary } from "../../components/feeSummary/FeeSummary"; import { getDefaultRequiredVal } from "../../../../common/helpers/util"; +import { TRANSACTION_TYPES } from "../../types/payment.d"; +import { + CONSOLIDATED_PAYMENT_METHODS, + PAYMENT_METHODS_WITH_CARD, + PAYMENT_METHOD_TYPE_DISPLAY, + getPaymentMethod, +} from "../../../../common/types/paymentMethods"; type PermitAction = "void" | "revoke" | "amend"; @@ -56,12 +58,8 @@ const transactionIdRules = { }, }; -const refundOptions = Object.values(REFUND_METHODS).map((refundMethod) => ({ - value: refundMethod, - label: refundMethodDisplayText(refundMethod), -})); - -const DEFAULT_REFUND_METHOD = REFUND_METHODS.Cheque; +const refundOptions = Object.keys(CONSOLIDATED_PAYMENT_METHODS); +const DEFAULT_REFUND_OPTION = PAYMENT_METHOD_TYPE_DISPLAY.CHEQUE; export const RefundPage = ({ permitHistory, @@ -84,19 +82,52 @@ export const RefundPage = ({ amountToRefund: number; onFinish: (refundData: RefundFormData) => void; }) => { - const [shouldUsePrevPaymentMethod, setShouldUsePrevPaymentMethod] = - useState(true); - - const getRefundMethodForPrevPayMethod = () => { + // Get last valid transaction's payment method + // eg. zero dollar amounts (from amendment) is not considered valid payment method + // Also, if the transaction is of payment method type with an associated card type, then its card type must not be empty + const getPrevPaymentMethod = () => { if (!permitHistory || permitHistory.length === 0) - return DEFAULT_REFUND_METHOD; - const cardType = permitHistory[0].pgCardType; - return getRefundMethodByCardType(cardType); + return undefined; + + const prevValidTransaction = permitHistory.find(history => { + return history.transactionTypeId !== TRANSACTION_TYPES.Z + && ( + ( + PAYMENT_METHODS_WITH_CARD.includes(history.paymentMethodTypeCode) + && !!history.paymentCardTypeCode + ) + || ( + !PAYMENT_METHODS_WITH_CARD.includes(history.paymentMethodTypeCode) + && !history.paymentCardTypeCode + ) + ); + }); + + if (!prevValidTransaction) return undefined; + + return getPaymentMethod( + prevValidTransaction.paymentMethodTypeCode, + prevValidTransaction.paymentCardTypeCode, + ); + }; + + const getRefundMethodType = () => { + const prevPaymentMethod = getPrevPaymentMethod(); + + if (!prevPaymentMethod) + return CONSOLIDATED_PAYMENT_METHODS[DEFAULT_REFUND_OPTION].paymentMethodTypeCode; + + return CONSOLIDATED_PAYMENT_METHODS[prevPaymentMethod].paymentMethodTypeCode; }; const getRefundCardType = () => { - if (!permitHistory || permitHistory.length === 0) return ""; - return getDefaultRequiredVal("", permitHistory[0].pgCardType); + const prevPaymentMethod = getPrevPaymentMethod(); + + if (!prevPaymentMethod) { + return CONSOLIDATED_PAYMENT_METHODS[DEFAULT_REFUND_OPTION].paymentCardTypeCode; + } + + return CONSOLIDATED_PAYMENT_METHODS[prevPaymentMethod].paymentCardTypeCode; }; const getRefundOnlineMethod = () => { @@ -104,11 +135,22 @@ export const RefundPage = ({ return getDefaultRequiredVal("", permitHistory[0].pgPaymentMethod); }; + const disableRefundCardSelection = !getPrevPaymentMethod() || !getRefundCardType(); + + // only show refund method selection (both card selection and cheque) when amount to refund is greater than 0 + // we use a small epsilon since there may be decimal precision errors when doing decimal comparisons + const enableRefundMethodSelection = Math.abs(amountToRefund) > 0.0000001; + + const [shouldUsePrevPaymentMethod, setShouldUsePrevPaymentMethod] = + useState(!disableRefundCardSelection); + const formMethods = useForm({ defaultValues: { shouldUsePrevPaymentMethod, - refundMethod: getRefundMethodForPrevPayMethod(), - refundCardType: getRefundCardType(), + refundMethod: getPaymentMethod( + getRefundMethodType(), + getRefundCardType(), + ), refundOnlineMethod: getRefundOnlineMethod(), transactionId: "", }, @@ -126,9 +168,10 @@ export const RefundPage = ({ } = formMethods; useEffect(() => { - const refundMethod = getRefundMethodForPrevPayMethod(); - setValue("refundMethod", refundMethod); - setValue("refundCardType", getRefundCardType()); + const refundMethod = getRefundMethodType(); + const refundCardType = getRefundCardType(); + setShouldUsePrevPaymentMethod(!disableRefundCardSelection); + setValue("refundMethod", getPaymentMethod(refundMethod, refundCardType)); setValue("refundOnlineMethod", getRefundOnlineMethod()); }, [permitHistory, permitHistory.length]); @@ -136,11 +179,6 @@ export const RefundPage = ({ const usePrev = shouldUsePrev === "true"; setShouldUsePrevPaymentMethod(usePrev); setValue("shouldUsePrevPaymentMethod", usePrev); - setValue( - "refundMethod", - usePrev ? getRefundMethodForPrevPayMethod() : REFUND_METHODS.Cheque, - ); - setValue("refundCardType", usePrev ? getRefundCardType() : ""); setValue("refundOnlineMethod", usePrev ? getRefundOnlineMethod() : ""); clearErrors("transactionId"); }; @@ -154,10 +192,6 @@ export const RefundPage = ({ const showReasonSection = (permitAction === "void" || permitAction === "revoke") && reason; - // only show refund method selection when amount to refund is greater than 0 - // we use a small epsilon since there may be decimal precision errors when doing decimal comparisons - const enableRefundSelection = Math.abs(amountToRefund) > 0.0000001; - return (
@@ -198,7 +232,7 @@ export const RefundPage = ({ ) : null}
- {enableRefundSelection ? ( + {enableRefundMethodSelection ? (
Choose a Refund Method
@@ -212,84 +246,87 @@ export const RefundPage = ({ value={value} onChange={(e) => handleRefundMethodChange(e.target.value)} > -
- } - /> -
- ( - - - Payment Method - - - - )} + {!disableRefundCardSelection ? ( +
+ } /> - - ( - - - Transaction ID - - - {invalid ? ( - + ( + + + Payment Method + + + + )} + /> + + ( + + + Transaction ID + + + {invalid ? ( + + {getErrorMessage(errors, "transactionId")} + + ) : null} + + )} + /> +
-
+ ) : null} +
{ - const paymentMethod = getPaymentMethod( - originalRow.pgPaymentMethod, - originalRow.pgCardType, - ); - return getDefaultRequiredVal( - "NA", - applyWhenNotNullable(paymentMethodDisplayText, paymentMethod), + if (originalRow.transactionTypeId === TRANSACTION_TYPES.Z) { + return "NA"; + } + + return getPaymentMethod( + originalRow.paymentMethodTypeCode, + originalRow.paymentCardTypeCode, ); }, id: "paymentMethod", @@ -65,7 +64,7 @@ export const TransactionHistoryTable = ({ }, { accessorFn: (originalRow) => - getDefaultRequiredVal("NA", originalRow.pgTransactionId), + getDefaultRequiredVal(originalRow.transactionOrderNumber, originalRow.pgTransactionId), id: "providerTransactionId", header: "Transaction ID", muiTableHeadCellProps: { diff --git a/frontend/src/features/permits/pages/Refund/types/RefundFormData.ts b/frontend/src/features/permits/pages/Refund/types/RefundFormData.ts index 25f2f6f18..a6e183061 100644 --- a/frontend/src/features/permits/pages/Refund/types/RefundFormData.ts +++ b/frontend/src/features/permits/pages/Refund/types/RefundFormData.ts @@ -1,13 +1,8 @@ -import { - BamboraPaymentMethod, - CardType, - RefundMethod, -} from "../../../types/PaymentMethod"; +import { BamboraPaymentMethod } from "../../../types/PaymentMethod"; export interface RefundFormData { shouldUsePrevPaymentMethod: boolean; - refundMethod: RefundMethod; + refundMethod: string; refundOnlineMethod: BamboraPaymentMethod | ""; - refundCardType: CardType | ""; transactionId?: string; } diff --git a/frontend/src/features/permits/pages/Void/helpers/mapper.ts b/frontend/src/features/permits/pages/Void/helpers/mapper.ts index d7af22ad1..5692bc417 100644 --- a/frontend/src/features/permits/pages/Void/helpers/mapper.ts +++ b/frontend/src/features/permits/pages/Void/helpers/mapper.ts @@ -1,4 +1,5 @@ -import { PAYMENT_METHOD_TYPE_CODE } from "../../../../../common/types/paymentMethods"; +import { getDefaultRequiredVal } from "../../../../../common/helpers/util"; +import { CONSOLIDATED_PAYMENT_METHODS, PAYMENT_METHOD_TYPE_CODE } from "../../../../../common/types/paymentMethods"; import { PERMIT_STATUSES } from "../../../types/PermitStatus"; import { RefundFormData } from "../../Refund/types/RefundFormData"; import { @@ -12,7 +13,7 @@ export const mapToRevokeRequestData = ( ): RevokePermitRequestData => { return { status: PERMIT_STATUSES.REVOKED, - paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB, // hardcoded to "WEB" - Web + paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB, // hardcoded to "WEB" for revoke transactionAmount: 0, comment: voidPermitFormData.reason, }; @@ -23,17 +24,38 @@ export const mapToVoidRequestData = ( refundData: RefundFormData, amountToRefund: number, ): VoidPermitRequestData => { + 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; + }; + return { status: PERMIT_STATUSES.VOIDED, pgTransactionId: refundData.transactionId, - paymentMethodTypeCode: PAYMENT_METHOD_TYPE_CODE.WEB, // hardcoded to "WEB" - Web + paymentMethodTypeCode: getRefundMethodType(), transactionAmount: amountToRefund, pgPaymentMethod: refundData.refundOnlineMethod ? refundData.refundOnlineMethod : undefined, - pgCardType: refundData.refundCardType - ? refundData.refundCardType - : undefined, + pgCardType: getRefundCardType(), comment: voidPermitFormData.reason, }; }; diff --git a/frontend/src/features/permits/pages/Void/types/VoidPermit.ts b/frontend/src/features/permits/pages/Void/types/VoidPermit.ts index 8f9a4d565..543436dea 100644 --- a/frontend/src/features/permits/pages/Void/types/VoidPermit.ts +++ b/frontend/src/features/permits/pages/Void/types/VoidPermit.ts @@ -1,6 +1,6 @@ -import { PaymentMethodTypeCode } from "../../../../../common/types/paymentMethods"; -import { BamboraPaymentMethod, CardType } from "../../../types/PaymentMethod"; -import { PermitStatus } from "../../../types/PermitStatus"; +import { PaymentCardTypeCode, PaymentMethodTypeCode } from "../../../../../common/types/paymentMethods"; +import { BamboraPaymentMethod } from "../../../types/PaymentMethod"; +import { PermitStatus, PERMIT_STATUSES } from "../../../types/PermitStatus"; import { PermitsActionResponse } from "../../../types/permit"; export interface VoidPermitFormData { @@ -12,18 +12,18 @@ export interface VoidPermitFormData { } export interface VoidPermitRequestData { - status: Extract; + status: Extract; pgTransactionId?: string; - paymentMethodTypeCode: PaymentMethodTypeCode; // hardcoded to "WEB" - Web + paymentMethodTypeCode: PaymentMethodTypeCode; transactionAmount: number; pgTransactionDate?: string; pgPaymentMethod?: BamboraPaymentMethod; - pgCardType?: CardType; + pgCardType?: PaymentCardTypeCode; comment: string; } export interface RevokePermitRequestData { - status: Extract; + status: Extract; paymentMethodTypeCode: PaymentMethodTypeCode; // hardcoded to "WEB" - Web pgPaymentMethod?: BamboraPaymentMethod; transactionAmount: 0; diff --git a/frontend/src/features/permits/types/PermitHistory.ts b/frontend/src/features/permits/types/PermitHistory.ts index aa6724b38..395f3e221 100644 --- a/frontend/src/features/permits/types/PermitHistory.ts +++ b/frontend/src/features/permits/types/PermitHistory.ts @@ -1,4 +1,5 @@ -import { BamboraPaymentMethod, CardType } from "./PaymentMethod"; +import { PaymentCardTypeCode, PaymentMethodTypeCode } from "../../../common/types/paymentMethods"; +import { BamboraPaymentMethod } from "./PaymentMethod"; import { TransactionType } from "./payment"; export interface PermitHistory { @@ -9,7 +10,8 @@ export interface PermitHistory { transactionOrderNumber: string; pgTransactionId: string | null; pgPaymentMethod: BamboraPaymentMethod | null; - pgCardType: CardType | null; + paymentCardTypeCode: PaymentCardTypeCode | null; + paymentMethodTypeCode: PaymentMethodTypeCode; transactionTypeId: TransactionType; permitId: number; transactionSubmitDate: string | null; diff --git a/frontend/src/features/permits/types/payment.d.ts b/frontend/src/features/permits/types/payment.d.ts index 5bb3d26ea..82666f4f0 100644 --- a/frontend/src/features/permits/types/payment.d.ts +++ b/frontend/src/features/permits/types/payment.d.ts @@ -1,5 +1,5 @@ -import { PaymentMethodTypeCode } from "../../../common/types/paymentMethods"; -import { BamboraPaymentMethod, CardType } from "./PaymentMethod"; +import { PaymentCardTypeCode, PaymentMethodTypeCode } from "../../../common/types/paymentMethods"; +import { BamboraPaymentMethod } from "./PaymentMethod"; export interface PayBCPaymentDetails { authCode: string; @@ -9,7 +9,7 @@ export interface PayBCPaymentDetails { avsPostalMatch: string; avsProcessed: string; avsResult: string; - cardType: CardType; + cardType: string; cvdId: number; trnApproved: number; messageId: string; @@ -32,28 +32,6 @@ export interface PayBCPaymentDetails { trnType: string; } -export interface Transaction { - //transactionId: number; - transactionType: string; - transactionOrderNumber: string; - providerTransactionId: number; - transactionAmount: number; - approved: number; - authCode: string; - cardType: string; - transactionDate: string; - cvdId: number; - paymentMethod: string; - paymentMethodTypeCode: PaymentMethodTypeCode; - messageId: string; - messageText: string; -} - -export interface PermitTransaction { - permitId: string; - transactionId: number; -} - export const TRANSACTION_TYPES = { P: "P", R: "R", @@ -72,7 +50,7 @@ export interface PaymentGatewayData { pgTransactionId: string; pgApproved: number; pgAuthCode: string; - pgCardType: CardType; + pgCardType: PaymentCardTypeCode; pgTransactionDate: string; pgCvdId: number; pgPaymentMethod: BamboraPaymentMethod; @@ -84,6 +62,7 @@ export interface StartTransactionRequestData extends Partial { transactionTypeId: TransactionType; paymentMethodTypeCode: PaymentMethodTypeCode; + paymentCardTypeCode?: PaymentCardTypeCode; applicationDetails: { applicationId: string; transactionAmount: number; @@ -95,6 +74,7 @@ export interface StartTransactionResponseData transactionId: string; transactionTypeId: TransactionType; paymentMethodTypeCode: PaymentMethodTypeCode; + paymentCardTypeCode?: PaymentCardTypeCode | null; totalTransactionAmount: number; transactionSubmitDate: string; transactionOrderNumber: string; @@ -109,5 +89,5 @@ export type CompleteTransactionRequestData = Partial; export interface CompleteTransactionResponseData extends Partial { - transactionid: string; + transactionId: string; }