Skip to content

Commit cec8110

Browse files
authored
Merge pull request #374 from icefoganalytics/test
WUP and NARS
2 parents c7ba051 + 5305285 commit cec8110

File tree

27 files changed

+1277
-72
lines changed

27 files changed

+1277
-72
lines changed

db/2025_updates.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
CREATE TABLE sfa.noc_codes (
3+
noc_2016_code NVARCHAR(10),
4+
noc_2016_title NVARCHAR(255),
5+
gsim_type_of_change NVARCHAR(255),
6+
noc_2021_code NVARCHAR(10) ,
7+
noc_2021_title NVARCHAR(255),
8+
notes NVARCHAR(max)
9+
);

src/api/controllers/admin/reporting-controller.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,94 @@ export default class ReportingController extends BaseController {
290290
);
291291
}
292292

293+
async runNars2024FTReport() {
294+
return ReportingService.runNars2024FTReport({ format: this.format }).then((reportData) => {
295+
if (this.format == "html") {
296+
this.response.send(reportData);
297+
} else if (this.format == "csv") {
298+
this.response.setHeader("Content-disposition", `attachment; filename="PPYT.CSLS.NARS_2425.001.csv"`);
299+
this.response.setHeader("Content-type", "text/csv");
300+
this.response.send(reportData);
301+
} else if (this.format == "json") {
302+
this.response.json(reportData);
303+
} else {
304+
this.response.setHeader("Content-disposition", `attachment; filename="PPYT.CSLS.NARS_2425.001.txt"`);
305+
this.response.setHeader("Content-type", "text/plain");
306+
this.response.send(reportData);
307+
}
308+
});
309+
}
310+
311+
async runNars2024PTReport() {
312+
return ReportingService.runNars2024PTReport({ format: this.format }).then((reportData) => {
313+
if (this.format == "html") {
314+
this.response.send(reportData);
315+
} else if (this.format == "csv") {
316+
this.response.setHeader("Content-disposition", `attachment; filename="PPYT.CSLS.PT_NARS_2425.001.csv"`);
317+
this.response.setHeader("Content-type", "text/csv");
318+
this.response.send(reportData);
319+
} else if (this.format == "json") {
320+
this.response.json(reportData);
321+
} else {
322+
this.response.setHeader("Content-disposition", `attachment; filename="PPYT.CSLS.PT_NARS_2425.001.txt"`);
323+
this.response.setHeader("Content-type", "text/plain");
324+
this.response.send(reportData);
325+
}
326+
});
327+
}
328+
329+
async runNars2024DisabilityReport() {
330+
return ReportingService.runNars2024DisabilityReport({ format: this.format, academic_year_id: 2024 }).then(
331+
(reportData) => {
332+
if (this.format == "html") {
333+
this.response.send(reportData);
334+
} else if (this.format == "csv") {
335+
this.response.setHeader(
336+
"Content-disposition",
337+
`attachment; filename="PPYT.CSLS.PDEXPAND_2425.${moment().format("YYYY-MM-DD")}.csv"`
338+
);
339+
this.response.setHeader("Content-type", "text/csv");
340+
this.response.send(reportData);
341+
} else if (this.format == "json") {
342+
this.response.json(reportData);
343+
} else {
344+
this.response.setHeader(
345+
"Content-disposition",
346+
`attachment; filename="PPYT.CSLS.PDEXPAND_2425.${moment().format("YYYY-MM-DD")}.txt"`
347+
);
348+
this.response.setHeader("Content-type", "text/plain");
349+
this.response.send(reportData);
350+
}
351+
}
352+
);
353+
}
354+
355+
async runNars2024DisabilityRCLReport() {
356+
return ReportingService.runNars2024DisabilityRCLReport({ format: this.format, academic_year_id: 2024 }).then(
357+
(reportData) => {
358+
if (this.format == "html") {
359+
this.response.send(reportData);
360+
} else if (this.format == "csv") {
361+
this.response.setHeader(
362+
"Content-disposition",
363+
`attachment; filename="PPYT.CSLS.PDReducedCourseLoad_2425.${moment().format("YYYY-MM-DD")}.csv"`
364+
);
365+
this.response.setHeader("Content-type", "text/csv");
366+
this.response.send(reportData);
367+
} else if (this.format == "json") {
368+
this.response.json(reportData);
369+
} else {
370+
this.response.setHeader(
371+
"Content-disposition",
372+
`attachment; filename="PPYT.CSLS.PDReducedCourseLoad_2425.${moment().format("YYYY-MM-DD")}.txt"`
373+
);
374+
this.response.setHeader("Content-type", "text/plain");
375+
this.response.send(reportData);
376+
}
377+
}
378+
);
379+
}
380+
293381
async runStepReport() {
294382
let academic_year_id = parseInt(this.request.params.academic_year_id ?? moment().format("YYYY"));
295383

src/api/routes/admin/assessment/assessment-yukon-grant-router.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import knex from "knex";
44
import { ReturnValidationErrors } from "@/middleware";
55
import { DB_CONFIG } from "@/config";
66
import { AssessmentService } from "@/services/admin/assessments/assessment-service";
7+
import { writeAuditLog } from "@/services/audit-service";
78

89
const db = knex(DB_CONFIG);
910
export const assessmentYukonGrantRouter = express.Router();
@@ -57,7 +58,16 @@ assessmentYukonGrantRouter.post(
5758
delete updatedItem.extras;
5859
delete updatedItem.id;
5960

60-
const updated = await db("sfa.assessment").insert(updatedItem);
61+
const updated = await db("sfa.assessment").insert(updatedItem).returning("id");
62+
63+
await writeAuditLog({
64+
application_id: fundingRequest.application_id,
65+
funding_request_id: fundingRequest.id,
66+
assessment_id: updated[0].id,
67+
user_id: req.user.id,
68+
user_name: req.user.display_name.replace(".", " "),
69+
title: `Assessment Created`,
70+
});
6171

6272
if (updated) {
6373
return res.status(200).json({ messages: [{ variant: "success", text: "Assessment saved" }] });
@@ -102,15 +112,23 @@ assessmentYukonGrantRouter.patch(
102112
await builder.load(true);
103113

104114
const updatedItem = builder.assessment;
105-
115+
106116
if (doDisburse) {
107117
const travel = updatedItem.travel_allowance + updatedItem.airfare_amount;
108118
let netAmount = updatedItem.extras.netAmount - travel;
109119
let transDisburseNum = updatedItem.air_travel_disbursement_period;
120+
121+
// this only applies when disburseCount > 1
122+
// for first disbursement, 16 weeks
123+
// optional for second disbursement, up to 20 weeks
124+
// last disbursement, remainder
125+
// transDisburseNum works to put travel in right spot
126+
110127
const disburseCount = updatedItem.disbursements_required;
111128

112129
if (transDisburseNum > disburseCount) transDisburseNum = disburseCount;
113130

131+
// this is the problem line
114132
let disburseAmount = Math.ceil(netAmount / disburseCount);
115133
let disburseRemaining = netAmount;
116134

src/api/routes/admin/csg-threshold-router.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,6 @@ csgThresholdRouter.put(
162162

163163
delete (recalc as any).id;
164164
delete (recalc as any).assessment_type_id;
165-
(recalc as any).student_contribution_override = null;
166-
(recalc as any).spouse_contribution_override = null;
167-
(recalc as any).parent_contribution_override = null;
168-
(recalc as any).return_uncashable_cert = null;
169-
(recalc as any).csl_non_reason_id = null;
170-
(recalc as any).csl_over_reason_id = null;
171165

172166
await db("sfa.assessment").where({ id: assessment_id }).update(recalc);
173167
return res.status(200).json({ data: "Assessment Saved" });

src/api/routes/admin/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ adminRouter.use("/reporting/nars2023pt", routedTo(ReportingController, "runNars2
198198
adminRouter.use("/reporting/nars2023dis", routedTo(ReportingController, "runNars2023DisabilityReport"));
199199
adminRouter.use("/reporting/nars2023disrcl", routedTo(ReportingController, "runNars2023DisabilityRCLReport"));
200200

201+
adminRouter.use("/reporting/nars2024", routedTo(ReportingController, "runNars2023FTReport"));
202+
adminRouter.use("/reporting/nars2024pt", routedTo(ReportingController, "runNars2024PTReport"));
203+
adminRouter.use("/reporting/nars2024dis", routedTo(ReportingController, "runNars2024DisabilityReport"));
204+
adminRouter.use("/reporting/nars2024disrcl", routedTo(ReportingController, "runNars2024DisabilityRCLReport"));
205+
201206
adminRouter.use("/reporting/step/:academic_year_id", routedTo(ReportingController, "runStepReport"));
202207
adminRouter.use(
203208
"/reporting/approvedFunding/:academic_year_id",

src/api/routes/reference-router.ts

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,69 @@
11
import express, { Request, Response } from "express";
22
import knex from "knex";
3+
import { parse } from "papaparse";
34

45
import { DB_CONFIG } from "../config";
6+
import { isArray } from "lodash";
57

68
const db = knex(DB_CONFIG);
79

810
export const referenceRouter = express.Router();
911

1012
referenceRouter.get("/city", async (req: Request, res: Response) => {
11-
let list = await db("sfa.city").orderBy("description");
12-
res.json({ data: list })
13+
let list = await db("sfa.city").orderBy("description");
14+
res.json({ data: list });
1315
});
1416

1517
referenceRouter.get("/province", async (req: Request, res: Response) => {
16-
let list = await db("sfa.province").orderBy("description");
17-
res.json({ data: list })
18+
let list = await db("sfa.province").orderBy("description");
19+
res.json({ data: list });
1820
});
1921

2022
referenceRouter.get("/country", async (req: Request, res: Response) => {
21-
let list = await db("sfa.country").orderBy("description");
22-
res.json({ data: list })
23+
let list = await db("sfa.country").orderBy("description");
24+
res.json({ data: list });
2325
});
2426

2527
referenceRouter.get("/institution_level", async (req: Request, res: Response) => {
26-
let levels = await db("sfa.institution_level");
27-
res.json({ data: levels })
28+
let levels = await db("sfa.institution_level");
29+
res.json({ data: levels });
30+
});
31+
32+
referenceRouter.get("/noc_codes", async (req: Request, res: Response) => {
33+
let codes = await db("sfa.noc_codes").select("noc_2021_code", "noc_2021_title");
34+
res.json({ data: codes });
35+
});
36+
37+
referenceRouter.post("/noc_codes", async (req: Request, res: Response) => {
38+
if (!req.files || !req.files.file) return res.status(400).json({ message: "No file provided" });
39+
40+
const file = isArray(req.files.file) ? req.files.file[0] : req.files.file; // Expecting an array of NOC code objects
41+
const contents = file.data.toString("utf-8");
42+
const csv = parse<{
43+
noc2016v13code: string;
44+
noc2016v13title: string;
45+
gsimtypeofchange: string;
46+
noc2021v10code: string;
47+
noc2021v10title: string;
48+
notes: string;
49+
}>(contents, {
50+
header: true,
51+
skipEmptyLines: true,
52+
transformHeader: (header) => header.toLowerCase().replace(/\s/g, "").replace(".", "").trim(), // remove spaces and dots
53+
});
54+
55+
await db("sfa.noc_codes").delete();
56+
57+
for (const line of csv.data) {
58+
await db("sfa.noc_codes").insert({
59+
noc_2016_code: line.noc2016v13code,
60+
noc_2016_title: line.noc2016v13title,
61+
gsim_type_of_change: line.gsimtypeofchange,
62+
noc_2021_code: line.noc2021v10code,
63+
noc_2021_title: line.noc2021v10title,
64+
notes: line.notes,
65+
});
66+
}
67+
68+
res.json({ message: "NOC codes updated successfully" });
2869
});

src/api/services/admin/assessments/yukon-grant-service.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ export class YukonGrantService {
5858

5959
if (!institutionCampus) throw new Error("Institution Campus not found");
6060

61-
this.parent.assessment.home_city_id = homeAddress.city_id;
62-
this.parent.assessment.destination_city_id = institutionCampus.address_city_id;
61+
this.parent.assessment.home_city_id = this.parent.assessment.home_city_id ?? homeAddress.city_id;
62+
this.parent.assessment.destination_city_id =
63+
this.parent.assessment.destination_city_id ?? institutionCampus.address_city_id;
6364

6465
if (!this.parent.assessment.home_city_id) throw new Error("Home City not found for Student Address");
6566

src/api/services/admin/reporting-service.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,102 @@ export default class ReportingService {
304304
return lines.join("\n");
305305
}
306306

307+
static async runNars2024FTReport({ format = "json" }: { format: string | undefined }): Promise<any> {
308+
let service = new NarsV17_2ReportingService({
309+
startDate: new Date("2024-06-01"),
310+
endDate: new Date("2025-05-31"),
311+
year: 2024,
312+
});
313+
314+
let results = await service.runReport();
315+
316+
if (format == "json") {
317+
return results.map((r) => r.toJson());
318+
} else if (format == "csv") {
319+
let lines = results.map((r) => r.toCsv());
320+
lines.unshift(results[0].columns.map((c) => c.field).join(","));
321+
return lines.join("\n");
322+
}
323+
324+
let lines = results.map((r) => r.toString());
325+
return lines.join("\n");
326+
}
327+
328+
static async runNars2024PTReport({ format = "json" }: { format: string | undefined }): Promise<any> {
329+
let service = new NarsPTReportingService({
330+
startDate: new Date("2024-06-01"),
331+
endDate: new Date("2025-05-31"),
332+
year: 2024,
333+
});
334+
335+
let results = await service.runReport();
336+
337+
if (format == "json") {
338+
return results.map((r) => r.toJson());
339+
} else if (format == "csv") {
340+
let lines = results.map((r) => r.toCsv());
341+
lines.unshift(results[0].columns.map((c) => c.field).join(","));
342+
return lines.join("\n");
343+
}
344+
345+
let lines = results.map((r) => r.toString());
346+
return lines.join("\n");
347+
}
348+
349+
static async runNars2024DisabilityReport({
350+
format = "json",
351+
academic_year_id,
352+
}: {
353+
format: string | undefined;
354+
academic_year_id: number;
355+
}): Promise<any> {
356+
let service = new NarsDisabilityReportingService({
357+
startDate: new Date("2024-06-01"),
358+
endDate: new Date("2025-05-31"),
359+
year: academic_year_id,
360+
});
361+
362+
let results = await service.runReport();
363+
364+
if (format == "json") {
365+
return results.map((r) => r.toJson());
366+
} else if (format == "csv") {
367+
let lines = results.map((r) => r.toCsv());
368+
lines.unshift(results[0].columns.map((c) => c.field).join(","));
369+
return lines.join("\n");
370+
}
371+
372+
let lines = results.map((r) => r.toString());
373+
return lines.join("\n");
374+
}
375+
376+
static async runNars2024DisabilityRCLReport({
377+
format = "json",
378+
academic_year_id,
379+
}: {
380+
format: string | undefined;
381+
academic_year_id: number;
382+
}): Promise<any> {
383+
let service = new NarsDisabilityRCLReportingService({
384+
startDate: new Date("2024-06-01"),
385+
endDate: new Date("2025-05-31"),
386+
year: academic_year_id,
387+
});
388+
389+
let results = await service.runReport();
390+
391+
if (format == "json") {
392+
return results.map((r) => r.toJson());
393+
} else if (format == "csv") {
394+
let lines = results.map((r) => r.toCsv());
395+
lines.unshift(results[0].columns.map((c) => c.field).join(","));
396+
return lines.join("\n");
397+
}
398+
399+
let lines = results.map((r) => r.toString());
400+
return lines.join("\n");
401+
}
402+
307403
static async runStepReport({
308404
academic_year_id,
309405
format = "json",

src/web/src/components/adminHome/SubRoutesSideBar.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default {
4747
{title:"Funding Group", path: "/administration/funding-group"},
4848
{title:"Status", path: "/administration/status"},
4949
{title:"Status Reason", path: "/administration/status-reason"},
50+
{title:"NOC Codes", path: "/administration/noc-code"},
5051
],
5152
ecerts_reports:[
5253
{title:"CSL MSFAA Receive", path: "/administration/csl-msfaa-receive"},

src/web/src/components/application/assessments/views/YukonGrant.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@
568568
:fundingRequestId="assessment?.funding_request_id"
569569
:disbursementTypeId="1"
570570
@disbursementChanged="disbursementChanged"
571-
:showCert="false"
571+
:showCert="true"
572572
:showBatch="true"
573573
/>
574574
</v-card-text>

0 commit comments

Comments
 (0)