Skip to content

Commit

Permalink
Platform/Base - UI: Payment method override (#416)
Browse files Browse the repository at this point in the history
* add alternate payment option to fee widget

* simplify setup method

* update payment redirect in application submit

* update payment for platform on dashboard mount

* bump version

* fix i18n file
  • Loading branch information
deetz99 authored Dec 23, 2024
1 parent 903582f commit cb501da
Show file tree
Hide file tree
Showing 17 changed files with 273 additions and 110 deletions.
180 changes: 113 additions & 67 deletions strr-base-web/app/components/connect/fee/Widget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ const {
totalPriorityFees,
totalProcessingFees,
totalGst,
totalPst
totalPst,
userSelectedPaymentMethod,
allowedPaymentMethods,
userPaymentAccount,
allowAlternatePaymentMethod
} = storeToRefs(useConnectFeeStore())
const isPlaceholderActive = ref(false)
Expand Down Expand Up @@ -46,7 +50,7 @@ const getItemFee = (feeItem: ConnectFeeItem) => {
return '$ -'
}
if (feeItem.waived) {
return t('feeSummary.noFee')
return t('ConnectFeeWidget.feeSummary.noFee')
}
return `$${(feeItem.filingFees * (feeItem.quantity || 1)).toFixed(2)}`
}
Expand All @@ -62,8 +66,8 @@ const getItemFee = (feeItem: ConnectFeeItem) => {
:role="isFoldable ? 'button' : 'title'"
class="flex w-full bg-midnightBlue-900 py-2 pl-4 text-lg font-bold transition-all"
:class="[folded ? 'rounded' : 'rounded-b-none rounded-t', isFoldable ? '' : 'pointer-events-none']"
:aria-label="$t('feeSummary.title')"
:label="$t('feeSummary.title')"
:aria-label="$t('ConnectFeeWidget.feeSummary.title')"
:label="$t('ConnectFeeWidget.feeSummary.title')"
@click="toggleFolded"
>
<template #trailing>
Expand All @@ -76,72 +80,114 @@ const getItemFee = (feeItem: ConnectFeeItem) => {
</div>
</template>
</UButton>
<div
class="divide-y divide-bcGovGray-300 text-sm transition-all"
:class="folded ? 'h-[0px] overflow-hidden': 'px-4 pt-1'"
>
<div
v-for="feeItem in feeItems"
:key="feeItem.filingTypeCode"
class="flex justify-between py-3"
>
<div>
<p class="font-bold">
{{ $t(`feeSummary.itemLabels.${feeItem.filingTypeCode}`) }}
<ConnectTransitionCollapse>
<div v-if="!folded">
<div class="divide-y divide-bcGovGray-300 px-4 pt-1 text-sm">
<div
v-for="feeItem in feeItems"
:key="feeItem.filingTypeCode"
class="flex justify-between py-3"
>
<div>
<p class="font-bold">
{{ $t(`ConnectFeeWidget.feeSummary.itemLabels.${feeItem.filingTypeCode}`) }}
</p>
<p v-if="feeItem.quantity !== undefined && feeItem.quantityDesc" class="pl-4 text-gray-600">
x {{ feeItem.quantity }} {{ feeItem.quantityDesc }}
</p>
</div>
<p>{{ getItemFee(feeItem) }}</p>
</div>
<ConnectFeeExtraFee
v-if="feeOptions.showFutureEffectiveFees"
:description="$t('ConnectFeeWidget.feeSummary.futureEffectiveFees')"
:fee="totalFutureEffectiveFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showPriorityFees"
:description="$t('ConnectFeeWidget.feeSummary.priorityFees')"
:fee="totalPriorityFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showProcessingFees"
:description="$t('ConnectFeeWidget.feeSummary.processingFees')"
:fee="totalProcessingFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showServiceFees"
:description="$t('ConnectFeeWidget.feeSummary.serviceFees')"
:fee="isPlaceholderActive ? placeholderFeeItem.serviceFees : totalServiceFees"
show-fee-value
/>
<ConnectFeeExtraFee
v-if="feeOptions.showPst"
:description="$t('ConnectFeeWidget.feeSummary.pst')"
:fee="totalPst"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showGst"
:description="$t('ConnectFeeWidget.feeSummary.gst')"
:fee="totalGst"
:show-fee-value="isPlaceholderActive"
/>
</div>
<div class="flex flex-row items-end justify-between border-y border-gray-300 p-3">
<p class="mb-1 font-bold">
{{ $t("ConnectFeeWidget.feeSummary.total") }}
</p>
<p v-if="feeItem.quantity !== undefined && feeItem.quantityDesc" class="pl-4 text-gray-600">
x {{ feeItem.quantity }} {{ feeItem.quantityDesc }}
<p class="flex items-end text-sm text-bcGovGray-700">
<span class="mb-1">{{ $t("currency.cad") }}</span>
<b class="ml-[5px] flex items-end text-2xl text-black">
{{ !isPlaceholderActive ? `$${total.toFixed(2)}` : '$ -' }}
</b>
</p>
</div>
<p>{{ getItemFee(feeItem) }}</p>
</div>
<ConnectFeeExtraFee
v-if="feeOptions.showFutureEffectiveFees"
:description="$t('feeSummary.futureEffectiveFees')"
:fee="totalFutureEffectiveFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showPriorityFees"
:description="$t('feeSummary.priorityFees')"
:fee="totalPriorityFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showProcessingFees"
:description="$t('feeSummary.processingFees')"
:fee="totalProcessingFees"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showServiceFees"
:description="$t('feeSummary.serviceFees')"
:fee="isPlaceholderActive ? placeholderFeeItem.serviceFees : totalServiceFees"
show-fee-value
/>
<ConnectFeeExtraFee
v-if="feeOptions.showPst"
:description="$t('feeSummary.pst')"
:fee="totalPst"
:show-fee-value="isPlaceholderActive"
/>
<ConnectFeeExtraFee
v-if="feeOptions.showGst"
:description="$t('feeSummary.gst')"
:fee="totalGst"
:show-fee-value="isPlaceholderActive"
/>
<div class="flex flex-row items-end justify-between py-3">
<p class="mb-1 font-bold">
{{ $t("feeSummary.total") }}
</p>
<p class="flex items-end text-sm text-bcGovGray-700">
<span class="mb-1">{{ $t("currency.cad") }}</span>
<b class="ml-[5px] flex items-end text-2xl text-black">
{{ !isPlaceholderActive ? `$${total.toFixed(2)}` : '$ -' }}
</b>
</p>
<USelectMenu
v-if="allowAlternatePaymentMethod && allowedPaymentMethods.length > 1"
v-slot="{ open }"
v-model="userSelectedPaymentMethod"
:options="allowedPaymentMethods"
value-attribute="value"
:ui-menu="{
option: {
base: 'cursor-pointer',
size: 'text-xs'
},
base: '-mt-1',
rounded: 'rounded-b'
}"
:ui="{
size: { lg: 'h-min' },
color: {
gray: {
outline: 'bg-white ring-0 hover:bg-gray-200 hover:border-gray-600 focus:border-none focus:ring-0',
}
}
}"
>
<button
class="flex w-full items-center justify-between gap-4 py-2 pl-4 pr-2 text-left hover:bg-gray-100"
>
<span class="text-xs">
{{
$t(`ConnectFeeWidget.payingWith.${userSelectedPaymentMethod}`, {
account: userPaymentAccount?.cfsAccount?.bankAccountNumber }
)
}}
</span>

