Skip to content

Commit

Permalink
Merge pull request #323 from framgia/HRIS-374
Browse files Browse the repository at this point in the history
HRIS-374 [BE] Navbar:Time In
  • Loading branch information
Miguel21Monacillo authored Sep 10, 2024
2 parents 4d5e6f2 + 8d76c38 commit dce8f8e
Show file tree
Hide file tree
Showing 14 changed files with 4,890 additions and 1,727 deletions.
15 changes: 15 additions & 0 deletions api_v2/config/multer.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { diskStorage } from 'multer';
import { extname } from 'path';

export const multerOptions = {
storage: diskStorage({
destination: './uploads',
filename: (_req, file, cb) => {
const randomName = Array(32)
.fill(null)
.map(() => Math.round(Math.random() * 16).toString(16))
.join('');
return cb(null, `${randomName}${extname(file.originalname)}`);
},
}),
};
6,302 changes: 4,586 additions & 1,716 deletions api_v2/package-lock.json

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion api_v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@apollo/server": "^4.10.4",
"@azure/storage-blob": "^12.23.0",
"@nestjs/apollo": "^12.1.0",
"@nestjs/axios": "^3.0.2",
"@nestjs/bull": "^10.1.1",
Expand All @@ -33,18 +34,23 @@
"@nestjs/graphql": "^12.1.1",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-express": "^10.3.10",
"@nestjs/schedule": "^4.0.2",
"@nestjs/swagger": "^7.3.1",
"@prisma/client": "^5.15.1",
"@types/luxon": "^3.4.2",
"@types/uuid": "^10.0.0",
"aws-sdk": "^2.1659.0",
"axios": "^1.7.2",
"bull": "^4.13.0",
"cache-manager": "^5.6.1",
"graphql": "^16.8.1",
"graphql-upload": "^14.0.0",
"graphql-upload-ts": "^2.1.2",
"luxon": "^3.4.4",
"multer": "^1.4.5-lts.1",
"multer-azure-blob-storage": "^1.2.0",
"multer-s3": "^3.0.1",
"path": "^0.12.7",
"prisma-case-format": "^2.2.1",
"prisma-class-generator": "^0.2.9",
Expand All @@ -57,7 +63,9 @@
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/graphql-upload": "^16.0.7",
"@types/jest": "^29.5.2",
"@types/multer": "^1.4.12",
"@types/node": "^20.3.1",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
Expand Down
4 changes: 4 additions & 0 deletions api_v2/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { UserModule } from './user/user.module';
import { DtrManagementModule } from './dtr-management/dtr-management.module';
import { NotificationsModule } from './notifications/notifications.module';
import { TimeOutModule } from './time-out/time-out.module';
import { TimeInModule } from './time-in/time-in.module';
import { OvertimeModule } from './overtime/overtime.module';
import { LeavesModule } from './leaves/leaves.module';

Expand Down Expand Up @@ -58,6 +59,8 @@ import { LeavesModule } from './leaves/leaves.module';
path: join(process.cwd(), 'src/graphql/graphql.ts'),
outputAs: 'class',
},
csrfPrevention: false,
uploads: false,
}),
}),
ScheduleModule.forRoot(),
Expand Down Expand Up @@ -92,6 +95,7 @@ import { LeavesModule } from './leaves/leaves.module';
DtrManagementModule,
NotificationsModule,
TimeOutModule,
TimeInModule,
OvertimeModule,
LeavesModule,
],
Expand Down
18 changes: 12 additions & 6 deletions api_v2/src/file-upload/file-upload.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { join, parse } from 'path';
import { join, parse, dirname } from 'path';
import { v4 as uuidv4 } from 'uuid';
import { Stream } from 'stream';
import { createWriteStream, existsSync, mkdirSync } from 'fs';
Expand Down Expand Up @@ -55,18 +55,24 @@ export class FileUploadService {
async processFileUploading(filePath: string, stream: Stream): Promise<void> {
const uploadDirectory = join(process.cwd(), 'wwwroot');
const fullPath = join(uploadDirectory, filePath);

const dir = fullPath.substring(0, fullPath.lastIndexOf('/'));
if (!existsSync(uploadDirectory)) {
mkdirSync(uploadDirectory, { recursive: true });
}
const dir = dirname(fullPath);
console.log('Directory to create:', dir);
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
try {
mkdirSync(dir, { recursive: true });
} catch (error) {
console.error(`Error creating directory: ${error.message}`);
throw error;
}
}

return new Promise((resolve, reject) => {
const writeStream = createWriteStream(fullPath);
stream.pipe(writeStream).on('finish', resolve).on('error', reject);
});
}

