From 6e095f606cbd1b0f111c99774fad557032ba81fc Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 23 Jul 2020 16:13:30 -0400 Subject: [PATCH] fixed total cost when toggling between hourly and non-hourly updated change log --- CHANGELOG.md | 2 + .../ContractorResourceForm.js | 32 ++++++++++++++- .../ContractorResourceForm.test.js | 40 ++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60427ed184..eb8a49ec85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Anticipated release: July 27, 2020 #### 🐛 Bugs fixed - Text Boxes for TinyMCE don't update when navigating between "Activity Overview" sections between Activities ([#2316]) +- The hourly resource and FFY costs are not overwriting as expected ([#2236]) #### ⚙️ Behind the scenes @@ -20,3 +21,4 @@ See our [release history](https://github.com/18F/cms-hitech-apd/releases) [#2316]: https://github.com/18F/cms-hitech-apd/issues/2316 [#2349]: https://github.com/18F/cms-hitech-apd/issues/2349 [#2340]: https://github.com/18F/cms-hitech-apd/issues/2340 +[#2236]: https://github.com/18F/cms-hitech-apd/issues/2236 diff --git a/web/src/containers/activity/ContractorResource/ContractorResourceForm.js b/web/src/containers/activity/ContractorResource/ContractorResourceForm.js index dfe832fe30..c182b83736 100644 --- a/web/src/containers/activity/ContractorResource/ContractorResourceForm.js +++ b/web/src/containers/activity/ContractorResource/ContractorResourceForm.js @@ -1,6 +1,6 @@ import { FormLabel, TextField } from '@cmsgov/design-system-core'; import PropTypes from 'prop-types'; -import React, { Fragment, useMemo } from 'react'; +import React, { Fragment, useMemo, useState } from 'react'; import { connect } from 'react-redux'; import Choice from '../../../components/Choice'; @@ -37,6 +37,12 @@ const ContractorResourceForm = ({ setHourlyRateForYear }) => { const apdFFYs = useMemo(() => Object.keys(years), [years]); + const [nonHourlyCost, setNonHourlyCost] = useState( + apdFFYs.reduce( + (o, ffy) => ({ ...o, [ffy]: !hourly.useHourly ? years[ffy] : '' }), + {} + ) + ); const getHandler = action => ({ target: { value } }) => { action(activityIndex, index, value); @@ -48,10 +54,34 @@ const ContractorResourceForm = ({ const setHourlyOff = () => { setIsHourly(activityIndex, index, false); + + // set cost to non-hourly cost saved from last time the radio button was switched (if any) + apdFFYs.forEach(ffy => { + if (nonHourlyCost[ffy]) { + setCostForYear(activityIndex, index, ffy, nonHourlyCost[ffy]); + } + }); }; const setHourlyOn = () => { + // save non-hourly cost in case the radio button is switched back to non-hourly + setNonHourlyCost( + apdFFYs.reduce((o, ffy) => ({ ...o, [ffy]: years[ffy] }), {}) + ); + setIsHourly(activityIndex, index, true); + + // set cost to hours x rate + apdFFYs.forEach(ffy => { + if (hourly.data[ffy].hours && hourly.data[ffy].rate) { + setCostForYear( + activityIndex, + index, + ffy, + hourly.data[ffy].hours * hourly.data[ffy].rate + ); + } + }); }; const getHandlerForYearlyCost = year => ({ target: { value } }) => { diff --git a/web/src/containers/activity/ContractorResource/ContractorResourceForm.test.js b/web/src/containers/activity/ContractorResource/ContractorResourceForm.test.js index 278b1411b5..c5ebc86807 100644 --- a/web/src/containers/activity/ContractorResource/ContractorResourceForm.test.js +++ b/web/src/containers/activity/ContractorResource/ContractorResourceForm.test.js @@ -1,4 +1,4 @@ -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import React from 'react'; import { plain as ContractorForm } from './ContractorResourceForm'; @@ -190,4 +190,42 @@ describe('the ContractorResourceForm component', () => { 9364 ); }); + + test('handles changing from non-hourly to hourly and back, replacing cost totals', () => { + // start with non-hourly and fill in the total cost + props.item.hourly.useHourly = false; + const component = mount(); + + component + .findWhere( + c => + c.name() === 'input' && c.prop('name') === 'contractor-cost-ffy-1066' + ) + .simulate('change', { target: { value: '53792' } }); + + // now we have the non-hourly cost + expect(props.setCostForYear).toHaveBeenCalledWith(43, 1, '1066', 53792); + + // switch to hourly and we have the hourly cost + component + .findWhere( + c => + c.name() === 'input' && + c.prop('name') === 'apd-activity-contractor-hourly-key 1-yes' + ) + .simulate('change'); + expect(props.setIsHourly).toHaveBeenCalledWith(43, 1, true); + expect(props.setCostForYear).toHaveBeenCalledWith(43, 1, '1066', 1000); + + // switch back to non-hourly and we should have the original cost total + component + .findWhere( + c => + c.name() === 'input' && + c.prop('name') === 'apd-activity-contractor-hourly-key 1-no' + ) + .simulate('change'); + expect(props.setIsHourly).toHaveBeenCalledWith(43, 1, false); + expect(props.setCostForYear).toHaveBeenCalledWith(43, 1, '1066', 53792); + }); });