Skip to content

Commit

Permalink
Merge pull request #53625 from shubham1206agra/per-diem-4
Browse files Browse the repository at this point in the history
Implemented Edit/Delete Per diem rates
  • Loading branch information
Gonals authored Dec 19, 2024
2 parents e42622c + 89a2c5a commit 1e6a70e
Show file tree
Hide file tree
Showing 32 changed files with 995 additions and 93 deletions.
3 changes: 3 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,8 @@ const ONYXKEYS = {
RULES_MAX_EXPENSE_AGE_FORM_DRAFT: 'rulesMaxExpenseAgeFormDraft',
DEBUG_DETAILS_FORM: 'debugDetailsForm',
DEBUG_DETAILS_FORM_DRAFT: 'debugDetailsFormDraft',
WORKSPACE_PER_DIEM_FORM: 'workspacePerDiemForm',
WORKSPACE_PER_DIEM_FORM_DRAFT: 'workspacePerDiemFormDraft',
},
} as const;

Expand Down Expand Up @@ -826,6 +828,7 @@ type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.RULES_MAX_EXPENSE_AGE_FORM]: FormTypes.RulesMaxExpenseAgeForm;
[ONYXKEYS.FORMS.SEARCH_SAVED_SEARCH_RENAME_FORM]: FormTypes.SearchSavedSearchRenameForm;
[ONYXKEYS.FORMS.DEBUG_DETAILS_FORM]: FormTypes.DebugReportForm | FormTypes.DebugReportActionForm | FormTypes.DebugTransactionForm | FormTypes.DebugTransactionViolationForm;
[ONYXKEYS.FORMS.WORKSPACE_PER_DIEM_FORM]: FormTypes.WorkspacePerDiemForm;
};

