Skip to content

Commit

Permalink
Merge pull request #389 from bcgov/ofmcc-6327-funding-reallocation-view
Browse files Browse the repository at this point in the history
OFMCC-6327 - Funding Reallocation View
  • Loading branch information
vietle-cgi authored Oct 21, 2024
2 parents 3933ec7 + 106ccef commit 09d4138
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 16 deletions.
4 changes: 4 additions & 0 deletions backend/src/components/fundingAgreements.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ async function getFundingAgreements(req, res) {
try {
const fundingAgreements = []
let operation = 'ofm_fundings?$select=ofm_fundingid,ofm_funding_number,ofm_declaration,ofm_start_date,ofm_end_date,_ofm_application_value,_ofm_facility_value,statuscode,statecode'
if (req.query?.includeFundingEnvelopes) {
operation +=
',ofm_envelope_hr_total,ofm_envelope_hr_wages_paidtimeoff,ofm_envelope_hr_benefits,ofm_envelope_hr_employerhealthtax,ofm_envelope_hr_prodevhours,ofm_envelope_hr_prodevexpenses,ofm_envelope_programming,ofm_envelope_administrative,ofm_envelope_operational,ofm_envelope_facility'
}
if (req.query?.includeEA) {
operation += '&$expand=ofm_application($select=_ofm_expense_authority_value;$expand=ofm_expense_authority($select=ofm_first_name,ofm_last_name))'
}
Expand Down
12 changes: 12 additions & 0 deletions backend/src/util/mapping/Mappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,18 @@ const FundingAgreementMappings = [
{ back: 'statecode', front: 'stateCode' },
{ back: 'ofm_declaration', front: 'agreeConsentCertify' },
{ back: '[email protected]', front: 'facilityName' },

// Annual Base Funding
{ back: 'ofm_envelope_hr_total', front: 'envelopeHRTotal' },
{ back: 'ofm_envelope_hr_wages_paidtimeoff', front: 'envelopeHRWagePaidTimeOff' },
{ back: 'ofm_envelope_hr_benefits', front: 'envelopeHRBenefits' },
{ back: 'ofm_envelope_hr_employerhealthtax', front: 'envelopeHREmployerHealthTax' },
{ back: 'ofm_envelope_hr_prodevhours', front: 'envelopeHRProDevHours' },
{ back: 'ofm_envelope_hr_prodevexpenses', front: 'envelopeHRProDevExpenses' },
{ back: 'ofm_envelope_programming', front: 'envelopeProgramming' },
{ back: 'ofm_envelope_administrative', front: 'envelopeAdministrative' },
{ back: 'ofm_envelope_operational', front: 'envelopeOperational' },
{ back: 'ofm_envelope_facility', front: 'envelopeFacility' },
]

const PaymentMappings = [
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TheEnvBar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<v-app-bar class="env-bar" v-if="bannerColor" :color="bannerColor" height="20">
<v-app-bar v-if="bannerColor" class="env-bar" :color="bannerColor" height="20">
<div>
<h3 class="env-text">{{ bannerEnvironment }} Environment</h3>
</div>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/TheSnackBar.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<div @mouseover="pause = true" @mouseleave="pause = false">
<v-snackbar v-model="showSnackBar" :timeout="timeout" elevation="24" location="top" centered :color="colour" transition="slide-y-transition" class="snackbar">
Expand Down
108 changes: 108 additions & 0 deletions frontend/src/components/funding/BaseFundingCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<v-card elevation="2" class="ma-2">
<v-card-title class="card-title"><strong>Base Funding Paid</strong></v-card-title>
<v-skeleton-loader :loading="loading" type="table-tbody" class="pa-6">
<v-container fluid class="pa-0">
<div>The base funding shown is only from the current fiscal year and does not include changes from funding re-allocation requests.</div>
<v-row no-gutters class="my-4">
<v-col cols="12" lg="6">
<v-card class="pa-4 mb-2 mb-sm-0 mr-lg-4">
<div>
<h5 class="mb-4">Instructional Human Resources</h5>
<h3>$ {{ format.formatDecimalNumber(fundingDetails?.envelopeHRTotal) }}</h3>
<v-row no-gutters class="my-1">
<v-col cols="12" sm="8">> Wages and paid time off</v-col>
<v-col cols="12" sm="4">
<strong>${{ format.formatDecimalNumber(fundingDetails?.envelopeHRWagePaidTimeOff) }}</strong>
</v-col>
</v-row>
<v-row no-gutters class="my-1">
<v-col cols="12" sm="8">> Benefits</v-col>
<v-col cols="12" sm="4">
<strong>${{ format.formatDecimalNumber(fundingDetails?.envelopeHRBenefits) }}</strong>
</v-col>
</v-row>
<v-row no-gutters class="my-1">
<v-col cols="12" sm="8">> Employer Health Tax</v-col>
<v-col cols="12" sm="4">
<strong>${{ format.formatDecimalNumber(fundingDetails?.envelopeHREmployerHealthTax) }}</strong>
</v-col>
</v-row>
<v-row no-gutters class="my-1">
<v-col cols="12" sm="8">> Professional Development Hours</v-col>
<v-col cols="12" sm="4">
<strong>${{ format.formatDecimalNumber(fundingDetails?.envelopeHRProDevHours) }}</strong>
</v-col>
</v-row>
<v-row no-gutters class="my-1">
<v-col cols="12" sm="8">> Professional Development Expenses</v-col>
<v-col cols="12" sm="4">
<strong>${{ format.formatDecimalNumber(fundingDetails?.envelopeHRProDevExpenses) }}</strong>
</v-col>
</v-row>
</div>
</v-card>
</v-col>

<v-col cols="12" lg="6" class="mb-sm-4 mb-lg-0">
<v-row no-gutters>
<v-col cols="12" sm="6">
<v-card class="pa-4 mt-2 mt-sm-4 mt-lg-0 mr-sm-2 ml-lg-2">
<h5 class="mb-4">Programming</h5>
<h3>$ {{ format.formatDecimalNumber(fundingDetails?.envelopeProgramming) }}</h3>
</v-card>
</v-col>
<v-col cols="12" sm="6">
<v-card class="pa-4 mt-4 mt-lg-0 ml-sm-2 ml-lg-4">
<h5 class="mb-4">Administrative</h5>
<h3>$ {{ format.formatDecimalNumber(fundingDetails?.envelopeAdministrative) }}</h3>
</v-card>
</v-col>
<v-col cols="12" sm="6">
<v-card class="pa-4 mt-4 mt-lg-6 ml-lg-2 mr-sm-2">
<h5 class="mb-4">Facility</h5>
<h3>$ {{ format.formatDecimalNumber(fundingDetails?.envelopeFacility) }}</h3>
</v-card>
</v-col>
<v-col cols="12" sm="6">
<v-card class="pa-4 mt-4 mt-lg-6 ml-sm-2 ml-lg-4">
<h5 class="mb-4">Operational</h5>
<h3>$ {{ format.formatDecimalNumber(fundingDetails?.envelopeOperational) }}</h3>
</v-card>
</v-col>
</v-row>
</v-col>
</v-row>
</v-container>
</v-skeleton-loader>
</v-card>
</template>

<script>
import format from '@/utils/format'
export default {
name: 'BaseFundingCard',
props: {
loading: {
type: Boolean,
default: true,
},
fundingDetails: {
type: Object,
required: true,
default: () => {
return {}
},
},
},
created() {
this.format = format
},
}
</script>
<style scoped>
.card-title {
background-color: lightgray;
}
</style>
93 changes: 93 additions & 0 deletions frontend/src/components/funding/FundingAllocationInfoTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<template>
<v-container fluid class="pa-0">
<div class="funding-info-table">
<template v-if="$vuetify.display.mdAndUp">
<v-row no-gutters>
<v-col cols="2" class="funding-info-table-header"><strong>Funding Envelopes</strong></v-col>
<v-col cols="2" class="funding-envelope-types"><strong>Facility</strong></v-col>
<v-col cols="2" class="funding-envelope-types"><strong>Operational</strong></v-col>
<v-col cols="2" class="funding-envelope-types"><strong>Administration</strong></v-col>
<v-col cols="2" class="funding-envelope-types"><strong>Programming</strong></v-col>
<v-col cols="2" class="funding-envelope-types"><strong>Human Resources</strong></v-col>
</v-row>
<v-row no-gutters>
<v-col cols="2" class="funding-info-table-header"><strong>Receive Funds</strong></v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Need Ministry Approval</v-col>
</v-row>
<v-row no-gutters>
<v-col cols="2" class="funding-info-table-header"><strong>Sending Funds</strong></v-col>
<v-col cols="2" class="funding-info-table-cell">Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="2" class="funding-info-table-cell">Need Ministry Approval</v-col>
</v-row>
</template>
<template v-else>
<v-row no-gutters>
<v-col cols="4" class="funding-info-table-header"><strong>Funding Envelopes</strong></v-col>
<v-col cols="4" class="funding-info-table-header"><strong>Receive Funds</strong></v-col>
<v-col cols="4" class="funding-info-table-header"><strong>Sending Funds</strong></v-col>
</v-row>
<v-row no-gutters>
<v-col cols="4" class="funding-envelope-types"><strong>Facility</strong></v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="4" class="funding-info-table-cell">Need Ministry Approval</v-col>
</v-row>
<v-row no-gutters>
<v-col cols="4" class="funding-envelope-types"><strong>Operational</strong></v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
</v-row>
<v-row no-gutters>
<v-col cols="4" class="funding-envelope-types"><strong>Administration</strong></v-col>
<v-col cols="4" class="funding-info-table-cell">Need Ministry Approval</v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
</v-row>
<v-row no-gutters>
<v-col cols="4" class="funding-envelope-types"><strong>Programming</strong></v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
<v-col cols="4" class="funding-info-table-cell">Does Not Need Ministry Approval</v-col>
</v-row>
<v-row no-gutters>
<v-col cols="4" class="funding-envelope-types"><strong>Human Resources</strong></v-col>
<v-col cols="4" class="funding-info-table-cell">Need Ministry Approval</v-col>
<v-col cols="4" class="funding-info-table-cell">Need Ministry Approval</v-col>
</v-row>
</template>
</div>
</v-container>
</template>

<script>
export default {
name: 'FundingAllocationInfoTable',
}
</script>

<style scoped>
.funding-info-table {
border: 1px solid;
}
.funding-info-table-header {
border: 1px solid;
padding: 10px !important;
background-color: lightgray;
}
.funding-envelope-types {
border: 1px solid;
padding: 10px !important;
background-color: #f0f0f0;
}
.funding-info-table-cell {
border: 1px solid;
padding: 10px !important;
}
</style>
30 changes: 22 additions & 8 deletions frontend/src/components/funding/FundingAllocationTab.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<template>
<v-container fluid class="pa-0">
<div class="my-2">View or submit a change for your centre's current monthly funding allocations. Funds can be re-allocated based on the rules below.</div>
<v-row v-if="hasPermission(PERMISSIONS.SUBMIT_CHANGE_REQUEST)" no-gutters class="my-4 pr-2 justify-end">
<div class="ma-2">View or submit a change for your centre's current monthly funding allocations. Funds can be re-allocated based on the rules below.</div>
<v-row v-if="hasPermission(PERMISSIONS.SUBMIT_CHANGE_REQUEST)" no-gutters class="ma-2 justify-end">
<AppButton :loading="loading" @click="toggleAssistanceRequestDialog()">Request to Re-allocate Funds</AppButton>
</v-row>
<h2 class="mb-2">Funding Re-Allocation Rules</h2>
<AppAlertBanner type="info">Note: Total funds re-allocated cannot be more than the base funding for each envelope.</AppAlertBanner>
<FundingSearchCard :loading="loading" :select-single-facility="true" :show-date-filter="false" class="my-6" @search="loadFundingDetails" />
<h2 class="ma-2">Funding Re-Allocation Rules</h2>
<AppAlertBanner type="info" class="ma-2 mb-4">Note: Total funds re-allocated cannot be more than the base funding for each envelope.</AppAlertBanner>
<FundingAllocationInfoTable class="pa-2" />
<FundingSearchCard :loading="loading" :select-single-facility="true" :show-date-filter="false" :show-reset-button="false" class="my-10" @search="loadFundingDetails" />
<BaseFundingCard :loading="loading" :funding-details="fundingDetails" />
<NewRequestDialog
class="pa-0"
:show="showAssistanceRequestDialog"
Expand All @@ -19,24 +21,28 @@
<script>
import { mapState } from 'pinia'
import BaseFundingCard from '@/components/funding/BaseFundingCard.vue'
import FundingAllocationInfoTable from '@/components/funding/FundingAllocationInfoTable.vue'
import FundingSearchCard from '@/components/funding/FundingSearchCard.vue'
import NewRequestDialog from '@/components/messages/NewRequestDialog.vue'
import AppAlertBanner from '@/components/ui/AppAlertBanner.vue'
import AppButton from '@/components/ui/AppButton.vue'
import FundingAgreementService from '@/services/fundingAgreementService'
import { useAppStore } from '@/stores/app'
import alertMixin from '@/mixins/alertMixin.js'
import permissionsMixin from '@/mixins/permissionsMixin'
import { REQUEST_CATEGORY_NAMES } from '@/utils/constants'
import { FUNDING_AGREEMENT_STATUS_CODES, REQUEST_CATEGORY_NAMES } from '@/utils/constants'
export default {
name: 'FundingAllocationTab',
components: { AppAlertBanner, AppButton, FundingSearchCard, NewRequestDialog },
components: { AppAlertBanner, AppButton, BaseFundingCard, FundingAllocationInfoTable, FundingSearchCard, NewRequestDialog },
mixins: [alertMixin, permissionsMixin],
data() {
return {
loading: false,
showAssistanceRequestDialog: false,
selectedFacility: null,
fundingDetails: {},
}
},
Expand All @@ -49,8 +55,16 @@ export default {
},
methods: {
loadFundingDetails(searchQueries) {
async loadFundingDetails(searchQueries) {
this.selectedFacility = searchQueries?.facilities
try {
this.loading = true
this.fundingDetails = await FundingAgreementService.getFundingEnvelopesByFacilityIdAndStatus(this.selectedFacility?.facilityId, FUNDING_AGREEMENT_STATUS_CODES.ACTIVE)
} catch (error) {
this.setFailureAlert('Failed to load funding details', error)
} finally {
this.loading = false
}
},
toggleAssistanceRequestDialog() {
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/components/funding/FundingSearchCard.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<v-form ref="form" v-model="isFormComplete" class="ma-2">
<v-card class="pa-6">
<v-card elevation="2" class="pa-6">
<v-row no-gutters>
<v-col cols="12" lg="6" class="mb-6 mb-lg-0">
<v-row>
Expand Down Expand Up @@ -110,7 +110,7 @@
</v-row>
</v-card>
<v-row no-gutters class="mt-2" justify="end">
<AppButton id="reset" :primary="false" size="large" width="100px" :loading="loading" class="mr-8" @click="resetFilter">Reset</AppButton>
<AppButton v-if="showResetButton" id="reset" :primary="false" size="large" width="100px" :loading="loading" class="mr-8" @click="resetFilter">Reset</AppButton>
<AppButton id="search" size="large" width="150px" :loading="loading" @click="search">Search</AppButton>
</v-row>
</v-form>
Expand Down Expand Up @@ -153,6 +153,10 @@ export default {
type: Boolean,
default: false,
},
showResetButton: {
type: Boolean,
default: true,
},
},
emits: ['search'],
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/services/fundingAgreementService.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,17 @@ export default {
throw error
}
},

async getFundingEnvelopesByFacilityIdAndStatus(facilityId, statusCode) {
try {
if (!facilityId && !statusCode) return
const response = await ApiService.apiAxios.get(
`${ApiRoutes.FUNDING_AGREEMENTS}?facilityId=${facilityId}&stateCode=${CRM_STATE_CODES.ACTIVE}&statusCode=${statusCode}&includeFundingEnvelopes=true`,
)
return response?.data[0]
} catch (error) {
console.log(`Failed to get funding envelopes of the last funding agreement by facility id and status - ${error}`)
throw error
}
},
}
2 changes: 1 addition & 1 deletion frontend/src/views/MessagingView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<OrganizationHeader />
<v-container fluid v-bind="$attrs">
<v-card>
<v-tabs v-model="tab" bg-color="#ffffff" density="compact" color="#003366">
<v-tabs v-model="tab" bg-color="#ffffff" density="compact" color="#003366" show-arrows>
<v-tab value="notifications">
<strong>
Notifications
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/views/funding/FundingOverviewView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<v-container fluid v-bind="$attrs">
<h1 class="mb-2">Funding</h1>
<v-card>
<v-tabs v-model="tab" bg-color="#ffffff" density="compact" color="#003366">
<v-tabs v-model="tab" bg-color="#ffffff" density="compact" color="#003366" show-arrows>
<v-tab v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AGREEMENT)" value="agreements">
<v-icon size="large">mdi-file-document-outline</v-icon>
<strong>Funding Agreements</strong>
Expand All @@ -12,7 +12,8 @@
<v-icon size="large">mdi-history</v-icon>
<strong>Payment Records</strong>
</v-tab>
<v-tab v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AMOUNTS)" value="funding-allocation">
<!-- TODO (vietle-cgi) - update permission once we receive confirmation for this requirement -->
<v-tab v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AGREEMENT)" value="funding-allocation">
<v-icon size="large">mdi-call-split</v-icon>
<strong>Funding Allocation</strong>
</v-tab>
Expand All @@ -25,7 +26,8 @@
<v-window-item v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AMOUNTS)" value="payment-records">
<PaymentRecordsTab />
</v-window-item>
<v-window-item v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AMOUNTS)" value="funding-allocation">
<!-- TODO (vietle-cgi) - update permission once we receive confirmation for this requirement -->
<v-window-item v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AGREEMENT)" value="funding-allocation">
<FundingAllocationTab />
</v-window-item>
</v-window>
Expand Down
Loading

0 comments on commit 09d4138

Please sign in to comment.