diff --git a/src/domain/Challenge.ts b/src/domain/Challenge.ts index c2da2f2..800b0d1 100644 --- a/src/domain/Challenge.ts +++ b/src/domain/Challenge.ts @@ -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"; @@ -909,11 +909,21 @@ class ChallengeDomain extends CoreOperations { title: string, payments: UpdateChallengeInputForACL_PaymentACL[] ): Promise { + 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) => { @@ -934,43 +944,22 @@ class ChallengeDomain extends CoreOperations { 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; @@ -995,7 +984,7 @@ class ChallengeDomain extends CoreOperations { } console.log("Generate payment with payload", payload); - await PaymentCreator.createPayment(payload, await m2mToken.getM2MToken()); + await WalletApi.createPayment(payload, token); } return totalAmount; diff --git a/src/util/PaymentCreator.ts b/src/util/WalletApi.ts similarity index 71% rename from src/util/PaymentCreator.ts rename to src/util/WalletApi.ts index 89ee1b5..b50a8c7 100644 --- a/src/util/PaymentCreator.ts +++ b/src/util/WalletApi.ts @@ -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"; @@ -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) { @@ -55,6 +55,27 @@ class PaymentCreator { } } } + + async getPaymentsByChallengeId(challengeId: string, token?: string): Promise { + 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();