Skip to content

Commit

Permalink
Merge pull request #43149 from rushatgabhane/gl-code
Browse files Browse the repository at this point in the history
Policy category - Add GL Code
  • Loading branch information
Gonals authored Jul 11, 2024
2 parents bef871e + 16b6308 commit 45eec25
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/categories/:categoryName/edit',
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/edit` as const,
},
WORKSPACE_CATEGORY_GL_CODE: {
route: 'settings/workspaces/:policyID/categories/:categoryName/gl-code',
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/gl-code` as const,
},
WORKSPACE_MORE_FEATURES: {
route: 'settings/workspaces/:policyID/more-features',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/more-features` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ const SCREENS = {
NAME: 'Workspace_Profile_Name',
CATEGORY_CREATE: 'Category_Create',
CATEGORY_EDIT: 'Category_Edit',
CATEGORY_GL_CODE: 'Category_GL_Code',
CATEGORY_SETTINGS: 'Category_Settings',
CATEGORIES_SETTINGS: 'Categories_Settings',
MORE_FEATURES: 'Workspace_More_Features',
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2670,6 +2670,8 @@ export default {
existingCategoryError: 'A category with this name already exists.',
invalidCategoryName: 'Invalid category name.',
importedFromAccountingSoftware: 'The categories below are imported from your',
glCode: 'GL code',
updateGLCodeFailureMessage: 'An error occurred while updating the GL code, please try again.',
},
moreFeatures: {
spendSection: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2718,6 +2718,8 @@ export default {
existingCategoryError: 'Ya existe una categoría con este nombre.',
invalidCategoryName: 'Lo nombre de la categoría es invalido.',
importedFromAccountingSoftware: 'Categorías importadas desde',
glCode: 'Código GL',
updateGLCodeFailureMessage: 'Se produjo un error al actualizar el código GL. Inténtelo nuevamente.',
},
moreFeatures: {
spendSection: {
Expand Down
7 changes: 7 additions & 0 deletions src/libs/API/parameters/UpdatePolicyCategoryGLCodeParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type UpdatePolicyCategoryGLCodeParams = {
policyID: string;
categoryName: string;
glCode: string;
};

export default UpdatePolicyCategoryGLCodeParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export type {default as CreateWorkspaceCategoriesParams} from './CreateWorkspace
export type {default as RenameWorkspaceCategoriesParams} from './RenameWorkspaceCategoriesParams';
export type {default as SetWorkspaceRequiresCategoryParams} from './SetWorkspaceRequiresCategoryParams';
export type {default as DeleteWorkspaceCategoriesParams} from './DeleteWorkspaceCategoriesParams';
export type {default as UpdatePolicyCategoryGLCodeParams} from './UpdatePolicyCategoryGLCodeParams';
export type {default as SetWorkspaceAutoReportingFrequencyParams} from './SetWorkspaceAutoReportingFrequencyParams';
export type {default as SetWorkspaceAutoReportingMonthlyOffsetParams} from './SetWorkspaceAutoReportingMonthlyOffsetParams';
export type {default as SetWorkspaceApprovalModeParams} from './SetWorkspaceApprovalModeParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const WRITE_COMMANDS = {
CREATE_POLICY_TAG: 'CreatePolicyTag',
RENAME_POLICY_TAG: 'RenamePolicyTag',
SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory',
UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode',
DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories',
DELETE_POLICY_REPORT_FIELD: 'DeletePolicyReportField',
SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired',
Expand Down Expand Up @@ -425,6 +426,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams;
[WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams;
[WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams;
[WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE]: Parameters.UpdatePolicyCategoryGLCodeParams;
[WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD]: Parameters.DeletePolicyReportField;
[WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag;
[WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.OWNER_CHANGE_ERROR]: () => require<ReactComponentModule>('../../../../pages/workspace/members/WorkspaceOwnerChangeErrorPage').default,
[SCREENS.WORKSPACE.CATEGORY_CREATE]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CreateCategoryPage').default,
[SCREENS.WORKSPACE.CATEGORY_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/EditCategoryPage').default,
[SCREENS.WORKSPACE.CATEGORY_GL_CODE]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategoryGLCodePage').default,
[SCREENS.WORKSPACE.CREATE_DISTANCE_RATE]: () => require<ReactComponentModule>('../../../../pages/workspace/distanceRates/CreateDistanceRatePage').default,
[SCREENS.WORKSPACE.DISTANCE_RATES_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/distanceRates/PolicyDistanceRatesSettingsPage').default,
[SCREENS.WORKSPACE.DISTANCE_RATE_DETAILS]: () => require<ReactComponentModule>('../../../../pages/workspace/distanceRates/PolicyDistanceRateDetailsPage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,13 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.TAG_LIST_VIEW,
SCREENS.WORKSPACE.TAG_GL_CODE,
],
[SCREENS.WORKSPACE.CATEGORIES]: [SCREENS.WORKSPACE.CATEGORY_CREATE, SCREENS.WORKSPACE.CATEGORY_SETTINGS, SCREENS.WORKSPACE.CATEGORIES_SETTINGS, SCREENS.WORKSPACE.CATEGORY_EDIT],
[SCREENS.WORKSPACE.CATEGORIES]: [
SCREENS.WORKSPACE.CATEGORY_CREATE,
SCREENS.WORKSPACE.CATEGORY_SETTINGS,
SCREENS.WORKSPACE.CATEGORIES_SETTINGS,
SCREENS.WORKSPACE.CATEGORY_EDIT,
SCREENS.WORKSPACE.CATEGORY_GL_CODE,
],
[SCREENS.WORKSPACE.DISTANCE_RATES]: [
SCREENS.WORKSPACE.CREATE_DISTANCE_RATE,
SCREENS.WORKSPACE.DISTANCE_RATES_SETTINGS,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,12 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
categoryName: (categoryName: string) => decodeURIComponent(categoryName),
},
},
[SCREENS.WORKSPACE.CATEGORY_GL_CODE]: {
path: ROUTES.WORKSPACE_CATEGORY_GL_CODE.route,
parse: {
categoryName: (categoryName: string) => decodeURIComponent(categoryName),
},
},
[SCREENS.WORKSPACE.CREATE_DISTANCE_RATE]: {
path: ROUTES.WORKSPACE_CREATE_DISTANCE_RATE.route,
},
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ type SettingsNavigatorParamList = {
categoryName: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.CATEGORY_GL_CODE]: {
policyID: string;
categoryName: string;
};
[SCREENS.WORKSPACE.CATEGORY_SETTINGS]: {
policyID: string;
categoryName: string;
Expand Down
71 changes: 70 additions & 1 deletion src/libs/actions/Policy/Category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import lodashUnion from 'lodash/union';
import type {NullishDeep, OnyxCollection, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {EnablePolicyCategoriesParams, OpenPolicyCategoriesPageParams, SetPolicyDistanceRatesDefaultCategoryParams} from '@libs/API/parameters';
import type {EnablePolicyCategoriesParams, OpenPolicyCategoriesPageParams, SetPolicyDistanceRatesDefaultCategoryParams, UpdatePolicyCategoryGLCodeParams} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as ErrorUtils from '@libs/ErrorUtils';
import getIsNarrowLayout from '@libs/getIsNarrowLayout';
Expand Down Expand Up @@ -331,6 +331,74 @@ function renamePolicyCategory(policyID: string, policyCategory: {oldName: string
API.write(WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY, parameters, onyxData);
}

function updatePolicyCategoryGLCode(policyID: string, categoryName: string, glCode: string) {
const policyCategoryToUpdate = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`]?.[categoryName] ?? {};

