Skip to content

fix: add endpoint to update legacy payment records #715

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 10, 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
6 changes: 4 additions & 2 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module.exports = {
UPDATE: process.env.SCOPE_CHALLENGES_UPDATE || "update:challenges",
DELETE: process.env.SCOPE_CHALLENGES_DELETE || "delete:challenges",
ALL: process.env.SCOPE_CHALLENGES_ALL || "all:challenges",
PAYMENT: process.env.SCOPE_PAYMENT || "create:payments",
},

DEFAULT_CONFIDENTIALITY_TYPE: process.env.DEFAULT_CONFIDENTIALITY_TYPE || "public",
Expand Down Expand Up @@ -129,7 +130,8 @@ module.exports = {
GRPC_CHALLENGE_SERVER_HOST: process.env.GRPC_DOMAIN_CHALLENGE_SERVER_HOST || "localhost",
GRPC_CHALLENGE_SERVER_PORT: process.env.GRPC_DOMAIN_CHALLENGE_SERVER_PORT || 8888,
GRPC_ACL_SERVER_HOST: process.env.GRPC_ACL_SERVER_HOST || "localhost",
GRPC_ACL_SERVER_PORT: process.env.GRPC_ACL_SERVER_PORT || 8889,
GRPC_ACL_SERVER_PORT: process.env.GRPC_ACL_SERVER_PORT || 40020,

SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID: process.env.SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID || '517e76b0-8824-4e72-9b48-a1ebde1793a8'
SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID:
process.env.SKIP_PROJECT_ID_BY_TIMLINE_TEMPLATE_ID || "517e76b0-8824-4e72-9b48-a1ebde1793a8",
};
21 changes: 21 additions & 0 deletions src/controllers/ChallengeController.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ async function updateChallenge(req, res) {
res.send(result);
}

/**
* Update Legacy Payout (Updates informixoltp:payment_detail)
* This has no effect other than to keep DW in sync for looker with
* Updates that happen in Wallet
*/
async function updateLegacyPayout(req, res) {
logger.debug(
`updateLegacyPayout User: ${JSON.stringify(req.authUser)} - ChallengeID: ${
req.params.challengeId
} - Body: ${JSON.stringify(req.body)}`
);
const result = await service.updateLegacyPayout(
req,
req.authUser,
req.params.challengeId,
req.body
);
res.send(result);
}