type OnyxFormDraftValuesMapping = {
Expand Down
20 changes: 20 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,26 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/per-diem/settings',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/per-diem/settings` as const,
},
WORKSPACE_PER_DIEM_DETAILS: {
route: 'settings/workspaces/:policyID/per-diem/details/:rateID/:subRateID',
getRoute: (policyID: string, rateID: string, subRateID: string) => `settings/workspaces/${policyID}/per-diem/details/${rateID}/${subRateID}` as const,
},
WORKSPACE_PER_DIEM_EDIT_DESTINATION: {
route: 'settings/workspaces/:policyID/per-diem/edit/destination/:rateID/:subRateID',
getRoute: (policyID: string, rateID: string, subRateID: string) => `settings/workspaces/${policyID}/per-diem/edit/destination/${rateID}/${subRateID}` as const,
},
WORKSPACE_PER_DIEM_EDIT_SUBRATE: {
route: 'settings/workspaces/:policyID/per-diem/edit/subrate/:rateID/:subRateID',
getRoute: (policyID: string, rateID: string, subRateID: string) => `settings/workspaces/${policyID}/per-diem/edit/subrate/${rateID}/${subRateID}` as const,
},
WORKSPACE_PER_DIEM_EDIT_AMOUNT: {
route: 'settings/workspaces/:policyID/per-diem/edit/amount/:rateID/:subRateID',
getRoute: (policyID: string, rateID: string, subRateID: string) => `settings/workspaces/${policyID}/per-diem/edit/amount/${rateID}/${subRateID}` as const,
},
WORKSPACE_PER_DIEM_EDIT_CURRENCY: {
route: 'settings/workspaces/:policyID/per-diem/edit/currency/:rateID/:subRateID',
getRoute: (policyID: string, rateID: string, subRateID: string) => `settings/workspaces/${policyID}/per-diem/edit/currency/${rateID}/${subRateID}` as const,
},
RULES_CUSTOM_NAME: {
route: 'settings/workspaces/:policyID/rules/name',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/name` as const,
Expand Down
5 changes: 5 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,11 @@ const SCREENS = {
PER_DIEM_IMPORT: 'Per_Diem_Import',
PER_DIEM_IMPORTED: 'Per_Diem_Imported',
PER_DIEM_SETTINGS: 'Per_Diem_Settings',
PER_DIEM_DETAILS: 'Per_Diem_Details',
PER_DIEM_EDIT_DESTINATION: 'Per_Diem_Edit_Destination',
PER_DIEM_EDIT_SUBRATE: 'Per_Diem_Edit_Subrate',
PER_DIEM_EDIT_AMOUNT: 'Per_Diem_Edit_Amount',
PER_DIEM_EDIT_CURRENCY: 'Per_Diem_Edit_Currency',
},

EDIT_REQUEST: {
Expand Down
13 changes: 8 additions & 5 deletions src/components/AmountWithoutCurrencyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ type AmountFormProps = {

/** Callback to update the amount in the FormProvider */
onInputChange?: (value: string) => void;

/** Should we allow negative number as valid input */
shouldAllowNegative?: boolean;
} & Partial<BaseTextInputProps>;

function AmountWithoutCurrencyForm(
{value: amount, onInputChange, inputID, name, defaultValue, accessibilityLabel, role, label, ...rest}: AmountFormProps,
{value: amount, onInputChange, shouldAllowNegative = false, inputID, name, defaultValue, accessibilityLabel, role, label, ...rest}: AmountFormProps,
ref: ForwardedRef<BaseTextInputRef>,
) {
const {toLocaleDigit} = useLocalize();
Expand All @@ -32,13 +35,13 @@ function AmountWithoutCurrencyForm(
// More info: https://github.com/Expensify/App/issues/16974
const newAmountWithoutSpaces = stripSpacesFromAmount(newAmount);
const replacedCommasAmount = replaceCommasWithPeriod(newAmountWithoutSpaces);
const withLeadingZero = addLeadingZero(replacedCommasAmount);
if (!validateAmount(withLeadingZero, 2)) {
const withLeadingZero = addLeadingZero(replacedCommasAmount, shouldAllowNegative);
if (!validateAmount(withLeadingZero, 2, CONST.IOU.AMOUNT_MAX_LENGTH, shouldAllowNegative)) {
return;
}
onInputChange?.(withLeadingZero);
},
[onInputChange],
[onInputChange, shouldAllowNegative],
);

const formattedAmount = replaceAllDigits(currentAmount, toLocaleDigit);
Expand All @@ -54,7 +57,7 @@ function AmountWithoutCurrencyForm(
accessibilityLabel={accessibilityLabel}
role={role}
ref={ref}
keyboardType={CONST.KEYBOARD_TYPE.DECIMAL_PAD}
keyboardType={!shouldAllowNegative ? CONST.KEYBOARD_TYPE.DECIMAL_PAD : undefined}
// On android autoCapitalize="words" is necessary when keyboardType="decimal-pad" or inputMode="decimal" to prevent input lag.
// See https://github.com/Expensify/App/issues/51868 for more information
autoCapitalize="words"
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import type {
DeleteConfirmationParams,
DidSplitAmountMessageParams,
EditActionParams,
EditDestinationSubtitleParams,
ElectronicFundsParams,
EnterMagicCodeParams,
ExportAgainModalDescriptionParams,
Expand Down Expand Up @@ -2639,6 +2640,9 @@ const translations = {
existingRateError: ({rate}: CustomUnitRateParams) => `A rate with value ${rate} already exists.`,
},
importPerDiemRates: 'Import per diem rates',
editPerDiemRate: 'Edit per diem rate',
editDestinationSubtitle: ({destination}: EditDestinationSubtitleParams) => `Updating this destination will change it for all ${destination} per diem subrates.`,
editCurrencySubtitle: ({destination}: EditDestinationSubtitleParams) => `Updating this currency will change it for all ${destination} per diem subrates.`,
},
qbd: {
exportOutOfPocketExpensesDescription: 'Set how out-of-pocket expenses export to QuickBooks Desktop.',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import type {
DeleteConfirmationParams,
DidSplitAmountMessageParams,
EditActionParams,
EditDestinationSubtitleParams,
ElectronicFundsParams,
EnterMagicCodeParams,
ExportAgainModalDescriptionParams,
Expand Down Expand Up @@ -2663,6 +2664,9 @@ const translations = {
existingRateError: ({rate}: CustomUnitRateParams) => `Ya existe una tasa con el valor ${rate}.`,
},
importPerDiemRates: 'Importar tasas de per diem',
editPerDiemRate: 'Editar la tasa de per diem',
editDestinationSubtitle: ({destination}: EditDestinationSubtitleParams) => `Actualizar este destino lo modificará para todas las subtasas per diem de ${destination}.`,
editCurrencySubtitle: ({destination}: EditDestinationSubtitleParams) => `Actualizar esta moneda la modificará para todas las subtasas per diem de ${destination}.`,
},
qbd: {
exportOutOfPocketExpensesDescription: 'Establezca cómo se exportan los gastos de bolsillo a QuickBooks Desktop.',
Expand Down
5 changes: 5 additions & 0 deletions src/languages/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,10 @@ type ChatWithAccountManagerParams = {
accountManagerDisplayName: string;
};

type EditDestinationSubtitleParams = {
destination: string;
};

type FlightLayoverParams = {
layover: string;
};
Expand Down Expand Up @@ -798,5 +802,6 @@ export type {
CompanyNameParams,
CustomUnitRateParams,
ChatWithAccountManagerParams,
EditDestinationSubtitleParams,
FlightLayoverParams,
};
6 changes: 6 additions & 0 deletions src/libs/API/parameters/UpdateWorkspaceCustomUnitParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type UpdateWorkspaceCustomUnitParams = {
policyID: string;
customUnit: string;
};

export default UpdateWorkspaceCustomUnitParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ export type {default as TogglePlatformMuteParams} from './TogglePlatformMutePara
export type {default as JoinAccessiblePolicyParams} from './JoinAccessiblePolicyParams';
export type {default as ImportPerDiemRatesParams} from './ImportPerDiemRatesParams';
export type {default as ExportPerDiemCSVParams} from './ExportPerDiemCSVParams';
export type {default as UpdateWorkspaceCustomUnitParams} from './UpdateWorkspaceCustomUnitParams';
export type {default as DismissProductTrainingParams} from './DismissProductTraining';
export type {default as OpenWorkspacePlanPageParams} from './OpenWorkspacePlanPage';
export type {default as ResetSMSDeliveryFailureParams} from './ResetSMSDeliveryFailureParams';
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ const WRITE_COMMANDS = {
SELF_TOUR_VIEWED: 'SelfTourViewed',
UPDATE_INVOICE_COMPANY_NAME: 'UpdateInvoiceCompanyName',
UPDATE_INVOICE_COMPANY_WEBSITE: 'UpdateInvoiceCompanyWebsite',
UPDATE_WORKSPACE_CUSTOM_UNIT: 'UpdateWorkspaceCustomUnit',
VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES: 'ValidateUserAndGetAccessiblePolicies',
DISMISS_PRODUCT_TRAINING: 'DismissProductTraining',
RESET_SMS_DELIVERY_FAILURE: 'ResetSMSDeliveryFailure',
Expand Down Expand Up @@ -767,6 +768,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams;
[WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null;
[WRITE_COMMANDS.UPDATE_WORKSPACE_CUSTOM_UNIT]: Parameters.UpdateWorkspaceCustomUnitParams;
[WRITE_COMMANDS.RESET_SMS_DELIVERY_FAILURE]: Parameters.ResetSMSDeliveryFailureParams;

[WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams;
Expand Down
20 changes: 14 additions & 6 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,25 @@ function convertToDistanceInMeters(distance: number, unit: Unit): number {
function getCustomUnitRateID(reportID: string) {
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`];
const policy = PolicyUtils.getPolicy(report?.policyID ?? parentReport?.policyID ?? '-1');
const policy = PolicyUtils.getPolicy(report?.policyID ?? parentReport?.policyID);
let customUnitRateID: string = CONST.CUSTOM_UNITS.FAKE_P2P_ID;