<UIcon
name="i-mdi-caret-down"
class="size-5 text-blue-500 transition-transform"
:class="[open && 'rotate-180']"
/>
</button>
</USelectMenu>
</div>
</div>
</ConnectTransitionCollapse>
</div>
</template>
1 change: 1 addition & 0 deletions strr-base-web/app/composables/useStrrBasePermit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const useStrrBasePermit = <R extends ApiRegistrationResp, A extends ApiAp
if (applications.length) {
// Set active strata to the most recent application (ordered by api: newest to oldest)
application.value = applications[0]
await updatePaymentDetails<A>(application.value?.header.applicationNumber as string)
if (application.value?.header.registrationId) {
// Get linked registration if applicable
registration.value = await getAccountRegistrations<R>(
Expand Down
6 changes: 6 additions & 0 deletions strr-base-web/app/enums/connect-payment-method.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum ConnectPaymentMethod {
DIRECT_PAY = 'DIRECT_PAY',
PAD = 'PAD',
BCOL = 'BCOL',
JV = 'JV'
}
23 changes: 23 additions & 0 deletions strr-base-web/app/interfaces/connect-pay-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ConnectPaymentMethod } from '~/enums/connect-payment-method'

export interface ConnectPayAccount {
accountId: string
accountName: string
billable: boolean
cfsAccount: {
bankAccountNumber: string
bankInstitutionNumber: string
bankTransitNumber: string
cfsAccountNumber: string
cfsPartyNumber: string
cfsSiteNumber: string
paymentMethod: ConnectPaymentMethod
status: string // enum ??
}
credit: number
id: number
padTosAcceptedBy: string
padTosAcceptedDate: string
paymentMethod: ConnectPaymentMethod
version: number
}
3 changes: 3 additions & 0 deletions strr-base-web/app/interfaces/strr-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export interface ApiBusinessDetails {
}

export interface ApiBaseRegistration {
header?: {
paymentMethod: ConnectPaymentMethod
}
registrationType: ApplicationType
businessDetails: ApiBusinessDetails
}
Expand Down
42 changes: 29 additions & 13 deletions strr-base-web/app/locales/en-CA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,19 +387,6 @@ export default {
BCEID: ''
}
},
feeSummary: {
title: 'Fee Summary',
total: 'Total Fees',
noFee: 'No Fee',
priorityFees: 'Priority Fees',
futureEffectiveFees: 'Future Effective Fees',
serviceFees: 'Service Fee',
itemLabels: {
PLACEHOLDER: 'Placeholder (Replace Me)', // each project using the connect fee widget should change the placeholder filingTypeCode
TEST: 'This is test entry',
undefined: 'Item Fee'
}
},
validation: {
required: 'Required',
address: {
Expand Down Expand Up @@ -521,5 +508,34 @@ export default {
content: 'An unknown error occured, please refresh the page or try again later.'
}
}
},
ConnectFeeWidget: {
feeSummary: {
title: 'Fee Summary',
total: 'Total Fees',
noFee: 'No Fee',
priorityFees: 'Priority Fees',
futureEffectiveFees: 'Future Effective Fees',
serviceFees: 'Service Fee',
itemLabels: {
PLACEHOLDER: 'Placeholder (Replace Me)', // each project using the connect fee widget should change the placeholder filingTypeCode
TEST: 'This is test entry',
undefined: 'Item Fee'
}
},
paymentMethod: {
DIRECT_PAY: 'Credit Card',
PAD: 'Pre-authorized Debit (PAD) {account}',
BCOL: 'Online Banking',
JV: 'Journal Voucher',
undefined: 'Default'
},
payingWith: {
DIRECT_PAY: 'Paying with Credit Card',
PAD: 'Paying with Pre-authorized Debit (PAD) {account}',
BCOL: 'Paying with Online Banking',
JV: 'Paying with Journal Voucher',
undefined: 'Paying with default method'
}
}
}
49 changes: 48 additions & 1 deletion strr-base-web/app/stores/connectFee.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { ConnectPaymentMethod } from '~/enums/connect-payment-method'

