diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 4d7031ce388d..aac8b7d80b0c 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -2884,6 +2884,8 @@ const CONST = { // Note: These payment types are used when building IOU reportAction message values in the server and should // not be changed. LOCATION_PERMISSION_PROMPT_THRESHOLD_DAYS: 7, + // Maximum number of splits allowed for expenses + SPLITS_LIMIT: 30, PAYMENT_TYPE: { ELSEWHERE: 'Elsewhere', EXPENSIFY: 'Expensify', diff --git a/src/languages/de.ts b/src/languages/de.ts index 3eec31e092ee..8713b93dc2c8 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1347,6 +1347,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Satz für diesen Workspace ungültig. Bitte wählen Sie einen verfügbaren Satz aus dem Workspace aus.', endDateBeforeStartDate: 'Das Enddatum darf nicht vor dem Startdatum liegen', endDateSameAsStartDate: 'Das Enddatum darf nicht mit dem Startdatum identisch sein', + manySplitsProvided: `Zu viele Aufteilungen angegeben. Das Maximum ist ${CONST.IOU.SPLITS_LIMIT} Aufteilungen`, + dateRangeExceedsMaxDays: `Der Datumsbereich darf ${CONST.IOU.SPLITS_LIMIT} Tage nicht überschreiten`, }, dismissReceiptError: 'Fehler ausblenden', dismissReceiptErrorConfirmation: 'Achtung! Wenn du diesen Fehler verwirfst, wird dein hochgeladener Beleg vollständig entfernt. Bist du sicher?', diff --git a/src/languages/en.ts b/src/languages/en.ts index 5eccbf24d955..451ba537f7f3 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1323,6 +1323,8 @@ const translations = { invalidRate: 'Rate not valid for this workspace. Please select an available rate from the workspace.', endDateBeforeStartDate: "The end date can't be before the start date", endDateSameAsStartDate: "The end date can't be the same as the start date", + manySplitsProvided: `Too many splits provided. The maximum is ${CONST.IOU.SPLITS_LIMIT} splits`, + dateRangeExceedsMaxDays: `The date range can't exceed ${CONST.IOU.SPLITS_LIMIT} days`, }, dismissReceiptError: 'Dismiss error', dismissReceiptErrorConfirmation: 'Heads up! Dismissing this error will remove your uploaded receipt entirely. Are you sure?', diff --git a/src/languages/es.ts b/src/languages/es.ts index 848330eae0e6..3304582443d2 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1030,6 +1030,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Tasa no válida para este espacio de trabajo. Por favor, selecciona una tasa disponible en el espacio de trabajo.', endDateBeforeStartDate: 'La fecha de finalización no puede ser anterior a la fecha de inicio', endDateSameAsStartDate: 'La fecha de finalización no puede ser la misma que la fecha de inicio', + manySplitsProvided: `Se proporcionaron demasiadas divisiones. El máximo es ${CONST.IOU.SPLITS_LIMIT} divisiones`, + dateRangeExceedsMaxDays: `El rango de fechas no puede exceder los ${CONST.IOU.SPLITS_LIMIT} días`, }, dismissReceiptError: 'Descartar error', dismissReceiptErrorConfirmation: '¡Atención! Descartar este error eliminará completamente tu recibo cargado. ¿Estás seguro?', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 254e907e4f7b..ac2ca93e0571 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1348,6 +1348,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Taux non valide pour cet espace de travail. Veuillez sélectionner un taux disponible dans l’espace de travail.', endDateBeforeStartDate: 'La date de fin ne peut pas être antérieure à la date de début', endDateSameAsStartDate: 'La date de fin ne peut pas être identique à la date de début', + manySplitsProvided: `Trop de partages fournis. Le maximum est de ${CONST.IOU.SPLITS_LIMIT} partages`, + dateRangeExceedsMaxDays: `La plage de dates ne peut pas dépasser ${CONST.IOU.SPLITS_LIMIT} jours`, }, dismissReceiptError: 'Ignorer l’erreur', dismissReceiptErrorConfirmation: 'Attention ! Ignorer cette erreur supprimera entièrement votre reçu téléchargé. Êtes-vous sûr ?', diff --git a/src/languages/it.ts b/src/languages/it.ts index fe4058ef154e..eb34e6edfa18 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1342,6 +1342,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Tariffa non valida per questo workspace. Seleziona una tariffa disponibile dal workspace.', endDateBeforeStartDate: 'La data di fine non può essere precedente alla data di inizio', endDateSameAsStartDate: 'La data di fine non può essere uguale alla data di inizio', + manySplitsProvided: `Troppe suddivisioni fornite. Il massimo è ${CONST.IOU.SPLITS_LIMIT} suddivisioni`, + dateRangeExceedsMaxDays: `L'intervallo di date non può superare i ${CONST.IOU.SPLITS_LIMIT} giorni`, }, dismissReceiptError: 'Ignora errore', dismissReceiptErrorConfirmation: 'Attenzione! Se ignori questo errore, la ricevuta caricata verrà rimossa completamente. Sei sicuro?', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index a228b8a97117..7c2f8c3cfe86 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1342,6 +1342,8 @@ const translations: TranslationDeepObject = { invalidRate: 'このワークスペースでは無効なレートです。ワークスペースから利用可能なレートを選択してください。', endDateBeforeStartDate: '終了日は開始日より前にはできません', endDateSameAsStartDate: '終了日は開始日と同じにはできません', + manySplitsProvided: `提供された分割が多すぎます。最大は${CONST.IOU.SPLITS_LIMIT}分割です`, + dateRangeExceedsMaxDays: `期間は${CONST.IOU.SPLITS_LIMIT}日を超えることはできません`, }, dismissReceiptError: 'エラーを閉じる', dismissReceiptErrorConfirmation: '注意!このエラーを無視すると、アップロードした領収書が完全に削除されます。本当に実行しますか?', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index c595478e05f3..cfd2aaaed760 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1341,6 +1341,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Tarief is niet geldig voor deze workspace. Selecteer een beschikbaar tarief uit de workspace.', endDateBeforeStartDate: 'De einddatum kan niet vóór de startdatum liggen', endDateSameAsStartDate: 'De einddatum mag niet hetzelfde zijn als de startdatum', + manySplitsProvided: `Te veel splits opgegeven. Het maximum is ${CONST.IOU.SPLITS_LIMIT} splits`, + dateRangeExceedsMaxDays: `Het datumbereik mag niet meer dan ${CONST.IOU.SPLITS_LIMIT} dagen zijn`, }, dismissReceiptError: 'Foutmelding sluiten', dismissReceiptErrorConfirmation: 'Let op! Als je deze foutmelding negeert, wordt je geüploade bon volledig verwijderd. Weet je het zeker?', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 6eebe97af67d..01cf14c683c4 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1339,6 +1339,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Stawka nie jest prawidłowa dla tego przestrzeni roboczej. Wybierz dostępną stawkę z tej przestrzeni roboczej.', endDateBeforeStartDate: 'Data zakończenia nie może być wcześniejsza niż data rozpoczęcia', endDateSameAsStartDate: 'Data zakończenia nie może być taka sama jak data rozpoczęcia', + manySplitsProvided: `Podano zbyt wiele podziałów. Maksimum to ${CONST.IOU.SPLITS_LIMIT} podziałów`, + dateRangeExceedsMaxDays: `Zakres dat nie może przekraczać ${CONST.IOU.SPLITS_LIMIT} dni`, }, dismissReceiptError: 'Odrzuć błąd', dismissReceiptErrorConfirmation: 'Uwaga! Odrzucenie tego błędu spowoduje całkowite usunięcie przesłanego paragonu. Czy na pewno chcesz kontynuować?', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 7ce8ea8f69f5..2a6869e0d7f9 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1338,6 +1338,8 @@ const translations: TranslationDeepObject = { invalidRate: 'Taxa inválida para este workspace. Selecione uma taxa disponível do workspace.', endDateBeforeStartDate: 'A data de término não pode ser anterior à data de início', endDateSameAsStartDate: 'A data de término não pode ser igual à data de início', + manySplitsProvided: `Muitas divisões fornecidas. O máximo é ${CONST.IOU.SPLITS_LIMIT} divisões`, + dateRangeExceedsMaxDays: `O intervalo de datas não pode exceder ${CONST.IOU.SPLITS_LIMIT} dias`, }, dismissReceiptError: 'Dispensar erro', dismissReceiptErrorConfirmation: 'Atenção! Ignorar este erro removerá completamente o seu recibo enviado. Tem certeza?', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index f4ae3091f4a3..e1dbaea99d48 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1319,6 +1319,8 @@ const translations: TranslationDeepObject = { invalidRate: '此汇率对该工作区无效。请选择此工作区中的可用汇率。', endDateBeforeStartDate: '结束日期不能早于开始日期', endDateSameAsStartDate: '结束日期不能与开始日期相同', + manySplitsProvided: `提供的拆分过多。最多为${CONST.IOU.SPLITS_LIMIT}个拆分`, + dateRangeExceedsMaxDays: `日期范围不能超过${CONST.IOU.SPLITS_LIMIT}天`, }, dismissReceiptError: '忽略错误', dismissReceiptErrorConfirmation: '提醒!关闭此错误会完全删除你上传的收据。确定要继续吗?', diff --git a/src/pages/iou/SplitExpenseCreateDateRagePage.tsx b/src/pages/iou/SplitExpenseCreateDateRagePage.tsx index 7cb001e41d9a..ad42b6e8f194 100644 --- a/src/pages/iou/SplitExpenseCreateDateRagePage.tsx +++ b/src/pages/iou/SplitExpenseCreateDateRagePage.tsx @@ -1,3 +1,4 @@ +import {differenceInDays} from 'date-fns'; import React from 'react'; import {View} from 'react-native'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -76,6 +77,8 @@ function SplitExpenseCreateDateRagePage({route}: SplitExpenseCreateDateRagePageP errors[INPUT_IDS.END_DATE] = translate('iou.error.endDateBeforeStartDate'); } else if (endDate.getTime() === startDate.getTime()) { errors[INPUT_IDS.END_DATE] = translate('iou.error.endDateSameAsStartDate'); + } else if (differenceInDays(endDate, startDate) + 1 > CONST.IOU.SPLITS_LIMIT) { + errors[INPUT_IDS.END_DATE] = translate('iou.error.dateRangeExceedsMaxDays'); } } diff --git a/src/pages/iou/SplitExpensePage.tsx b/src/pages/iou/SplitExpensePage.tsx index 450398995790..c20c56e31fc0 100644 --- a/src/pages/iou/SplitExpensePage.tsx +++ b/src/pages/iou/SplitExpensePage.tsx @@ -150,6 +150,10 @@ function SplitExpensePage({route}: SplitExpensePageProps) { }, [draftTransaction]); const onSaveSplitExpense = useCallback(() => { + if (splitExpenses.length > CONST.IOU.SPLITS_LIMIT) { + setErrorMessage(translate('iou.error.manySplitsProvided')); + return; + } if (splitExpenses.length <= 1 && !childTransactions.length) { const splitFieldDataFromOriginalTransactionWithoutID = {...splitFieldDataFromOriginalTransaction, transactionID: ''}; const splitExpenseWithoutID = {...splitExpenses.at(0), transactionID: ''};