Skip to content

Commit

Permalink
Status linked eligibility criteria (#102)
Browse files Browse the repository at this point in the history
* Display enrollment criteria on valid beneficiary status tab selection

Update panel title accordingly

* Fix the bug where custom filters not loading for advanced filters

Which also affects default enrollment criteria

* Allow edit and persistence of status linked eligibility criteria

Also build in migration of old array storage format without status

* Fix disappearing advanced search filter dropdown bug for group plans

* Minor refactoring to improve consistency

Also address linter complaints
  • Loading branch information
weilu authored Jul 30, 2024
1 parent 16d8ac0 commit b92db6f
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 32 deletions.
9 changes: 5 additions & 4 deletions src/components/BenefitPlanBeneficiariesSearcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import {
DEFAULT_PAGE_SIZE,
RIGHT_BENEFICIARY_SEARCH,
ROWS_PER_PAGE_OPTIONS,
MODULE_NAME,
BENEFIT_PLAN_LABEL,
RIGHT_BENEFICIARY_UPDATE,
} from '../constants';
import BenefitPlanBeneficiariesFilter from './BenefitPlanBeneficiariesFilter';
Expand Down Expand Up @@ -201,6 +199,8 @@ function BenefitPlanBeneficiariesSearcher({
/>
);

const additionalParams = benefitPlan ? { benefitPlan: `${benefitPlan.id}` } : null;

useEffect(() => {
// refresh when appliedCustomFilters is changed
}, [appliedCustomFilters]);
Expand Down Expand Up @@ -247,8 +247,9 @@ function BenefitPlanBeneficiariesSearcher({
cacheTabName={`${benefitPlan?.id}-${status}`}
isCustomFiltering
objectForCustomFiltering={benefitPlan}
moduleName={MODULE_NAME}
objectType={BENEFIT_PLAN_LABEL}
moduleName="individual"
objectType="Individual"
additionalCustomFilterParams={additionalParams}
appliedCustomFilters={appliedCustomFilters}
setAppliedCustomFilters={setAppliedCustomFilters}
appliedFiltersRowStructure={appliedFiltersRowStructure}
Expand Down
64 changes: 45 additions & 19 deletions src/components/BenefitPlanEligibilityCriteriaPanel.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
decodeId, fetchCustomFilter, PublishedComponent, useModulesManager, useTranslations,
Expand All @@ -8,7 +8,11 @@ import AddCircle from '@material-ui/icons/Add';
import {
Button, Divider, Grid, Paper, Typography,
} from '@material-ui/core';
import { CLEARED_STATE_FILTER } from '../constants';
import {
CLEARED_STATE_FILTER,
BENEFICIARY_STATUS,
DEFAULT_BENEFICIARY_STATUS,
} from '../constants';
import { isBase64Encoded } from '../util/advanced-criteria-utils';

const useStyles = makeStyles((theme) => ({
Expand All @@ -23,6 +27,7 @@ function BenefitPlanEligibilityCriteriaPanel({
edited,
benefitPlan,
onEditedChanged,
activeTab,
}) {
const classes = useStyles();
const dispatch = useDispatch();
Expand All @@ -31,19 +36,28 @@ function BenefitPlanEligibilityCriteriaPanel({
const moduleFilterName = 'individual';
const objectFilterType = 'Individual';
const modulesManager = useModulesManager();
const { formatMessage } = useTranslations('socialProtection', modulesManager);
const { formatMessage, formatMessageWithValues } = useTranslations('socialProtection', modulesManager);
const customFilters = useSelector((state) => state.core.customFilters);
const [filters, setFilters] = useState([]);

const getAdvancedCriteria = () => {
const { jsonExt } = benefitPlan ?? {};
try {
const jsonData = JSON.parse(jsonExt);
return jsonData?.advanced_criteria || [];
} catch (error) {
return [];
const status = Object.values(BENEFICIARY_STATUS).find((value) => (
activeTab.toUpperCase().includes(value)
));
const show = status !== undefined;

const getAdvancedCriteria = useCallback((status) => {
const jsonExt = benefitPlan?.jsonExt || '{}';
const jsonData = JSON.parse(jsonExt);

// Note: advanced_criteria is migrated from [filters] to {status: filters}
// For backward compatibility POTENTIAL status take on the old filters
let criteria = jsonData?.advanced_criteria || {};
if (Array.isArray(criteria)) {
criteria = { [DEFAULT_BENEFICIARY_STATUS]: criteria };
}
};

return criteria[status] || [];
}, [benefitPlan?.jsonExt]);

const handleRemoveFilter = () => {
setFilters([]);
Expand Down Expand Up @@ -74,8 +88,8 @@ function BenefitPlanEligibilityCriteriaPanel({

useEffect(() => {
if (editedBenefitPlan?.id) {
const criteria = getAdvancedCriteria();
if (criteria?.length && !arraysAreEqual(criteria, filters)) {
const criteria = getAdvancedCriteria(status);
if (!arraysAreEqual(criteria, filters)) {
setFilters(criteria);
}
const paramsToFetchFilters = createParams(
Expand All @@ -86,32 +100,43 @@ function BenefitPlanEligibilityCriteriaPanel({
);
fetchFilters(paramsToFetchFilters);
}
}, [editedBenefitPlan?.id]);
}, [editedBenefitPlan?.id, status]);

useEffect(() => {
if (editedBenefitPlan?.id) {
const { jsonExt } = editedBenefitPlan;
const jsonData = JSON.parse(jsonExt);
const json = { ...jsonData, advanced_criteria: filters };
let advancedCriteria = jsonData?.advanced_criteria || {};
// migrate old advanced_criteria
if (Array.isArray(advancedCriteria)) {
advancedCriteria = { [DEFAULT_BENEFICIARY_STATUS]: jsonData?.advanced_criteria };
}
const editedAdvancedCriteria = { ...advancedCriteria, [status]: filters };
const json = { ...jsonData, advanced_criteria: editedAdvancedCriteria };

if (!filters.length) {
delete json.advanced_criteria;
delete json.advanced_criteria[status];
} else if (!!filters.length && !filters[0].field) {
delete json.advanced_criteria;
delete json.advanced_criteria[status];
}

const appendedJsonExt = Object.keys(json).length === 0 ? benefitPlan.jsonExt : JSON.stringify(json);

onEditedChanged({ ...editedBenefitPlan, jsonExt: appendedJsonExt });
}
}, [filters]);
}, [filters, status]);

const beneficiaryStatus = formatMessage(`benefitPlan.${activeTab.replace('Tab', '')}.label`);

return (
show && (
<Paper className={classes.paper}>
<Grid container alignItems="center" direction="row" className={classes.paperHeader}>
<Grid item xs={12}>
<Typography variant="h6" className={classes.tableTitle}>
{formatMessage('benefitPlan.BenefitPlanEligibilityCriteriaPanel.title')}
{formatMessageWithValues('benefitPlan.BenefitPlanEligibilityCriteriaPanel.title', {
beneficiaryStatus,
})}
</Typography>
</Grid>
<Grid item xs={12}>
Expand Down Expand Up @@ -169,6 +194,7 @@ function BenefitPlanEligibilityCriteriaPanel({
</Grid>
</Grid>
</Paper>
)
);
}

Expand Down
10 changes: 5 additions & 5 deletions src/components/BenefitPlanGroupBeneficiariesSearcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,11 @@ import {
RIGHT_BENEFICIARY_UPDATE,
ROWS_PER_PAGE_OPTIONS,
CLEARED_STATE_FILTER,
BENEFIT_PLAN_LABEL,
MODULE_NAME,
} from '../constants';
import BenefitPlanGroupBeneficiariesFilter from './BenefitPlanGroupBeneficiariesFilter';
import BeneficiaryStatusPicker from '../pickers/BeneficiaryStatusPicker';
import { applyNumberCircle } from '../util/searcher-utils';


function BenefitPlanGroupBeneficiariesSearcher({
rights,
intl,
Expand Down Expand Up @@ -191,6 +188,8 @@ function BenefitPlanGroupBeneficiariesSearcher({
/>
);

const additionalParams = benefitPlan ? { benefitPlan: `${benefitPlan.id}` } : null;

useEffect(() => {
// refresh when appliedCustomFilters is changed
}, [appliedCustomFilters]);
Expand Down Expand Up @@ -233,8 +232,9 @@ function BenefitPlanGroupBeneficiariesSearcher({
cacheTabName={`${benefitPlan?.id}-${status}`}
isCustomFiltering
objectForCustomFiltering={benefitPlan}
moduleName={MODULE_NAME}
objectType={BENEFIT_PLAN_LABEL}
moduleName="individual"
objectType="Individual"
additionalCustomFilterParams={additionalParams}
appliedCustomFilters={appliedCustomFilters}
setAppliedCustomFilters={setAppliedCustomFilters}
appliedFiltersRowStructure={appliedFiltersRowStructure}
Expand Down
7 changes: 5 additions & 2 deletions src/components/BenefitPlanTabPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const useStyles = makeStyles((theme) => ({
}));

function BenefitPlanTabPanel({
intl, rights, benefitPlan, setConfirmedAction,
intl, rights, benefitPlan, setConfirmedAction, onActiveTabChange,
}) {
const classes = useStyles();
const modulesManager = useModulesManager();
Expand All @@ -50,7 +50,10 @@ function BenefitPlanTabPanel({

const tabStyle = (tab) => (isSelected(tab) ? classes.selectedTab : classes.unselectedTab);

const handleChange = (_, tab) => setActiveTab(tab);
const handleChange = (_, tab) => {
setActiveTab(tab);
onActiveTabChange(tab);
};

const payrollCreateRights = modulesManager.getRef(PAYROLL_CREATE_RIGHTS_PUB_REF);

Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export const BENEFICIARY_STATUS = {
SUSPENDED: 'SUSPENDED',
};

export const DEFAULT_BENEFICIARY_STATUS = 'POTENTIAL';

export const FIELD_TYPES = {
INTEGER: 'integer',
NUMBER: 'number',
Expand Down
10 changes: 9 additions & 1 deletion src/pages/BenefitPlanPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import _ from 'lodash';
import { withTheme, withStyles } from '@material-ui/core/styles';
import DeleteIcon from '@material-ui/icons/Delete';
import PauseIcon from '@material-ui/icons/Pause';
import { RIGHT_BENEFICIARY_SEARCH, RIGHT_BENEFIT_PLAN_UPDATE } from '../constants';
import {
BENEFIT_PLAN_BENEFICIARIES_LIST_TAB_VALUE,
RIGHT_BENEFICIARY_SEARCH,
RIGHT_BENEFIT_PLAN_UPDATE,
} from '../constants';
import {
fetchBenefitPlan, deleteBenefitPlan, closeBenefitPlan, updateBenefitPlan, clearBenefitPlan, createBenefitPlan,
} from '../actions';
Expand Down Expand Up @@ -178,6 +182,8 @@ function BenefitPlanPage({
);
};

const [childActiveTab, setChildActiveTab] = useState(BENEFIT_PLAN_BENEFICIARIES_LIST_TAB_VALUE);

const getBenefitPlanPanels = () => {
const panels = [];
if (benefitPlan?.id && benefitPlan?.beneficiaryDataSchema) {
Expand Down Expand Up @@ -220,6 +226,8 @@ function BenefitPlanPage({
save={handleSave}
HeadPanel={BenefitPlanHeadPanel}
Panels={getBenefitPlanPanels()}
onActiveTabChange={setChildActiveTab}
activeTab={childActiveTab}
rights={rights}
actions={actions}
setConfirmedAction={setConfirmedAction}
Expand Down
2 changes: 1 addition & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"socialProtection.benefitUploadRecord.sourceName": "Filename",
"socialProtection.benefitUploadRecord.workflow": "Workflow",
"socialProtection.benefitUploadRecord.percentageOfInvalidItems": "Percentage of invalid items",
"socialProtection.benefitPlan.BenefitPlanEligibilityCriteriaPanel.title": "Default Enrollment Criteria",
"socialProtection.benefitPlan.BenefitPlanEligibilityCriteriaPanel.title": "{beneficiaryStatus} Beneficiary Enrollment Criteria",
"socialProtection.benefitPlan.benefitPlanBeneficiaries.uploadHistoryTable.downloadUploadFile": "Download Upload File",
"socialProtection.benefitPlan.benefitPlanBeneficiaries.uploadHistoryTable.downloadInvalidItems": "Download Invalid Items",
"socialProtection.benefitPlan.benefitPlanBeneficiaries.uploadHistoryTable.validationErrors": "Validation Errors",
Expand Down

0 comments on commit b92db6f

Please sign in to comment.