@@ -17,7 +17,7 @@ const router = express.Router()
1717router . use ( ( req , res , next ) => {
1818 const token = req . get ( 'x-auth-token' )
1919 if ( ! ! token && token === AUTH_TOKEN ) {
20- next ( )
20+ next ( )
2121 } else {
2222 res . status ( 401 ) . json ( { message : 'Invalid auth token' } )
2323 }
@@ -80,6 +80,29 @@ router.post('/lambda/json-to-excel/common-styled', async (req, res) => {
8080 }
8181} )
8282
83+ router . post ( '/lambda/json-to-excel/client-styled' , async ( req , res ) => {
84+ console . log ( 'styled working' )
85+ try {
86+ const jsonData = req . body . excel
87+ const excelData = await convertJsonToStyledExcel ( jsonData )
88+ let finalBuffer = excelData
89+ if ( jsonData . Countries . data ?. length ) {
90+ const sheetName = 'Clients'
91+ const wb = new ExcelJS . Workbook ( )
92+ await wb . xlsx . load ( excelData )
93+ await injectClientTemplateColumnsIntoSheet ( wb , sheetName , jsonData . Countries . data )
94+ finalBuffer = await wb . xlsx . writeBuffer ( )
95+ } else {
96+ console . log ( '❌ No countries found, skipping injection' )
97+ }
98+ const url = await uploadToAWS ( req . body . config , finalBuffer )
99+ return res . json ( { url } )
100+ } catch ( error ) {
101+ console . log ( 'error' , error )
102+ res . status ( 400 ) . json ( { message : 'error in your request payload' , error : error . message , rawError : error } )
103+ }
104+ } )
105+
83106router . post ( '/api/jsonToExcel' , async ( req , res ) => {
84107 try {
85108 console . log ( 'old path' )
@@ -113,6 +136,76 @@ const uploadToAWS = async (config, excelData) => {
113136 const response = await s3 . upload ( dataset ) . promise ( )
114137 return response . Location
115138}
139+ async function injectClientTemplateColumnsIntoSheet ( workbook , sheetName , data ) {
140+ const sheet = workbook . getWorksheet ( sheetName ) || workbook . worksheets [ 0 ]
141+ if ( ! sheet ) throw new Error ( 'Target sheet not found' )
142+ // Create (or reuse) a hidden sheet "Countries"
143+ const countrySheet = workbook . getWorksheet ( 'Countries' ) || workbook . addWorksheet ( 'Countries' )
144+ countrySheet . state = 'veryHidden'
145+ // Headers
146+ countrySheet . getCell ( 'A1' ) . value = 'Country'
147+ countrySheet . getCell ( 'B1' ) . value = 'Currency'
148+ // find max nob length
149+ const maxNobs = Math . max ( ...data . map ( c => ( c . nob || [ ] ) . length ) )
150+ for ( let j = 0 ; j < maxNobs ; j ++ ) {
151+ countrySheet . getCell ( 1 , 3 + j ) . value = `NOB${ j + 1 } `
152+ }
153+ // Fill rows
154+ data . forEach ( ( c , i ) => {
155+ const r = i + 2
156+ countrySheet . getCell ( r , 1 ) . value = c . country || ''
157+ countrySheet . getCell ( r , 2 ) . value = c . currency || ''
158+ ; ( c . nob || [ ] ) . forEach ( ( n , j ) => {
159+ countrySheet . getCell ( r , 3 + j ) . value = n
160+ } )
161+ // Named range for each country NOBs
162+ const fromCol = 3
163+ const toCol = 2 + maxNobs
164+ const range = `${ countrySheet . name } !$${ String . fromCharCode ( 65 + fromCol - 1 ) } ${ r } :$${ String . fromCharCode ( 65 + toCol - 1 ) } ${ r } `
165+ // countrySheet.workbook.definedNames.addName(c.country.replace(/\s+/g, "_"), range)
166+ } )
167+ const lastRow = data . length + 1
168+ const countryList = `Countries!$A$2:$A$${ lastRow } `
169+ // Find target columns in client sheet
170+ const findHeaderCol = ( names ) => {
171+ const headerRow = sheet . getRow ( 1 )
172+ for ( let col = 1 ; col <= sheet . columnCount ; col ++ ) {
173+ const val = headerRow . getCell ( col ) ?. value
174+ const text = typeof val === 'object'
175+ ? ( val ?. richText ?. map ( rt => rt . text ) . join ( '' ) || val ?. result || '' )
176+ : ( val || '' )
177+ if ( names . includes ( String ( text ) . trim ( ) ) ) return col
178+ }
179+ return null
180+ }
181+ let colCountry = findHeaderCol ( [ 'Country' , 'country' ] )
182+ let colNob = findHeaderCol ( [ 'Nature of Business*' , 'category' , 'NoB' ] )
183+ let colCurrency = findHeaderCol ( [ 'Currency' , 'currency' ] )
184+ // Apply validations row-wise
185+ const maxRow = Math . max ( sheet . rowCount , 200 )
186+ for ( let row = 2 ; row <= maxRow ; row ++ ) {
187+ const countryCell = sheet . getRow ( row ) . getCell ( colCountry )
188+ // Country dropdown
189+ countryCell . dataValidation = {
190+ type : 'list' ,
191+ allowBlank : true ,
192+ formulae : [ countryList ] ,
193+ }
194+ // Nob dropdown (dependent on country)
195+ const nobCell = sheet . getRow ( row ) . getCell ( colNob )
196+ const nobFormula = `=OFFSET(Countries!$C$2,MATCH(${ countryCell . address } ,Countries!$A$2:$A$${ lastRow } ,0)-1,0,1,COUNTA(OFFSET(Countries!$C$2,MATCH(${ countryCell . address } ,Countries!$A$2:$A$${ lastRow } ,0)-1,0,1,200)))`
197+ nobCell . dataValidation = {
198+ type : 'list' ,
199+ allowBlank : true ,
200+ formulae : [ nobFormula ] ,
201+ }
202+ // Currency autofill
203+ const currencyCell = sheet . getRow ( row ) . getCell ( colCurrency )
204+ currencyCell . value = {
205+ formula : `=IF(${ countryCell . address } ="","",VLOOKUP(${ countryCell . address } ,Countries!$A$2:$B$${ lastRow } ,2,FALSE))`
206+ }
207+ }
208+ }
116209
117210const convertJsonToExcel = ( jsonData ) => {
118211 const workbook = xlsx . utils . book_new ( )
0 commit comments