Skip to content

Commit 0df2d1c

Browse files
committed
adds the route to get a specific document
1 parent 1ee0497 commit 0df2d1c

File tree

6 files changed

+137
-8
lines changed

6 files changed

+137
-8
lines changed

constants/progresses.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ const RESPONSE_MESSAGES = {
1111
PROGRESS_ALREADY_CREATED,
1212
};
1313

14-
module.exports = { RESPONSE_MESSAGES, MILLISECONDS_IN_DAY };
14+
const TYPE_MAP = {
15+
user: "userId",
16+
task: "taskId",
17+
};
18+
19+
module.exports = { RESPONSE_MESSAGES, MILLISECONDS_IN_DAY, TYPE_MAP };

controllers/progresses.js

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
const { Conflict, NotFound } = require("http-errors");
2-
const { createProgressDocument, getProgressDocument, getRangeProgressData } = require("../models/progresses");
2+
const {
3+
createProgressDocument,
4+
getProgressDocument,
5+
getRangeProgressData,
6+
getProgressByDate,
7+
} = require("../models/progresses");
38
const { RESPONSE_MESSAGES } = require("../constants/progresses");
49
const { PROGRESS_DOCUMENT_RETRIEVAL_SUCCEEDED, PROGRESS_DOCUMENT_CREATED_SUCCEEDED } = RESPONSE_MESSAGES;
510

@@ -171,4 +176,57 @@ const getProgressRangeData = async (req, res) => {
171176
}
172177
};
173178

174-
module.exports = { createProgress, getProgress, getProgressRangeData };
179+
/**
180+
* @typedef {Object} progressPathParams
181+
* @property {string} type - The type of progress document user or task.
182+
* @property {string} typeId - The ID of the type.
183+
* @property {string} date - The iso format date of the query.
184+
*/
185+
186+
/**
187+
* @typedef {Object} ProgressDocument
188+
* @property {string} id - The id of the progress document.
189+
* @property {string} type - The type of progress document.
190+
* @property {string} completed - The completed progress.
191+
* @property {string} planned - The planned progress.
192+
* @property {string} blockers - The blockers.
193+
* @property {string} userId - The User ID
194+
* @property {string} [taskId] - The task ID (optional).
195+
* @property {number} createdAt - The timestamp when the progress document was created.
196+
* @property {number} date - The timestamp for the day the progress document was created.
197+
*/
198+
199+
/**
200+
* @typedef {Object} GetProgressByDateResponse
201+
* @property {string} message - The success message.
202+
* @property {ProgressDocument} data - An array of progress documents
203+
*/
204+
205+
/**
206+
* Retrieves the progress documents based on provided query parameters.
207+
* @param {Object} req - The HTTP request object.
208+
* @param {progressPathParams} req.params - The query parameters
209+
* @param {Object} res - The HTTP response object.
210+
* @returns {Promise<void>} A Promise that resolves when the response is sent.
211+
*/
212+
213+
const getProgressBydDateController = async (req, res) => {
214+
try {
215+
const data = await getProgressByDate(req.params);
216+
return res.json({
217+
message: PROGRESS_DOCUMENT_RETRIEVAL_SUCCEEDED,
218+
data,
219+
});
220+
} catch (error) {
221+
if (error instanceof NotFound) {
222+
return res.status(404).json({
223+
message: error.message,
224+
});
225+
}
226+
return res.status(400).json({
227+
message: error.message,
228+
});
229+
}
230+
};
231+
232+
module.exports = { createProgress, getProgress, getProgressRangeData, getProgressBydDateController };

middlewares/validators/progresses.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,26 @@ const validateGetRangeProgressRecordsParams = async (req, res, next) => {
9292
res.boom.badRequest(error.details[0].message);
9393
}
9494
};
95+
96+
const validateGetDayProgressParams = async (req, res, next) => {
97+
const schema = joi.object({
98+
type: joi.string().valid("user", "task").required().messages({
99+
"any.only": "Type field is restricted to either 'user' or 'task'.",
100+
}),
101+
typeId: joi.string().required(),
102+
date: joi.date().iso().required(),
103+
});
104+
try {
105+
await schema.validateAsync(req.params, { abortEarly: false });
106+
next();
107+
} catch (error) {
108+
logger.error(`Error validating payload: ${error}`);
109+
res.boom.badRequest(error.details[0].message);
110+
}
111+
};
95112
module.exports = {
96113
validateCreateProgressRecords,
97114
validateGetProgressRecordsQuery,
98115
validateGetRangeProgressRecordsParams,
116+
validateGetDayProgressParams,
99117
};

