Skip to content

Pm 1237 withdraw memo #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 16, 2025
Merged
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
31 changes: 28 additions & 3 deletions src/api/withdrawal/dto/withdraw.dto.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import { ApiProperty } from '@nestjs/swagger';
import { ArrayNotEmpty, IsArray, IsNotEmpty, IsUUID } from 'class-validator';
import {
ArrayNotEmpty,
IsArray,
IsNotEmpty,
IsOptional,
IsString,
IsUUID,
MaxLength,
} from 'class-validator';
import { ENV_CONFIG } from 'src/config';

export class WithdrawRequestDto {
export class WithdrawRequestDtoBase {
@ApiProperty({
description: 'The ID of the winnings to withdraw',
example: ['3fa85f64-5717-4562-b3fc-2c963f66afa6'],
})
@IsArray()
@ArrayNotEmpty()
@IsUUID('4',{ each: true })
@IsUUID('4', { each: true })
@IsNotEmpty({ each: true })
winningsIds: string[];
}

export class WithdrawRequestDtoWithMemo extends WithdrawRequestDtoBase {
@ApiProperty({
description:
'A short note (30 chars max) which that will show up on your bank statement',
example: 'Topcoder payment for week 05/17',
})
@IsString()
@IsOptional()
@MaxLength(30)
memo?: string;
}

export const WithdrawRequestDto = ENV_CONFIG.ACCEPT_CUSTOM_PAYMENTS_MEMO
? WithdrawRequestDtoWithMemo
: WithdrawRequestDtoBase;
2 changes: 2 additions & 0 deletions src/api/withdrawal/withdrawal.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export class WithdrawalController {
@HttpCode(HttpStatus.OK)
async doWithdraw(
@User() user: UserInfo,
// @ts-expect-error: Suppress error for 'WithdrawRequestDto' being used as a type
@Body() body: WithdrawRequestDto,
): Promise<ResponseDto<string>> {
const result = new ResponseDto<string>();
Expand All @@ -55,6 +56,7 @@ export class WithdrawalController {
user.id,
user.handle,
body.winningsIds,
body.memo,
);
result.status = ResponseStatusType.SUCCESS;
return result;
Expand Down
8 changes: 7 additions & 1 deletion src/api/withdrawal/withdrawal.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,12 @@ export class WithdrawalService {
}
}

async withdraw(userId: string, userHandle: string, winningsIds: string[]) {
async withdraw(
userId: string,
userHandle: string,
winningsIds: string[],
paymentMemo?: string,
) {
this.logger.log('Processing withdrawal request');
const hasActiveTaxForm = await this.taxFormRepo.hasActiveTaxForm(userId);

Expand Down Expand Up @@ -206,6 +211,7 @@ export class WithdrawalService {
paymentBatch.id,
totalAmount,
paymentRelease.payment_release_id,
paymentMemo,
);

await this.updateDbReleaseRecord(tx, paymentRelease, trolleyPayment.id);
Expand Down
16 changes: 15 additions & 1 deletion src/config/config.env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IsInt, IsOptional, IsString } from 'class-validator';
import { Transform } from 'class-transformer';
import { IsBoolean, IsInt, IsOptional, IsString } from 'class-validator';

export class ConfigEnv {
@IsString()
Expand Down Expand Up @@ -54,4 +55,17 @@ export class ConfigEnv {
@IsInt()
@IsOptional()
TROLLEY_MINIMUM_PAYMENT_AMOUNT: number = 0;

@IsBoolean()
@IsOptional()
@Transform(({ value }) => {
if (typeof value === 'boolean') return value;

if (typeof value === 'string') {
return value.toLowerCase() === 'true';
}

return false;
})
ACCEPT_CUSTOM_PAYMENTS_MEMO;
}
3 changes: 2 additions & 1 deletion src/shared/global/trolley.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,15 @@ export class TrolleyService {
paymentBatchId: string,
totalAmount: number,
transactionId: string,
paymentMemo?: string,
) {
const paymentPayload = {
recipient: {
id: recipientId,
},
sourceAmount: totalAmount.toString(),
sourceCurrency: 'USD',
memo: 'Topcoder payment',
memo: paymentMemo ?? 'Topcoder payment',
externalId: transactionId,
};

Expand Down