Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pages/api/paybutton/download/transactions/[paybuttonId].ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default async (req: any, res: any): Promise<void> => {
};
const transactions = await fetchTransactionsByPaybuttonId(paybutton.id, networkIdArray)
res.setHeader('Content-Type', 'text/csv')
await downloadTxsFile(res, quoteSlug, timezone, transactions)
await downloadTxsFile(res, quoteSlug, timezone, transactions, userId, paybuttonId)
} catch (error: any) {
switch (error.message) {
case RESPONSE_MESSAGES.PAYBUTTON_ID_NOT_PROVIDED_400.message:
Expand Down
2 changes: 1 addition & 1 deletion pages/api/payments/download/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default async (req: any, res: any): Promise<void> => {
networkIdArray = [networkId]
};
const transactions = await fetchAllPaymentsByUserId(userId, networkIdArray)
await downloadTxsFile(res, quoteSlug, timezone, transactions)
await downloadTxsFile(res, quoteSlug, timezone, transactions, userId)
} catch (error: any) {
switch (error.message) {
case RESPONSE_MESSAGES.METHOD_NOT_ALLOWED.message:
Expand Down
10 changes: 5 additions & 5 deletions tests/unittests/utils/files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,20 @@ describe('collapseSmallPayments', () => {


it('should collapse small payments correctly', () => {
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1);
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1, 'dev2-uid');

expect(result).toHaveLength(3);
});

it('should collapse small payments threshold 2 USD', () => {
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 2);
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 2, 'dev2-uid');

expect(result).toHaveLength(1);
});


it('amount should be the sum of colapsed tx amounts', () => {
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1);
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1, 'dev2-uid');
const sumOfSmallPaymentsAmount = Number(mockedSmallerThen1UsdPayments.reduce((sum, payment) => sum.plus(payment.amount), new Decimal(0)));

const collapsedPayment = result[1];
Expand All @@ -214,7 +214,7 @@ describe('collapseSmallPayments', () => {
});

it('value should be the sum of colapsed tx values - USD', () => {
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1);
const result = collapseSmallPayments(mockedPayments, currencyUsd, timezone, 1, 'dev2-uid');
const sumOfSmallPaymentsAmount = Number(mockedSmallerThen1UsdPayments.reduce((sum, payment) => sum.plus(Number(getTransactionValue(payment)[currencyUsd])), new Decimal(0)));

const collapsedPayment = result[1];
Expand All @@ -223,7 +223,7 @@ describe('collapseSmallPayments', () => {
});

it('value should be the sum of colapsed tx values - CAD', () => {
const result = collapseSmallPayments(mockedPayments, currencyCad, timezone, 1);
const result = collapseSmallPayments(mockedPayments, currencyCad, timezone, 1, 'dev2-uid');
const sumOfSmallPaymentsAmount = Number(mockedSmallerThen1UsdPayments.reduce((sum, payment) => sum.plus(Number(getTransactionValue(payment)[currencyCad])), new Decimal(0)));

const collapsedPayment = result[1];
Expand Down
70 changes: 56 additions & 14 deletions utils/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ export const collapseSmallPayments = (
payments: TransactionsWithPaybuttonsAndPrices[],
currency: SupportedQuotesType,
timezone: string,
collapseThreshold: number
collapseThreshold: number,
userId: string,
paybuttonId?: string
): TransactionFileData[] => {
const treatedPayments: TransactionFileData[] = []
const tempTxGroups: Record<string, TransactionsWithPaybuttonsAndPrices[]> = {}
Expand All @@ -133,7 +135,7 @@ export const collapseSmallPayments = (
const tempTxGroup = tempTxGroups[groupKey]
if (tempTxGroup === undefined || tempTxGroup.length === 0) return
if (tempTxGroup.length === 1) {
pushTx(tempTxGroup[0])
pushTx(tempTxGroup[0], groupKey)
tempTxGroups[groupKey] = []
return
}
Expand Down Expand Up @@ -164,8 +166,8 @@ export const collapseSmallPayments = (
)
}
const rate = new Prisma.Decimal(uniquePrices.values().next().value as number)
const buttonName = tempTxGroup[0].address.paybuttons[0].paybutton.name
const notes = `${buttonName} - ${tempTxGroup.length.toString()} transactions`
const buttonNames = groupKey.split('_').slice(2).join(' ; ')
const notes = `${buttonNames} - ${tempTxGroup.length.toString()} transactions`

totalPaymentsTreated += tempTxGroup.length

Expand All @@ -184,11 +186,12 @@ export const collapseSmallPayments = (
tempTxGroups[groupKey] = []
}

const pushTx = (tx: TransactionsWithPaybuttonsAndPrices): void => {
const pushTx = (tx: TransactionsWithPaybuttonsAndPrices, groupKey: string): void => {
const { timestamp, hash, address, amount } = tx
const values = getTransactionValue(tx)
const value = Number(values[currency])
const rate = tx.prices.find(p => p.price.quoteId === QUOTE_IDS[currency.toUpperCase()])!.price.value
const buttonNames = groupKey.split('_').slice(2).join(' ; ')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason for this spaces around the ;? It's somewhat counter intuitive and uncommon, so I'd take it out if there is no particular reason for it.


treatedPayments.push({
amount,
Expand All @@ -198,7 +201,7 @@ export const collapseSmallPayments = (
rate,
currency,
address: address.address,
notes: '',
notes: buttonNames,
newtworkId: address.networkId
} as TransactionFileData)
totalPaymentsTreated += 1
Expand All @@ -210,19 +213,55 @@ export const collapseSmallPayments = (
const value = Number(values[currency])
const dateKey = moment.tz(timestamp * 1000, timezone).format('YYYY-MM-DD')
const dateKeyUTC = moment.utc(timestamp * 1000).format('YYYY-MM-DD')
const groupKey = `${dateKey}_${dateKeyUTC}`
const uniqueButtonNames = new Set(
tx.address.paybuttons
.filter(pb => pb.paybutton.providerUserId === userId)
.map(pb => pb.paybutton.name)
)
let buttonNamesKey: string | undefined = ''
if (uniqueButtonNames.size > 1) {
if (paybuttonId !== undefined) {
buttonNamesKey = tx.address.paybuttons.find(pb => pb.paybutton.id === paybuttonId)?.paybutton.name ?? ''
} else {
buttonNamesKey = [...uniqueButtonNames].join('_')
}
} else {
buttonNamesKey = uniqueButtonNames.values().next().value ?? ''
}

const groupKey = `${dateKey}_${dateKeyUTC}_${buttonNamesKey}`
let nextGroupKey: string | null = ''

const nextPayment = payments[index + 1]
const nextDateKey = nextPayment === undefined ? null : moment.tz(nextPayment.timestamp * 1000, timezone).format('YYYY-MM-DD')
const nextDateKeyUTC = nextPayment === undefined ? null : moment.utc(nextPayment.timestamp * 1000).format('YYYY-MM-DD')
const nextGroupKey = nextDateKey === null || nextDateKeyUTC === null ? null : `${nextDateKey}_${nextDateKeyUTC}`
if (nextPayment !== undefined) {
const nextDateKey = moment.tz(nextPayment.timestamp * 1000, timezone).format('YYYY-MM-DD')
const nextDateKeyUTC = moment.utc(nextPayment.timestamp * 1000).format('YYYY-MM-DD')
const nextUniqueButtonName = new Set(
nextPayment.address.paybuttons
.filter(pb => pb.paybutton.providerUserId === userId)
.map(pb => pb.paybutton.name)
)
let nextButtonName: string | undefined = ''
if (nextUniqueButtonName.size > 1) {
if (paybuttonId !== undefined) {
nextButtonName = nextPayment.address.paybuttons.find(pb => pb.paybutton.id === paybuttonId)?.paybutton.name ?? ''
} else {
nextButtonName = [...nextUniqueButtonName].join('_')
}
} else {
nextButtonName = uniqueButtonNames.values().next().value ?? ''
}
nextGroupKey = `${nextDateKey}_${nextDateKeyUTC}_${nextButtonName}`
} else {
nextGroupKey = null
}

if (value < collapseThreshold) {
if (tempTxGroups[groupKey] === undefined) tempTxGroups[groupKey] = []
tempTxGroups[groupKey].push(tx)
} else {
Object.keys(tempTxGroups).forEach(pushTempGroup)
pushTx(tx)
pushTx(tx, groupKey)
}

if (nextGroupKey !== groupKey) {
Expand Down Expand Up @@ -282,14 +321,17 @@ export const downloadTxsFile = async (
currency: SupportedQuotesType,
timezone: string,
transactions: TransactionsWithPaybuttonsAndPrices[],
userId: string,
paybuttonId?: string,
collapseTransactions: boolean = true,
collapseThreshold: number = DEFAULT_CSV_COLLAPSE_THRESHOLD): Promise<void> => {
collapseThreshold: number = DEFAULT_CSV_COLLAPSE_THRESHOLD
): Promise<void> => {
const sortedPayments = sortPaymentsByNetworkId(transactions)
let treatedPayments: TransactionFileData[] = []
if (collapseTransactions) {
treatedPayments = collapseSmallPayments(sortedPayments, currency, timezone, collapseThreshold)
treatedPayments = collapseSmallPayments(sortedPayments, currency, timezone, collapseThreshold, userId, paybuttonId)
} else {
treatedPayments = getPaybuttonTransactionsFileData(transactions, currency, timezone)
treatedPayments = getPaybuttonTransactionsFileData(sortedPayments, currency, timezone)
}
const mappedPaymentsData = treatedPayments.map(payment => formatPaybuttonTransactionsFileData(payment))

Expand Down