Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/backend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { AppService } from './app.service';
import { SiteModule } from '../site/site.module';
import { ApplicationsModule } from '../applications/applications.module';
import { DynamoDbService } from '../dynamodb';
import { LambdaService } from '../lambda';


@Module({
imports: [SiteModule,UserModule, ApplicationsModule],
controllers: [AppController],
providers: [AppService, DynamoDbService],
providers: [AppService, DynamoDbService, LambdaService],
})
export class AppModule {}
5 changes: 4 additions & 1 deletion apps/backend/src/applications/applications.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { Module } from '@nestjs/common';
import { ApplicationsService } from './applications.service';
import { ApplicationsController } from './applications.controller';
import { DynamoDbService } from '../dynamodb';
import { LambdaService } from '../lambda';
import { UserService } from '../user/user.service';
import { SiteService } from '../site/site.service';

@Module({
imports: [],
providers: [ApplicationsService, DynamoDbService],
providers: [ApplicationsService, DynamoDbService, LambdaService, UserService, SiteService],
controllers: [ApplicationsController],
exports: [ApplicationsService],
})
Expand Down
26 changes: 25 additions & 1 deletion apps/backend/src/applications/applications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { ApplicationInputModel, ApplicationsModel } from './applications.model';
import { DynamoDbService } from '../dynamodb';
import { ApplicationStatus } from './applications.model';
import { NewApplicationInput } from '../dtos/newApplicationsDTO';
import { LambdaService } from '../lambda';
import { UserService } from '../user/user.service';
import { SiteService } from '../site/site.service';

@Injectable()
export class ApplicationsService {
private readonly tableName = 'gibostonApplications';
constructor(private readonly dynamoDbService: DynamoDbService) {}
constructor(private readonly dynamoDbService: DynamoDbService, private readonly lambdaService:LambdaService,
private readonly userService: UserService, private readonly siteService: SiteService) {}

/**
* Gets all applications.
Expand Down Expand Up @@ -75,6 +79,26 @@ export class ApplicationsService {
console.log("Received application data:", applicationData);
try {
const result = await this.dynamoDbService.postItem(this.tableName, applicationModel);

if (result.$metadata.httpStatusCode !== 200) {
throw new Error('Error posting application');
}
const user = await this.userService.getUser(applicationData.userId);
const site = await this.siteService.getSite(applicationData.siteId);
const name = user.firstName;
const email = user.email;

const siteName = site.siteName;
const timeFrame = "30 days"
const emailData = {"firstName":name, "userEmail":email, "siteName":siteName, "timeFrame":timeFrame};



const lambdaResult = await this.lambdaService.invokeLambda('giSendApplicationConfirmation', emailData );
console.log("Lambda result: ", lambdaResult);



return {...result, newApplicationId: newId.toString()};
} catch (e) {
throw new Error("Unable to post new application: " + e);
Expand Down
75 changes: 60 additions & 15 deletions apps/backend/src/dtos/newApplicationsDTO.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,60 @@
export type NewApplicationInput = {
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',
}

import { ApiProperty } from '@nestjs/swagger';
import { IsNumber, IsArray, IsString, IsBoolean, IsEnum, IsOptional } from 'class-validator';

export enum ApplicationStatus {
APPROVED = 'Approved',
PENDING = 'Pending',
DENIED = 'Denied',
}

export class NewApplicationInput {
@ApiProperty({
description: 'User ID of the applicant',
example: 123,
})
@IsNumber()
userId: number;

@ApiProperty({
description: 'Site ID associated with the application',
example: 456,
})
@IsNumber()
siteId: number;

@ApiProperty({
description: 'Array of names associated with the application (defaults to an empty array if not provided)',
example: ['John Doe', 'Jane Doe'],
required: false,
})
@IsArray()
@IsString({ each: true })
@IsOptional()
names: string[] = []; // Default to an empty array if not provided

@ApiProperty({
description: 'Status of the application',
enum: ApplicationStatus,
example: ApplicationStatus.PENDING,
required: false,
})
@IsEnum(ApplicationStatus)
@IsOptional()
status: ApplicationStatus = ApplicationStatus.PENDING; // Default to "PENDING"

@ApiProperty({
description: 'Date the application was submitted (defaults to an ISO string if not provided)',
example: '2025-02-06T10:00:00Z',
required: false,
})
@IsString()
@IsOptional()
dateApplied: string = new Date().toISOString(); // Default to ISO string

@ApiProperty({
description: 'Indicates if this is the user’s first application',
example: true,
})
@IsBoolean()
isFirstApplication: boolean;
}
33 changes: 33 additions & 0 deletions apps/backend/src/lambda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Injectable } from '@nestjs/common';
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';

@Injectable()
export class LambdaService {
private readonly lambdaClient: LambdaClient;

constructor() {
this.lambdaClient = new LambdaClient({
region: process.env.AWS_REGION,
});
}

public async invokeLambda(functionName: string, payload: Record<string, any>) {
try {
const command = new InvokeCommand({
FunctionName: functionName,
Payload: Buffer.from(JSON.stringify(payload)),
});

const response = await this.lambdaClient.send(command);

if (response.Payload) {
return JSON.parse(Buffer.from(response.Payload).toString());
}

throw new Error('No response payload from Lambda function');
} catch (error) {
console.error('Error invoking Lambda:', error);
throw error;
}
}
}
Loading
Loading