export const useConnectFeeStore = defineStore('connect/fee', () => {
const { $payApi } = useNuxtApp()
const { t } = useI18n()

const feeOptions = ref({
showFutureEffectiveFees: false,
Expand Down Expand Up @@ -112,6 +115,45 @@ export const useConnectFeeStore = defineStore('connect/fee', () => {
placeholderFeeItem.value.serviceFees = fees
}

// alternate payment option stuff
const userPaymentAccount = ref<ConnectPayAccount>({} as ConnectPayAccount)
const userSelectedPaymentMethod = ref<ConnectPaymentMethod>(ConnectPaymentMethod.DIRECT_PAY)
const allowAlternatePaymentMethod = ref<boolean>(false)
const allowedPaymentMethods = ref<{ label: string, value: ConnectPaymentMethod }[]>([])

const initAlternatePaymentMethod = async () => {
const accountId = useConnectAccountStore().currentAccount.id
try {
// get payment account
const res = await $payApi<ConnectPayAccount>(`/accounts/${accountId}`)
userPaymentAccount.value = res
userSelectedPaymentMethod.value = res.paymentMethod

// add options to allowedPaymentMethods
const defaultMethod = userPaymentAccount.value.paymentMethod
if (defaultMethod !== undefined) {
const accountNum = userPaymentAccount.value.cfsAccount?.bankAccountNumber ?? ''
allowedPaymentMethods.value.push({
label: t(`ConnectFeeWidget.paymentMethod.${defaultMethod}`, { account: accountNum }),
value: defaultMethod
})

// only add direct pay if not default option
if (defaultMethod !== ConnectPaymentMethod.DIRECT_PAY) {
allowedPaymentMethods.value.push({
label: t(`ConnectFeeWidget.paymentMethod.${ConnectPaymentMethod.DIRECT_PAY}`),
value: ConnectPaymentMethod.DIRECT_PAY
})
}
}

// only set allowed flag to true if previous steps didnt cause an error
allowAlternatePaymentMethod.value = true
} catch (e) {
logFetchError(e, 'Error initializing user payment account')
}
}

return {
feeOptions,
fees,
Expand All @@ -128,6 +170,11 @@ export const useConnectFeeStore = defineStore('connect/fee', () => {
removeFee,
setFeeQuantity,
setPlaceholderFilingTypeCode,
setPlaceholderServiceFee
setPlaceholderServiceFee,
initAlternatePaymentMethod,
userPaymentAccount,
userSelectedPaymentMethod,
allowedPaymentMethods,
allowAlternatePaymentMethod
}
})
Loading

0 comments on commit cb501da

Please sign in to comment.