/**
* Generates a unique file name by appending a UUID key to the given file name.
*
Expand Down
2 changes: 1 addition & 1 deletion api_v2/src/graphql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ export abstract class IQuery {

abstract timeEntries(
date?: Nullable<string>,
status?: Nullable<WorkStatusEnum>,
status?: Nullable<string>,
): TimeEntryDTO[] | Promise<TimeEntryDTO[]>;

abstract timesheetSummary(
Expand Down
2 changes: 0 additions & 2 deletions api_v2/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.enableCors();

await app.listen(3001);
}
bootstrap();
44 changes: 44 additions & 0 deletions api_v2/src/shared/storage.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// src/storage/storage.service.ts

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { S3 } from 'aws-sdk';

@Injectable()
export class StorageService {
private s3: S3;

constructor(private configService: ConfigService) {
// Initialize AWS S3
this.s3 = new S3({
accessKeyId: this.configService.get('AWS_ACCESS_KEY_ID'),
secretAccessKey: this.configService.get('AWS_SECRET_ACCESS_KEY'),
region: this.configService.get('AWS_REGION'),
});
}

async uploadFile(file: Express.Multer.File): Promise<string> {
if (this.configService.get('AWS_ACCESS_KEY_ID')) {
return this.uploadToS3(file);
} else {
throw new Error('No storage configuration found');
}
}

private async uploadToS3(file: Express.Multer.File): Promise<string> {
const uploadParams = {
Bucket: this.configService.get('S3_BUCKET_NAME'),
Key: `${Date.now()}-${file.originalname}`,
Body: file.buffer,
ACL: 'public-read',
};

try {
const result = await this.s3.upload(uploadParams).promise();
return result.Location;
} catch (error) {
console.error('Error uploading file to S3:', error);
throw new Error('Failed to upload file to S3');
}
}
}
17 changes: 17 additions & 0 deletions api_v2/src/time-in/time-in.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Module } from '@nestjs/common';
import { TimeInService } from './time-in.service';
import { TimeInResolver } from './time-in.resolver';
import { PrismaService } from '@/prisma/prisma.service';
import { TimeInServiceInputValidation } from '@/utilities/validation/timeInServiceInputValidation';
import { FileUploadService } from '@/file-upload/file-upload.service';

@Module({
providers: [
TimeInResolver,
TimeInService,
PrismaService,
TimeInServiceInputValidation,
FileUploadService,
],
})
export class TimeInModule {}
28 changes: 28 additions & 0 deletions api_v2/src/time-in/time-in.resolver.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TimeInResolver } from './time-in.resolver';
import { TimeInService } from './time-in.service';
import { PrismaService } from '@/prisma/prisma.service';
import { TimeInServiceInputValidation } from '@/utilities/validation/timeInServiceInputValidation';
import { FileUploadService } from '@/file-upload/file-upload.service';

describe('TimeInResolver', () => {
let resolver: TimeInResolver;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
TimeInResolver,
TimeInService,
PrismaService,
TimeInServiceInputValidation,
FileUploadService,
],
}).compile();

resolver = module.get<TimeInResolver>(TimeInResolver);
});

it('should be defined', () => {
expect(resolver).toBeDefined();
});
});
27 changes: 27 additions & 0 deletions api_v2/src/time-in/time-in.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Resolver, Mutation, Args } from '@nestjs/graphql';
import { TimeInService } from './time-in.service';
import { TimeInRequestInput } from '@/graphql/graphql';
import { GraphQLError } from 'graphql';
import { Logger } from '@nestjs/common';

@Resolver()
export class TimeInResolver {
private readonly logger = new Logger();
constructor(private readonly timeInService: TimeInService) {}

@Mutation(() => String)
async updateTimeIn(
@Args('timeIn') timeIn: TimeInRequestInput,
): Promise<string> {
try {
this.logger.log('timeIn', timeIn);
const result = await this.timeInService.update(timeIn);
return result;
} catch (error) {
if (error instanceof GraphQLError) {
throw error;
}
throw new Error(error.message || 'Something went wrong...');
}
}
}
26 changes: 26 additions & 0 deletions api_v2/src/time-in/time-in.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TimeInService } from './time-in.service';
import { PrismaService } from '@/prisma/prisma.service';
import { TimeInServiceInputValidation } from '@/utilities/validation/timeInServiceInputValidation';
import { FileUploadService } from '@/file-upload/file-upload.service';

describe('TimeInService', () => {
let service: TimeInService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
TimeInService,
PrismaService,
TimeInServiceInputValidation,
FileUploadService,
],
}).compile();

service = module.get<TimeInService>(TimeInService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
Loading

0 comments on commit dce8f8e

Please sign in to comment.