Skip to content

Commit ea5d9f0

Browse files
17534 - New NSF Resource Implementation and NSF Invoice PDF Download (#2658)
* NSF Invoices and PDF * Version update * Step fix * Refactoring to use state * Updating * Version update and PR feedback
1 parent 78cdb1a commit ea5d9f0

File tree

8 files changed

+114
-85
lines changed

8 files changed

+114
-85
lines changed

auth-web/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auth-web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "auth-web",
3-
"version": "2.4.58",
3+
"version": "2.4.59",
44
"appName": "Auth Web",
55
"sbcName": "SBC Common Components",
66
"private": true,

auth-web/src/components/auth/account-freeze/AccountOverview.vue

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { AccessType } from '@/util/constants'
21
<template>
32
<div>
43
<p class="mb-10">
@@ -28,15 +27,15 @@ import { AccessType } from '@/util/constants'
2827
</div>
2928
</v-col>
3029
<v-col class="text-end">
31-
${{ nsfFee.toFixed(2) }}
30+
${{ nsfAmount.toFixed(2) }}
3231
</v-col>
3332
</v-row>
3433
<v-row>
3534
<v-col cols="9">
3635
Total Transactions
3736
</v-col>
3837
<v-col class="text-end">
39-
${{ totalTransactionAmount.toFixed(2) }}
38+
${{ totalAmount.toFixed(2) }}
4039
</v-col>
4140
</v-row>
4241
<v-divider class="my-2" />
@@ -45,7 +44,7 @@ import { AccessType } from '@/util/constants'
4544
Total Amount Due
4645
</v-col>
4746
<v-col class="text-end">
48-
${{ totalAmountToPay.toFixed(2) }}
47+
${{ totalAmountRemaining.toFixed(2) }}
4948
</v-col>
5049
</v-row>
5150
</v-card-text>
@@ -61,7 +60,7 @@ import { AccessType } from '@/util/constants'
6160
large
6261
text
6362
color="primary"
64-
@click="downloadTransactionPDF"
63+
@click="downloadNSFInvoicesPDF"
6564
>
6665
<v-icon class="ml-n2">
6766
mdi-download
@@ -85,56 +84,52 @@ import { AccessType } from '@/util/constants'
8584
</template>
8685

8786
<script lang="ts">
88-
import { Component, Mixins } from 'vue-property-decorator'
89-
import { mapActions, mapState } from 'pinia'
87+
import { computed, defineComponent, onMounted, reactive, toRefs } from '@vue/composition-api'
9088
import CommonUtils from '@/util/common-util'
9189
import { FailedInvoice } from '@/models/invoice'
92-
import { Organization } from '@/models/Organization'
93-
import Steppable from '@/components/auth/common/stepper/Steppable.vue'
9490
import { useOrgStore } from '@/stores/org'
9591
96-
@Component({
97-
computed: {
98-
...mapState(useOrgStore, [
99-
'currentOrganization'
100-
])
101-
},
102-
methods: {
103-
...mapActions(useOrgStore, [
104-
'calculateFailedInvoices'
105-
])
106-
}
107-
})
108-
export default class AccountOverview extends Mixins(Steppable) {
109-
private readonly currentOrganization!: Organization
110-
private readonly calculateFailedInvoices!: () => FailedInvoice
111-
private formatDate = CommonUtils.formatDisplayDate
112-
private nsfFee: number = 0
113-
private nsfCount: number = 0
114-
private totalTransactionAmount: number = 0
115-
private totalAmountToPay: number = 0
116-
private totalPaidAmount: number = 0
92+
export default defineComponent({
93+
name: 'AccountOverviewView',
94+
emits: ['step-forward'],
95+
setup (_, { emit }) {
96+
const orgStore = useOrgStore()
97+
const currentOrganization = computed(() => orgStore.currentOrganization)
98+
const currentMembership = computed(() => orgStore.currentMembership)
99+
const calculateFailedInvoices: any = orgStore.calculateFailedInvoices
100+
const downloadNSFInvoicesPDF: any = orgStore.downloadNSFInvoicesPDF
101+
const formatDate = CommonUtils.formatDisplayDate
102+
const suspendedDate = (currentOrganization.value?.suspendedOn) ? formatDate(new Date(currentOrganization.value.suspendedOn)) : ''
117103
118-
private goNext () {
119-
this.stepForward()
120-
}
104+
const state = reactive({
105+
nsfAmount: 0,
106+
totalAmount: 0,
107+
totalAmountRemaining: 0,
108+
totalPaidAmount: 0
109+
})
121110
122-
private get suspendedDate () {
123-
return (this.currentOrganization?.suspendedOn) ? this.formatDate(new Date(this.currentOrganization.suspendedOn)) : ''
124-
}
111+
const goNext = () => {
112+
emit('step-forward')
113+
}
125114
126-
private downloadTransactionPDF () {
127-
// download PDF
128-
}
115+
onMounted(async () => {
116+
const failedInvoices: FailedInvoice = await calculateFailedInvoices()
117+
state.totalAmount = failedInvoices?.totalTransactionAmount || 0
118+
state.nsfAmount = failedInvoices?.nsfFee || 0
119+
state.totalAmountRemaining = failedInvoices?.totalAmountToPay || 0
120+
})
129121
130-
async mounted () {
131-
const failedInvoices: FailedInvoice = await this.calculateFailedInvoices()
132-
this.nsfCount = failedInvoices?.nsfCount || 0
133-
this.totalTransactionAmount = failedInvoices?.totalTransactionAmount || 0
134-
this.nsfFee = failedInvoices?.nsfFee || 0
135-
this.totalAmountToPay = failedInvoices?.totalAmountToPay || 0
122+
return {
123+
...toRefs(state),
124+
currentOrganization,
125+
currentMembership,
126+
suspendedDate,
127+
downloadNSFInvoicesPDF,
128+
goNext
129+
}
136130
}
137-
}
131+
})
132+
138133
</script>
139134

140135
<style lang="scss" scoped>

auth-web/src/components/auth/common/stepper/Stepper.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
v-bind="getPropsForStep(step)"
6363
keep-alive
6464
@final-step-action="emitFinalStepAction"
65+
@step-forward="emitStepForward"
6566
/>
6667
</template>
6768
</div>
@@ -170,6 +171,10 @@ export default class Stepper extends Vue {
170171
emitFinalStepAction (stepperData) {
171172
return stepperData
172173
}
174+
175+
@Emit('step-forward')
176+
emitStepForward () : void {
177+
}
173178
}
174179
</script>
175180

auth-web/src/models/invoice.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,13 @@ export interface FailedInvoice {
4343
nsfFee?:number
4444
totalTransactionAmount?: number
4545
totalAmountToPay?: number
46+
invoices?: InvoiceList[]
47+
}
48+
49+
export interface NonSufficientFundsInvoiceListResponse {
50+
invoices: InvoiceList[]
51+
total: number
52+
totalAmount: number
53+
totalAmountRemaining: number
54+
nsfAmount: number
4655
}

auth-web/src/services/payment.services.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,15 @@ export default class PaymentService {
192192
static removeAccountFees (accountId: string | number): AxiosPromise<any> {
193193
return axios.delete(`${ConfigHelper.getPayAPIURL()}/accounts/${accountId}/fees`)
194194
}
195+
196+
static getNSFInvoices (accountId: string | number): AxiosPromise<any> {
197+
return axios.get(`${ConfigHelper.getPayAPIURL()}/accounts/${accountId}/nsf`)
198+
}
199+
200+
static downloadNSFInvoicesPDF (accountId: string | number): AxiosPromise<any> {
201+
const url = `${ConfigHelper.getPayAPIURL()}/accounts/${accountId}/nsf/statement`
202+
const headers = { 'Accept': 'application/pdf' }
203+
const body = {}
204+
return axios.post(url, body, { headers, responseType: 'blob' as 'json' })
205+
}
195206
}

auth-web/src/stores/org.ts

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
} from '@/models/Organization'
3737
import { BcolAccountDetails, BcolProfile } from '@/models/bcol'
3838
import { CreateRequestBody as CreateInvitationRequestBody, Invitation } from '@/models/Invitation'
39+
import { FailedInvoice, NonSufficientFundsInvoiceListResponse } from '@/models/invoice'
3940
import { Products, ProductsRequestBody } from '@/models/Staff'
4041
import { StatementFilterParams, StatementNotificationSettings, StatementSettings, StatementsSummary } from '@/models/statement'
4142
import { computed, reactive, toRefs } from '@vue/composition-api'
@@ -47,7 +48,7 @@ import CommonUtils from '@/util/common-util'
4748
import ConfigHelper from '@/util/config-helper'
4849
import { EmptyResponse } from '@/models/global'
4950
import InvitationService from '@/services/invitation.services'
50-
import { InvoiceList } from '@/models/invoice'
51+
5152
import KeyCloakService from 'sbc-common-components/src/services/keycloak.services'
5253
import OrgService from '@/services/org.services'
5354
import PaymentService from '@/services/payment.services'
@@ -741,39 +742,39 @@ export const useOrgStore = defineStore('org', () => {
741742
return response?.data
742743
}
743744

744-
async function getFailedInvoices (): Promise<InvoiceList[]> {
745-
const response = await PaymentService.getFailedInvoices(state.currentOrganization.id)
746-
// if there is any failed payment which is partially paid, return only that payment.
747-
let items = response?.data?.items || []
748-
items.forEach(payment => {
749-
if (payment.paidAmount > 0) {
750-
items = [payment]
751-
}
752-
})
753-
return items
754-
}
755-
756-
// to calculate failed invoices. need to move appropriate place since its returning data than commiting to store (which is not standard)
757-
async function calculateFailedInvoices () {
758-
let totalPaidAmount = 0
759-
let totalAmountToPay = 0
760-
let nsfCount = 0
761-
let nsfFee = 0
762-
let totalTransactionAmount = 0
763-
const failedInvoices: InvoiceList[] = await getFailedInvoices()
764-
failedInvoices?.forEach((failedInvoice) => {
765-
totalPaidAmount += failedInvoice?.paidAmount
766-
totalAmountToPay += failedInvoice?.invoices?.map(el => el.total).reduce((accumulator, invoiceTotal) => accumulator + invoiceTotal)
767-
failedInvoice?.invoices?.forEach((invoice) => {
768-
const nsfItems = invoice?.lineItems?.filter(lineItem => (lineItem.description === 'NSF'))
769-
.map(el => el.total)
770-
nsfCount += nsfItems.length
771-
nsfFee += (nsfItems.length) ? nsfItems?.reduce((accumulator, currentValue) => accumulator + currentValue) : 0
772-
})
773-
})
774-
totalTransactionAmount = totalAmountToPay - nsfFee
775-
totalAmountToPay = totalAmountToPay - totalPaidAmount
776-
return { totalTransactionAmount, totalAmountToPay, nsfFee, nsfCount }
745+
async function getNSFInvoices (): Promise<NonSufficientFundsInvoiceListResponse> {
746+
try {
747+
const response = await PaymentService.getNSFInvoices(state.currentOrganization.id)
748+
return response?.data || {}
749+
} catch (error) {
750+
// eslint-disable-next-line no-console
751+
console.error('get NSF invoices operation failed! - ', error)
752+
}
753+
}
754+
755+
async function downloadNSFInvoicesPDF (): Promise<any> {
756+
try {
757+
const response = await PaymentService.downloadNSFInvoicesPDF(state.currentOrganization.id)
758+
CommonUtils.fileDownload(response?.data, `non-sufficient_funds_invoice.pdf`, response?.headers['content-type'])
759+
} catch (error) {
760+
// eslint-disable-next-line no-console
761+
console.error('download NSF invoices PDF operation failed! - ', error)
762+
}
763+
}
764+
765+
async function calculateFailedInvoices (): Promise<FailedInvoice> {
766+
const nsfInvoices = await getNSFInvoices()
767+
const invoices = nsfInvoices?.invoices || []
768+
const totalAmount = nsfInvoices?.totalAmount || 0
769+
const totalAmountRemaining = nsfInvoices?.totalAmountRemaining || 0
770+
const nsfAmount = nsfInvoices?.nsfAmount || 0
771+
772+
return {
773+
invoices: invoices,
774+
nsfFee: nsfAmount,
775+
totalAmountToPay: totalAmountRemaining,
776+
totalTransactionAmount: totalAmount
777+
}
777778
}
778779

779780
async function resetAccountSetupProgress (): Promise<void> {
@@ -1093,7 +1094,6 @@ export const useOrgStore = defineStore('org', () => {
10931094
getStatementRecipients,
10941095
updateStatementNotifications,
10951096
getOrgPayments,
1096-
getFailedInvoices,
10971097
calculateFailedInvoices,
10981098
resetAccountSetupProgress,
10991099
resetAccountWhileSwitchingPremium,
@@ -1123,6 +1123,8 @@ export const useOrgStore = defineStore('org', () => {
11231123
updateOrganizationAccessType,
11241124
$reset,
11251125
isStaffOrSbcStaff,
1126-
removeOrgAccountFees
1126+
removeOrgAccountFees,
1127+
getNSFInvoices,
1128+
downloadNSFInvoicesPDF
11271129
}
11281130
})

auth-web/src/views/auth/account-freeze/AccountFreezeUnlockView.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
</div>
2525
<v-card flat>
2626
<Stepper
27+
ref="stepper"
2728
:stepper-configuration="stepperConfig"
2829
:isLoading="isLoading"
2930
:stepperColor="'error'"
3031
@final-step-action="unlockAccount"
32+
@step-forward="handleStepForward"
3133
/>
3234
</v-card>
3335

@@ -119,6 +121,7 @@ export default class AccountFreezeUnlockView extends Vue {
119121
120122
$refs: {
121123
errorDialog: InstanceType<typeof ModalDialog>
124+
stepper: InstanceType<typeof Stepper>
122125
}
123126
124127
private stepperConfig: Array<StepConfiguration> =
@@ -157,5 +160,9 @@ export default class AccountFreezeUnlockView extends Vue {
157160
private closeError () {
158161
this.$refs.errorDialog.close()
159162
}
163+
164+
private handleStepForward () {
165+
this.$refs.stepper.stepForward()
166+
}
160167
}
161168
</script>

0 commit comments

Comments
 (0)