Skip to content

Commit

Permalink
feat: compute review status on API level
Browse files Browse the repository at this point in the history
This commit adds
1. the functionality to compute the review status for all reviews when queried from the database. This computation is done on the API level and is not stored in the db.

2. a new "rejected" review status based on the criteria outlined [here](#294)
  • Loading branch information
Extheoisah committed Jun 20, 2024
1 parent 8ee2836 commit 1117ae6
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
10 changes: 6 additions & 4 deletions api/app/controllers/review.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Op } from "sequelize";

import { Review, Transaction, Transcript, User } from "../db/models";
import { DB_QUERY_LIMIT, DB_START_PAGE } from "../utils/constants";
import { buildCondition, buildReviewResponse } from "../utils/review.inference";
import { buildCondition, buildReviewResponse, computeReviewStatus } from "../utils/review.inference";
import { parseMdToJSON } from "../helpers/transcript";
import axios from "axios";
import { BaseParsedMdContent, TranscriptAttributes } from "../types/transcript";
Expand Down Expand Up @@ -161,7 +161,8 @@ export async function findOne(req: Request, res: Response) {
const branchUrl = data.branchUrl;
const transcriptData = data.transcript.dataValues;
const transcript = await transcriptWrapper(transcriptData, branchUrl);
return res.status(200).send({ ...data.dataValues, transcript });
const reviewWithComputedStatus = computeReviewStatus(data);
return res.status(200).send({ ...reviewWithComputedStatus.dataValues, transcript });
} catch (err) {
res.status(500).send({
message: "Error retrieving review with id=" + id,
Expand Down Expand Up @@ -325,10 +326,11 @@ export const getReviewsByPaymentStatus = async (
);
const unpaidMergedReviews = mergedReviews.filter(
(review) => !creditTransactionReviewIds.includes(review.id)
);
).map((review) => computeReviewStatus(review));
const paidMergedReviews = mergedReviews.filter((review) =>
creditTransactionReviewIds.includes(review.id)
);
).map((review) => computeReviewStatus(review))


let response: {
totalItems: number;
Expand Down
10 changes: 9 additions & 1 deletion api/app/types/review.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import { Review } from "../db/models";

// This type combines the ReviewAttributes and Review model
// because the Review model which extends the Model class
// does not have the status field in the database schema.
// It is only present in the API level and is not stored in the database.
export type IReview = Review & ReviewAttributes;

export interface ReviewAttributes {
id?: number;
submittedAt?: Date | null;
Expand All @@ -7,9 +15,9 @@ export interface ReviewAttributes {
transcriptId: number;
pr_url?: string | null;
branchUrl?: string | null;
status?: string;
}


export interface BuildConditionArgs {
status?: string;
transcriptId?: number;
Expand Down
55 changes: 52 additions & 3 deletions api/app/utils/review.inference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { Op } from "sequelize";
import { TranscriptAttributes } from "../types/transcript";
import { wordCount } from "./functions";
import { EXPIRYTIMEINHOURS, HOUR_END_OF_DAY, MILLISECOND_END_OF_DAY, MINUTE_END_OF_DAY, QUERY_REVIEW_STATUS, SECOND_END_OF_DAY } from "./constants";
import { Review } from "../db/models";
import { BuildConditionArgs } from "../types/review";
import { BuildConditionArgs, IReview } from "../types/review";

const unixEpochTimeInMilliseconds = getUnixTimeFromHours(EXPIRYTIMEINHOURS);

Expand Down Expand Up @@ -260,7 +259,7 @@ export const buildCondition = ({
};

export const buildReviewResponse = (
reviews: Review[],
reviews: IReview[],
page: number,
limit: number,
totalItems: number
Expand All @@ -269,6 +268,10 @@ export const buildReviewResponse = (
const hasNextPage = page < totalPages;
const hasPreviousPage = page > 1;

reviews.forEach((review) => {
computeReviewStatus(review);
});

return {
totalItems,
totalPages,
Expand All @@ -280,6 +283,52 @@ export const buildReviewResponse = (
};
};

export const computeReviewStatus = (review: IReview) => {
const currentTime = new Date().getTime();
const isExpiredReview = (review: IReview) => {
return (
(!review.submittedAt && !review.mergedAt && !review.archivedAt && review.createdAt < new Date(currentTime - unixEpochTimeInMilliseconds)) ||
(!review.submittedAt && !review.mergedAt && review.archivedAt && review.createdAt < new Date(currentTime - unixEpochTimeInMilliseconds))
);
}

const isActiveReview = (review: IReview) => {
const timeStringAt24HoursPrior = new Date(
currentTime - unixEpochTimeInMilliseconds
).toISOString();
return (
!review.submittedAt &&
!review.mergedAt &&
!review.archivedAt &&
review.createdAt > timeStringAt24HoursPrior
);
}

const isPendingReview = (review: IReview) => {
return review.submittedAt && !review.mergedAt && !review.archivedAt;
}

const isRejectedReview = (review: IReview) => {
return review.archivedAt && review.submittedAt && !review.mergedAt;
}

if (isPendingReview(review)) {
review.dataValues.status = QUERY_REVIEW_STATUS.PENDING;
} else if (isActiveReview(review)) {
review.dataValues.status = QUERY_REVIEW_STATUS.ACTIVE;
} else if (isExpiredReview(review)) {
review.dataValues.status = "expired";
} else if (review.mergedAt && !review.archivedAt) {
review.dataValues.status = QUERY_REVIEW_STATUS.MERGED;
}else if (isRejectedReview(review)) {
review.dataValues.status = "rejected";
} else {
review.dataValues.status = "unknown";
}

return review;
}

export {
getUnixTimeFromHours,
buildIsActiveCondition,
Expand Down

0 comments on commit 1117ae6

Please sign in to comment.