if (isEmptyObject(policy)) {
return customUnitRateID;
}

if (ReportUtils.isPolicyExpenseChat(report) || ReportUtils.isPolicyExpenseChat(parentReport)) {
const distanceUnit = Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE);
const lastSelectedDistanceRateID = lastSelectedDistanceRates?.[policy?.id ?? '-1'] ?? '-1';
const lastSelectedDistanceRate = distanceUnit?.rates[lastSelectedDistanceRateID] ?? {};
if (lastSelectedDistanceRate.enabled && lastSelectedDistanceRateID) {
const distanceUnit = Object.values(policy.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE);
const lastSelectedDistanceRateID = lastSelectedDistanceRates?.[policy.id];
const lastSelectedDistanceRate = lastSelectedDistanceRateID ? distanceUnit?.rates[lastSelectedDistanceRateID] : undefined;
if (lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) {
customUnitRateID = lastSelectedDistanceRateID;
} else {
customUnitRateID = getDefaultMileageRate(policy)?.customUnitRateID ?? '-1';
const defaultMileageRate = getDefaultMileageRate(policy);
if (!defaultMileageRate?.customUnitRateID) {
return customUnitRateID;
}
customUnitRateID = defaultMileageRate.customUnitRateID;
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/libs/MoneyRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,23 @@ function stripDecimalsFromAmount(amount: string): string {
* Adds a leading zero to the amount if user entered just the decimal separator
*
* @param amount - Changed amount from user input
* @param shouldAllowNegative - Should allow negative numbers
*/
function addLeadingZero(amount: string): string {
function addLeadingZero(amount: string, shouldAllowNegative = false): string {
if (shouldAllowNegative && amount.startsWith('-.')) {
return `-0${amount}`;
}
return amount.startsWith('.') ? `0${amount}` : amount;
}

/**
* Check if amount is a decimal up to 3 digits
*/
function validateAmount(amount: string, decimals: number, amountMaxLength: number = CONST.IOU.AMOUNT_MAX_LENGTH): boolean {
function validateAmount(amount: string, decimals: number, amountMaxLength: number = CONST.IOU.AMOUNT_MAX_LENGTH, shouldAllowNegative = false): boolean {
const regexString =
decimals === 0
? `^\\d{1,${amountMaxLength}}$` // Don't allow decimal point if decimals === 0
: `^\\d{1,${amountMaxLength}}(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point
? `^${shouldAllowNegative ? '-?' : ''}\\d{1,${amountMaxLength}}$` // Don't allow decimal point if decimals === 0
: `^${shouldAllowNegative ? '-?' : ''}\\d{1,${amountMaxLength}}(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point
const decimalNumberRegex = new RegExp(regexString, 'i');
return amount === '' || decimalNumberRegex.test(amount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,11 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.PER_DIEM_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/ImportPerDiemPage').default,
[SCREENS.WORKSPACE.PER_DIEM_IMPORTED]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/ImportedPerDiemPage').default,
[SCREENS.WORKSPACE.PER_DIEM_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/WorkspacePerDiemSettingsPage').default,
[SCREENS.WORKSPACE.PER_DIEM_DETAILS]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/WorkspacePerDiemDetailsPage').default,
[SCREENS.WORKSPACE.PER_DIEM_EDIT_DESTINATION]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/EditPerDiemDestinationPage').default,
[SCREENS.WORKSPACE.PER_DIEM_EDIT_SUBRATE]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/EditPerDiemSubratePage').default,
[SCREENS.WORKSPACE.PER_DIEM_EDIT_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/EditPerDiemAmountPage').default,
[SCREENS.WORKSPACE.PER_DIEM_EDIT_CURRENCY]: () => require<ReactComponentModule>('../../../../pages/workspace/perDiem/EditPerDiemCurrencyPage').default,
});

const EnablePaymentsStackNavigator = createModalStackNavigator<EnablePaymentsNavigatorParamList>({
Expand Down
11 changes: 10 additions & 1 deletion src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,16 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.RULES_MAX_EXPENSE_AGE,
SCREENS.WORKSPACE.RULES_BILLABLE_DEFAULT,
],
[SCREENS.WORKSPACE.PER_DIEM]: [SCREENS.WORKSPACE.PER_DIEM_IMPORT, SCREENS.WORKSPACE.PER_DIEM_IMPORTED, SCREENS.WORKSPACE.PER_DIEM_SETTINGS],
[SCREENS.WORKSPACE.PER_DIEM]: [
SCREENS.WORKSPACE.PER_DIEM_IMPORT,
SCREENS.WORKSPACE.PER_DIEM_IMPORTED,
SCREENS.WORKSPACE.PER_DIEM_SETTINGS,
SCREENS.WORKSPACE.PER_DIEM_DETAILS,
SCREENS.WORKSPACE.PER_DIEM_EDIT_DESTINATION,
SCREENS.WORKSPACE.PER_DIEM_EDIT_SUBRATE,
SCREENS.WORKSPACE.PER_DIEM_EDIT_AMOUNT,
SCREENS.WORKSPACE.PER_DIEM_EDIT_CURRENCY,
],
};

export default FULL_SCREEN_TO_RHP_MAPPING;
15 changes: 15 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,21 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.PER_DIEM_SETTINGS]: {
path: ROUTES.WORKSPACE_PER_DIEM_SETTINGS.route,
},
[SCREENS.WORKSPACE.PER_DIEM_DETAILS]: {
path: ROUTES.WORKSPACE_PER_DIEM_DETAILS.route,
},
[SCREENS.WORKSPACE.PER_DIEM_EDIT_DESTINATION]: {
path: ROUTES.WORKSPACE_PER_DIEM_EDIT_DESTINATION.route,
},
[SCREENS.WORKSPACE.PER_DIEM_EDIT_SUBRATE]: {
path: ROUTES.WORKSPACE_PER_DIEM_EDIT_SUBRATE.route,
},
[SCREENS.WORKSPACE.PER_DIEM_EDIT_AMOUNT]: {
path: ROUTES.WORKSPACE_PER_DIEM_EDIT_AMOUNT.route,
},
[SCREENS.WORKSPACE.PER_DIEM_EDIT_CURRENCY]: {
path: ROUTES.WORKSPACE_PER_DIEM_EDIT_CURRENCY.route,
},
},
},
[SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: {
Expand Down
25 changes: 25 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,31 @@ type SettingsNavigatorParamList = {
[SCREENS.WORKSPACE.PER_DIEM_SETTINGS]: {
policyID: string;
};
[SCREENS.WORKSPACE.PER_DIEM_DETAILS]: {
policyID: string;
rateID: string;
subRateID: string;
};
[SCREENS.WORKSPACE.PER_DIEM_EDIT_DESTINATION]: {
policyID: string;
rateID: string;
subRateID: string;
};
[SCREENS.WORKSPACE.PER_DIEM_EDIT_SUBRATE]: {
policyID: string;
rateID: string;
subRateID: string;
};
[SCREENS.WORKSPACE.PER_DIEM_EDIT_AMOUNT]: {
policyID: string;
rateID: string;
subRateID: string;
};
[SCREENS.WORKSPACE.PER_DIEM_EDIT_CURRENCY]: {
policyID: string;
rateID: string;
subRateID: string;
};
} & ReimbursementAccountNavigatorParamList;

type NewChatNavigatorParamList = {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function getRateDisplayValue(value: number, toLocaleDigit: (arg: string) => stri
return numValue.toString().replace('.', toLocaleDigit('.')).substring(0, value.toString().length);
}

function getUnitRateValue(toLocaleDigit: (arg: string) => string, customUnitRate?: Rate, withDecimals?: boolean) {
function getUnitRateValue(toLocaleDigit: (arg: string) => string, customUnitRate?: Partial<Rate>, withDecimals?: boolean) {
return getRateDisplayValue((customUnitRate?.rate ?? 0) / CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET, toLocaleDigit, withDecimals);
}

Expand Down
Loading

0 comments on commit 1e6a70e

Please sign in to comment.