finalized application acceptance system and started making types shared across front and backend
This commit is contained in:
@@ -2,23 +2,22 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
import pool from '../db';
|
||||
import { approveApplication, createApplication, getApplicationByID, getApplicationComments, getApplicationList, getMemberApplication } from '../services/applicationService';
|
||||
import { MemberState, setUserState } from '../services/memberService';
|
||||
import { getRankByName, insertMemberRank } from '../services/rankService';
|
||||
import { ApplicationFull, CommentRow } from "@app/shared/types/application"
|
||||
import { assignUserToStatus } from '../services/statusService';
|
||||
|
||||
// POST /application
|
||||
router.post('/', async (req, res) => {
|
||||
try {
|
||||
const App = req.body?.App || {};
|
||||
const memberID = req.user.id;
|
||||
|
||||
// TODO: replace with current user ID
|
||||
const memberId = 1;
|
||||
|
||||
const sql = `INSERT INTO applications (member_id, app_version, app_data) VALUES (?, ?, ?);`;
|
||||
const appVersion = 1;
|
||||
|
||||
const params = [memberId, appVersion, JSON.stringify(App)]
|
||||
|
||||
console.log(params)
|
||||
|
||||
await pool.query(sql, params);
|
||||
createApplication(memberID, appVersion, JSON.stringify(App))
|
||||
setUserState(memberID, MemberState.Applicant);
|
||||
|
||||
res.sendStatus(201);
|
||||
} catch (err) {
|
||||
@@ -30,18 +29,7 @@ router.post('/', async (req, res) => {
|
||||
// GET /application/all
|
||||
router.get('/all', async (req, res) => {
|
||||
try {
|
||||
const sql = `SELECT
|
||||
member.name AS member_name,
|
||||
app.id,
|
||||
app.member_id,
|
||||
app.submitted_at,
|
||||
app.app_status
|
||||
FROM applications AS app
|
||||
LEFT JOIN members AS member
|
||||
ON member.id = app.member_id;`
|
||||
|
||||
const rows = await pool.query(sql);
|
||||
|
||||
const rows = await getApplicationList();
|
||||
res.status(200).json(rows);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@@ -49,47 +37,35 @@ router.get('/all', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/me', async (req, res) => {
|
||||
let userID = req.user.id;
|
||||
|
||||
console.log("application/me")
|
||||
|
||||
let app = getMemberApplication(userID);
|
||||
console.log(app);
|
||||
})
|
||||
|
||||
// GET /application/:id
|
||||
router.get('/:id', async (req, res) => {
|
||||
let appID = req.params.id;
|
||||
|
||||
//TODO: Replace with real user Authorization and whatnot
|
||||
// if the application is not "me" and I am not a recruiter, deny access to the application (return 403 or whatever)
|
||||
if (appID === "me")
|
||||
appID = 2;
|
||||
|
||||
try {
|
||||
const conn = await pool.getConnection()
|
||||
|
||||
const application = await conn.query(
|
||||
`SELECT app.*,
|
||||
member.name AS member_name
|
||||
FROM applications AS app
|
||||
INNER JOIN members AS member ON member.id = app.member_id
|
||||
WHERE app.id = ?;`,
|
||||
[appID]
|
||||
);
|
||||
const application = await getApplicationByID(appID);
|
||||
|
||||
if (!Array.isArray(application) || application.length === 0) {
|
||||
conn.release();
|
||||
return res.status(204).json("Application Not Found");
|
||||
}
|
||||
|
||||
const comments = await conn.query(`SELECT app.id AS comment_id,
|
||||
app.post_content,
|
||||
app.poster_id,
|
||||
app.post_time,
|
||||
app.last_modified,
|
||||
member.name AS poster_name
|
||||
FROM application_comments AS app
|
||||
INNER JOIN members AS member ON member.id = app.poster_id
|
||||
WHERE app.application_id = ?;`,
|
||||
[appID]);
|
||||
const comments: CommentRow[] = await getApplicationComments(appID);
|
||||
|
||||
conn.release()
|
||||
|
||||
const output = {
|
||||
application: application[0],
|
||||
const output: ApplicationFull = {
|
||||
application,
|
||||
comments,
|
||||
}
|
||||
return res.status(200).json(output);
|
||||
@@ -104,26 +80,27 @@ router.get('/:id', async (req, res) => {
|
||||
router.post('/approve/:id', async (req, res) => {
|
||||
const appID = req.params.id;
|
||||
|
||||
const sql = `
|
||||
UPDATE applications
|
||||
SET approved_at = NOW()
|
||||
WHERE id = ?
|
||||
AND approved_at IS NULL
|
||||
AND denied_at IS NULL
|
||||
`;
|
||||
try {
|
||||
const result = await pool.execute(sql, appID);
|
||||
const app = await getApplicationByID(appID);
|
||||
const result = await approveApplication(appID);
|
||||
|
||||
console.log(result);
|
||||
console.log("START");
|
||||
console.log(app, result);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
res.status(400).json('Something went wrong approving the application');
|
||||
//guard against failures
|
||||
if (result.affectedRows != 1) {
|
||||
throw new Error("Something went wrong approving the application");
|
||||
}
|
||||
|
||||
if (result.affectedRows == 1) {
|
||||
res.sendStatus(200);
|
||||
}
|
||||
console.log(app.member_id);
|
||||
//update user profile
|
||||
await setUserState(app.member_id, MemberState.Member);
|
||||
|
||||
let nextRank = await getRankByName('Recruit')
|
||||
await insertMemberRank(app.member_id, nextRank.id);
|
||||
//assign user to "pending basic"
|
||||
await assignUserToStatus(app.member_id, 1);
|
||||
res.sendStatus(200);
|
||||
} catch (err) {
|
||||
console.error('Approve failed:', err);
|
||||
res.status(500).json({ error: 'Failed to approve application' });
|
||||
@@ -7,7 +7,7 @@ const { getAllRanks, insertMemberRank } = require('../services/rankService')
|
||||
ur.post('/', async (req, res) => {3
|
||||
try {
|
||||
const change = req.body?.change;
|
||||
await insertMemberRank(change);
|
||||
await insertMemberRank(change.member_id, change.rank_id, change.date);
|
||||
|
||||
res.sendStatus(201);
|
||||
} catch (err) {
|
||||
|
||||
71
api/src/services/applicationService.ts
Normal file
71
api/src/services/applicationService.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { ApplicationListRow, ApplicationRow, CommentRow } from "@app/shared/types/application";
|
||||
import pool from "../db";
|
||||
|
||||
export async function createApplication(memberID: number, appVersion: number, app: string) {
|
||||
const sql = `INSERT INTO applications (member_id, app_version, app_data) VALUES (?, ?, ?);`;
|
||||
const params = [memberID, appVersion, JSON.stringify(app)]
|
||||
return await pool.query(sql, params);
|
||||
}
|
||||
|
||||
export async function getMemberApplication(memberID: number): Promise<ApplicationRow> {
|
||||
const sql = `SELECT app.*,
|
||||
member.name AS member_name
|
||||
FROM applications AS app
|
||||
INNER JOIN members AS member ON member.id = app.member_id
|
||||
WHERE app.member_id = ?;`;
|
||||
|
||||
let app: ApplicationRow[] = await pool.query(sql, [memberID]);
|
||||
return app[0];
|
||||
}
|
||||
|
||||
export async function getApplicationByID(appID: number): Promise<ApplicationRow> {
|
||||
const sql =
|
||||
`SELECT app.*,
|
||||
member.name AS member_name
|
||||
FROM applications AS app
|
||||
INNER JOIN members AS member ON member.id = app.member_id
|
||||
WHERE app.id = ?;`;
|
||||
let app: ApplicationRow[] = await pool.query(sql, [appID]);
|
||||
return app[0];
|
||||
}
|
||||
|
||||
export async function getApplicationList(): Promise<ApplicationListRow[]> {
|
||||
const sql = `SELECT
|
||||
member.name AS member_name,
|
||||
app.id,
|
||||
app.member_id,
|
||||
app.submitted_at,
|
||||
app.app_status
|
||||
FROM applications AS app
|
||||
LEFT JOIN members AS member
|
||||
ON member.id = app.member_id;`
|
||||
|
||||
const rows: ApplicationListRow[] = await pool.query(sql);
|
||||
return rows;
|
||||
}
|
||||
|
||||
export async function approveApplication(id) {
|
||||
const sql = `
|
||||
UPDATE applications
|
||||
SET approved_at = NOW()
|
||||
WHERE id = ?
|
||||
AND approved_at IS NULL
|
||||
AND denied_at IS NULL
|
||||
`;
|
||||
|
||||
const result = await pool.execute(sql, id);
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getApplicationComments(appID: number): Promise<CommentRow[]> {
|
||||
return await pool.query(`SELECT app.id AS comment_id,
|
||||
app.post_content,
|
||||
app.poster_id,
|
||||
app.post_time,
|
||||
app.last_modified,
|
||||
member.name AS poster_name
|
||||
FROM application_comments AS app
|
||||
INNER JOIN members AS member ON member.id = app.poster_id
|
||||
WHERE app.application_id = ?;`,
|
||||
[appID]);
|
||||
}
|
||||
@@ -1,8 +1,23 @@
|
||||
import pool from "../db";
|
||||
|
||||
export enum MemberState {
|
||||
Guest = "guest",
|
||||
Applicant = "applicant",
|
||||
Member = "member",
|
||||
Retired = "retired",
|
||||
Banned = "banned",
|
||||
Denied = "denied"
|
||||
}
|
||||
|
||||
export async function getUserData(userID: number) {
|
||||
const sql = `SELECT * FROM members WHERE id = ?`;
|
||||
const res = await pool.query(sql, [userID]);
|
||||
return res[0] ?? null;
|
||||
}
|
||||
|
||||
export async function setUserState(userID: number, state: MemberState) {
|
||||
const sql = `UPDATE members
|
||||
SET state = ?
|
||||
WHERE id = ?;`;
|
||||
return await pool.query(sql, [state, userID]);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import pool from "../db";
|
||||
|
||||
async function getAllRanks() {
|
||||
const rows = await pool.query(
|
||||
'SELECT id, name, short_name, sort_id FROM ranks;'
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
async function insertMemberRank(change) {
|
||||
const sql = `
|
||||
INSERT INTO members_ranks (member_id, rank_id, event_date)
|
||||
VALUES (?, ?, ?);
|
||||
`;
|
||||
const params = [change.member_id, change.rank_id, change.date];
|
||||
await pool.query(sql, params);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAllRanks,
|
||||
insertMemberRank
|
||||
};
|
||||
32
api/src/services/rankService.ts
Normal file
32
api/src/services/rankService.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import pool from "../db";
|
||||
|
||||
export async function getAllRanks() {
|
||||
const rows = await pool.query(
|
||||
'SELECT id, name, short_name, sort_id FROM ranks;'
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
export async function getRankByName(name: string) {
|
||||
const rows = await pool.query(`SELECT id, name, short_name, sort_id FROM ranks WHERE name = ?`, [name]);
|
||||
|
||||
if (rows.length === 0)
|
||||
throw new Error("Could not find rank: " + name);
|
||||
|
||||
return rows[0];
|
||||
}
|
||||
|
||||
export async function insertMemberRank(member_id: number, rank_id: number, date: Date): Promise<void>;
|
||||
export async function insertMemberRank(member_id: number, rank_id: number): Promise<void>;
|
||||
|
||||
export async function insertMemberRank(member_id: number, rank_id: number, date?: Date): Promise<void> {
|
||||
const sql = date
|
||||
? `INSERT INTO members_ranks (member_id, rank_id, event_date) VALUES (?, ?, ?);`
|
||||
: `INSERT INTO members_ranks (member_id, rank_id, event_date) VALUES (?, ?, NOW());`;
|
||||
|
||||
const params = date
|
||||
? [member_id, rank_id, date]
|
||||
: [member_id, rank_id];
|
||||
|
||||
await pool.query(sql, params);
|
||||
}
|
||||
6
api/src/services/statusService.ts
Normal file
6
api/src/services/statusService.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import pool from "../db"
|
||||
|
||||
export async function assignUserToStatus(userID: number, statusID: number) {
|
||||
const sql = `INSERT INTO members_statuses (member_id, status_id, event_date) VALUES (?, ?, NOW())`
|
||||
await pool.execute(sql, [userID, statusID]);
|
||||
}
|
||||
@@ -6,7 +6,10 @@
|
||||
"types": [
|
||||
"node",
|
||||
"express"
|
||||
]
|
||||
],
|
||||
"paths": {
|
||||
"@app/shared/*": ["../shared/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
|
||||
Reference in New Issue
Block a user