From 7b75c2b8aa53626927b3b90bfeff11c16f6d97ff Mon Sep 17 00:00:00 2001 From: lissavxo Date: Wed, 26 Mar 2025 16:32:35 -0300 Subject: [PATCH 1/3] feat: fetchAddressesByPaybuttonIds method --- services/addressService.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/services/addressService.ts b/services/addressService.ts index 50bac46b5..9bfb87bee 100644 --- a/services/addressService.ts +++ b/services/addressService.ts @@ -339,3 +339,20 @@ export async function fetchAddressesByPaybuttonId (paybuttonId: string): Promise return addressesIds } + +export async function fetchAddressesByPaybuttonIds (paybuttonIds: string[]): Promise { + const addresses = await prisma.addressesOnButtons.findMany({ + where: { + paybuttonId: { + in: paybuttonIds + } + } + }) + const addressesIds = addresses.map(result => result.addressId) + + if (addressesIds.length === 0) { + throw new Error(RESPONSE_MESSAGES.NO_ADDRESS_FOUND_404.message) + } + + return addressesIds +} From 355fc93c1bd9726d37c799d46a3a41c5da030213 Mon Sep 17 00:00:00 2001 From: lissavxo Date: Wed, 26 Mar 2025 16:33:08 -0300 Subject: [PATCH 2/3] feat: paybuttons filter transactionService --- services/transactionService.ts | 74 ++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/services/transactionService.ts b/services/transactionService.ts index 4fa9a8d2a..6e5ff5053 100644 --- a/services/transactionService.ts +++ b/services/transactionService.ts @@ -1,7 +1,7 @@ import prisma from 'prisma/clientInstance' import { Prisma, Transaction } from '@prisma/client' import { RESPONSE_MESSAGES, USD_QUOTE_ID, CAD_QUOTE_ID, N_OF_QUOTES, UPSERT_TRANSACTION_PRICES_ON_DB_TIMEOUT, SupportedQuotesType, NETWORK_IDS } from 'constants/index' -import { fetchAddressBySubstring, fetchAddressById, fetchAddressesByPaybuttonId, addressExists } from 'services/addressService' +import { fetchAddressBySubstring, fetchAddressById, fetchAddressesByPaybuttonId, addressExists, fetchAddressesByPaybuttonIds } from 'services/addressService' import { AllPrices, QuoteValues, fetchPricesForNetworkAndTimestamp, flattenTimestamp } from 'services/priceService' import _ from 'lodash' import { CacheSet } from 'redis/index' @@ -563,7 +563,8 @@ export async function getPaymentsByUserIdOrderedByButtonName ( userId: string, page: number, pageSize: number, - orderDesc = true + orderDesc = true, + paybuttonId?: string ): Promise { const offset = page * pageSize @@ -596,7 +597,11 @@ export async function getPaymentsByUserIdOrderedByButtonName ( WHERE au.\`addressId\` = a.\`id\` AND au.\`userId\` = ${userId} ) + AND t.\`amount\` > 0 AND p.\`providerUserId\` = ${userId} + AND ( + ${paybuttonId ?? null} IS NULL OR paybuttonId = ${paybuttonId} + ) GROUP BY t.id, p.id ORDER BY p.\`name\` ASC LIMIT ${pageSize} @@ -631,6 +636,9 @@ export async function getPaymentsByUserIdOrderedByButtonName ( AND au.\`userId\` = ${userId} ) AND p.\`providerUserId\` = ${userId} + AND ( + ${paybuttonId !== undefined ? paybuttonId : null} IS NULL OR paybuttonId = ${paybuttonId} + ) GROUP BY t.id, p.id ORDER BY p.\`name\` DESC LIMIT ${pageSize} @@ -681,12 +689,13 @@ export async function fetchAllPaymentsByUserIdWithPagination ( page: number, pageSize: number, orderBy?: string, - orderDesc = true + orderDesc = true, + paybuttonId?: string ): Promise { const orderDescString: Prisma.SortOrder = orderDesc ? 'desc' : 'asc' if (orderBy === 'buttonDisplayDataList') { return await getPaymentsByUserIdOrderedByButtonName( - userId, page, pageSize, orderDesc + userId, page, pageSize, orderDesc, paybuttonId ) } let orderByQuery @@ -712,8 +721,7 @@ export async function fetchAllPaymentsByUserIdWithPagination ( timestamp: orderDescString } } - - const transactions = await prisma.transaction.findMany({ + const query = { where: { address: { userProfiles: { @@ -724,13 +732,24 @@ export async function fetchAllPaymentsByUserIdWithPagination ( }, amount: { gt: 0 - } + }, + addressId: {} }, include: includePaybuttonsAndPrices, orderBy: orderByQuery, skip: page * Number(pageSize), take: Number(pageSize) - }) + } + + let addressIdList = [] + if (paybuttonId !== undefined) { + addressIdList = await fetchAddressesByPaybuttonId(paybuttonId) + query.where.addressId = { + in: addressIdList + } + } + + const transactions = await prisma.transaction.findMany(query) const transformedData: Payment[] = [] for (let index = 0; index < transactions.length; index++) { @@ -783,3 +802,42 @@ export async function fetchTxCountByPaybuttonId (paybuttonId: string): Promise { + if (paybuttonIds !== undefined) { + const addressIdList = await fetchAddressesByPaybuttonIds(paybuttonIds) + + return await prisma.transaction.count({ + where: { + address: { + userProfiles: { + some: { + userId + } + } + }, + addressId: { + in: addressIdList + }, + amount: { + gt: 0 + } + } + }) + } else { + return await prisma.transaction.count({ + where: { + address: { + userProfiles: { + some: { + userId + } + } + }, + amount: { + gt: 0 + } + } + }) + } +} From 7944de69a9c98d9beb9128c50f80e497e423a8e1 Mon Sep 17 00:00:00 2001 From: lissavxo Date: Wed, 26 Mar 2025 16:43:39 -0300 Subject: [PATCH 3/3] feat: button filter payments --- pages/api/payments/count/index.ts | 11 +++---- pages/api/payments/index.ts | 4 +-- pages/payments/index.tsx | 55 ++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/pages/api/payments/count/index.ts b/pages/api/payments/count/index.ts index 96c3eb1be..547fe334c 100644 --- a/pages/api/payments/count/index.ts +++ b/pages/api/payments/count/index.ts @@ -1,16 +1,13 @@ -import { CacheGet } from 'redis/index' -import { fetchUserProfileFromId } from 'services/userService' +import { fetchPaymentsCountByUserId } from 'services/transactionService' import { setSession } from 'utils/setSession' export default async (req: any, res: any): Promise => { if (req.method === 'GET') { await setSession(req, res) const userId = req.session.userId - const userReqTimezone = req.headers.timezone as string - const userProfile = await fetchUserProfileFromId(userId) - const userPreferredTimezone = userProfile?.preferredTimezone - const timezone = userPreferredTimezone !== '' ? userPreferredTimezone : userReqTimezone - const resJSON = await CacheGet.paymentsCount(userId, timezone) + const paybuttonId = (req.query.paybuttonId === '' || req.query.paybuttonId === undefined) ? undefined : req.query.paybuttonId as string + const paybuttonIds = paybuttonId !== undefined ? [paybuttonId] : undefined + const resJSON = await fetchPaymentsCountByUserId(userId, paybuttonIds) res.status(200).json(resJSON) } } diff --git a/pages/api/payments/index.ts b/pages/api/payments/index.ts index 84215e557..0665164a0 100644 --- a/pages/api/payments/index.ts +++ b/pages/api/payments/index.ts @@ -9,8 +9,8 @@ export default async (req: any, res: any): Promise => { const pageSize = req.query.pageSize as number const orderDesc: boolean = !!(req.query.orderDesc === '' || req.query.orderDesc === undefined || req.query.orderDesc === 'true') const orderBy = (req.query.orderBy === '' || req.query.orderBy === undefined) ? undefined : req.query.orderBy as string - - const resJSON = await fetchAllPaymentsByUserIdWithPagination(userId, page, pageSize, orderBy, orderDesc) + const paybuttonId = (req.query.paybuttonId === '' || req.query.paybuttonId === undefined) ? undefined : req.query.paybuttonId as string + const resJSON = await fetchAllPaymentsByUserIdWithPagination(userId, page, pageSize, orderBy, orderDesc, paybuttonId) res.status(200).json(resJSON) } } diff --git a/pages/payments/index.tsx b/pages/payments/index.tsx index 6785a8f96..dd9b3bab3 100644 --- a/pages/payments/index.tsx +++ b/pages/payments/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react' +import React, { useCallback, useEffect, useMemo, useState } from 'react' import supertokensNode from 'supertokens-node' import * as SuperTokensConfig from '../../config/backendConfig' import Session from 'supertokens-node/recipe/session' @@ -17,6 +17,7 @@ import TopBar from 'components/TopBar' import { fetchUserWithSupertokens, UserWithSupertokens } from 'services/userService' import { UserProfile } from '@prisma/client' import Button from 'components/Button' +import { PaybuttonWithAddresses } from 'services/paybuttonService' export const getServerSideProps: GetServerSideProps = async (context) => { // this runs on the backend, so we must call init on supertokens-node SDK @@ -57,6 +58,8 @@ export default function Payments ({ user, userId }: PaybuttonsProps): React.Reac const [selectedCurrencyCSV, setSelectedCurrencyCSV] = useState('') const [paybuttonNetworks, setPaybuttonNetworks] = useState>(new Set()) const [loading, setLoading] = useState(false) + const [paybuttons, setPaybuttons] = useState() + const [selectedButton, setSelectedButton] = useState('all') const fetchPaybuttons = async (): Promise => { const res = await fetch(`/api/paybuttons?userId=${user?.userProfile.id}`, { @@ -74,6 +77,7 @@ export default function Payments ({ user, userId }: PaybuttonsProps): React.Reac return p.addresses.forEach((c: { address: { networkId: number } }) => networkIds.add(c.address.networkId)) }) + setPaybuttons(paybuttons) setPaybuttonNetworks(networkIds) } @@ -81,22 +85,28 @@ export default function Payments ({ user, userId }: PaybuttonsProps): React.Reac void getDataAndSetUpCurrencyCSV() }, []) - function fetchData (): Function { - return async (page: number, pageSize: number, orderBy: string, orderDesc: boolean) => { - const paymentsResponse = await fetch(`/api/payments?page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&orderDesc=${String(orderDesc)}`) - const paymentsCountResponse = await fetch('/api/payments/count', { - headers: { - Timezone: timezone + const fetchData = useCallback( + (selectedButton: string): Function => { + return async (page: number, pageSize: number, orderBy: string, orderDesc: boolean) => { + const buttonFilter = selectedButton !== 'all' ? `&paybuttonId=${selectedButton}` : '' + const buttonFilterCount = selectedButton !== 'all' ? `?paybuttonId=${selectedButton}` : '' + + const paymentsResponse = await fetch(`/api/payments?page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&orderDesc=${String(orderDesc)}${buttonFilter}`) + const paymentsCountResponse = await fetch(`/api/payments/count${buttonFilterCount}`, { + headers: { + Timezone: timezone + } + }) + const totalCount = await paymentsCountResponse.json() + const payments = await paymentsResponse.json() + return { + data: payments, + totalCount } - }) - const totalCount = await paymentsCountResponse.json() - const payments = await paymentsResponse.json() - return { - data: payments, - totalCount } - } - } + }, + [selectedButton, timezone] + ) const columns = useMemo( () => [ @@ -215,6 +225,18 @@ export default function Payments ({ user, userId }: PaybuttonsProps): React.Reac <>
+ + {paybuttonNetworks.size > 1 ? (