Skip to content

Conversation

@kkartunov
Copy link
Contributor

No description provided.

getWinningsTotalsByWinnerID(winnerId: string) {
return this.prisma.$queryRaw<
{ payment_type: 'PAYMENT' | 'REWARD'; total_owed: number }[]
{ payment_type: 'PAYMENT'; total_owed: number }[]

Choose a reason for hiding this comment

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

[❗❗ correctness]
The removal of 'REWARD' from the payment_type union may impact the correctness of the query results if REWARD payments are still relevant to the business logic. Ensure that this change aligns with the intended functionality and that REWARD payments are handled appropriately elsewhere if needed.

tx: Prisma.TransactionClient,
) {
const winnings = await tx.$queryRaw<ReleasableWinningRow[]>`
const winnings = await this.prisma.$queryRaw<ReleasableWinningRow[]>`

Choose a reason for hiding this comment

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

[❗❗ correctness]
Switching from tx.$queryRaw to this.prisma.$queryRaw changes the transaction context. Ensure that this change does not affect transaction integrity or lead to race conditions, especially in concurrent environments.

return totalAmount;
}

private async createDbPaymentRelease(

Choose a reason for hiding this comment

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

[❗❗ correctness]
The removal of the tx: Prisma.TransactionClient parameter suggests that the transaction context might no longer be passed to createDbPaymentRelease. Ensure that this change does not affect the transactional integrity of the operation, as it could lead to partial updates or data inconsistencies if the function was previously relying on a transaction context.

) {
try {
const paymentRelease = await tx.payment_releases.create({
const paymentRelease = await this.prisma.payment_releases.create({

Choose a reason for hiding this comment

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

[❗❗ correctness]
Switching from tx.payment_releases.create to this.prisma.payment_releases.create changes the context from a transaction-scoped operation to a potentially non-transactional one. Ensure that this change does not inadvertently affect transactional integrity, especially in a hotfix context where duplicated payments are a concern.

) {
try {
await tx.payment_releases.update({
await this.prisma.payment_releases.update({

Choose a reason for hiding this comment

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

[❗❗ correctness]
Switching from tx to this.prisma for database updates changes the transaction context. Ensure that this does not affect transaction integrity, especially if tx was part of a larger transaction scope.

this.logger.log(
`DB payment_release[${paymentRelease.payment_release_id}] updated successfully with trolley payment id: ${externalTxId}`,
);
if (data.externalTxId) {

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The conditional logging based on data.externalTxId might lead to missing logs if externalTxId is not provided. Consider logging the update operation regardless of externalTxId presence for better traceability.

throw new Error('Failed to fetch UserInfo for withdrawal!');
}

if (userInfo.email.toLowerCase().indexOf('wipro.com') > -1) {

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The check for the email domain wipro.com is hardcoded. Consider externalizing this configuration to allow for easier updates and maintenance, especially if more domains need to be added or changed in the future.

throw new Error('Failed to fetch UserInfo for withdrawal!');
}

if (userInfo.email.toLowerCase().indexOf('wipro.com') > -1) {

Choose a reason for hiding this comment

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

[💡 readability]
The use of indexOf for checking the presence of a substring can be replaced with includes for better readability and clarity.


const paymentBatch = await this.trolleyService.startBatchPayment(
`${userId}_${userHandle}`,
try {

Choose a reason for hiding this comment

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

[❗❗ correctness]
The try block starting here does not have a corresponding catch block to handle potential errors from this.paymentsService.updatePaymentProcessingState. This could lead to unhandled promise rejections if an error occurs. Consider adding a catch block to handle errors appropriately.

this.logger.error(errorMsg, error);
throw new Error(errorMsg);
}
try {

Choose a reason for hiding this comment

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

[❗❗ correctness]
The try block starting here does not have a corresponding catch block to handle potential errors from this.trolleyService.startProcessingPayment. This could lead to unhandled promise rejections if an error occurs. Consider adding a catch block to handle errors appropriately.

throw new Error(errorMsg);
}

try {

Choose a reason for hiding this comment

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

[❗❗ correctness]
The try block starting here does not have a corresponding catch block to handle potential errors from this.tcChallengesService.updateLegacyPayments. This could lead to unhandled promise rejections if an error occurs. Consider adding a catch block to handle errors appropriately.

const prismaClient = transaction || this.prisma;

const r = await prismaClient.payment.updateMany({
const r = await this.prisma.payment.updateMany({

Choose a reason for hiding this comment

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

[❗❗ correctness]
Removing the ability to pass a transaction object might impact transactional integrity if this method is intended to be used within a transaction context. Consider whether this change could lead to unintended side effects, such as partial updates if the method is called within a transaction block elsewhere.

);
} catch (e) {
this.logger.error(
`Failed to update payment processing state: ${e?.message} for winnings '${winningsIds.join(',')}`,

Choose a reason for hiding this comment

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

[⚠️ correctness]
Using optional chaining (e?.message) is a good practice to avoid runtime errors when e is undefined or null. However, ensure that e is always an object or undefined in this context to prevent any unexpected behavior. Consider adding a fallback message for cases where e might not be an object.

status: 'FAILED',
});

await this.trolleyService.removePayment(

Choose a reason for hiding this comment

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

[❗❗ correctness]
Consider handling errors that might occur during removePayment. If removePayment fails, it could leave the system in an inconsistent state. Ensure that any errors are logged or handled appropriately to maintain system integrity.


async removePayment(paymentId: string, batchId: string) {
try {
await this.client.payment.remove(paymentId, batchId);

Choose a reason for hiding this comment

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

[⚠️ maintainability]
Consider handling specific error types separately to provide more granular error handling and potentially recover from certain errors. This can improve the robustness of the error handling logic.

this.logger.debug(`Removed trolley payment with id ${paymentId}`);
} catch (error) {
this.logger.error(
`Failed to remove trolley payment: '${error.message}'!`,

Choose a reason for hiding this comment

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

[💡 readability]
Logging the error message alone may not provide sufficient context for debugging. Consider including additional error properties, such as error.code or error.stack, if available, to enhance the log output.

return { error: otpResponse };
}
} catch (error) {
if (error.code === 'P2010' && error.meta?.code === '55P03') {

Choose a reason for hiding this comment

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

[⚠️ maintainability]
The error handling for P2010 with meta.code 55P03 is specific and may not cover other potential error scenarios. Consider logging or handling other error codes to ensure robustness.

error,
);

throw new Error(

Choose a reason for hiding this comment

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

[⚠️ design]
Throwing a generic Error with a message might not provide enough context for upstream error handling. Consider using a custom error type to encapsulate additional context or metadata.

};
}
return await this.prisma.$transaction(async (tx) => {
const records = await tx.$queryRaw<otp>`

Choose a reason for hiding this comment

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

[❗❗ security]
Using tx.$queryRaw with string interpolation for SQL queries can lead to SQL injection vulnerabilities. Consider using parameterized queries to ensure safety.

WHERE otp_hash=${hashOtp(otpCode)}
ORDER BY expiration_time DESC
LIMIT 1
FOR UPDATE NOWAIT;

Choose a reason for hiding this comment

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

[⚠️ correctness]
The use of FOR UPDATE NOWAIT in the query may lead to transaction failures if the row is locked by another transaction. Ensure that the application logic can handle such cases gracefully.

@kkartunov kkartunov merged commit 3f297e3 into master Oct 22, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants