Skip to content

Commit

Permalink
Add total hours sheet tracking for signing out and amending hours
Browse files Browse the repository at this point in the history
  • Loading branch information
Cow-Van committed May 12, 2024
1 parent f10ef4b commit b9b665c
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 105 deletions.
32 changes: 17 additions & 15 deletions src/api/routes/users.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import express from "express";

import User, { getUserByPassword, updateUser } from "../../models/User.model";
import { createSession, deleteSessionBySessionId, doesSessionExist, getSessionBySessionId, getSessionsByUserId, updateSession } from "../../models/Session.model";
import {
createSession,
deleteSessionBySessionId,
doesSessionExist,
getSessionBySessionId,
getSessionsByUserId,
updateSession,
} from "../../models/Session.model";
import Time, { isOverlappingPreviousTimes } from "../../utils/time";
import { InvalidTimeError, RowNotFoundError } from "../../utils/errors";
import { addSingleSessionToSpreadsheet } from "../../utils/spreadsheet-hours";

const router = express.Router();

Expand Down Expand Up @@ -98,9 +106,7 @@ router.post("/session", async (req, res) => {
let previousSessionTimes: Time[] = [];

for (const session of previousSessions) {
previousSessionTimes.push(
new Time(session.start_time, session.end_time)
);
previousSessionTimes.push(new Time(session.start_time, session.end_time));
}

if (isOverlappingPreviousTimes(newSessionTime, previousSessionTimes)) {
Expand All @@ -109,12 +115,9 @@ router.post("/session", async (req, res) => {
});
}

await createSession(
user.user_id,
req.body.start_time,
req.body.end_time,
true
);
const session = await createSession(user.user_id, req.body.start_time, req.body.end_time, true);

await addSingleSessionToSpreadsheet(user, session);

return res.status(200).json({
description: "Amended new session!",
Expand Down Expand Up @@ -152,9 +155,7 @@ router.patch("/session", async (req, res) => {
continue;
}

previousSessionTimes.push(
new Time(session.start_time, session.end_time)
);
previousSessionTimes.push(new Time(session.start_time, session.end_time));
}

if (isOverlappingPreviousTimes(editedSessionTime, previousSessionTimes)) {
Expand Down Expand Up @@ -194,10 +195,11 @@ router.delete("/session", async (req, res) => {

const deleted = await deleteSessionBySessionId(req.body.session_id);

if (!deleted) { // Should never happen
if (!deleted) {
// Should never happen
return res.status(500).json({
description: "Could not delete session!",
})
});
}

return res.status(200).json({
Expand Down
4 changes: 2 additions & 2 deletions src/integration-tests/info-routes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("Info Routes", () => {
description: "Returning all users!",
users: structuredClone(fakeUsers).map((user: Partial<User>) => {
delete user.password;
user.signed_in = (user.signed_in) ? 1 : 0 as any;
user.signed_in = user.signed_in ? 1 : (0 as any);
return user;
}),
})
Expand All @@ -51,7 +51,7 @@ describe("Info Routes", () => {
it("should return user data given valid user ID", (done) => {
const user: Partial<User> = structuredClone(fakeUsers[16]); // Random user
delete user.password;
user.signed_in = (user.signed_in) ? 1 : 0 as any;
user.signed_in = user.signed_in ? 1 : (0 as any);

request(app)
.get(`/api/v1/info/users/${user.user_id}`)
Expand Down
1 change: 1 addition & 0 deletions src/integration-tests/users-routes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ describe("User Routes", () => { // TODO: make each api request into a helper fun
let startTime;
let endTime;

// Creates a valid session
outer: for (const fakeUser of fakeUsers) { // TODO: Turn into helper function
let sessions = fakeSessions.filter((session: Session) => session.user_id === fakeUser.user_id);
let lastSession = sessions[0];
Expand Down
38 changes: 8 additions & 30 deletions src/models/Config.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,24 @@ async function getConfigByName(name: string): Promise<Config> {
return configs[0];
}

async function createConfigs(
newConfigs: Config[]
): Promise<Config[]> {
const sql =
`INSERT INTO ${configsTableName} (name, value) VALUES ? RETURNING name, value`;
const params = newConfigs.map((newConfig) => [
newConfig.name,
newConfig.value,
]);
const [configs] = await db.query<ConfigRowDataPacket[]>(sql, [
params,
]);
async function createConfigs(newConfigs: Config[]): Promise<Config[]> {
const sql = `INSERT INTO ${configsTableName} (name, value) VALUES ? RETURNING name, value`;
const params = newConfigs.map((newConfig) => [newConfig.name, newConfig.value]);
const [configs] = await db.query<ConfigRowDataPacket[]>(sql, [params]);

return configs;
}

async function createConfig(name: string, value: string): Promise<Config> {
const sql =
`INSERT INTO ${configsTableName} (name, value) VALUES (?, ?) RETURNING name, value`;
const [configs] = await db.query<ConfigRowDataPacket[]>(sql, [
name,
value,
]);
const sql = `INSERT INTO ${configsTableName} (name, value) VALUES (?, ?) RETURNING name, value`;
const [configs] = await db.query<ConfigRowDataPacket[]>(sql, [name, value]);

return configs[0];
}

async function updateConfig(name: string, newValue: string): Promise<boolean> {
const sql = `UPDATE ${configsTableName} SET value = ? WHERE name = ?`;
const [resHeader] = await db.query<ResultSetHeader>(sql, [
newValue,
name,
]);
const [resHeader] = await db.query<ResultSetHeader>(sql, [newValue, name]);

return resHeader.affectedRows > 0;
}
Expand All @@ -75,11 +60,4 @@ async function deleteConfigByName(name: string): Promise<Config> {
}

export default Config;
export {
getAllConfigs,
getConfigByName,
createConfigs,
createConfig,
updateConfig,
deleteConfigByName,
};
export { getAllConfigs, getConfigByName, createConfigs, createConfig, updateConfig, deleteConfigByName };
45 changes: 32 additions & 13 deletions src/models/Session.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ async function doesSessionExist(session_id: number): Promise<boolean> {
return sessions.length > 0;
}

async function createSession(user_id: number, start_time: number, end_time: number, amended: boolean): Promise<boolean> {
const sql = `INSERT INTO ${sessionsTableName} (user_id, start_time, end_time, amended) SELECT user_id, ?, ?, ? FROM ${usersTableName} WHERE user_id = ?`;
async function createSession(user_id: number, start_time: number, end_time: number, amended: boolean): Promise<Session> {
const sql = `INSERT INTO ${sessionsTableName} (user_id, start_time, end_time, amended) SELECT user_id, ?, ?, ? FROM ${usersTableName} WHERE user_id = ?
RETURNING session_id, user_id, start_time, end_time, amended`;
const params = [start_time, end_time, amended, user_id];

const [resHeader] = await db.query<ResultSetHeader>(sql, params);
const [sessions] = await db.query<SessionRowDataPacket[]>(sql, params);

return resHeader.affectedRows === 1;
return sessions[0];
}

async function updateSession(session_id: number, values: Partial<Session>): Promise<boolean> {
Expand All @@ -69,19 +70,37 @@ async function updateSession(session_id: number, values: Partial<Session>): Prom
return resHeader.affectedRows === 1;
}

async function deleteSessionBySessionId(session_id: number): Promise<boolean> {
const sql = `DELETE FROM ${sessionsTableName} WHERE session_id = ?`;
const [resHeader] = await db.query<ResultSetHeader>(sql, [session_id]);
async function deleteSessionBySessionId(session_id: number): Promise<Session> {
const sql = `DELETE FROM ${sessionsTableName} WHERE session_id = ? RETURNING session_id, user_id, start_time, end_time, amended`;
const [sessions] = await db.query<SessionRowDataPacket[]>(sql, [session_id]);

return resHeader.affectedRows === 1;
return sessions[0];
}

async function deleteSessionsByUserPassword(password: number): Promise<boolean> {
const sql = `DELETE FROM ${sessionsTableName} WHERE user_id = (SELECT user_id from ${usersTableName} WHERE password = ?)`;
const [resHeader] = await db.query<ResultSetHeader>(sql, [password]);
async function deleteSessionsByUserId(user_id: number): Promise<Session> {
const sql = `DELETE FROM ${sessionsTableName} WHERE user_id = ? RETURNING session_id, user_id, start_time, end_time, amended`;
const [sessions] = await db.query<SessionRowDataPacket[]>(sql, [user_id]);

return resHeader.affectedRows > 0;
return sessions[0];
}

async function deleteSessionsByUserPassword(password: number): Promise<Session> {
const sql = `DELETE FROM ${sessionsTableName} WHERE user_id = (SELECT user_id from ${usersTableName} WHERE password = ?)
RETURNING (session_id, user_id, start_time, end_time, amended)`;
const [sessions] = await db.query<SessionRowDataPacket[]>(sql, [password]);

return sessions[0];
}

export default Session;
export { getAllSessions, getSessionsByUserId, getSessionBySessionId, doesSessionExist, createSession, updateSession, deleteSessionBySessionId, deleteSessionsByUserPassword };
export {
getAllSessions,
getSessionsByUserId,
getSessionBySessionId,
doesSessionExist,
createSession,
updateSession,
deleteSessionBySessionId,
deleteSessionsByUserId,
deleteSessionsByUserPassword,
};
47 changes: 11 additions & 36 deletions src/models/User.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ async function getUserById(userId: number): Promise<User> {
const [users] = await db.query<UserRowDataPacket[]>(sql, [userId]);

if (users.length < 1) {
throw new RowNotFoundError(
`User of ID: ${userId} not found in table: ${usersTableName}`
);
throw new RowNotFoundError(`User of ID: ${userId} not found in table: ${usersTableName}`);
}

return users[0];
Expand All @@ -49,49 +47,26 @@ async function getUserByPassword(password: string): Promise<User> {
return users[0];
}

async function createUser(
first_name: string,
last_name: string,
password: string
): Promise<User> {
const sql =
`INSERT INTO ${usersTableName} (first_name, last_name, password) VALUES (?, ?, ?); SELECT user_id, first_name, last_name FROM ${usersTableName} where password = ?`;
const [users] = await db.query<UserRowDataPacket[]>(sql, [
first_name,
last_name,
password,
password,
]);
async function createUser(first_name: string, last_name: string, password: string): Promise<User> {
const sql = `INSERT INTO ${usersTableName} (first_name, last_name, password) VALUES (?, ?, ?) RETURNING user_id, first_name, last_name, password, signed_in, last_signed_in, total_time`;
const [users] = await db.query<UserRowDataPacket[]>(sql, [first_name, last_name, password, password]);

return users[0];
}

async function updateUser(
user_id: number,
values: Partial<User>
): Promise<boolean> {
async function updateUser(user_id: number, values: Partial<User>): Promise<boolean> {
const update = updateBuilder(usersTableName, values, { user_id });
const [resHeader] = await db.query<ResultSetHeader>(
update.query,
update.params
);
const [resHeader] = await db.query<ResultSetHeader>(update.query, update.params);

return resHeader.affectedRows === 1;
}

async function deleteUserByPassword(password: number): Promise<boolean> {
const sql = `DELETE FROM ${usersTableName} WHERE password = ?`;
const [resHeader] = await db.query<ResultSetHeader>(sql, [password]);
async function deleteUserByPassword(password: number): Promise<User> {
const sql = `DELETE FROM ${usersTableName} WHERE password = ? RETURNING user_id, first_name, last_name, password, signed_in, last_signed_in, total_time`;
const [users] = await db.query<UserRowDataPacket[]>(sql, [password]);

return resHeader.affectedRows === 1;
return users[0];
}

export default User;
export {
getAllUsers,
getUserById,
getUserByPassword,
createUser,
updateUser,
deleteUserByPassword,
};
export { getAllUsers, getUserById, getUserByPassword, createUser, updateUser, deleteUserByPassword };
6 changes: 3 additions & 3 deletions src/spreadsheet/sheets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ async function getSheets(): Promise<sheets_v4.Sheets> {

async function getSheetNameById(spreadsheetId: string, sheetId: number): Promise<string> {
const sheets = await getSheets();
const data = (await asyncExponentialBackoff(async () => (await sheets.spreadsheets.get({
const data = (await asyncExponentialBackoff(async () => await sheets.spreadsheets.get({
spreadsheetId,
includeGridData: false,
})))).data;
}))).data;

for (let i = 0; i < data.sheets!.length; i++) {
if (data.sheets![i].properties!.sheetId! === sheetId) {
if (data.sheets![i].properties!.sheetId! == sheetId) {
return data.sheets![i].properties!.title!;
}
}
Expand Down
27 changes: 22 additions & 5 deletions src/utils/spreadsheet-hours/add-single-session.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import Session from "../../models/Session.model";
import User from "../../models/User.model";
import { readCell } from "../../spreadsheet";
import { readCell, writeCell } from "../../spreadsheet";
import { Cell } from "../../spreadsheet/cell";
import { RangeNotFound } from "../errors";
import { getUserRowFromTotalHoursSheet, getUserRowFromHoursHistorySheet } from "./helpers/get-user-row";
import { msTimesToHourDuration } from "./helpers/times-to-duration";

// Add session time to spreadsheet
async function addSingleSession(user: User, session: Session): Promise<void> {
async function addSingleSessionToSpreadsheet(user: User, session: Session): Promise<void> {
// No spreadsheets while testing
if (process.env.NODE_ENV === "testing") {
return;
}

const totalHoursSheetRow = await getUserRowFromTotalHoursSheet(user);
const hoursHistorySheetRow = await getUserRowFromHoursHistorySheet(user);
const cell = new Cell(process.env.TOTAL_HOURS_SHEET_HOURS_COLUMN, totalHoursSheetRow);

const hoursCellData = await readCell(process.env.HOURS_SPREADSHEET_ID, process.env.TOTAL_HOURS_SHEET_ID, new Cell(process.env.TOTAL_HOURS_SHEET_HOURS_COLUMN, totalHoursSheetRow));
let totalHours = isFinite(parseFloat(hoursCellData)) ? parseFloat(hoursCellData) : 0; // If is not finite, then set to 0 TODO: have it check the hours logged in database
let hoursCellData;
try {
hoursCellData = await readCell(process.env.HOURS_SPREADSHEET_ID, process.env.TOTAL_HOURS_SHEET_ID, cell);
} catch (e) {
if (e instanceof RangeNotFound) {
hoursCellData = "";
} else {
throw e;
}
}

let totalHours = isFinite(parseFloat(hoursCellData)) ? parseFloat(hoursCellData) : 0; // If is not finite, then set to 0 TODO: have it check the hours logged in database
totalHours += msTimesToHourDuration(session.start_time, session.end_time);
await writeCell(process.env.HOURS_SPREADSHEET_ID, process.env.TOTAL_HOURS_SHEET_ID, cell, totalHours);
// TODO: total hours calculation
}

export { addSingleSession }
export { addSingleSessionToSpreadsheet };
2 changes: 1 addition & 1 deletion src/utils/spreadsheet-hours/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { addSingleSession } from "./add-single-session";
export { addSingleSessionToSpreadsheet } from "./add-single-session";

0 comments on commit b9b665c

Please sign in to comment.