diff --git a/package.json b/package.json index abc8b4712..0a529cfde 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "pg": "^8.8.0", "pino-http": "^8.2.0", "portable-fetch": "^3.0.0", + "read-excel-file": "^5.7.1", "reflect-metadata": "0.1.13", "rimraf": "^5.0.5", "rxjs": "^7.8.1", diff --git a/src/features/children/children.controller.ts b/src/features/children/children.controller.ts index df5d1ff52..f1852a160 100644 --- a/src/features/children/children.controller.ts +++ b/src/features/children/children.controller.ts @@ -50,8 +50,14 @@ import { NgoEntity } from 'src/entities/ngo.entity'; import { SyncService } from '../sync/sync.service'; import { LocationEntity } from 'src/entities/location.entity'; import { NgoParams } from 'src/types/parameters/NgoParammeters'; -import { formatDate, truncateString } from 'src/utils/helpers'; +import { + captilizeFirstLetter as capitalizeFirstLetter, + truncateString, +} from 'src/utils/helpers'; import axios from 'axios'; +import { AllUserEntity } from 'src/entities/user.entity'; +import { checkIfFileOrDirectoryExists, moveFile } from 'src/utils/file'; +import fs from 'fs'; @ApiTags('Children') @ApiSecurity('flask-access-token') @@ -308,6 +314,50 @@ export class ChildrenController { if (!files) { throw new ServerError('No files were uploaded!'); } + // for local purposes - organized folders and files + const newChildFolder = `../../Docs/children${ + SexEnum.MALE ? '/boys/' : '/girls/' + }organized/${capitalizeFirstLetter(body.sayNameEn)}-${body.sayNameFa}`; + + const originalAwakeGirl = `../../Docs/children/girls/${ + files.awakeFile[0].filename.split('-s-')[0] + }.png`; + const originalAwakeBoy = `../../Docs/children/boys/${ + files.awakeFile[0].filename.split('-s-')[0] + }.png`; + const originalSleptGirl = `../../Docs/children/girls/${ + files.sleptFile[0].filename.split('-s-')[0] + }.png`; + const originalSleptBoy = `../../Docs/children/boys/${ + files.sleptFile[0].filename.split('-s-')[0] + }.png`; + + const newAwakeName = `awake-${body.sayNameEn.toLowerCase()}.png`; + const newSleepName = `sleep-${body.sayNameEn.toLowerCase()}.png`; + + console.log(originalAwakeBoy); + + if ( + checkIfFileOrDirectoryExists(originalAwakeGirl) || + checkIfFileOrDirectoryExists(originalAwakeBoy) + ) { + if (!checkIfFileOrDirectoryExists(newChildFolder)) { + fs.mkdirSync(newChildFolder); + } + if (Number(body.sex) === SexEnum.MALE) { + moveFile(originalAwakeBoy, `${newChildFolder}/${newAwakeName}`); + moveFile(originalSleptBoy, `${newChildFolder}/${newSleepName}`); + } + if (Number(body.sex) === SexEnum.FEMALE) { + moveFile(originalSleptGirl, `${newChildFolder}/${newAwakeName}`); + moveFile( + originalSleptGirl, + `${newChildFolder}/sleep-${body.sayNameFa}.png`, + ); + } + } else { + throw new ServerError('could not find the file'); + } return await this.childrenService.createPreRegisterChild( files.awakeFile[0].filename, @@ -393,11 +443,48 @@ export class ChildrenController { console.log('\x1b[36m%s\x1b[0m', 'Created a Location ...'); } const ngo = await this.ngoService.getNgoById(Number(body.ngoId)); - const sw = await this.userService.getContributorByFlaskId( + + let nestSocialWorker: AllUserEntity; + let swNgo: NgoEntity; + + nestSocialWorker = await this.userService.getContributorByFlaskId( Number(body.swId), PanelContributors.SOCIAL_WORKER, ); + if (!nestSocialWorker) { + const flaskSocialWorker = await this.userService.getFlaskSocialWorker( + body.swId, + ); + + const swDetails = { + typeId: flaskSocialWorker.type_id, + firstName: flaskSocialWorker.firstName, + lastName: flaskSocialWorker.lastName, + avatarUrl: flaskSocialWorker.avatar_url, + flaskUserId: flaskSocialWorker.id, + birthDate: + flaskSocialWorker.birth_date && + new Date(flaskSocialWorker.birth_date), + panelRole: PanelContributors.SOCIAL_WORKER, + userName: flaskSocialWorker.userName, + }; + + swNgo = await this.syncService.syncContributorNgo(flaskSocialWorker); + console.log('\x1b[36m%s\x1b[0m', 'Creating a Social Worker ...\n'); + nestSocialWorker = await this.userService.createContributor( + swDetails, + swNgo, + ); + console.log('\x1b[36m%s\x1b[0m', 'Created a Social Worker ...\n'); + } + + const contributor = nestSocialWorker.contributions.find( + (c) => c.flaskUserId === Number(body.swId), + ); + if (!nestSocialWorker || !ngo || !contributor) { + throw new ServerError('This social worker has not contributed yet'); + } return await this.childrenService.updatePreRegisterChild( candidate.id, { @@ -423,7 +510,7 @@ export class ChildrenController { }, location, ngo, - sw.contributions.find((c) => c.flaskUserId === body.swId), + contributor, ); } catch (e) { throw new ServerError(e); @@ -448,12 +535,11 @@ export class ChildrenController { throw new ForbiddenException(403, 'You Are not the Super admin'); } let ngoIds: number[]; - if ( panelFlaskTypeId === FlaskUserTypesEnum.ADMIN || panelFlaskTypeId === FlaskUserTypesEnum.SUPER_ADMIN ) { - ngoIds = (await this.ngoService.getFlaskNgos()).map((n) => n.id); + ngoIds = (await this.ngoService.getAllFlaskNgos()).map((n) => n.id); if (Number(status) === PreRegisterStatusEnum.NOT_REGISTERED) { return await this.childrenService.getChildrenPreRegisterNotRegistered( { @@ -549,6 +635,23 @@ export class ChildrenController { }; } + @Get(`generate/say/names`) + @ApiOperation({ description: 'Get all children from db' }) + async generateNames(@Req() req: Request) { + const panelFlaskUserId = req.headers['panelFlaskUserId']; + const panelFlaskTypeId = req.headers['panelFlaskTypeId']; + if ( + !isAuthenticated(panelFlaskUserId, panelFlaskTypeId) && + !( + panelFlaskTypeId === FlaskUserTypesEnum.SUPER_ADMIN || + panelFlaskTypeId === FlaskUserTypesEnum.ADMIN + ) + ) { + throw new ForbiddenException(403, 'You Are not the Super admin'); + } + return await this.downloadService.excelStream('src/resources/names.xlsx'); + } + @UseInterceptors(ChildrenInterceptor) @Post(`flask/all`) @ApiOperation({ description: 'Get all flask children from db' }) @@ -847,7 +950,6 @@ export class ChildrenController { ); console.log('\x1b[36m%s\x1b[0m`, `Created a Social Worker ...\n'); } - console.log(child.id_ngo); if (!nestSocialWorker) { throw new ServerError('we need the sw'); diff --git a/src/features/download/download.controller.ts b/src/features/download/download.controller.ts index 0081567a7..c81f79516 100644 --- a/src/features/download/download.controller.ts +++ b/src/features/download/download.controller.ts @@ -4,6 +4,7 @@ import { ForbiddenException, Get, Param, + Query, Req, Res, StreamableFile, @@ -43,15 +44,15 @@ export class DownloadController { ) { throw new ForbiddenException(403, 'You Are not the Super admin'); } - const file = await this.downloadService.imageBuffer(path); + const file = await this.downloadService.imageReadBuffer(path); response.contentType('image/png'); response.send(file); } - @Get('stream/:path') + @Get('stream') async stream( @Req() req: Request, - @Param('path') path: string, + @Query('path') path: string, @Res() response: Response, ) { const panelFlaskUserId = req.headers['panelFlaskUserId']; @@ -66,8 +67,8 @@ export class DownloadController { file.pipe(response); } - @Get('streamable/:path') - async streamable(@Param('path') path: string, @Req() req: Request) { + @Get('streamable') + async streamable(@Query('path') path: string, @Req() req: Request) { const panelFlaskUserId = req.headers['panelFlaskUserId']; const panelFlaskTypeId = req.headers['panelFlaskTypeId']; if ( @@ -77,9 +78,10 @@ export class DownloadController { throw new ForbiddenException(403, 'You Are not the Super admin'); } const file = await this.downloadService.fileStream(path); - // or - // const file = this.downloadService.fileBuffer(); return new StreamableFile(file); // 👈 supports Buffer and Stream + // or + // const file = this.downloadService.fileBuffer(path); + // return file } @Get('streamable2/:flaskNeedId') diff --git a/src/features/download/download.service.ts b/src/features/download/download.service.ts index 67768845b..888d464b6 100644 --- a/src/features/download/download.service.ts +++ b/src/features/download/download.service.ts @@ -5,20 +5,40 @@ import { join } from 'path'; import { createWriteStream } from 'fs'; import axios from 'axios'; import { Readable } from 'stream'; -import { createFile } from 'src/utils/file'; import { prepareUrl } from 'src/utils/helpers'; import { ServerError } from 'src/filters/server-exception.filter'; import mime from 'mime'; import fs from 'fs'; import { WalletExceptionFilter } from 'src/filters/wallet-exception.filter'; import { File } from '@web-std/file'; +import readXlsxFile from 'read-excel-file/node'; @Injectable() export class DownloadService { private readonly logger = new Logger(DownloadService.name); constructor(private httpService: HttpService) {} - async imageBuffer(fileName: string) { + // Excel + async excelReadBuffer(path: string) { + // `rows` is an array of rows + // each row being an array of cells. + return readXlsxFile(path); + } + + async excelStream(path: string) { + // `rows` is an array of rows + // each row being an array of cells. + return readXlsxFile(fs.createReadStream(path)); + } + + async excelFileBuffer(path: string) { + // `rows` is an array of rows + // each row being an array of cells. + return readXlsxFile(Buffer.from(fs.readFileSync(path))); + } + + // image and files + async imageReadBuffer(fileName: string) { return readFileSync(join(process.cwd(), fileName)); } diff --git a/src/features/midjourney/midjourney.controller.ts b/src/features/midjourney/midjourney.controller.ts index afb631e59..aeef68d84 100644 --- a/src/features/midjourney/midjourney.controller.ts +++ b/src/features/midjourney/midjourney.controller.ts @@ -139,7 +139,7 @@ export class MidjourneyController { return { totalReady: needsWithSignatures.meta.totalItems, total: count, - list, + list, }; } @@ -165,7 +165,7 @@ export class MidjourneyController { throw new ForbiddenException(403, 'You Are not the Super admin'); } const theImage = await this.midjourneyService.getImage(flaskNeedId); - const file = await this.downloadService.imageBuffer(theImage.fileName); + const file = await this.downloadService.imageReadBuffer(theImage.fileName); response.contentType('image/png'); response.send(file); } diff --git a/src/features/ngo/ngo.service.ts b/src/features/ngo/ngo.service.ts index 12b31efff..b2a1eb818 100644 --- a/src/features/ngo/ngo.service.ts +++ b/src/features/ngo/ngo.service.ts @@ -163,6 +163,13 @@ export class NgoService { .getMany(); } + getAllFlaskNgos(): Promise { + return this.ngoFlaskRepository + .createQueryBuilder('ngo') + .cache(10000) + .getMany(); + } + getFlaskNgo(flaskNgoId: number): Promise { return this.ngoFlaskRepository.findOne({ where: { id: flaskNgoId }, diff --git a/src/features/wallet/wallet.service.ts b/src/features/wallet/wallet.service.ts index 394f782f5..3b40e9d4b 100644 --- a/src/features/wallet/wallet.service.ts +++ b/src/features/wallet/wallet.service.ts @@ -188,8 +188,6 @@ export class WalletService { }; let role: string; const allRoles = []; -console.log(need); -console.log(flaskUserId); // could have multiple roles e.g. [Auditor, SocialWorker] if (needRoles.socialWorker === flaskUserId) { diff --git a/src/resources/names.xlsx b/src/resources/names.xlsx new file mode 100644 index 000000000..a405f7a4f Binary files /dev/null and b/src/resources/names.xlsx differ diff --git a/src/storage/avatarStorage.ts b/src/storage/avatarStorage.ts index bf8c9b4f1..6bdec38a2 100644 --- a/src/storage/avatarStorage.ts +++ b/src/storage/avatarStorage.ts @@ -3,12 +3,13 @@ import { uuid } from 'uuidv4'; import path from 'path'; export const avatarStorage = { - storage: diskStorage({ - destination: './uploads/children/avatars', - filename: (req, file, cb) => { - const fileName: string = path.parse(file.originalname).name.replace(/\s/g, '') + uuid() // unique id - const extension: string = path.parse(file.originalname).ext - return cb(null, `${fileName}${extension}`) - } - }) -} \ No newline at end of file + storage: diskStorage({ + destination: './uploads/children/avatars', + filename: (req, file, cb) => { + const fileName: string = + path.parse(file.originalname).name.replace(/\s/g, '') + '-s-' + uuid(); // unique id + const extension: string = path.parse(file.originalname).ext; + return cb(null, `${fileName}${extension}`); + }, + }), +}; diff --git a/src/utils/file.ts b/src/utils/file.ts index 9cc324ead..3f024ff0e 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -42,11 +42,12 @@ export const getFile = async ( export const createFile = async ( path: string, fileName: string, - data: string, + data: string | NodeJS.ArrayBufferView, ): Promise => { if (!checkIfFileOrDirectoryExists(path)) { fs.mkdirSync(path); } + console.log(`${path}/${fileName}`); const writeFile = promisify(fs.writeFile); return await writeFile(`${path}/${fileName}`, data, 'utf8'); @@ -64,3 +65,7 @@ export const deleteFile = async (path: string): Promise => { return await unlink(path); }; + +export const moveFile = async (oldPath: string, newPath: string) => { + fs.rename(oldPath, newPath, () => console.log('Moved a file...')); +}; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 111390ee0..fb108eec0 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -899,3 +899,7 @@ export function shuffleArray(array: any[]) { return array; } + +export function captilizeFirstLetter(word: string) { + return word.charAt(0).toUpperCase() + word.slice(1); +}