models/progresses.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const { Conflict } = require("http-errors");
1+
const { Conflict, NotFound } = require("http-errors");
22
const fireStore = require("../utils/firestore");
33
const progressesCollection = fireStore.collection("progresses");
4-
const { RESPONSE_MESSAGES } = require("../constants/progresses");
4+
const { RESPONSE_MESSAGES, TYPE_MAP } = require("../constants/progresses");
55
const {
66
buildQueryToFetchDocs,
77
getProgressDocs,
@@ -11,8 +11,9 @@ const {
1111
buildQueryForPostingProgress,
1212
assertTaskExists,
1313
getProgressDateTimestamp,
14+
buildQueryToSearchProgressByDay,
1415
} = require("../utils/progresses");
15-
const { PROGRESS_ALREADY_CREATED } = RESPONSE_MESSAGES;
16+
const { PROGRESS_ALREADY_CREATED, PROGRESS_DOCUMENT_NOT_FOUND } = RESPONSE_MESSAGES;
1617

1718
/**
1819
* Adds a new progress document for the given user or task, with a limit of one progress document per day.
@@ -68,4 +69,22 @@ const getRangeProgressData = async (queryParams) => {
6869
};
6970
};
7071

71-
module.exports = { createProgressDocument, getProgressDocument, getRangeProgressData };
72+
/**
73+
* This function fetches the progress records for a particular user or task on the specified date.
74+
* @param pathParams {object} This is the data that will be used for querying the db. It should contain type, typeId and date
75+
* @returns {Promise<object>} A Promise that resolves with the progress records of the queried user or task.
76+
* @throws {Error} If the userId or taskId is invalid or does not exist.
77+
**/
78+
async function getProgressByDate(pathParams) {
79+
const { type, typeId, date } = pathParams;
80+
await assertUserOrTaskExists({ [TYPE_MAP[type]]: typeId });
81+
const query = buildQueryToSearchProgressByDay({ [TYPE_MAP[type]]: typeId, date });
82+
const result = await query.get();
83+
if (!result.size) {
84+
throw new NotFound(PROGRESS_DOCUMENT_NOT_FOUND);
85+
}
86+
const doc = result.docs[0];
87+
return { id: doc.id, ...doc.data() };
88+
}
89+
90+
module.exports = { createProgressDocument, getProgressDocument, getRangeProgressData, getProgressByDate };

routes/progresses.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,18 @@ const {
55
validateCreateProgressRecords,
66
validateGetProgressRecordsQuery,
77
validateGetRangeProgressRecordsParams,
8+
validateGetDayProgressParams,
89
} = require("../middlewares/validators/progresses");
9-
const { createProgress, getProgress, getProgressRangeData } = require("../controllers/progresses");
10+
const {
11+
createProgress,
12+
getProgress,
13+
getProgressRangeData,
14+
getProgressBydDateController,
15+
} = require("../controllers/progresses");
1016

1117
router.post("/", authenticate, validateCreateProgressRecords, createProgress);
1218
router.get("/", validateGetProgressRecordsQuery, getProgress);
19+
router.get("/:type/:typeId/date/:date", validateGetDayProgressParams, getProgressBydDateController);
1320
router.get("/range", validateGetRangeProgressRecordsParams, getProgressRangeData);
1421

1522
module.exports = router;

utils/progresses.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,27 @@ const getProgressRecords = async (query, queryParams) => {
178178
return progressRecords;
179179
};
180180

181+
/**
182+
* Retrieves progress records for a given date range.
183+
* @param {Object} pathParamsObject - An object containing the type , typeId and date.
184+
* @param {string} pathParamsObject.type - The type of the record i.e user or task.
185+
* @param {string} pathParamsObject.typeId - The id of the type i.e user or task.
186+
* @param {string} pathParamsObject.date - The date of the record
187+
* @returns {Query} A Firestore query object that filters progress documents based on the given parameters.
188+
*
189+
*/
190+
const buildQueryToSearchProgressByDay = (pathParams) => {
191+
const { userId, taskId, date } = pathParams;
192+
let query = progressesCollection;
193+
if (userId) {
194+
query = query.where("userId", "==", userId);
195+
} else {
196+
query = query.where("taskId", "==", taskId);
197+
}
198+
const dateTimeStamp = new Date(date).setUTCHours(0, 0, 0, 0);
199+
query = query.where("date", "==", dateTimeStamp).limit(1);
200+
return query;
201+
};
181202
module.exports = {
182203
getProgressDateTimestamp,
183204
buildQueryForPostingProgress,
@@ -188,4 +209,5 @@ module.exports = {
188209
getProgressDocs,
189210
buildRangeProgressQuery,
190211
getProgressRecords,
212+
buildQueryToSearchProgressByDay,
191213
};

0 commit comments

Comments
 (0)