Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ function MoneyRequestView({
const reportNameToDisplay = isFromMergeTransaction ? (updatedTransaction?.reportName ?? translate('common.none')) : getReportName(parentReport, parentReportDerivedName);
const shouldShowReport = !!parentReportID || (isFromMergeTransaction && !!reportNameToDisplay);
const reportCopyValue = !canEditReport && reportNameToDisplay !== translate('common.none') ? reportNameToDisplay : undefined;
const shouldShowCategoryAnalyzing = isCategoryBeingAnalyzed(updatedTransaction ?? transaction);
const shouldShowCategoryAnalyzing = isCategoryBeingAnalyzed(updatedTransaction ?? transaction, policy);

// In this case we want to use this value. The shouldUseNarrowLayout will always be true as this case is handled when we display ReportScreen in RHP.
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6190,6 +6190,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
deleteFailureMessage: 'Beim Löschen der Kategorie ist ein Fehler aufgetreten, bitte versuche es erneut.',
categoryName: 'Kategoriename',
requiresCategory: 'Mitglieder müssen alle Ausgaben kategorisieren',
autoCategorizeNewExpenses: 'Neue Ausgaben automatisch kategorisieren',
showCategoryGLCodes: 'Sachkonten beim Kategorisieren von Ausgaben anzeigen',
needCategoryForExportToIntegration: (connectionName: string) => `Alle Ausgaben müssen kategorisiert werden, um nach ${connectionName} exportiert zu werden.`,
subtitle: 'Verschaffe dir einen besseren Überblick darüber, wofür Geld ausgegeben wird. Verwende unsere Standardkategorien oder füge eigene hinzu.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/el.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6305,6 +6305,7 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
deleteFailureMessage: 'Παρουσιάστηκε σφάλμα κατά τη διαγραφή της κατηγορίας, δοκιμάστε ξανά',
categoryName: 'Όνομα κατηγορίας',
requiresCategory: 'Τα μέλη πρέπει να κατηγοριοποιούν όλες τις δαπάνες',
autoCategorizeNewExpenses: 'Αυτόματη κατηγοριοποίηση νέων δαπανών',
showCategoryGLCodes: 'Εμφάνιση κωδικών GL κατά την κατηγοριοποίηση δαπανών',
needCategoryForExportToIntegration: (connectionName: string) => `Όλες οι δαπάνες πρέπει να κατηγοριοποιηθούν για να γίνει η εξαγωγή στο ${connectionName}.`,
subtitle: 'Αποκτήστε μια καλύτερη εικόνα για το πού ξοδεύονται τα χρήματα. Χρησιμοποιήστε τις προεπιλεγμένες κατηγορίες μας ή προσθέστε τις δικές σας.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6267,6 +6267,7 @@ const translations = {
deleteFailureMessage: 'An error occurred while deleting the category, please try again',
categoryName: 'Category name',
requiresCategory: 'Members must categorize all expenses',
autoCategorizeNewExpenses: 'Auto-categorize new expenses',
showCategoryGLCodes: 'Show GL codes when categorizing expenses',
needCategoryForExportToIntegration: (connectionName: string) => `All expenses must be categorized in order to export to ${connectionName}.`,
subtitle: 'Get a better overview of where money is being spent. Use our default categories or add your own.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6066,6 +6066,7 @@ ${amount} para ${merchant} - ${date}`,
deleteFailureMessage: 'Se ha producido un error al intentar eliminar la categoría. Por favor, inténtalo más tarde.',
categoryName: 'Nombre de la categoría',
requiresCategory: 'Los miembros deben clasificar todos los gastos',
autoCategorizeNewExpenses: 'Categorizar automáticamente los gastos nuevos',
showCategoryGLCodes: 'Mostrar códigos GL al categorizar gastos',
needCategoryForExportToIntegration: (connectionName) => `Todos los gastos deben estar categorizados para poder exportar a ${connectionName}.`,
subtitle: 'Obtén una visión general de dónde te gastas el dinero. Utiliza las categorías predeterminadas o añade las tuyas propias.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6198,6 +6198,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
deleteFailureMessage: "Une erreur s'est produite lors de la suppression de la catégorie, veuillez réessayer",
categoryName: 'Nom de la catégorie',
requiresCategory: 'Les membres doivent catégoriser toutes les dépenses',
autoCategorizeNewExpenses: 'Catégoriser automatiquement les nouvelles dépenses',
showCategoryGLCodes: 'Afficher les codes de grand livre lors de la catégorisation des dépenses',
needCategoryForExportToIntegration: (connectionName: string) => `Toutes les dépenses doivent être catégorisées afin de pouvoir être exportées vers ${connectionName}.`,
subtitle: 'Obtenez une meilleure vue d’ensemble de l’endroit où l’argent est dépensé. Utilisez nos catégories par défaut ou ajoutez les vôtres.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6153,6 +6153,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
deleteFailureMessage: 'Si è verificato un errore durante l’eliminazione della categoria, riprova per favore',
categoryName: 'Nome categoria',
requiresCategory: 'I membri devono categorizzare tutte le spese',
autoCategorizeNewExpenses: 'Categorizza automaticamente le nuove spese',
showCategoryGLCodes: 'Mostra i codici CO.GE. quando classifichi le spese',
needCategoryForExportToIntegration: (connectionName: string) => `Tutte le spese devono essere categorizzate per poterle esportare su ${connectionName}.`,
subtitle: 'Ottieni una panoramica migliore di dove viene speso il denaro. Usa le nostre categorie predefinite oppure aggiungi le tue.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6079,6 +6079,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
deleteFailureMessage: 'カテゴリの削除中にエラーが発生しました。もう一度お試しください',
categoryName: 'カテゴリ名',
requiresCategory: 'メンバーはすべての経費を分類する必要があります',
autoCategorizeNewExpenses: '新しい経費を自動分類する',
showCategoryGLCodes: '経費を分類するときに GL コードを表示する',
needCategoryForExportToIntegration: (connectionName: string) => `${connectionName} にエクスポートするには、すべての経費にカテゴリを指定する必要があります。`,
subtitle: 'お金がどこで使われているかを、より分かりやすく把握しましょう。デフォルトのカテゴリを使うか、自分用のカテゴリを追加できます。',
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6145,6 +6145,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
deleteFailureMessage: 'Er is een fout opgetreden bij het verwijderen van de categorie, probeer het opnieuw',
categoryName: 'Categorienaam',
requiresCategory: 'Leden moeten alle uitgaven categoriseren',
autoCategorizeNewExpenses: 'Nieuwe uitgaven automatisch categoriseren',
showCategoryGLCodes: 'Toon GL-codes bij het categoriseren van uitgaven',
needCategoryForExportToIntegration: (connectionName: string) => `Alle onkosten moeten worden gecategoriseerd om te kunnen exporteren naar ${connectionName}.`,
subtitle: 'Krijg beter inzicht in waar geld wordt uitgegeven. Gebruik onze standaardcategorieën of voeg je eigen categorieën toe.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6166,6 +6166,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
deleteFailureMessage: 'Wystąpił błąd podczas usuwania kategorii, spróbuj ponownie',
categoryName: 'Nazwa kategorii',
requiresCategory: 'Członkowie muszą kategoryzować wszystkie wydatki',
autoCategorizeNewExpenses: 'Automatycznie kategoryzuj nowe wydatki',
showCategoryGLCodes: 'Pokaż kody GL podczas kategoryzowania wydatków',
needCategoryForExportToIntegration: (connectionName: string) => `Wszystkie wydatki muszą zostać skategoryzowane, aby można je było wyeksportować do ${connectionName}.`,
subtitle: 'Uzyskaj lepszy wgląd w to, gdzie wydawane są pieniądze. Użyj naszych domyślnych kategorii lub dodaj własne.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6143,6 +6143,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
deleteFailureMessage: 'Ocorreu um erro ao excluir a categoria, tente novamente',
categoryName: 'Nome da categoria',
requiresCategory: 'Os membros devem categorizar todas as despesas',
autoCategorizeNewExpenses: 'Categorizar automaticamente novas despesas',
showCategoryGLCodes: 'Mostrar códigos GL ao categorizar despesas',
needCategoryForExportToIntegration: (connectionName: string) => `Todas as despesas devem ser categorizadas para serem exportadas para ${connectionName}.`,
subtitle: 'Tenha uma visão melhor de onde o dinheiro está sendo gasto. Use nossas categorias padrão ou adicione as suas.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5936,6 +5936,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
deleteFailureMessage: '删除类别时出错,请重试',
categoryName: '类别名称',
requiresCategory: '成员必须为所有报销分类',
autoCategorizeNewExpenses: '自动为新报销分类',
showCategoryGLCodes: '在分类报销时显示总账科目代码',
needCategoryForExportToIntegration: (connectionName: string) => `要导出到 ${connectionName},所有报销都必须先进行分类。`,
subtitle: '更好地了解资金的支出去向。使用我们的默认类别或添加你自己的类别。',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type SetPolicyAutoCategorizeNewExpensesParams = {
policyID: string;
enabled: boolean;
};

export default SetPolicyAutoCategorizeNewExpensesParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export type {default as SetWorkspaceCategoriesEnabledParams} from './SetWorkspac
export type {default as CreateWorkspaceCategoriesParams} from './CreateWorkspaceCategoriesParams';
export type {default as RenameWorkspaceCategoriesParams} from './RenameWorkspaceCategoriesParams';
export type {default as SetWorkspaceRequiresCategoryParams} from './SetWorkspaceRequiresCategoryParams';
export type {default as SetPolicyAutoCategorizeNewExpensesParams} from './SetPolicyAutoCategorizeNewExpensesParams';
export type {default as SetPolicyShowCategoryGLCodesParams} from './SetPolicyShowCategoryGLCodesParams';
export type {default as DeleteWorkspaceCategoriesParams} from './DeleteWorkspaceCategoriesParams';
export type {default as UpdatePolicyCategoryPayrollCodeParams} from './UpdatePolicyCategoryPayrollCodeParams';
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 @@ -189,6 +189,7 @@ const WRITE_COMMANDS = {
CREATE_POLICY_TAG: 'CreatePolicyTag',
RENAME_POLICY_TAG: 'RenamePolicyTag',
SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory',
SET_POLICY_AUTO_CATEGORIZE_NEW_EXPENSES: 'SetPolicyAutoCategorizeNewExpenses',
SET_POLICY_SHOW_CATEGORY_GL_CODES: 'SetPolicyShowCategoryGLCodes',
UPDATE_POLICY_CATEGORY_PAYROLL_CODE: 'UpdatePolicyCategoryPayrollCode',
UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode',
Expand Down Expand Up @@ -847,6 +848,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.EXPORT_RECEIPTS_TO_ZIP]: Parameters.ExportReceiptsToZipParams;
[WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams;
[WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams;
[WRITE_COMMANDS.SET_POLICY_AUTO_CATEGORIZE_NEW_EXPENSES]: Parameters.SetPolicyAutoCategorizeNewExpensesParams;
[WRITE_COMMANDS.SET_POLICY_SHOW_CATEGORY_GL_CODES]: Parameters.SetPolicyShowCategoryGLCodesParams;
[WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams;
[WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_PAYROLL_CODE]: Parameters.UpdatePolicyCategoryPayrollCodeParams;
Expand Down
11 changes: 9 additions & 2 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1795,12 +1795,19 @@ function isReceiptBeingScanned(transaction: OnyxInputOrEntry<Transaction>): bool

/**
* Check if category is being analyzed (manual request creation or auto-categorization grace period)
*
* @param transaction - The transaction whose category may still be auto-categorized
* @param policy - The workspace policy; auto-categorize defaults to on when the attribute is unset
*/
function isCategoryBeingAnalyzed(transaction: OnyxEntry<Transaction>): boolean {
function isCategoryBeingAnalyzed(transaction: OnyxEntry<Transaction>, policy?: OnyxEntry<Policy>): boolean {
if (!transaction) {
return false;
}

if (policy?.autoCategorizeNewExpenses === false) {
return false;
}

if (isExpenseUnreported(transaction)) {
return false;
}
Expand Down Expand Up @@ -2095,7 +2102,7 @@ function shouldShowViolation(
return isAttendeeTrackingEnabledForPolicy(policy);
}

if (violationName === CONST.VIOLATIONS.MISSING_CATEGORY && isCategoryBeingAnalyzed(transaction)) {
if (violationName === CONST.VIOLATIONS.MISSING_CATEGORY && isCategoryBeingAnalyzed(transaction, policy)) {
return false;
}

Expand Down
57 changes: 57 additions & 0 deletions src/libs/actions/Policy/Category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,62 @@ function setWorkspaceRequiresCategory(policyData: PolicyData, requiresCategory:
API.write(WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY, parameters, onyxData);
}

function setPolicyAutoCategorizeNewExpenses(policyID: string, enabled: boolean) {
const onyxData: OnyxData<typeof ONYXKEYS.COLLECTION.POLICY> = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
autoCategorizeNewExpenses: enabled,
errorFields: {
autoCategorizeNewExpenses: null,
},
pendingFields: {
autoCategorizeNewExpenses: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
errorFields: {
autoCategorizeNewExpenses: null,
},
pendingFields: {
autoCategorizeNewExpenses: null,
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
autoCategorizeNewExpenses: !enabled,
errorFields: {
autoCategorizeNewExpenses: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateFailureMessage'),
},
pendingFields: {
autoCategorizeNewExpenses: null,
},
},
},
],
};

const parameters = {
policyID,
enabled,
};

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

function setPolicyShowCategoryGLCodes(policyID: string | undefined, showCategoryGLCodes: boolean) {
if (!policyID) {
return;
Expand Down Expand Up @@ -2004,5 +2060,6 @@ export {
setWorkspaceCategoryDescriptionHint,
setWorkspaceCategoryEnabled,
setWorkspaceRequiresCategory,
setPolicyAutoCategorizeNewExpenses,
setPolicyShowCategoryGLCodes,
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnec
import withPolicyConnections from '@pages/workspace/withPolicyConnections';
import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';

import {setPolicyShowCategoryGLCodes, setWorkspaceRequiresCategory} from '@userActions/Policy/Category';
import {setPolicyAutoCategorizeNewExpenses, setPolicyShowCategoryGLCodes, setWorkspaceRequiresCategory} from '@userActions/Policy/Category';
import {clearPolicyErrorField} from '@userActions/Policy/Policy';

import CONST from '@src/CONST';
Expand Down Expand Up @@ -60,6 +60,13 @@ function DynamicWorkspaceCategoriesSettingsPage({policy, route}: DynamicWorkspac
[policyData],
);

const updateAutoCategorizeNewExpenses = useCallback(
(value: boolean) => {
setPolicyAutoCategorizeNewExpenses(policyID, value);
},
[policyID],
);

const updateShowCategoryGLCodes = (value: boolean) => {
setPolicyShowCategoryGLCodes(policyID, value);
};
Expand All @@ -83,9 +90,6 @@ function DynamicWorkspaceCategoriesSettingsPage({policy, route}: DynamicWorkspac
const hasEnabledCategories = hasEnabledOptions(policyData.categories);
const isToggleDisabled = !policy?.areCategoriesEnabled || !hasEnabledCategories || isConnectedToAccounting;

// Under the revamp only the GL codes toggle is left here, so the page has nothing to show without it.
const shouldBlockEmptySettings = isRulesRevampEnabled && !policy?.glCodes;

const onSelectItem = (item: ListItem) => {
if (!item.groupID) {
return;
Expand All @@ -111,7 +115,6 @@ function DynamicWorkspaceCategoriesSettingsPage({policy, route}: DynamicWorkspac
policyID={policyID}
accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
featureName={CONST.POLICY.MORE_FEATURES.ARE_CATEGORIES_ENABLED}
shouldBeBlocked={shouldBlockEmptySettings}
>
<ScreenWrapper
enableEdgeToEdgeBottomSafeAreaPadding
Expand All @@ -138,6 +141,17 @@ function DynamicWorkspaceCategoriesSettingsPage({policy, route}: DynamicWorkspac
shouldPlaceSubtitleBelowSwitch
/>
)}
<ToggleSettingOptionRow
title={translate('workspace.categories.autoCategorizeNewExpenses')}
switchAccessibilityLabel={translate('workspace.categories.autoCategorizeNewExpenses')}
isActive={policy?.autoCategorizeNewExpenses ?? true}
onToggle={updateAutoCategorizeNewExpenses}
pendingAction={policy?.pendingFields?.autoCategorizeNewExpenses}
disabled={!policy?.areCategoriesEnabled || !hasEnabledCategories}
wrapperStyle={[styles.pv2, styles.mh5]}
errors={policy?.errorFields?.autoCategorizeNewExpenses ?? undefined}
onCloseError={() => clearPolicyErrorField(policy?.id, 'autoCategorizeNewExpenses')}
/>
{!!policy?.glCodes && (
<ToggleSettingOptionRow
title={translate('workspace.categories.showCategoryGLCodes')}
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2999,6 +2999,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback<
/** Whether new transactions need to be categorized */
requiresCategory?: boolean;

/** Whether new uncategorized expenses get a category picked for them automatically. Defaults to true when unset. */
autoCategorizeNewExpenses?: boolean;

/** Whether to show category GL codes when selecting a category */
showCategoryGLCodes?: boolean;

Expand Down
Loading
Loading