/**
* Delete challenge
* @param {Object} req the request
Expand Down Expand Up @@ -152,6 +172,7 @@ module.exports = {
createChallenge,
getChallenge,
updateChallenge,
updateLegacyPayout,
deleteChallenge,
getChallengeStatistics,
sendNotifications,
Expand Down
10 changes: 9 additions & 1 deletion src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

const constants = require("../app-constants");
const {
SCOPES: { READ, CREATE, UPDATE, DELETE, ALL },
SCOPES: { PAYMENT, READ, CREATE, UPDATE, DELETE, ALL },
} = require("config");

module.exports = {
Expand Down Expand Up @@ -112,6 +112,14 @@ module.exports = {
scopes: [UPDATE, ALL],
},
},
"/challenges/:challengeId/legacy-payment": {
patch: {
controller: "ChallengeController",
method: "updateLegacyPayout",
auth: "jwt",
scopes: [PAYMENT],
},
},
"/challenges/:challengeId/statistics": {
get: {
controller: "ChallengeController",
Expand Down
134 changes: 134 additions & 0 deletions src/services/ChallengeService.js
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,13 @@ updateChallenge.schema = {
)
.optional(),
overview: Joi.any().forbidden(),
v5Payout: Joi.object().keys({
userId: Joi.number().integer().positive().required(),
amount: Joi.number().allow(null),
status: Joi.string().allow(null),
datePaid: Joi.string().allow(null),
releaseDate: Joi.string().allow(null),
}),
})
.unknown(true)
.required(),
Expand Down Expand Up @@ -2498,6 +2505,132 @@ async function indexChallengeAndPostToKafka(updatedChallenge, track, type) {
});
}

async function updateLegacyPayout(currentUser, challengeId, data) {
const challenge = await challengeDomain.lookup(getLookupCriteria("id", challengeId));
const { v5Payout } = data;

// SQL qurey to fetch the payment and payment_detail record
let sql = `SELECT * FROM informixoltp:payment p
INNER JOIN informixoltp:payment_detail pd ON p.most_recent_detail_id = pd.payment_detail_id
WHERE p.user_id = ${v5Payout.userId} AND`;

if (challenge.legacyId != null) {
sql += ` pd.component_project_id = ${challenge.legacyId}`;
} else {
sql += ` pd.jira_issue_id = \'${challengeId}\'`;
}

sql += " ORDER BY pd.payment_detail_id ASC";

console.log("Fetch legacy payment detail: ", sql);

const result = await aclQueryDomain.rawQuery({ sql });
let updateClauses = [`date_modified = current`];

const statusMap = {
Paid: 53,
OnHold: 55,
OnHoldAdmin: 55,
Owed: 56,
Cancelled: 65,
EnteredIntoPaymentSystem: 70,
};

if (v5Payout.status != null) {
updateClauses.push(`payment_status_id = ${statusMap[v5Payout.status]}`);
if (v5Payout.status === "Paid") {
updateClauses.push(`date_paid = '${v5Payout.datePaid}'`);
} else {
updateClauses.push("date_paid = null");
}
}

if (v5Payout.releaseDate != null) {
updateClauses.push(`date_due = '${v5Payout.releaseDate}'`);
}

const paymentDetailIds = result.rows.map(
(row) => row.fields.find((field) => field.key === "payment_detail_id").value
);

if (v5Payout.amount != null) {
updateClauses.push(`total_amount = ${v5Payout.amount}`);
if (paymentDetailIds.length === 1) {
updateClauses.push(`net_amount = ${v5Payout.amount}`);
updateClauses.push(`gross_amount = ${v5Payout.amount}`);
}
}

if (paymentDetailIds.length === 0) {
return {
success: false,
message: "No payment detail record found",
};
}

const whereClause = [`payment_detail_id IN (${paymentDetailIds.join(",")})`];

const updateQuery = `UPDATE informixoltp:payment_detail SET ${updateClauses.join(
", "
)} WHERE ${whereClause.join(" AND ")}`;

console.log("Update Clauses", updateClauses);
console.log("Update Query", updateQuery);

await aclQueryDomain.rawQuery({ sql: updateQuery });

if (v5Payout.amount != null) {
if (paymentDetailIds.length > 1) {
const amountInCents = v5Payout.amount * 100;

const split1Cents = Math.round(amountInCents * 0.75);
const split2Cents = amountInCents - split1Cents;

const split1Dollars = Number((split1Cents / 100).toFixed(2));
const split2Dollars = Number((split2Cents / 100).toFixed(2));

const paymentUpdateQueries = paymentDetailIds.map((paymentDetailId, index) => {
let amt = 0;
if (index === 0) {
amt = split1Dollars;
}
if (index === 1) {
amt = split2Dollars;
}

return `UPDATE informixoltp:payment_detail SET date_modified = CURRENT, net_amount = ${amt}, gross_amount = ${amt} WHERE payment_detail_id = ${paymentDetailId}`;
});

console.log("Payment Update Queries", paymentUpdateQueries);

await Promise.all(
paymentUpdateQueries.map((query) => aclQueryDomain.rawQuery({ sql: query }))
);
}
}

return {
success: true,
message: "Successfully updated legacy payout",
};
}
updateLegacyPayout.schema = {
currentUser: Joi.any(),
challengeId: Joi.id(),
data: Joi.object()
.keys({
v5Payout: Joi.object().keys({
userId: Joi.number().integer().positive().required(),
amount: Joi.number().allow(null),
status: Joi.string().allow(null),
datePaid: Joi.string().allow(null),
releaseDate: Joi.string().allow(null),
}),
})
.unknown(true)
.required(),
};

/**
* Get SRM Schedule
* @param {Object} criteria the criteria
Expand Down Expand Up @@ -2562,6 +2695,7 @@ module.exports = {
getChallenge,
updateChallenge,
deleteChallenge,
updateLegacyPayout,
getChallengeStatistics,
sendNotifications,
advancePhase,
Expand Down