diff --git a/apps/backend/src/applications/applications.controller.ts b/apps/backend/src/applications/applications.controller.ts index c9f1223..e96d9db 100644 --- a/apps/backend/src/applications/applications.controller.ts +++ b/apps/backend/src/applications/applications.controller.ts @@ -1,7 +1,9 @@ -import { Controller, Get, Put, Param, Query } from '@nestjs/common'; +import { Controller, Get, Put, Post, Body, Param, Query } from '@nestjs/common'; import { ApplicationsService } from './applications.service'; import { ApplicationsModel } from './applications.model'; import { ApplicationStatus } from './applications.model'; +import { NewApplicationInput } from '../dtos/newApplicationsDTO'; + @Controller('applications') export class ApplicationsController { @@ -36,4 +38,10 @@ export class ApplicationsController { return this.applicationsService.updateApplicationStatus(appId, appStatus); } + + @Post() + public async postApplication(@Body() applicationData: NewApplicationInput) { + return this.applicationsService.postApplication(applicationData); + } + } diff --git a/apps/backend/src/applications/applications.model.ts b/apps/backend/src/applications/applications.model.ts index b8a48ec..84773cf 100644 --- a/apps/backend/src/applications/applications.model.ts +++ b/apps/backend/src/applications/applications.model.ts @@ -13,16 +13,19 @@ export type ApplicationsModel = { }; export type ApplicationInputModel = { - appId: {S: string}, - userId: {S: string}, - siteId: {S: string}, - names: {S: string}, - status: {S: string}, - dateApplied: {S: string}, - isFirstApplication: {S: string}, + appId: { + N: string +}, + userId: { N: string }, + siteId: { N: string }, + names: { SS: string[] }, // For an array of strings, use SS (String Set) in DynamoDB + status: { S: string }, + dateApplied: { S: string }, // Date should be formatted as a string, typically ISO string + isFirstApplication: { S: string }, }; + export enum ApplicationStatus { APPROVED = 'Approved', PENDING = 'Pending', diff --git a/apps/backend/src/applications/applications.service.ts b/apps/backend/src/applications/applications.service.ts index 6cfe0fe..8746717 100644 --- a/apps/backend/src/applications/applications.service.ts +++ b/apps/backend/src/applications/applications.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { ApplicationInputModel, ApplicationsModel } from './applications.model'; import { DynamoDbService } from '../dynamodb'; import { ApplicationStatus } from './applications.model'; -// import { NewApplicationInput } from '../dtos/newApplicationsDTO'; +import { NewApplicationInput } from '../dtos/newApplicationsDTO'; @Injectable() export class ApplicationsService { @@ -68,6 +68,40 @@ export class ApplicationsService { throw new Error('Unable to update application status: ' + e); } } + + public async postApplication(applicationData: NewApplicationInput) { + const applicationModel = this.PostInputToApplicationModel(applicationData); + console.log("Received application data:", applicationData); + + const newId = await this.dynamoDbService.getHighestAppId(this.tableName) + 1; + + applicationModel.appId.N = newId.toString(); + console.log("Using new ID:" + applicationModel.appId.N) + try { + const result = await this.dynamoDbService.postItem(this.tableName, applicationModel); + return {...result, newApplicationId: newId.toString()}; + } catch (e) { + throw new Error("Unable to post new application: " + e); + } +} + + +private PostInputToApplicationModel = (input: NewApplicationInput): ApplicationInputModel => { + + return { + appId: { N: input.appId.toString() }, + userId: { N: input.userId.toString() }, + siteId: { N: input.siteId.toString() }, + names: { SS: input.names }, + status: { S: input.status as ApplicationStatus}, + dateApplied: { S: input.dateApplied}, + isFirstApplication: { S: input.isFirstApplication.toString() }, + }; +}; + + + + private mapDynamoDBItemToApplication = (item: { [key: string]: any; @@ -83,3 +117,5 @@ export class ApplicationsService { }; }; } + + diff --git a/apps/backend/src/dtos/newApplicationsDTO.ts b/apps/backend/src/dtos/newApplicationsDTO.ts new file mode 100644 index 0000000..7612c4d --- /dev/null +++ b/apps/backend/src/dtos/newApplicationsDTO.ts @@ -0,0 +1,16 @@ +export type NewApplicationInput = { + appId: number; // Optional if auto-generated + userId: number; + siteId: number; + names: string[]; // Array with empty string by default if not provided + status: ApplicationStatus; // Defaults to "PENDING" + dateApplied: string; // Defaults to an ISO string if not provided + isFirstApplication: boolean; + }; + + export enum ApplicationStatus { + APPROVED = 'Approved', + PENDING = 'Pending', + DENIED = 'Denied', + } + diff --git a/apps/backend/src/dynamodb.ts b/apps/backend/src/dynamodb.ts index 0d23d9d..844454a 100644 --- a/apps/backend/src/dynamodb.ts +++ b/apps/backend/src/dynamodb.ts @@ -125,6 +125,38 @@ export class DynamoDbService { } } + public async getHighestAppId( + tableName: string, + ): Promise { + const params: any = { + TableName: tableName, + ProjectionExpression: 'appId', // Project only the appID attribute + }; + + try { + const data = await this.dynamoDbClient.send(new ScanCommand(params)); + console.log(data); + const appIds = data.Items.map((item) => parseInt(item.appId.N, 10)); // Convert to numbers + console.log("Scanned Items:", data.Items); + + console.log(appIds); + // Handle potential parsing errors + const validAppIds = appIds.filter((id) => !isNaN(id)); + + if (validAppIds.length === 0) { + return undefined; // No valid apps IDs found + } + + const highestAppId = validAppIds.reduce((max, current) => + Math.max(max, current), + ); + return highestAppId; + } catch (error) { + console.error('DynamoDB Scan Error:', error); + throw new Error(`Unable to scan table ${tableName}`); + } + } + public async getItem( tableName: string, key: { [key: string]: any },