const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
...policyCategoryToUpdate,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
pendingFields: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'GL Code': CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
// eslint-disable-next-line @typescript-eslint/naming-convention
'GL Code': glCode,
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
...policyCategoryToUpdate,
pendingAction: null,
pendingFields: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'GL Code': null,
},
// eslint-disable-next-line @typescript-eslint/naming-convention
'GL Code': glCode,
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
...policyCategoryToUpdate,
errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateGLCodeFailureMessage'),
pendingAction: null,
pendingFields: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'GL Code': null,
},
},
},
},
],
};

const parameters: UpdatePolicyCategoryGLCodeParams = {
policyID,
categoryName,
glCode,
};

API.write(WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE, parameters, onyxData);
}

function setWorkspaceRequiresCategory(policyID: string, requiresCategory: boolean) {
const onyxData: OnyxData = {
optimisticData: [
Expand Down Expand Up @@ -618,6 +686,7 @@ export {
setWorkspaceRequiresCategory,
createPolicyCategory,
renamePolicyCategory,
updatePolicyCategoryGLCode,
clearCategoryErrors,
enablePolicyCategories,
setPolicyDistanceRatesDefaultCategory,
Expand Down
87 changes: 87 additions & 0 deletions src/pages/workspace/categories/CategoryGLCodePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback} from 'react';
import {useOnyx} from 'react-native-onyx';
import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import type {FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import type {SettingsNavigatorParamList} from '@navigation/types';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import * as Category from '@userActions/Policy/Category';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/WorkspaceCategoryForm';

type EditCategoryPageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORY_GL_CODE>;

function CategoryGLCodePage({route}: EditCategoryPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const policyId = route.params.policyID ?? '-1';
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyId}`);

const categoryName = route.params.categoryName;
const glCode = policyCategories?.[categoryName]?.['GL Code'];
const {inputCallbackRef} = useAutoFocusInput();

const editGLCode = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FORM>) => {
const newGLCode = values.glCode.trim();
if (newGLCode !== glCode) {
Category.updatePolicyCategoryGLCode(route.params.policyID, categoryName, newGLCode);
}
Navigation.goBack();
},
[categoryName, glCode, route.params.policyID],
);

return (
<AccessOrNotFoundWrapper
accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
policyID={route.params.policyID}
featureName={CONST.POLICY.MORE_FEATURES.ARE_CATEGORIES_ENABLED}
>
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
style={[styles.defaultModalContainer]}
testID={CategoryGLCodePage.displayName}
shouldEnableMaxHeight
>
<HeaderWithBackButton
title={translate('workspace.categories.glCode')}
onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_CATEGORY_SETTINGS.getRoute(route.params.policyID, route.params.categoryName))}
/>
<FormProvider
formID={ONYXKEYS.FORMS.WORKSPACE_CATEGORY_FORM}
onSubmit={editGLCode}
submitButtonText={translate('common.save')}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
>
<InputWrapper
ref={inputCallbackRef}
InputComponent={TextInput}
defaultValue={glCode}
label={translate('workspace.categories.glCode')}
accessibilityLabel={translate('workspace.categories.glCode')}
inputID={INPUT_IDS.GL_CODE}
role={CONST.ROLE.PRESENTATION}
maxLength={CONST.MAX_LENGTH_256}
/>
</FormProvider>
</ScreenWrapper>
</AccessOrNotFoundWrapper>
);
}

CategoryGLCodePage.displayName = 'CategoryGLCodePage';

export default CategoryGLCodePage;
8 changes: 8 additions & 0 deletions src/pages/workspace/categories/CategorySettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ function CategorySettingsPage({route, policyCategories, navigation}: CategorySet
shouldShowRightIcon
/>
</OfflineWithFeedback>
<OfflineWithFeedback pendingAction={policyCategory.pendingFields?.['GL Code']}>
<MenuItemWithTopDescription
title={policyCategory['GL Code']}
description={translate(`workspace.categories.glCode`)}
onPress={() => Navigation.navigate(ROUTES.WORKSPACE_CATEGORY_GL_CODE.getRoute(route.params.policyID, policyCategory.name))}
shouldShowRightIcon
/>
</OfflineWithFeedback>
{!isThereAnyAccountingConnection && (
<MenuItem
icon={Expensicons.Trashcan}
Expand Down
2 changes: 2 additions & 0 deletions src/types/form/WorkspaceCategoryForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type Form from './Form';

const INPUT_IDS = {
CATEGORY_NAME: 'categoryName',
GL_CODE: 'glCode',
} as const;

type InputID = ValueOf<typeof INPUT_IDS>;
Expand All @@ -11,6 +12,7 @@ type WorkspaceCategoryForm = Form<
InputID,
{
[INPUT_IDS.CATEGORY_NAME]: string;
[INPUT_IDS.GL_CODE]: string;
}
>;

Expand Down

0 comments on commit 45eec25

Please sign in to comment.