Skip to content

Commit 70fc8a0

Browse files
committed
fix: allow switching existing sick/vacation policy to unlimited accrual
The update request was sending `complete: true` when switching to unlimited, which could cause API rejection for policies with employees that have existing balances. Now the update omits the `complete` flag (already-created policies don't need it re-asserted) and surfaces 422 errors as human-readable messages.
1 parent acb6194 commit 70fc8a0

3 files changed

Lines changed: 35 additions & 10 deletions

File tree

src/components/TimeOff/TimeOffManagement/PolicyConfigurationForm/PolicyConfigurationForm.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,6 @@ describe('PolicyConfigurationForm - edit mode (deriveFormDefaults)', () => {
10031003
policyResetDate: null,
10041004
accrualRate: null,
10051005
accrualRateUnit: null,
1006-
complete: true,
10071006
}),
10081007
},
10091008
})

src/components/TimeOff/TimeOffManagement/PolicyConfigurationForm/PolicyConfigurationForm.tsx

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import { useTimeOffPoliciesGetSuspense } from '@gusto/embedded-api/react-query/t
55
import type { TimeOffPolicyRequest } from '@gusto/embedded-api/models/components/timeoffpolicyrequest'
66
import type { TimeOffPolicy } from '@gusto/embedded-api/models/components/timeoffpolicy'
77
import type { PutV1TimeOffPoliciesTimeOffPolicyUuidRequestBody } from '@gusto/embedded-api/models/operations/putv1timeoffpoliciestimeoffpolicyuuid'
8+
import { UnprocessableEntityError } from '@gusto/embedded-api/models/errors/unprocessableentityerror'
89
import { useQueryClient } from '@tanstack/react-query'
10+
import { useTranslation } from 'react-i18next'
911
import { PolicyConfigurationFormPresentation } from './PolicyConfigurationFormPresentation'
1012
import type { PolicyConfigurationFormData } from './PolicyConfigurationFormTypes'
1113
import { BaseComponent, type BaseComponentInterface } from '@/components/Base'
1214
import { useBase } from '@/components/Base/useBase'
15+
import { SDKInternalError } from '@/types/sdkError'
1316
import { componentEvents } from '@/shared/constants'
1417
import { formatMonthDay } from '@/helpers/dateFormatting'
18+
import { useI18n } from '@/i18n'
1519

1620
export interface PolicyConfigurationFormProps extends BaseComponentInterface<'Company.TimeOff.CreateTimeOffPolicy'> {
1721
companyId: string
@@ -166,7 +170,6 @@ function buildUpdateRequestBody(
166170
accrualRate: null,
167171
accrualRateUnit: null,
168172
policyResetDate: null,
169-
complete: true,
170173
}
171174
}
172175

@@ -266,7 +269,9 @@ interface EditRootProps {
266269
}
267270

268271
function EditRoot({ companyId, policyType, policyId, defaultValues }: EditRootProps) {
272+
useI18n('Company.TimeOff.CreateTimeOffPolicy')
269273
const { onEvent, baseSubmitHandler } = useBase()
274+
const { t } = useTranslation('Company.TimeOff.CreateTimeOffPolicy')
270275
const queryClient = useQueryClient()
271276

272277
const { data: policyResponse } = useTimeOffPoliciesGetSuspense({
@@ -287,12 +292,23 @@ function EditRoot({ companyId, policyType, policyId, defaultValues }: EditRootPr
287292
await baseSubmitHandler(data, async () => {
288293
const requestBody = buildUpdateRequestBody(data, policyType, version)
289294

290-
await updateTimeOffPolicy({
291-
request: {
292-
timeOffPolicyUuid: policyId,
293-
requestBody,
294-
},
295-
})
295+
try {
296+
await updateTimeOffPolicy({
297+
request: {
298+
timeOffPolicyUuid: policyId,
299+
requestBody,
300+
},
301+
})
302+
} catch (err) {
303+
if (err instanceof UnprocessableEntityError) {
304+
const messages = err.errors.map(e => e.message).filter(Boolean)
305+
throw new SDKInternalError(
306+
t('errors.updatePolicyFailed', { details: messages.join('. ') }),
307+
'api_error',
308+
)
309+
}
310+
throw err
311+
}
296312

297313
void queryClient.invalidateQueries({
298314
queryKey: ['@gusto/embedded-api', 'timeOffPolicies', 'get'],
@@ -304,7 +320,16 @@ function EditRoot({ companyId, policyType, policyId, defaultValues }: EditRootPr
304320
})
305321
})
306322
},
307-
[baseSubmitHandler, policyId, policyType, version, updateTimeOffPolicy, queryClient, onEvent],
323+
[
324+
baseSubmitHandler,
325+
policyId,
326+
policyType,
327+
version,
328+
updateTimeOffPolicy,
329+
queryClient,
330+
onEvent,
331+
t,
332+
],
308333
)
309334

310335
const handleCancel = useCallback(() => {

src/i18n/en/Company.TimeOff.CreateTimeOffPolicy.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
"backCta": "Back",
8282
"cancelCta": "Cancel",
8383
"errors": {
84-
"updatePolicySettingsFailed": "Unable to update policy settings. {{details}}"
84+
"updatePolicySettingsFailed": "Unable to update policy settings. {{details}}",
85+
"updatePolicyFailed": "Unable to update this policy. {{details}}"
8586
},
8687
"flash": {
8788
"policyUpdated": "Details for this policy have been updated.",

0 commit comments

Comments
 (0)