@@ -23,6 +23,33 @@ import SCREENS from '@src/SCREENS';
2323import type { Errors } from '@src/types/onyx/OnyxCommon' ;
2424import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue' ;
2525
26+ /**
27+ * Parses a CSV cell value for receipt requirement columns.
28+ * Mirrors the OD import logic: "required"/"always_required" → 0,
29+ * "not_required" → DISABLED_MAX_EXPENSE_VALUE, numeric string → number.
30+ * Returns undefined for unmapped columns, empty/default values, or invalid input.
31+ */
32+ function parseCsvReceiptValue ( raw : string | undefined ) : number | undefined {
33+ if ( raw === undefined ) {
34+ return undefined ;
35+ }
36+ const trimmed = raw . trim ( ) . toLowerCase ( ) ;
37+ if ( ! trimmed || trimmed === 'default' ) {
38+ return undefined ;
39+ }
40+ if ( trimmed === 'required' || trimmed === 'always_required' ) {
41+ return 0 ;
42+ }
43+ if ( trimmed === 'not_required' ) {
44+ return CONST . DISABLED_MAX_EXPENSE_VALUE ;
45+ }
46+ const num = Number ( trimmed ) ;
47+ if ( Number . isFinite ( num ) && num >= 0 ) {
48+ return num ;
49+ }
50+ return undefined ;
51+ }
52+
2653type ImportedCategoriesPageProps = {
2754 route : RouteProp < SettingsNavigatorParamList , typeof SCREENS . WORKSPACE . DYNAMIC_CATEGORIES_IMPORTED | typeof SCREENS . SETTINGS_CATEGORIES . SETTINGS_CATEGORIES_IMPORTED > ;
2855} ;
@@ -52,7 +79,11 @@ function ImportedCategoriesPage({route}: ImportedCategoriesPageProps) {
5279 ) ;
5380
5481 if ( isControlPolicy ( policy ) ) {
55- roles . push ( { text : translate ( 'workspace.categories.glCode' ) , value : CONST . CSV_IMPORT_COLUMNS . GL_CODE } ) ;
82+ roles . push (
83+ { text : translate ( 'workspace.categories.glCode' ) , value : CONST . CSV_IMPORT_COLUMNS . GL_CODE } ,
84+ { text : translate ( 'workspace.rules.categoryRules.requireReceiptsOver' ) , value : CONST . CSV_IMPORT_COLUMNS . MAX_AMOUNT_NO_RECEIPT } ,
85+ { text : translate ( 'workspace.rules.categoryRules.requireItemizedReceiptsOver' ) , value : CONST . CSV_IMPORT_COLUMNS . MAX_AMOUNT_NO_ITEMIZED_RECEIPT } ,
86+ ) ;
5687 }
5788
5889 return roles ;
@@ -99,17 +130,29 @@ function ImportedCategoriesPage({route}: ImportedCategoriesPageProps) {
99130 const categoriesNamesColumn = columns . findIndex ( ( column ) => column === CONST . CSV_IMPORT_COLUMNS . NAME ) ;
100131 const categoriesGLCodeColumn = columns . findIndex ( ( column ) => column === CONST . CSV_IMPORT_COLUMNS . GL_CODE ) ;
101132 const categoriesEnabledColumn = columns . findIndex ( ( column ) => column === CONST . CSV_IMPORT_COLUMNS . ENABLED ) ;
133+ const categoriesMaxAmountNoReceiptColumn = columns . findIndex ( ( column ) => column === CONST . CSV_IMPORT_COLUMNS . MAX_AMOUNT_NO_RECEIPT ) ;
134+ const categoriesMaxAmountNoItemizedReceiptColumn = columns . findIndex ( ( column ) => column === CONST . CSV_IMPORT_COLUMNS . MAX_AMOUNT_NO_ITEMIZED_RECEIPT ) ;
102135 const categoriesNames = spreadsheet ?. data [ categoriesNamesColumn ] . map ( ( name ) => name ) ;
103136 const categoriesEnabled = categoriesEnabledColumn !== - 1 ? spreadsheet ?. data [ categoriesEnabledColumn ] . map ( ( enabled ) => enabled ) : [ ] ;
104137 const categoriesGLCode = categoriesGLCodeColumn !== - 1 ? spreadsheet ?. data [ categoriesGLCodeColumn ] . map ( ( glCode ) => glCode ) : [ ] ;
138+ const categoriesMaxAmountNoReceipt = categoriesMaxAmountNoReceiptColumn !== - 1 ? spreadsheet ?. data [ categoriesMaxAmountNoReceiptColumn ] : [ ] ;
139+ const categoriesMaxAmountNoItemizedReceipt = categoriesMaxAmountNoItemizedReceiptColumn !== - 1 ? spreadsheet ?. data [ categoriesMaxAmountNoItemizedReceiptColumn ] : [ ] ;
105140 const categories = categoriesNames ?. slice ( containsHeader ? 1 : 0 ) . map ( ( name , index ) => {
106141 const categoryAlreadyExists = policyCategories ?. [ name ] ;
107142 const existingGLCodeOrDefault = categoryAlreadyExists ?. [ 'GL Code' ] ?? '' ;
143+ const dataIndex = containsHeader ? index + 1 : index ;
144+
145+ const parsedMaxAmountNoReceipt = categoriesMaxAmountNoReceiptColumn !== - 1 ? parseCsvReceiptValue ( categoriesMaxAmountNoReceipt ?. [ dataIndex ] ?. toString ( ) ) : undefined ;
146+ const parsedMaxAmountNoItemizedReceipt =
147+ categoriesMaxAmountNoItemizedReceiptColumn !== - 1 ? parseCsvReceiptValue ( categoriesMaxAmountNoItemizedReceipt ?. [ dataIndex ] ?. toString ( ) ) : undefined ;
148+
108149 return {
109150 name,
110- enabled : categoriesEnabledColumn !== - 1 ? [ 'true' , 'yes' ] . includes ( categoriesEnabled ?. [ containsHeader ? index + 1 : index ] ?. toString ( ) . trim ( ) . toLowerCase ( ) ?? '' ) : true ,
151+ enabled : categoriesEnabledColumn !== - 1 ? [ 'true' , 'yes' ] . includes ( categoriesEnabled ?. [ dataIndex ] ?. toString ( ) . trim ( ) . toLowerCase ( ) ?? '' ) : true ,
111152 // eslint-disable-next-line @typescript-eslint/naming-convention
112- 'GL Code' : categoriesGLCodeColumn !== - 1 ? ( categoriesGLCode ?. [ containsHeader ? index + 1 : index ] ?? '' ) : existingGLCodeOrDefault ,
153+ 'GL Code' : categoriesGLCodeColumn !== - 1 ? ( categoriesGLCode ?. [ dataIndex ] ?? '' ) : existingGLCodeOrDefault ,
154+ ...( parsedMaxAmountNoReceipt !== undefined && { maxAmountNoReceipt : parsedMaxAmountNoReceipt } ) ,
155+ ...( parsedMaxAmountNoItemizedReceipt !== undefined && { maxAmountNoItemizedReceipt : parsedMaxAmountNoItemizedReceipt } ) ,
113156 } ;
114157 } ) ;
115158
0 commit comments