diff --git a/src/libs/actions/Policy/DistanceRate.ts b/src/libs/actions/Policy/DistanceRate.ts new file mode 100644 index 000000000000..f48c3e9033ac --- /dev/null +++ b/src/libs/actions/Policy/DistanceRate.ts @@ -0,0 +1,537 @@ +import type {NullishDeep, OnyxCollection, OnyxUpdate} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import * as API from '@libs/API'; +import type { + CreatePolicyDistanceRateParams, + DeletePolicyDistanceRatesParams, + EnablePolicyDistanceRatesParams, + OpenPolicyDistanceRatesPageParams, + SetPolicyDistanceRatesEnabledParams, + SetPolicyDistanceRatesUnitParams, + UpdatePolicyDistanceRateValueParams, +} from '@libs/API/parameters'; +import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import getIsNarrowLayout from '@libs/getIsNarrowLayout'; +import * as ReportUtils from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy, Report} from '@src/types/onyx'; +import type {ErrorFields} from '@src/types/onyx/OnyxCommon'; +import type {Attributes, CustomUnit, Rate} from '@src/types/onyx/Policy'; +import type {OnyxData} from '@src/types/onyx/Request'; +import {navigateWhenEnableFeature, removePendingFieldsFromCustomUnit} from './Policy'; + +type NewCustomUnit = { + customUnitID: string; + name: string; + attributes: Attributes; + rates: Rate; +}; + +const allPolicies: OnyxCollection = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY, + callback: (val, key) => { + if (!key) { + return; + } + if (val === null || val === undefined) { + // If we are deleting a policy, we have to check every report linked to that policy + // and unset the draft indicator (pencil icon) alongside removing any draft comments. Clearing these values will keep the newly archived chats from being displayed in the LHN. + // More info: https://github.com/Expensify/App/issues/14260 + const policyID = key.replace(ONYXKEYS.COLLECTION.POLICY, ''); + const policyReports = ReportUtils.getAllPolicyReports(policyID); + const cleanUpMergeQueries: Record<`${typeof ONYXKEYS.COLLECTION.REPORT}${string}`, NullishDeep> = {}; + const cleanUpSetQueries: Record<`${typeof ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${string}` | `${typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${string}`, null> = {}; + policyReports.forEach((policyReport) => { + if (!policyReport) { + return; + } + const {reportID} = policyReport; + cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] = null; + cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}`] = null; + }); + Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, cleanUpMergeQueries); + Onyx.multiSet(cleanUpSetQueries); + delete allPolicies[key]; + return; + } + + allPolicies[key] = val; + }, +}); + +/** + * Takes array of customUnitRates and removes pendingFields and errorFields from each rate - we don't want to send those via API + */ +function prepareCustomUnitRatesArray(customUnitRates: Rate[]): Rate[] { + const customUnitRateArray: Rate[] = []; + customUnitRates.forEach((rate) => { + const cleanedRate = {...rate}; + delete cleanedRate.pendingFields; + delete cleanedRate.errorFields; + customUnitRateArray.push(cleanedRate); + }); + + return customUnitRateArray; +} + +function openPolicyDistanceRatesPage(policyID?: string) { + if (!policyID) { + return; + } + + const params: OpenPolicyDistanceRatesPageParams = {policyID}; + + API.read(READ_COMMANDS.OPEN_POLICY_DISTANCE_RATES_PAGE, params); +} + +function enablePolicyDistanceRates(policyID: string, enabled: boolean) { + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areDistanceRatesEnabled: enabled, + pendingFields: { + areDistanceRatesEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + pendingFields: { + areDistanceRatesEnabled: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areDistanceRatesEnabled: !enabled, + pendingFields: { + areDistanceRatesEnabled: null, + }, + }, + }, + ], + }; + + const parameters: EnablePolicyDistanceRatesParams = {policyID, enabled}; + + API.write(WRITE_COMMANDS.ENABLE_POLICY_DISTANCE_RATES, parameters, onyxData); + + if (enabled && getIsNarrowLayout()) { + navigateWhenEnableFeature(policyID); + } +} + +function createPolicyDistanceRate(policyID: string, customUnitID: string, customUnitRate: Rate) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnitID]: { + rates: { + [customUnitRate.customUnitRateID ?? '']: { + ...customUnitRate, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + }, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnitID]: { + rates: { + [customUnitRate.customUnitRateID ?? '']: { + pendingAction: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnitID]: { + rates: { + [customUnitRate.customUnitRateID ?? '']: { + errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + const params: CreatePolicyDistanceRateParams = { + policyID, + customUnitID, + customUnitRate: JSON.stringify(customUnitRate), + }; + + API.write(WRITE_COMMANDS.CREATE_POLICY_DISTANCE_RATE, params, {optimisticData, successData, failureData}); +} + +function clearCreateDistanceRateItemAndError(policyID: string, customUnitID: string, customUnitRateIDToClear: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + customUnits: { + [customUnitID]: { + rates: { + [customUnitRateIDToClear]: null, + }, + }, + }, + }); +} + +function clearPolicyDistanceRatesErrorFields(policyID: string, customUnitID: string, updatedErrorFields: ErrorFields) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + customUnits: { + [customUnitID]: { + errorFields: updatedErrorFields, + }, + }, + }); +} + +function clearDeleteDistanceRateError(policyID: string, customUnitID: string, rateID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + customUnits: { + [customUnitID]: { + rates: { + [rateID]: { + errors: null, + }, + }, + }, + }, + }); +} + +function clearPolicyDistanceRateErrorFields(policyID: string, customUnitID: string, rateID: string, updatedErrorFields: ErrorFields) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + customUnits: { + [customUnitID]: { + rates: { + [rateID]: { + errorFields: updatedErrorFields, + }, + }, + }, + }, + }); +} + +function setPolicyDistanceRatesUnit(policyID: string, currentCustomUnit: CustomUnit, newCustomUnit: CustomUnit) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [newCustomUnit.customUnitID]: { + ...newCustomUnit, + pendingFields: {attributes: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [newCustomUnit.customUnitID]: { + pendingFields: {attributes: null}, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [currentCustomUnit.customUnitID]: { + ...currentCustomUnit, + errorFields: {attributes: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + pendingFields: {attributes: null}, + }, + }, + }, + }, + ]; + + const params: SetPolicyDistanceRatesUnitParams = { + policyID, + customUnit: JSON.stringify(removePendingFieldsFromCustomUnit(newCustomUnit)), + }; + + API.write(WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_UNIT, params, {optimisticData, successData, failureData}); +} + +function updatePolicyDistanceRateValue(policyID: string, customUnit: CustomUnit, customUnitRates: Rate[]) { + const currentRates = customUnit.rates; + const optimisticRates: Record = {}; + const successRates: Record = {}; + const failureRates: Record = {}; + const rateIDs = customUnitRates.map((rate) => rate.customUnitRateID); + + for (const rateID of Object.keys(customUnit.rates)) { + if (rateIDs.includes(rateID)) { + const foundRate = customUnitRates.find((rate) => rate.customUnitRateID === rateID); + optimisticRates[rateID] = {...foundRate, pendingFields: {rate: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}; + successRates[rateID] = {...foundRate, pendingFields: {rate: null}}; + failureRates[rateID] = { + ...currentRates[rateID], + pendingFields: {rate: null}, + errorFields: {rate: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + }; + } + } + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: optimisticRates, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: successRates, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: failureRates, + }, + }, + }, + }, + ]; + + const params: UpdatePolicyDistanceRateValueParams = { + policyID, + customUnitID: customUnit.customUnitID, + customUnitRateArray: JSON.stringify(prepareCustomUnitRatesArray(customUnitRates)), + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_RATE_VALUE, params, {optimisticData, successData, failureData}); +} + +function setPolicyDistanceRatesEnabled(policyID: string, customUnit: CustomUnit, customUnitRates: Rate[]) { + const currentRates = customUnit.rates; + const optimisticRates: Record = {}; + const successRates: Record = {}; + const failureRates: Record = {}; + const rateIDs = customUnitRates.map((rate) => rate.customUnitRateID); + + for (const rateID of Object.keys(currentRates)) { + if (rateIDs.includes(rateID)) { + const foundRate = customUnitRates.find((rate) => rate.customUnitRateID === rateID); + optimisticRates[rateID] = {...foundRate, pendingFields: {enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}; + successRates[rateID] = {...foundRate, pendingFields: {enabled: null}}; + failureRates[rateID] = { + ...currentRates[rateID], + pendingFields: {enabled: null}, + errorFields: {enabled: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + }; + } + } + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: optimisticRates, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: successRates, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: failureRates, + }, + }, + }, + }, + ]; + + const params: SetPolicyDistanceRatesEnabledParams = { + policyID, + customUnitID: customUnit.customUnitID, + customUnitRateArray: JSON.stringify(prepareCustomUnitRatesArray(customUnitRates)), + }; + + API.write(WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_ENABLED, params, {optimisticData, successData, failureData}); +} + +function deletePolicyDistanceRates(policyID: string, customUnit: CustomUnit, rateIDsToDelete: string[]) { + const currentRates = customUnit.rates; + const optimisticRates: Record = {}; + const successRates: Record = {}; + const failureRates: Record = {}; + + for (const rateID of Object.keys(currentRates)) { + if (rateIDsToDelete.includes(rateID)) { + optimisticRates[rateID] = { + ...currentRates[rateID], + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }; + failureRates[rateID] = { + ...currentRates[rateID], + pendingAction: null, + errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), + }; + } else { + optimisticRates[rateID] = currentRates[rateID]; + successRates[rateID] = currentRates[rateID]; + } + } + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: optimisticRates, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: successRates, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + customUnits: { + [customUnit.customUnitID]: { + rates: failureRates, + }, + }, + }, + }, + ]; + + const params: DeletePolicyDistanceRatesParams = { + policyID, + customUnitID: customUnit.customUnitID, + customUnitRateID: rateIDsToDelete, + }; + + API.write(WRITE_COMMANDS.DELETE_POLICY_DISTANCE_RATES, params, {optimisticData, successData, failureData}); +} + +export { + enablePolicyDistanceRates, + openPolicyDistanceRatesPage, + createPolicyDistanceRate, + clearCreateDistanceRateItemAndError, + clearDeleteDistanceRateError, + setPolicyDistanceRatesUnit, + clearPolicyDistanceRatesErrorFields, + clearPolicyDistanceRateErrorFields, + updatePolicyDistanceRateValue, + setPolicyDistanceRatesEnabled, + deletePolicyDistanceRates, +}; + +export type {NewCustomUnit}; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 4d918352ba91..2625e7d60dff 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -10,21 +10,17 @@ import * as API from '@libs/API'; import type { AddBillingCardAndRequestWorkspaceOwnerChangeParams, AddMembersToWorkspaceParams, - CreatePolicyDistanceRateParams, CreateWorkspaceFromIOUPaymentParams, CreateWorkspaceParams, DeleteMembersFromWorkspaceParams, - DeletePolicyDistanceRatesParams, DeleteWorkspaceAvatarParams, DeleteWorkspaceParams, EnablePolicyConnectionsParams, - EnablePolicyDistanceRatesParams, EnablePolicyReportFieldsParams, EnablePolicyTaxesParams, EnablePolicyWorkflowsParams, LeavePolicyParams, OpenDraftWorkspaceRequestParams, - OpenPolicyDistanceRatesPageParams, OpenPolicyMoreFeaturesPageParams, OpenPolicyTaxesPageParams, OpenPolicyWorkflowsPageParams, @@ -33,15 +29,12 @@ import type { OpenWorkspaceParams, OpenWorkspaceReimburseViewParams, RequestWorkspaceOwnerChangeParams, - SetPolicyDistanceRatesEnabledParams, - SetPolicyDistanceRatesUnitParams, SetWorkspaceApprovalModeParams, SetWorkspaceAutoReportingFrequencyParams, SetWorkspaceAutoReportingMonthlyOffsetParams, SetWorkspaceAutoReportingParams, SetWorkspacePayerParams, SetWorkspaceReimbursementParams, - UpdatePolicyDistanceRateValueParams, UpdateWorkspaceAvatarParams, UpdateWorkspaceCustomUnitAndRateParams, UpdateWorkspaceDescriptionParams, @@ -79,7 +72,7 @@ import type { TaxRatesWithDefault, Transaction, } from '@src/types/onyx'; -import type {ErrorFields, Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; +import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {OriginalMessageJoinPolicyChangeLog} from '@src/types/onyx/OriginalMessage'; import type {Attributes, CompanyAddress, CustomUnit, Rate, TaxRate, Unit} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; @@ -3215,16 +3208,6 @@ function declineJoinRequest(reportID: string, reportAction: OnyxEntry { Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policyID)); @@ -3275,54 +3258,6 @@ function enablePolicyConnections(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.ENABLE_POLICY_CONNECTIONS, parameters, onyxData); } -function enablePolicyDistanceRates(policyID: string, enabled: boolean) { - const onyxData: OnyxData = { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - areDistanceRatesEnabled: enabled, - pendingFields: { - areDistanceRatesEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, - }, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - pendingFields: { - areDistanceRatesEnabled: null, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - areDistanceRatesEnabled: !enabled, - pendingFields: { - areDistanceRatesEnabled: null, - }, - }, - }, - ], - }; - - const parameters: EnablePolicyDistanceRatesParams = {policyID, enabled}; - - API.write(WRITE_COMMANDS.ENABLE_POLICY_DISTANCE_RATES, parameters, onyxData); - - if (enabled && getIsNarrowLayout()) { - navigateWhenEnableFeature(policyID); - } -} - function enablePolicyReportFields(policyID: string, enabled: boolean) { const onyxData: OnyxData = { optimisticData: [ @@ -3571,121 +3506,6 @@ function openPolicyMoreFeaturesPage(policyID: string) { API.read(READ_COMMANDS.OPEN_POLICY_MORE_FEATURES_PAGE, params); } -function createPolicyDistanceRate(policyID: string, customUnitID: string, customUnitRate: Rate) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnitID]: { - rates: { - [customUnitRate.customUnitRateID ?? '']: { - ...customUnitRate, - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - }, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnitID]: { - rates: { - [customUnitRate.customUnitRateID ?? '']: { - pendingAction: null, - }, - }, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnitID]: { - rates: { - [customUnitRate.customUnitRateID ?? '']: { - errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), - }, - }, - }, - }, - }, - }, - ]; - - const params: CreatePolicyDistanceRateParams = { - policyID, - customUnitID, - customUnitRate: JSON.stringify(customUnitRate), - }; - - API.write(WRITE_COMMANDS.CREATE_POLICY_DISTANCE_RATE, params, {optimisticData, successData, failureData}); -} - -function clearCreateDistanceRateItemAndError(policyID: string, customUnitID: string, customUnitRateIDToClear: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { - customUnits: { - [customUnitID]: { - rates: { - [customUnitRateIDToClear]: null, - }, - }, - }, - }); -} - -function clearPolicyDistanceRatesErrorFields(policyID: string, customUnitID: string, updatedErrorFields: ErrorFields) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { - customUnits: { - [customUnitID]: { - errorFields: updatedErrorFields, - }, - }, - }); -} - -function clearDeleteDistanceRateError(policyID: string, customUnitID: string, rateID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { - customUnits: { - [customUnitID]: { - rates: { - [rateID]: { - errors: null, - }, - }, - }, - }, - }); -} - -function clearPolicyDistanceRateErrorFields(policyID: string, customUnitID: string, rateID: string, updatedErrorFields: ErrorFields) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { - customUnits: { - [customUnitID]: { - rates: { - [rateID]: { - errorFields: updatedErrorFields, - }, - }, - }, - }, - }); -} - /** * Takes removes pendingFields and errorFields from a customUnit */ @@ -3698,291 +3518,6 @@ function removePendingFieldsFromCustomUnit(customUnit: CustomUnit): CustomUnit { return cleanedCustomUnit; } -function setPolicyDistanceRatesUnit(policyID: string, currentCustomUnit: CustomUnit, newCustomUnit: CustomUnit) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [newCustomUnit.customUnitID]: { - ...newCustomUnit, - pendingFields: {attributes: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [newCustomUnit.customUnitID]: { - pendingFields: {attributes: null}, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [currentCustomUnit.customUnitID]: { - ...currentCustomUnit, - errorFields: {attributes: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, - pendingFields: {attributes: null}, - }, - }, - }, - }, - ]; - - const params: SetPolicyDistanceRatesUnitParams = { - policyID, - customUnit: JSON.stringify(removePendingFieldsFromCustomUnit(newCustomUnit)), - }; - - API.write(WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_UNIT, params, {optimisticData, successData, failureData}); -} - -/** - * Takes array of customUnitRates and removes pendingFields and errorFields from each rate - we don't want to send those via API - */ -function prepareCustomUnitRatesArray(customUnitRates: Rate[]): Rate[] { - const customUnitRateArray: Rate[] = []; - customUnitRates.forEach((rate) => { - const cleanedRate = {...rate}; - delete cleanedRate.pendingFields; - delete cleanedRate.errorFields; - customUnitRateArray.push(cleanedRate); - }); - - return customUnitRateArray; -} - -function updatePolicyDistanceRateValue(policyID: string, customUnit: CustomUnit, customUnitRates: Rate[]) { - const currentRates = customUnit.rates; - const optimisticRates: Record = {}; - const successRates: Record = {}; - const failureRates: Record = {}; - const rateIDs = customUnitRates.map((rate) => rate.customUnitRateID); - - for (const rateID of Object.keys(customUnit.rates)) { - if (rateIDs.includes(rateID)) { - const foundRate = customUnitRates.find((rate) => rate.customUnitRateID === rateID); - optimisticRates[rateID] = {...foundRate, pendingFields: {rate: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}; - successRates[rateID] = {...foundRate, pendingFields: {rate: null}}; - failureRates[rateID] = { - ...currentRates[rateID], - pendingFields: {rate: null}, - errorFields: {rate: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, - }; - } - } - - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: optimisticRates, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: successRates, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: failureRates, - }, - }, - }, - }, - ]; - - const params: UpdatePolicyDistanceRateValueParams = { - policyID, - customUnitID: customUnit.customUnitID, - customUnitRateArray: JSON.stringify(prepareCustomUnitRatesArray(customUnitRates)), - }; - - API.write(WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_RATE_VALUE, params, {optimisticData, successData, failureData}); -} - -function setPolicyDistanceRatesEnabled(policyID: string, customUnit: CustomUnit, customUnitRates: Rate[]) { - const currentRates = customUnit.rates; - const optimisticRates: Record = {}; - const successRates: Record = {}; - const failureRates: Record = {}; - const rateIDs = customUnitRates.map((rate) => rate.customUnitRateID); - - for (const rateID of Object.keys(currentRates)) { - if (rateIDs.includes(rateID)) { - const foundRate = customUnitRates.find((rate) => rate.customUnitRateID === rateID); - optimisticRates[rateID] = {...foundRate, pendingFields: {enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}; - successRates[rateID] = {...foundRate, pendingFields: {enabled: null}}; - failureRates[rateID] = { - ...currentRates[rateID], - pendingFields: {enabled: null}, - errorFields: {enabled: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, - }; - } - } - - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: optimisticRates, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: successRates, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: failureRates, - }, - }, - }, - }, - ]; - - const params: SetPolicyDistanceRatesEnabledParams = { - policyID, - customUnitID: customUnit.customUnitID, - customUnitRateArray: JSON.stringify(prepareCustomUnitRatesArray(customUnitRates)), - }; - - API.write(WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_ENABLED, params, {optimisticData, successData, failureData}); -} - -function deletePolicyDistanceRates(policyID: string, customUnit: CustomUnit, rateIDsToDelete: string[]) { - const currentRates = customUnit.rates; - const optimisticRates: Record = {}; - const successRates: Record = {}; - const failureRates: Record = {}; - - for (const rateID of Object.keys(currentRates)) { - if (rateIDsToDelete.includes(rateID)) { - optimisticRates[rateID] = { - ...currentRates[rateID], - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - }; - failureRates[rateID] = { - ...currentRates[rateID], - pendingAction: null, - errors: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'), - }; - } else { - optimisticRates[rateID] = currentRates[rateID]; - successRates[rateID] = currentRates[rateID]; - } - } - - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: optimisticRates, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: successRates, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - customUnits: { - [customUnit.customUnitID]: { - rates: failureRates, - }, - }, - }, - }, - ]; - - const params: DeletePolicyDistanceRatesParams = { - policyID, - customUnitID: customUnit.customUnitID, - customUnitRateID: rateIDsToDelete, - }; - - API.write(WRITE_COMMANDS.DELETE_POLICY_DISTANCE_RATES, params, {optimisticData, successData, failureData}); -} - function setPolicyCustomTaxName(policyID: string, customTaxName: string) { const policy = getPolicy(policyID); const originalCustomTaxName = policy?.taxRates?.name; @@ -4196,17 +3731,11 @@ export { setWorkspaceReimbursement, openPolicyWorkflowsPage, enablePolicyConnections, - enablePolicyDistanceRates, enablePolicyReportFields, enablePolicyTaxes, enablePolicyWorkflows, - openPolicyDistanceRatesPage, openPolicyMoreFeaturesPage, generateCustomUnitID, - createPolicyDistanceRate, - clearCreateDistanceRateItemAndError, - clearDeleteDistanceRateError, - setPolicyDistanceRatesUnit, clearQBOErrorField, clearXeroErrorField, clearWorkspaceReimbursementErrors, @@ -4215,11 +3744,6 @@ export { setPolicyCustomTaxName, clearPolicyErrorField, isCurrencySupportedForDirectReimbursement, - clearPolicyDistanceRatesErrorFields, - clearPolicyDistanceRateErrorFields, - updatePolicyDistanceRateValue, - setPolicyDistanceRatesEnabled, - deletePolicyDistanceRates, getPrimaryPolicy, createDraftWorkspace, buildPolicyData, diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index 245b4e4a291d..548f3b21d077 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -17,6 +17,7 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {FullScreenNavigatorParamList} from '@libs/Navigation/types'; import * as Category from '@userActions/Policy/Category'; +import * as DistanceRate from '@userActions/Policy/DistanceRate'; import * as Policy from '@userActions/Policy/Policy'; import * as Tag from '@userActions/Policy/Tag'; import CONST from '@src/CONST'; @@ -71,7 +72,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro isActive: policy?.areDistanceRatesEnabled ?? false, pendingAction: policy?.pendingFields?.areDistanceRatesEnabled, action: (isEnabled: boolean) => { - Policy.enablePolicyDistanceRates(policy?.id ?? '', isEnabled); + DistanceRate.enablePolicyDistanceRates(policy?.id ?? '', isEnabled); }, }, { diff --git a/src/pages/workspace/distanceRates/CreateDistanceRatePage.tsx b/src/pages/workspace/distanceRates/CreateDistanceRatePage.tsx index a03e8d9e18fa..2738b50e1901 100644 --- a/src/pages/workspace/distanceRates/CreateDistanceRatePage.tsx +++ b/src/pages/workspace/distanceRates/CreateDistanceRatePage.tsx @@ -15,7 +15,8 @@ import {getOptimisticRateName, validateRateValue} from '@libs/PolicyDistanceRate import Navigation from '@navigation/Navigation'; import type {SettingsNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import {createPolicyDistanceRate, generateCustomUnitID} from '@userActions/Policy/Policy'; +import {createPolicyDistanceRate} from '@userActions/Policy/DistanceRate'; +import {generateCustomUnitID} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRateDetailsPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRateDetailsPage.tsx index 1291e3fbce8a..012ba712d0aa 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRateDetailsPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRateDetailsPage.tsx @@ -20,7 +20,7 @@ import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import * as Policy from '@userActions/Policy/Policy'; +import * as DistanceRate from '@userActions/Policy/DistanceRate'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -65,7 +65,7 @@ function PolicyDistanceRateDetailsPage({policy, route}: PolicyDistanceRateDetail const toggleRate = () => { if (!rate?.enabled || canDisableOrDeleteRate) { - Policy.setPolicyDistanceRatesEnabled(policyID, customUnit, [{...rate, enabled: !rate?.enabled}]); + DistanceRate.setPolicyDistanceRatesEnabled(policyID, customUnit, [{...rate, enabled: !rate?.enabled}]); } else { setIsWarningModalVisible(true); } @@ -73,7 +73,7 @@ function PolicyDistanceRateDetailsPage({policy, route}: PolicyDistanceRateDetail const deleteRate = () => { Navigation.goBack(); - Policy.deletePolicyDistanceRates(policyID, customUnit, [rateID]); + DistanceRate.deletePolicyDistanceRates(policyID, customUnit, [rateID]); setIsDeleteModalVisible(false); }; @@ -95,7 +95,7 @@ function PolicyDistanceRateDetailsPage({policy, route}: PolicyDistanceRateDetail ]; const clearErrorFields = (fieldName: keyof Rate) => { - Policy.clearPolicyDistanceRateErrorFields(policyID, customUnit.customUnitID, rateID, {...errorFields, [fieldName]: null}); + DistanceRate.clearPolicyDistanceRateErrorFields(policyID, customUnit.customUnitID, rateID, {...errorFields, [fieldName]: null}); }; return ( diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRateEditPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRateEditPage.tsx index 954f5af0cf45..229d87443504 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRateEditPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRateEditPage.tsx @@ -17,7 +17,7 @@ import {validateRateValue} from '@libs/PolicyDistanceRatesUtils'; import type {SettingsNavigatorParamList} from '@navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import * as Policy from '@userActions/Policy/Policy'; +import * as DistanceRate from '@userActions/Policy/DistanceRate'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; @@ -45,7 +45,7 @@ function PolicyDistanceRateEditPage({policy, route}: PolicyDistanceRateEditPageP const currentRateValue = (rate?.rate ?? 0).toString(); const submitRate = (values: FormOnyxValues) => { - Policy.updatePolicyDistanceRateValue(policyID, customUnit, [{...rate, rate: Number(values.rate) * CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET}]); + DistanceRate.updatePolicyDistanceRateValue(policyID, customUnit, [{...rate, rate: Number(values.rate) * CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET}]); Keyboard.dismiss(); Navigation.goBack(); }; diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx index cecb081d2ea2..e659750754a1 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx @@ -26,7 +26,7 @@ import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import Navigation from '@libs/Navigation/Navigation'; import type {FullScreenNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import * as Policy from '@userActions/Policy/Policy'; +import * as DistanceRate from '@userActions/Policy/DistanceRate'; import ButtonWithDropdownMenu from '@src/components/ButtonWithDropdownMenu'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -68,17 +68,17 @@ function PolicyDistanceRatesPage({policy, route}: PolicyDistanceRatesPageProps) ); const fetchDistanceRates = useCallback(() => { - Policy.openPolicyDistanceRatesPage(policyID); + DistanceRate.openPolicyDistanceRatesPage(policyID); }, [policyID]); const dismissError = useCallback( (item: RateForList) => { if (customUnitRates[item.value].errors) { - Policy.clearDeleteDistanceRateError(policyID, customUnit?.customUnitID ?? '', item.value); + DistanceRate.clearDeleteDistanceRateError(policyID, customUnit?.customUnitID ?? '', item.value); return; } - Policy.clearCreateDistanceRateItemAndError(policyID, customUnit?.customUnitID ?? '', item.value); + DistanceRate.clearCreateDistanceRateItemAndError(policyID, customUnit?.customUnitID ?? '', item.value); }, [customUnit?.customUnitID, customUnitRates, policyID], ); @@ -132,7 +132,7 @@ function PolicyDistanceRatesPage({policy, route}: PolicyDistanceRatesPageProps) return; } - Policy.setPolicyDistanceRatesEnabled( + DistanceRate.setPolicyDistanceRatesEnabled( policyID, customUnit, selectedDistanceRates.filter((rate) => rate.enabled).map((rate) => ({...rate, enabled: false})), @@ -145,7 +145,7 @@ function PolicyDistanceRatesPage({policy, route}: PolicyDistanceRatesPageProps) return; } - Policy.setPolicyDistanceRatesEnabled( + DistanceRate.setPolicyDistanceRatesEnabled( policyID, customUnit, selectedDistanceRates.filter((rate) => !rate.enabled).map((rate) => ({...rate, enabled: true})), @@ -158,7 +158,7 @@ function PolicyDistanceRatesPage({policy, route}: PolicyDistanceRatesPageProps) return; } - Policy.deletePolicyDistanceRates( + DistanceRate.deletePolicyDistanceRates( policyID, customUnit, selectedDistanceRates.map((rate) => rate.customUnitRateID ?? ''), diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesSettingsPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesSettingsPage.tsx index fae566a74854..15f3aabd76e0 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRatesSettingsPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesSettingsPage.tsx @@ -15,7 +15,7 @@ import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {SettingsNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import * as Category from '@userActions/Policy/Category'; -import * as Policy from '@userActions/Policy/Policy'; +import * as DistanceRate from '@userActions/Policy/DistanceRate'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; @@ -48,7 +48,7 @@ function PolicyDistanceRatesSettingsPage({policy, policyCategories, route}: Poli const errorFields = customUnits[customUnitID]?.errorFields; const setNewUnit = (unit: UnitItemType) => { - Policy.setPolicyDistanceRatesUnit(policyID, customUnit, {...customUnit, attributes: {unit: unit.value}}); + DistanceRate.setPolicyDistanceRatesUnit(policyID, customUnit, {...customUnit, attributes: {unit: unit.value}}); }; const setNewCategory = (category: ListItem) => { @@ -63,7 +63,7 @@ function PolicyDistanceRatesSettingsPage({policy, policyCategories, route}: Poli }; const clearErrorFields = (fieldName: keyof CustomUnit) => { - Policy.clearPolicyDistanceRatesErrorFields(policyID, customUnitID, {...errorFields, [fieldName]: null}); + DistanceRate.clearPolicyDistanceRatesErrorFields(policyID, customUnitID, {...errorFields, [fieldName]: null}); }; return (