Skip to content

fix: duplicate payment generation #74

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 1 commit into from
Apr 24, 2024
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
51 changes: 20 additions & 31 deletions src/domain/Challenge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import ChallengeScheduler from "../util/ChallengeScheduler";
import { BAValidation, lockConsumeAmount } from "../api/BillingAccount";
import { ChallengeEstimator } from "../util/ChallengeEstimator";
import { V5_TRACK_IDS_TO_NAMES, V5_TYPE_IDS_TO_NAMES } from "../common/ConversionMap";
import PaymentCreator, { PaymentDetail } from "../util/PaymentCreator";
import WalletApi, { PaymentDetail } from "../util/WalletApi";
import { getChallengeResources } from "../api/v5Api";
import m2mToken from "../helpers/MachineToMachineToken";

Expand Down Expand Up @@ -909,11 +909,21 @@ class ChallengeDomain extends CoreOperations<Challenge, CreateChallengeInput> {
title: string,
payments: UpdateChallengeInputForACL_PaymentACL[]
): Promise<number> {
const token = await m2mToken.getM2MToken();

console.log(
`Generating payments for challenge ${challengeId}, ${title} with payments ${JSON.stringify(
payments
)} for challenge type ${challengeType}`
);

// Check if payment already exists
const existingPayments = await WalletApi.getPaymentsByChallengeId(challengeId, token);
if (existingPayments.length > 0) {
console.log(`Payments already exist for challenge ${challengeId}, skipping payment generation`);
return 0;
}

let totalAmount = 0;
// TODO: Make this list exhaustive
const mapType = (type: string) => {
Expand All @@ -934,43 +944,22 @@ class ChallengeDomain extends CoreOperations<Challenge, CreateChallengeInput> {
const nPayments = payments.length;
for (let i = 0; i < nPayments; i++) {
const payment = payments[i];
let details: PaymentDetail[] = [];
let details: PaymentDetail[] = [
{
totalAmount: payment.amount,
grossAmount: payment.amount,
installmentNumber: 1,
currency: "USD",
},
];

let description = title;

// TODO: Make this a more dynamic calculation
// TODO: splitRatio should be from challenge data
if (payment.type === "placement") {
const grossAmount1 = payment.amount * 0.75;
const grossAmount2 = payment.amount * 0.25;
details = [
{
totalAmount: payment.amount,
grossAmount: grossAmount1,
installmentNumber: 1,
currency: "USD",
},
{
totalAmount: payment.amount,
grossAmount: grossAmount2,
installmentNumber: 2,
currency: "USD",
},
];

description =
challengeType != "Task"
? `${title} - ${this.placeToOrdinal(placementMap[payment.handle])} Place`
: title;
} else {
details = [
{
totalAmount: payment.amount,
grossAmount: payment.amount,
installmentNumber: 1,
currency: "USD",
},
];
}

totalAmount += payment.amount;
Expand All @@ -995,7 +984,7 @@ class ChallengeDomain extends CoreOperations<Challenge, CreateChallengeInput> {
}

console.log("Generate payment with payload", payload);
await PaymentCreator.createPayment(payload, await m2mToken.getM2MToken());
await WalletApi.createPayment(payload, token);
}

return totalAmount;
Expand Down
27 changes: 24 additions & 3 deletions src/util/PaymentCreator.ts → src/util/WalletApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface PaymentPayload {
}

// TODO: Move this to a processor that handles challenge completion events from Harmony
class PaymentCreator {
class WalletApi {
private static readonly BASE_URL =
(process.env.TOPCODER_API_ENDPOINT ?? "https://api.topcoder-dev.com/v5") + "/payments";

Expand All @@ -40,7 +40,7 @@ class PaymentCreator {

try {
console.log(payload.externalId, "Creating payment. Attempt", attempts, payload);
const response = await axios.post(PaymentCreator.BASE_URL + "/winnings", payload, config);
const response = await axios.post(WalletApi.BASE_URL + "/winnings", payload, config);
console.log("Payment created", response.data);
return response;
} catch (error) {
Expand All @@ -55,6 +55,27 @@ class PaymentCreator {
}
}
}

async getPaymentsByChallengeId(challengeId: string, token?: string): Promise<any[]> {
const config = {
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
};

const payload = {
externalIds: [challengeId],
};

try {
const response = await axios.post(WalletApi.BASE_URL + "/winnings/list", payload, config);
return response.data.data;
} catch (err) {
return [];
}
}

}

export default new PaymentCreator();
export default new WalletApi();