@@ -40,7 +40,8 @@ const toHtmlTable = (rows, columns, summaryRow, exportColumns, isCustomExport, t
4040 const keys = Object . keys ( isCustomExport ? exportColumns : rows [ 0 ] ) ;
4141 columns = [ ] ;
4242 for ( const dataKey of keys ) {
43- columns . push ( { dataKey, title : isCustomExport ? exportColumns [ dataKey ] ?. name : dataKey } ) ;
43+ const { name : title = dataKey , ...others } = exportColumns [ dataKey ] || { } ;
44+ columns . push ( { dataKey, title, ...others } ) ;
4445 }
4546 }
4647
@@ -171,41 +172,45 @@ const updateKeys = function ({ data, keyMapping, columns, isForXML = false, user
171172 const updatedRecord = { } ;
172173
173174 for ( const ele of Object . keys ( keyMapping ) ) {
174- const keyName = isForXML ? ele : keyMapping [ ele ] ;
175- const { valueType, keepUTC = false } = columns [ ele ] ;
176-
177- let value = record [ ele ] ;
178-
179- const isParsable = columns [ ele ] ?. isParsable !== false ? true : columns [ ele ] ?. isParsable ;
180-
181- if ( util . dateTimeFields . includes ( valueType ) ) {
182- if ( value !== null && value !== undefined ) {
183- if ( userTimezoneOffset && ! keepUTC ) {
184- value = dayjs . utc ( value ) . add ( Number ( userTimezoneOffset ) , 'minute' )
175+ if ( columns [ ele ] ) {
176+ const keyName = isForXML ? ele : keyMapping [ ele ] ;
177+ const { valueType, keepUTC = false } = columns [ ele ] ;
178+
179+ let value = record [ ele ] ;
180+
181+ const isParsable = columns [ ele ] ?. isParsable !== false ? true : columns [ ele ] ?. isParsable ;
182+
183+ if ( util . dateTimeFields . includes ( valueType ) ) {
184+ if ( value !== null && value !== undefined ) {
185+ if ( userTimezoneOffset && ! keepUTC ) {
186+ value = dayjs . utc ( value ) . add ( Number ( userTimezoneOffset ) , 'minute' )
187+ }
188+ value = formatDateTime ( { value, format : valueType === 'date' ? userDateFormat : userDateTimeFormat } ) ;
189+ } else {
190+ value = '' ;
185191 }
186- value = formatDateTime ( { value, format : valueType === 'date' ? userDateFormat : userDateTimeFormat } ) ;
187- } else {
188- value = '' ;
192+ } else if ( valueType === 'boolean' ) {
193+ value = value === true || value === 1 ? 'Yes' : 'No' ;
194+ } else if ( valueType === 'number' && isParsable ) {
195+ value = value !== null ? parseInt ( value ) : '' ;
196+ } else if ( valueType === 'percentage' ) {
197+ value = util . percentageFormatter ( value ) ;
189198 }
190- } else if ( valueType === 'boolean' ) {
191- value = value === true || value === 1 ? 'Yes' : 'No' ;
192- } else if ( valueType === 'number' && isParsable ) {
193- value = value !== null ? parseInt ( value ) : '' ;
194- }
195199
196- for ( const field in lookupFields ) {
197- const lookupKeyName = lookupFields [ field ] . keyName ;
198- const key = isForXML ? keyName : ele ;
199- if ( lookupKeyName . includes ( key ) ) {
200- const lookupValue = lookupFields [ field ] . lookupKey ;
201- const indexValue = lookups [ lookupValue ] ?. findIndex ( e => e . value === value ) ;
202- if ( indexValue > - 1 ) {
203- value = lookups [ lookupValue ] [ indexValue ] . label ;
200+ for ( const field in lookupFields ) {
201+ const lookupKeyName = lookupFields [ field ] . keyName ;
202+ const key = isForXML ? keyName : ele ;
203+ if ( lookupKeyName . includes ( key ) ) {
204+ const lookupValue = lookupFields [ field ] . lookupKey ;
205+ const indexValue = lookups [ lookupValue ] ?. findIndex ( e => e . value === value ) ;
206+ if ( indexValue > - 1 ) {
207+ value = lookups [ lookupValue ] [ indexValue ] . label ;
208+ }
204209 }
205210 }
206- }
207211
208- updatedRecord [ keyName ] = [ undefined , null ] . includes ( value ) ? '' : value ;
212+ updatedRecord [ keyName ] = [ undefined , null ] . includes ( value ) ? '' : value ;
213+ }
209214 }
210215
211216 return updatedRecord ;
@@ -281,7 +286,9 @@ const sanitizeData = ({ data, columns = {}, responseType }) => {
281286 return data . map ( record =>
282287 fieldsToKeep . reduce ( ( acc , field ) => {
283288 let name = columns [ field ] ?. name || field ;
284- const value = record [ field ] ;
289+ // Fallback logic: check both the original field and the renamed column name.
290+ // This handles cases where columns have been renamed and the original field name might not exist in the record.
291+ const value = record [ field ] ?? record [ name ] ;
285292 if ( responseType === mimeTypes . xml ) {
286293 // Ensure name is a string before calling replace
287294 name = ( typeof name === 'string' ? name : String ( name || field ) ) . replace ( / [ ^ a - z A - Z 0 - 9 . _ - ] / g, '' ) ;
@@ -302,7 +309,7 @@ const responseTransformer = async function (req, res, next) {
302309 const exportColumns = others ?. exportColumns , userDateFormat = others ?. userDateFormat , isElastic = others ?. isElastic , userTimezoneOffset = others ?. userTimezoneOffset , lookups = others ?. lookups , lookupFields = others ?. lookupFields , addExecutionTimeLogger = others ?. addExecutionTimeLogger ;
303310 const dateTimeFormat = userDateFormat + util . dateTimeExportFormat ;
304311 const isMultiSheetExport = others ?. isMultiSheetExport || false ;
305-
312+
306313 // Safely handle req.path to prevent TypeError: r.replace is not a function
307314 const safePath = ( req . path && typeof req . path === 'string' ) ? req . path . substr ( 1 ) : 'export' ;
308315 fileName = `${ ! fileName ? safePath . replace ( util . fileNameRegex , '-' ) : fileName } -${ dayjs ( ) . format ( enums . fullDateFormat ) } ` ;
@@ -374,26 +381,7 @@ const responseTransformer = async function (req, res, next) {
374381 logger . info ( `Execution time taken for updateKeys: ${ endTimeUpdateKeys - updateKeysStartTime } ms` ) ;
375382 }
376383 }
377- }
378- // Iterates over each record to format Date fields using the appropriate date or datetime format.
379- // Also converts boolean values to strings based on the exportColumns configuration.
380- if ( Array . isArray ( data ) ) {
381- data = data . map ( record => {
382- const formattedRecord = { ...record } ; // create a shallow copy of the record
383- for ( const [ key , value ] of Object . entries ( record ) ) {
384- if ( exportColumns && ! exportColumns [ key ] ) {
385- continue ;
386- }
387- if ( value && value instanceof Date ) {
388- formattedRecord [ key ] = formatDateTime ( { value, format : dateTimeFormat || enums . dateTimeExportFormat } ) ; // format date or datetime
389- continue ;
390- }
391- if ( value !== null && value !== undefined && typeof value === 'boolean' ) {
392- formattedRecord [ key ] = value . toString ( ) ; // convert boolean to string
393- }
394- }
395- return formattedRecord ;
396- } ) ;
384+ data = sheets [ 0 ] . rows ;
397385 }
398386 switch ( responseType ) {
399387 case mimeTypes . json :
@@ -407,7 +395,6 @@ const responseTransformer = async function (req, res, next) {
407395 }
408396 return Object . keys ( others ) . length === 1 ? res . json ( data ) : res . json ( jsonResponse ) ;
409397 case mimeTypes . xlsx :
410- data = data . data || data ;
411398 res . set ( 'Content-Type' , responseType ) ;
412399 res . set ( 'Content-Disposition' , `attachment; filename="${ fileName } .xlsx"` ) ;
413400 return await toExcel ( { sheets, stream : res , exportColumns : true , userDateFormat, userDateTimeFormat : dateTimeFormat , userTimezoneOffset, lookups, lookupFields, addExecutionTimeLogger } ) ;
0 commit comments