@@ -119,122 +119,166 @@ export function streamToCSV (
119119 }
120120}
121121
122- export const collapseSmallPayments = (
123- payments : TransactionsWithPaybuttonsAndPrices [ ] ,
124- currency : SupportedQuotesType ,
125- timezone : string ,
126- collapseThreshold : number
127- ) : TransactionFileData [ ] => {
128- const treatedPayments : TransactionFileData [ ] = [ ]
129- const tempTxGroups : Record < string , TransactionsWithPaybuttonsAndPrices [ ] > = { }
130- let totalPaymentsTreated = 0
131-
132- const pushTempGroup = ( groupKey : string ) : void => {
133- const tempTxGroup = tempTxGroups [ groupKey ]
134- if ( tempTxGroup === undefined || tempTxGroup . length === 0 ) return
135- if ( tempTxGroup . length === 1 ) {
136- pushTx ( tempTxGroup [ 0 ] )
137- tempTxGroups [ groupKey ] = [ ]
138- return
139- }
140- const totalAmount = tempTxGroup . reduce ( ( sum , p ) => sum + Number ( p . amount ) , 0 )
141- const totalValue = tempTxGroup . reduce ( ( sum , p ) => sum + Number ( getTransactionValue ( p ) [ currency ] ) , 0 )
142- const uniquePrices : Set < number > = new Set ( )
143- const quoteId = QUOTE_IDS [ currency . toUpperCase ( ) ]
144- tempTxGroup
145- . forEach ( tx => {
146- const price = tx . prices . find ( p => p . price . quoteId === quoteId ) ! . price . value
147- uniquePrices . add ( Number ( price ) )
122+ const getUniquePrices = ( tempTxGroup : TransactionsWithPaybuttonsAndPrices [ ] , groupKey : string , currency : SupportedQuotesType ) : Set < number > => {
123+ const uniquePrices : Set < number > = new Set ( )
124+ const quoteId = QUOTE_IDS [ currency . toUpperCase ( ) ]
125+ tempTxGroup
126+ . forEach ( tx => {
127+ const price = tx . prices . find ( p => p . price . quoteId === quoteId ) ! . price . value
128+ uniquePrices . add ( Number ( price ) )
129+ } )
130+ if ( uniquePrices . size !== 1 ) {
131+ if ( uniquePrices . size > 1 ) {
132+ const nonUniquePrices = [ ...uniquePrices ]
133+ const txsForPrice : Record < number , string [ ] > = { }
134+ nonUniquePrices . forEach ( nonUniquePrice => {
135+ txsForPrice [ nonUniquePrice ] = tempTxGroup . filter ( tx => nonUniquePrice === tx . prices . find ( p => p . price . quoteId === quoteId ) ! . price . value . toNumber ( ) ) . map ( tx => tx . id )
148136 } )
149- if ( uniquePrices . size !== 1 ) {
150- if ( uniquePrices . size > 1 ) {
151- const nonUniquePrices = [ ...uniquePrices ]
152- const txsForPrice : Record < number , string [ ] > = { }
153- nonUniquePrices . forEach ( nonUniquePrice => {
154- txsForPrice [ nonUniquePrice ] = tempTxGroup . filter ( tx => nonUniquePrice === tx . prices . find ( p => p . price . quoteId === quoteId ) ! . price . value . toNumber ( ) ) . map ( tx => tx . id )
155- } )
156- console . error ( 'ERROR WHEN TRYING TO COLLAPSE TXS INTO DIFFERENT PRICES:' , { txsForPrice, nonUniquePrices } )
157- } else {
158- console . error ( 'ERROR WHEN TRYING TO COLLAPSE TXS INTO DIFFERENT PRICES, NO PRICES FOR GROUP KEY' , { groupKey } )
159- }
160-
161- throw new Error (
162- RESPONSE_MESSAGES
163- . INVALID_PRICES_AMOUNT_FOR_TX_ON_CSV_CREATION_500 ( tempTxGroup . length ) . message
164- )
137+ console . error ( 'ERROR WHEN TRYING TO COLLAPSE TXS INTO DIFFERENT PRICES:' , { txsForPrice, nonUniquePrices } )
138+ } else {
139+ console . error ( 'ERROR WHEN TRYING TO COLLAPSE TXS INTO DIFFERENT PRICES, NO PRICES FOR GROUP KEY' , { groupKey } )
165140 }
166- const rate = new Prisma . Decimal ( uniquePrices . values ( ) . next ( ) . value as number )
167- const buttonName = tempTxGroup [ 0 ] . address . paybuttons [ 0 ] . paybutton . name
168- const notes = `${ buttonName } - ${ tempTxGroup . length . toString ( ) } transactions`
169141
170- totalPaymentsTreated += tempTxGroup . length
142+ throw new Error (
143+ RESPONSE_MESSAGES
144+ . INVALID_PRICES_AMOUNT_FOR_TX_ON_CSV_CREATION_500 ( tempTxGroup . length ) . message
145+ )
146+ }
147+ return uniquePrices
148+ }
171149
172- treatedPayments . push ( {
173- amount : totalAmount ,
174- value : totalValue ,
175- date : moment . tz ( tempTxGroup [ 0 ] . timestamp * 1000 , timezone ) ,
176- transactionId : DEFAULT_MULTI_VALUES_LINE_LABEL ,
177- rate,
178- currency,
179- address : DEFAULT_MULTI_VALUES_LINE_LABEL ,
180- newtworkId : tempTxGroup [ 0 ] . address . networkId ,
181- notes
182- } as TransactionFileData )
150+ const collapsePaymentsPushTx = (
151+ tx : TransactionsWithPaybuttonsAndPrices ,
152+ groupKey : string ,
153+ currency : SupportedQuotesType ,
154+ treatedPayments : TransactionFileData [ ] ,
155+ timezone : string
156+ ) : void => {
157+ const { timestamp, hash, address, amount } = tx
158+ const values = getTransactionValue ( tx )
159+ const value = Number ( values [ currency ] )
160+ const rate = tx . prices . find ( p => p . price . quoteId === QUOTE_IDS [ currency . toUpperCase ( ) ] ) ! . price . value
161+ const buttonNames = groupKey . split ( '_' ) . slice ( 2 ) . join ( ';' )
162+
163+ treatedPayments . push ( {
164+ amount,
165+ value,
166+ date : moment . tz ( timestamp * 1000 , timezone ) ,
167+ transactionId : hash ,
168+ rate,
169+ currency,
170+ address : address . address ,
171+ notes : buttonNames ,
172+ newtworkId : address . networkId
173+ } as TransactionFileData )
174+ }
183175
176+ const collapsePaymentsPushTempGroup = (
177+ groupKey : string ,
178+ tempTxGroups : Record < string , TransactionsWithPaybuttonsAndPrices [ ] > ,
179+ currency : SupportedQuotesType ,
180+ treatedPayments : TransactionFileData [ ] ,
181+ timezone : string
182+ ) : void => {
183+ const tempTxGroup = tempTxGroups [ groupKey ]
184+ if ( tempTxGroup === undefined || tempTxGroup . length === 0 ) return
185+ if ( tempTxGroup . length === 1 ) {
186+ collapsePaymentsPushTx ( tempTxGroup [ 0 ] , groupKey , currency , treatedPayments , timezone )
184187 tempTxGroups [ groupKey ] = [ ]
188+ return
185189 }
190+ const totalAmount = tempTxGroup . reduce ( ( sum , p ) => sum + Number ( p . amount ) , 0 )
191+ const totalValue = tempTxGroup . reduce ( ( sum , p ) => sum + Number ( getTransactionValue ( p ) [ currency ] ) , 0 )
192+ const uniquePrices = getUniquePrices ( tempTxGroup , groupKey , currency )
193+ const rate = new Prisma . Decimal ( uniquePrices . values ( ) . next ( ) . value as number )
194+ const buttonNames = groupKey . split ( '_' ) . slice ( 2 ) . join ( ';' )
195+ const notes = `${ buttonNames } - ${ tempTxGroup . length . toString ( ) } transactions`
196+
197+ treatedPayments . push ( {
198+ amount : totalAmount ,
199+ value : totalValue ,
200+ date : moment . tz ( tempTxGroup [ 0 ] . timestamp * 1000 , timezone ) ,
201+ transactionId : DEFAULT_MULTI_VALUES_LINE_LABEL ,
202+ rate,
203+ currency,
204+ address : DEFAULT_MULTI_VALUES_LINE_LABEL ,
205+ newtworkId : tempTxGroup [ 0 ] . address . networkId ,
206+ notes
207+ } as TransactionFileData )
186208
187- const pushTx = ( tx : TransactionsWithPaybuttonsAndPrices ) : void => {
188- const { timestamp, hash, address, amount } = tx
189- const values = getTransactionValue ( tx )
190- const value = Number ( values [ currency ] )
191- const rate = tx . prices . find ( p => p . price . quoteId === QUOTE_IDS [ currency . toUpperCase ( ) ] ) ! . price . value
209+ tempTxGroups [ groupKey ] = [ ]
210+ }
192211
193- treatedPayments . push ( {
194- amount,
195- value,
196- date : moment . tz ( timestamp * 1000 , timezone ) ,
197- transactionId : hash ,
198- rate,
199- currency,
200- address : address . address ,
201- notes : '' ,
202- newtworkId : address . networkId
203- } as TransactionFileData )
204- totalPaymentsTreated += 1
212+ const getButtonNames = ( tx : TransactionsWithPaybuttonsAndPrices , userId : string , paybuttonId ?: string ) : string => {
213+ let buttonNamesKey : string = ''
214+ const uniqueButtonNames = new Set (
215+ tx . address . paybuttons
216+ . filter ( pb => pb . paybutton . providerUserId === userId )
217+ . map ( pb => pb . paybutton . name )
218+ )
219+ if ( uniqueButtonNames . size > 1 ) {
220+ if ( paybuttonId !== undefined ) {
221+ buttonNamesKey = tx . address . paybuttons . find ( pb => pb . paybutton . id === paybuttonId ) ?. paybutton . name ?? ''
222+ } else {
223+ buttonNamesKey = [ ...uniqueButtonNames ] . join ( '_' )
224+ }
225+ } else {
226+ buttonNamesKey = uniqueButtonNames . values ( ) . next ( ) . value ?? ''
205227 }
228+ return buttonNamesKey
229+ }
230+
231+ export const collapseSmallPayments = (
232+ payments : TransactionsWithPaybuttonsAndPrices [ ] ,
233+ currency : SupportedQuotesType ,
234+ timezone : string ,
235+ collapseThreshold : number ,
236+ userId : string ,
237+ paybuttonId ?: string
238+ ) : TransactionFileData [ ] => {
239+ const treatedPayments : TransactionFileData [ ] = [ ]
240+ const tempTxGroups : Record < string , TransactionsWithPaybuttonsAndPrices [ ] > = { }
206241
207242 payments . forEach ( ( tx : TransactionsWithPaybuttonsAndPrices , index : number ) => {
208243 const { timestamp } = tx
209244 const values = getTransactionValue ( tx )
210245 const value = Number ( values [ currency ] )
211246 const dateKey = moment . tz ( timestamp * 1000 , timezone ) . format ( 'YYYY-MM-DD' )
212247 const dateKeyUTC = moment . utc ( timestamp * 1000 ) . format ( 'YYYY-MM-DD' )
213- const groupKey = `${ dateKey } _${ dateKeyUTC } `
248+ const buttonNamesKey = getButtonNames ( tx , userId , paybuttonId )
249+
250+ const groupKey = `${ dateKey } _${ dateKeyUTC } _${ buttonNamesKey } `
214251
252+ let nextGroupKey : string | null = ''
215253 const nextPayment = payments [ index + 1 ]
216- const nextDateKey = nextPayment === undefined ? null : moment . tz ( nextPayment . timestamp * 1000 , timezone ) . format ( 'YYYY-MM-DD' )
217- const nextDateKeyUTC = nextPayment === undefined ? null : moment . utc ( nextPayment . timestamp * 1000 ) . format ( 'YYYY-MM-DD' )
218- const nextGroupKey = nextDateKey === null || nextDateKeyUTC === null ? null : `${ nextDateKey } _${ nextDateKeyUTC } `
254+ if ( nextPayment !== undefined ) {
255+ const nextDateKey = moment . tz ( nextPayment . timestamp * 1000 , timezone ) . format ( 'YYYY-MM-DD' )
256+ const nextDateKeyUTC = moment . utc ( nextPayment . timestamp * 1000 ) . format ( 'YYYY-MM-DD' )
257+ const nextButtonName = getButtonNames ( nextPayment , userId , paybuttonId )
258+
259+ nextGroupKey = `${ nextDateKey } _${ nextDateKeyUTC } _${ nextButtonName } `
260+ } else {
261+ nextGroupKey = null
262+ }
219263
220264 if ( value < collapseThreshold ) {
221265 if ( tempTxGroups [ groupKey ] === undefined ) tempTxGroups [ groupKey ] = [ ]
222266 tempTxGroups [ groupKey ] . push ( tx )
223267 } else {
224- Object . keys ( tempTxGroups ) . forEach ( pushTempGroup )
225- pushTx ( tx )
268+ Object . keys ( tempTxGroups ) . forEach ( key => {
269+ collapsePaymentsPushTempGroup ( key , tempTxGroups , currency , treatedPayments , timezone )
270+ } )
271+ collapsePaymentsPushTx ( tx , groupKey , currency , treatedPayments , timezone )
226272 }
227273
228274 if ( nextGroupKey !== groupKey ) {
229- pushTempGroup ( groupKey )
275+ collapsePaymentsPushTempGroup ( groupKey , tempTxGroups , currency , treatedPayments , timezone )
230276 }
231277 } )
232278
233- Object . keys ( tempTxGroups ) . forEach ( pushTempGroup )
234-
235- if ( totalPaymentsTreated !== payments . length ) {
236- throw new Error ( 'Error to collapse payments' )
237- }
279+ Object . keys ( tempTxGroups ) . forEach ( key => {
280+ collapsePaymentsPushTempGroup ( key , tempTxGroups , currency , treatedPayments , timezone )
281+ } )
238282
239283 return treatedPayments
240284}
@@ -282,14 +326,17 @@ export const downloadTxsFile = async (
282326 currency : SupportedQuotesType ,
283327 timezone : string ,
284328 transactions : TransactionsWithPaybuttonsAndPrices [ ] ,
329+ userId : string ,
330+ paybuttonId ?: string ,
285331 collapseTransactions : boolean = true ,
286- collapseThreshold : number = DEFAULT_CSV_COLLAPSE_THRESHOLD ) : Promise < void > => {
332+ collapseThreshold : number = DEFAULT_CSV_COLLAPSE_THRESHOLD
333+ ) : Promise < void > => {
287334 const sortedPayments = sortPaymentsByNetworkId ( transactions )
288335 let treatedPayments : TransactionFileData [ ] = [ ]
289336 if ( collapseTransactions ) {
290- treatedPayments = collapseSmallPayments ( sortedPayments , currency , timezone , collapseThreshold )
337+ treatedPayments = collapseSmallPayments ( sortedPayments , currency , timezone , collapseThreshold , userId , paybuttonId )
291338 } else {
292- treatedPayments = getPaybuttonTransactionsFileData ( transactions , currency , timezone )
339+ treatedPayments = getPaybuttonTransactionsFileData ( sortedPayments , currency , timezone )
293340 }
294341 const mappedPaymentsData = treatedPayments . map ( payment => formatPaybuttonTransactionsFileData ( payment ) )
295342
0 commit comments