1+ import isEmpty from 'lodash/isEmpty' ;
2+ import keyBy from 'lodash/keyBy' ;
13import reject from 'lodash/reject' ;
24import Onyx from 'react-native-onyx' ;
35import type { OnyxUpdate } from 'react-native-onyx' ;
@@ -162,6 +164,17 @@ function getTagViolationsForMultiLevelTags(
162164 return getTagViolationForIndependentTags ( policyTagList , filteredTransactionViolations , updatedTransaction ) ;
163165}
164166
167+ /**
168+ * Returns a period-separated string of violation messages for missing tag levels in a multi-level tag, based on error indexes.
169+ */
170+ function getTagViolationMessagesForMultiLevelTags ( tagName : string , errorIndexes : number [ ] , tags : PolicyTagLists , translate : LocaleContextProps [ 'translate' ] ) : string {
171+ if ( isEmpty ( errorIndexes ) || isEmpty ( tags ) ) {
172+ return translate ( 'violations.someTagLevelsRequired' , { tagName} ) ;
173+ }
174+ const tagsWithIndexes = keyBy ( Object . values ( tags ) , 'orderWeight' ) ;
175+ return errorIndexes . map ( ( i ) => translate ( 'violations.someTagLevelsRequired' , { tagName : tagsWithIndexes [ i ] ?. name } ) ) . join ( '. ' ) ;
176+ }
177+
165178/**
166179 * Extracts unique error messages from errors and actions
167180 */
@@ -392,7 +405,7 @@ const ViolationsUtils = {
392405 * possible values could be either translation keys that resolve to strings or translation keys that resolve to
393406 * functions.
394407 */
395- getViolationTranslation ( violation : TransactionViolation , translate : LocaleContextProps [ 'translate' ] , canEdit = true ) : string {
408+ getViolationTranslation ( violation : TransactionViolation , translate : LocaleContextProps [ 'translate' ] , canEdit = true , tags ?: PolicyTagLists ) : string {
396409 const {
397410 brokenBankConnection = false ,
398411 isAdmin = false ,
@@ -406,11 +419,12 @@ const ViolationsUtils = {
406419 surcharge = 0 ,
407420 invoiceMarkup = 0 ,
408421 maxAge = 0 ,
409- tagName,
422+ tagName = '' ,
410423 taxName,
411424 type,
412425 rterType,
413426 message = '' ,
427+ errorIndexes = [ ] ,
414428 } = violation . data ?? { } ;
415429
416430 switch ( violation . name ) {
@@ -481,7 +495,7 @@ const ViolationsUtils = {
481495 case 'smartscanFailed' :
482496 return translate ( 'violations.smartscanFailed' , { canEdit} ) ;
483497 case 'someTagLevelsRequired' :
484- return translate ( 'violations.someTagLevelsRequired' , { tagName } ) ;
498+ return getTagViolationMessagesForMultiLevelTags ( tagName , errorIndexes , tags ?? { } , translate ) ;
485499 case 'tagOutOfPolicy' :
486500 return translate ( 'violations.tagOutOfPolicy' , { tagName} ) ;
487501 case 'taxAmountChanged' :
@@ -520,6 +534,7 @@ const ViolationsUtils = {
520534 translate : LocaleContextProps [ 'translate' ] ,
521535 missingFieldError ?: string ,
522536 transactionThreadActions ?: ReportAction [ ] ,
537+ tags ?: PolicyTagLists ,
523538 ) : string {
524539 const errorMessages = extractErrorMessages ( transaction ?. errors ?? { } , transactionThreadActions ?. filter ( ( e ) => ! ! e . errors ) ?? [ ] , translate ) ;
525540
@@ -529,7 +544,7 @@ const ViolationsUtils = {
529544 // Some violations end with a period already so lets make sure the connected messages have only single period between them
530545 // and end with a single dot.
531546 ...transactionViolations . map ( ( violation ) => {
532- const message = ViolationsUtils . getViolationTranslation ( violation , translate ) ;
547+ const message = ViolationsUtils . getViolationTranslation ( violation , translate , true , tags ) ;
533548 if ( ! message ) {
534549 return ;
535550 }
0 commit comments