Compare commits

..

2 Commits

Author SHA1 Message Date
Kallesh B S
f24de4803f pdf generation 2025-08-07 15:15:19 +05:30
Kallesh B S
ad748be61d 7Aug Api modifications 2025-08-07 15:14:44 +05:30
7 changed files with 63 additions and 40 deletions

View File

@ -17,6 +17,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
import { Response } from 'express';
import { join } from 'path';
import { createReadStream } from 'fs';
import { deleteFilesAsync } from 'src/utils/helper';
@ApiTags('Carnet Application - Oracle')
@ -157,19 +158,28 @@ export class CarnetApplicationController {
@Post('PrintCarnet')
@Roles('ca', 'sa', 'ua')
async PrintCarnet(@Body() body: PrintCarnetDTO, @Res({ passthrough: true }) res: Response) {
const fileName = 'carnet.pdf';
const filePath = join(process.cwd(), 'public/carnet-pdf', fileName);
const filesArray = ['p2.pdf', fileName];
try {
await this.carnetApplicationService.PrintCarnet(body);
const filePath = join(process.cwd(), 'public/carnet-pdf', 'carnet.pdf');
res.set({
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="${'carnet.pdf'}"`,
'Content-Disposition': `attachment; filename="${fileName}"`,
});
const file = createReadStream(filePath);
return new StreamableFile(file);
const stream = createReadStream(filePath);
// Clean up files after response finishes streaming
res.on('finish', async () => {
await deleteFilesAsync(filesArray);
});
return new StreamableFile(stream);
} catch (error) {
return error.message
return error.message;
}
}

View File

@ -1167,7 +1167,7 @@ export class CarnetApplicationService {
}
async PrintCarnet(body: PrintCarnetDTO) {
let filesArray = ['p2.pdf']
try {
@ -1220,8 +1220,6 @@ export class CarnetApplicationService {
} catch (error) {
handleError(error, CarnetApplicationService.name)
} finally {
await deleteFilesAsync([...filesArray, 'carnet.pdf']);
}
}

View File

@ -32,35 +32,43 @@ export class ManageHoldersController {
@Get('SearchHolder/:P_SPID/:P_USERID')
@ApiQuery({ name: "P_HOLDERNAME", type: String, required: false, description: "Optional" })
@ApiQuery({ name: "P_HOLDERID", type: Number, required: false, description: "Optional" })
SearchHolder(
@Param('P_SPID') P_SPID: number,
@Param('P_USERID') P_USERID: string,
@Query('P_HOLDERID') P_HOLDERID?: number,
@Query('P_HOLDERNAME') P_HOLDERNAME?: string | null | undefined,
) {
let rawHolderName: string | null | undefined = P_HOLDERNAME;
if (typeof rawHolderName === 'string') {
rawHolderName = rawHolderName.trim();
rawHolderName = rawHolderName.replace(/^['"]|['"]$/g, '');
if (rawHolderName === '' || rawHolderName.toLowerCase() === 'null') {
rawHolderName = null;
} else {
const allowedPattern = /^[A-Za-z0-9 _@&.-]+$/;
// uncomment for strict validation
// if (!allowedPattern.test(rawHolderName)) {
// rawHolderName = null;
// }
if (!P_USERID) {
throw new BadRequestException('User ID is required');
}
} else {
rawHolderName = null;
// Sanitize holder name
let rawHolderName: string | null = null;
if (typeof P_HOLDERNAME === 'string') {
const trimmed = P_HOLDERNAME.trim().replace(/^['"]|['"]$/g, '');
rawHolderName = trimmed === '' || trimmed.toLowerCase() === 'null' ? null : trimmed;
}
if(!P_USERID){
return new BadRequestException();
// Validate and coerce P_HOLDERID
let holderId: number | null = null;
if (P_HOLDERID !== undefined && P_HOLDERID !== null) {
const parsed = Number(P_HOLDERID);
if (isNaN(parsed)) {
throw new BadRequestException('Invalid holder ID');
}
const body = { P_SPID,P_USERID,P_HOLDERNAME: rawHolderName }
holderId = parsed;
}
const body = {
P_SPID,
P_USERID,
P_HOLDERID: holderId,
P_HOLDERNAME: rawHolderName,
};
return this.manageHoldersService.SearchHolder(body)
}

View File

@ -631,7 +631,7 @@ export class ManageHoldersService {
}
};
SearchHolder = async (body: { P_SPID: number, P_USERID: string, P_HOLDERNAME: string | null }) => {
SearchHolder = async (body: { P_SPID: number, P_USERID: string, P_HOLDERID: number | null, P_HOLDERNAME: string | null }) => {
let connection;
try {
@ -640,11 +640,12 @@ export class ManageHoldersService {
const result: Result<any> = await connection.execute(
`BEGIN
MANAGEHOLDER_PKG.SearchHolder(
:P_SPID, :P_HOLDERNAME, :P_USERID, :P_CURSOR
:P_SPID, :P_HOLDERID, :P_HOLDERNAME, :P_USERID, :P_CURSOR
);
END;`,
{
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_HOLDERID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_HOLDERNAME: { val: body.P_HOLDERNAME, type: oracledb.DB_TYPE_NVARCHAR },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }

View File

@ -1,10 +1,10 @@
import { Body, Controller, Get, Patch, Post, Put, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Patch, Post, Put, Query, UseGuards } from '@nestjs/common';
import { ApiQuery, ApiTags } from '@nestjs/swagger';
import { ParamTableService } from './param-table.service';
import {
ActivateOrInactivateParamRecordDTO, CreateParamRecordDTO, CreateTableRecordDTO,
getParamValuesDTO, UpdateParamRecordDTO
getParamValuesDTO, SPID_DTO, UpdateParamRecordDTO
} from 'src/dto/property.dto';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
@ -53,10 +53,10 @@ export class ParamTableController {
return this.paramTableService.GETALLPARAMVALUES(body);
}
@Get('GetCountriesAndMessages')
@Get('GetCountriesAndMessages/:P_SPID')
@Roles('ca', 'sa', 'ua')
GET_COUNTRIES_AND_MESSAGES() {
return this.paramTableService.GET_COUNTRIES_AND_MESSAGES();
GET_COUNTRIES_AND_MESSAGES(@Param() body: SPID_DTO) {
return this.paramTableService.GET_COUNTRIES_AND_MESSAGES(body);
}
@Post('/CreateTableRecord')

View File

@ -8,7 +8,7 @@ import { closeOracleDbConnection, fetchCursor, handleError } from 'src/utils/hel
import {
ActivateOrInactivateParamRecordDTO, CreateParamRecordDTO, CreateTableRecordDTO,
getParamValuesDTO, UpdateParamRecordDTO
getParamValuesDTO, SPID_DTO, UpdateParamRecordDTO
} from 'src/dto/property.dto';
@Injectable()
@ -109,16 +109,17 @@ export class ParamTableService {
}
}
async GET_COUNTRIES_AND_MESSAGES() {
async GET_COUNTRIES_AND_MESSAGES(body: SPID_DTO) {
let connection;
try {
connection = await this.oracleDBService.getConnection();
const result = await connection.execute(
`BEGIN
MANAGEPARAMTABLE_PKG.GetCountriesAndMessages(:P_CURSOR);
MANAGEPARAMTABLE_PKG.GetCountriesAndMessages(:P_SPID, :P_CURSOR);
END;`,
{
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{ outFormat: oracledb.OUT_FORMAT_OBJECT }

View File

@ -11,6 +11,7 @@ const path = require('path');
import { PDFDocument as pdfl } from 'pdf-lib';
import PDFMerger from 'pdf-merger-js';
import * as fsPromises from 'fs/promises';
import { BadRequestException as BR } from 'src/exceptions/badRequest.exception';
const doc = new PDFDocument({
size: 'A4',
@ -21,13 +22,11 @@ const doc = new PDFDocument({
right: 50
}
});
const generalistFilePath = path.join(__dirname, '../../../public/carnet-pdf', 'p2.pdf')
doc.pipe(fs.createWriteStream(generalistFilePath));
const logger = new Logger('Helper');
export const handleError = (error: any, context: string = 'UnknownService'): never => {
if (error instanceof BadRequestException) {
if (error instanceof BadRequestException || error instanceof BR) {
logger.warn(`[${context}] ${error.message}`);
throw error;
}
@ -546,6 +545,9 @@ export const generateGeneralistPDF1 = async (jsonData: pdfGLData[], headerData:
// Finalize the PDF file
doc.end();
const generalistFilePath = path.join(__dirname, '../../../public/carnet-pdf', 'p2.pdf')
doc.pipe(fs.createWriteStream(generalistFilePath));
console.log('PDF created successfully!');
return "p2 done";
@ -581,6 +583,9 @@ export const generateGeneralistPDF2 = async (carnetNumber: string) => {
// Finalize PDF
doc.end();
const generalistFilePath = path.join(__dirname, '../../../public/carnet-pdf', 'p2.pdf')
doc.pipe(fs.createWriteStream(generalistFilePath));
return "p2 done"
}