From cecfa1030a1d5ca7466f20a5a3ea72e01cdf37a6 Mon Sep 17 00:00:00 2001 From: Kallesh B S Date: Tue, 23 Sep 2025 16:48:58 +0530 Subject: [PATCH] all api completed --- .../carnet-application.controller.ts | 166 ++--- .../carnet-application.service.ts | 570 +++++++++++++++++- .../sp-contacts/sp-contacts.controller.ts | 2 +- .../sp-contacts/sp-contacts.service.ts | 2 +- .../user-maintenance.controller.ts | 10 +- .../user-maintenance.service.ts | 92 ++- 6 files changed, 744 insertions(+), 98 deletions(-) diff --git a/src/pg/carnet-application/carnet-application.controller.ts b/src/pg/carnet-application/carnet-application.controller.ts index 18e30f0..2fa441d 100644 --- a/src/pg/carnet-application/carnet-application.controller.ts +++ b/src/pg/carnet-application/carnet-application.controller.ts @@ -183,120 +183,120 @@ export class CarnetApplicationController { } // [PRINT_PKG] - // @Post('PrintCarnet') - // @HttpCode(200) - // async PrintCarnet(@Body() body: PrintCarnetDTO, @Res({ passthrough: true }) res: Response) { + @Post('PrintCarnet') + @HttpCode(200) + async PrintCarnet(@Body() body: PrintCarnetDTO, @Res({ passthrough: true }) res: Response) { - // try { - // const { finalArray, carnetData }: any = await this.carnetApplicationService.PrintCarnet(body); - // // const filterCarnetData = finalArray.filter(item => item !== '2GeneralList.pdf') + try { + const { finalArray, carnetData }: any = await this.carnetApplicationService.PrintCarnet(body); + // const filterCarnetData = finalArray.filter(item => item !== '2GeneralList.pdf') - // let filesArray = [`${replaceSlashWithDash(carnetData.carnetNo)}p1.pdf`, `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`]; - // // await generateFinalPDF([...filesArray, '2GeneralList.pdf', ...carnetData], 'carnet.pdf'); - // await generateFinalPDF([...filesArray, ...finalArray, '13LastSheetP3.pdf', '13LastSheetP4.pdf'], `${replaceSlashWithDash(carnetData.carnetNo)}carnet.pdf`); + let filesArray = [`${replaceSlashWithDash(carnetData.carnetNo)}p1.pdf`, `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`]; + // await generateFinalPDF([...filesArray, '2GeneralList.pdf', ...carnetData], 'carnet.pdf'); + await generateFinalPDF([...filesArray, ...finalArray, '13LastSheetP3.pdf', '13LastSheetP4.pdf'], `${replaceSlashWithDash(carnetData.carnetNo)}carnet.pdf`); - // const fileName = `${replaceSlashWithDash(carnetData.carnetNo)}carnet.pdf`; + const fileName = `${replaceSlashWithDash(carnetData.carnetNo)}carnet.pdf`; - // res.set({ - // 'Content-Type': 'application/pdf', - // 'Content-Disposition': `attachment; filename="${fileName}"`, - // }); + res.set({ + 'Content-Type': 'application/pdf', + 'Content-Disposition': `attachment; filename="${fileName}"`, + }); - // const filePath = join(process.cwd(), 'dist/public/carnet-pdf', fileName); //server - // // const filePath = join(process.cwd(), 'public/carnet-pdf', fileName); //local + const filePath = join(process.cwd(), 'dist/public/carnet-pdf', fileName); //server + // const filePath = join(process.cwd(), 'public/carnet-pdf', fileName); //local - // console.log(filePath); + console.log(filePath); - // // console.log(filePath); + // console.log(filePath); - // const stream = createReadStream(filePath); + const stream = createReadStream(filePath); - // // Clean up files after response finishes streaming - // res.on('finish', async () => { - // await deleteFilesAsync([...filesArray, ...finalArray.filter(x => x !== `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`), fileName]); - // }); + // Clean up files after response finishes streaming + res.on('finish', async () => { + await deleteFilesAsync([...filesArray, ...finalArray.filter(x => x !== `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`), fileName]); + }); - // return new StreamableFile(stream); - // } catch (error) { - // if (error instanceof BadRequestException || error instanceof BR) { - // throw new BadRequestException("Download failed please check the details") - // } - // else { - // throw new InternalServerException("Error while downloading"); - // } - // } - // } + return new StreamableFile(stream); + } catch (error) { + if (error instanceof BadRequestException || error instanceof BR) { + throw new BadRequestException("Download failed please check the details") + } + else { + throw new InternalServerException("Error while downloading"); + } + } + } - // @Post('PrintGL') - // @HttpCode(200) - // async PrintGL(@Body() body: PrintGLDTO, @Res({ passthrough: true }) res: Response) { - // try { - // const { finalArray, carnetData }: any = await this.carnetApplicationService.PrintGL(body); + @Post('PrintGL') + @HttpCode(200) + async PrintGL(@Body() body: PrintGLDTO, @Res({ passthrough: true }) res: Response) { + try { + const { finalArray, carnetData }: any = await this.carnetApplicationService.PrintGL(body); - // let filesArray = [`${body.P_HEADERID}p2.pdf`]; - // // await generateFinalPDF([...filesArray, '2GeneralList.pdf', ...carnetData], 'carnet.pdf'); - // await generateFinalPDF([...filesArray, ...finalArray], `${body.P_HEADERID}-GL.pdf`); + let filesArray = [`${body.P_HEADERID}p2.pdf`]; + // await generateFinalPDF([...filesArray, '2GeneralList.pdf', ...carnetData], 'carnet.pdf'); + await generateFinalPDF([...filesArray, ...finalArray], `${body.P_HEADERID}-GL.pdf`); - // const fileName = `${body.P_HEADERID}-GL.pdf`; + const fileName = `${body.P_HEADERID}-GL.pdf`; - // res.set({ - // 'Content-Type': 'application/pdf', - // 'Content-Disposition': `attachment; filename="${fileName}"`, - // }); + res.set({ + 'Content-Type': 'application/pdf', + 'Content-Disposition': `attachment; filename="${fileName}"`, + }); - // const filePath = join(process.cwd(), 'dist/public/carnet-pdf', fileName); //server - // // const filePath = join(process.cwd(), 'public/carnet-pdf', fileName); //local + const filePath = join(process.cwd(), 'dist/public/carnet-pdf', fileName); //server + // const filePath = join(process.cwd(), 'public/carnet-pdf', fileName); //local - // // console.log(filePath); + // console.log(filePath); - // // console.log(filePath); + // console.log(filePath); - // const stream = createReadStream(filePath); + const stream = createReadStream(filePath); - // // Clean up files after response finishes streaming - // res.on('finish', async () => { - // await deleteFilesAsync([...filesArray, ...finalArray, fileName]); - // }); + // Clean up files after response finishes streaming + res.on('finish', async () => { + await deleteFilesAsync([...filesArray, ...finalArray, fileName]); + }); - // return new StreamableFile(stream); - // } catch (error) { - // if (error instanceof BadRequestException || error instanceof BR) { - // throw new BadRequestException("Download failed please check the details") - // } - // else { - // throw new InternalServerException("Error while downloading"); - // } - // } - // } + return new StreamableFile(stream); + } catch (error) { + if (error instanceof BadRequestException || error instanceof BR) { + throw new BadRequestException("Download failed please check the details") + } + else { + throw new InternalServerException("Error while downloading"); + } + } + } //[payment] - // @Post('InitiatePayment') - // async InitiatePayment(@Body() body: InitiatePaymentDTO) { - // return this.carnetApplicationService.InitiatePayment(body); - // } + @Post('InitiatePayment') + async InitiatePayment(@Body() body: InitiatePaymentDTO) { + return this.carnetApplicationService.InitiatePayment(body); + } - // @Post('CompletePayment') - // @HttpCode(200) - // async CapturePayment(@Body() body: CapturePaymentDTO) { - // return this.carnetApplicationService.CapturePayment(body); - // } + @Post('CompletePayment') + @HttpCode(200) + async CapturePayment(@Body() body: CapturePaymentDTO) { + return this.carnetApplicationService.CapturePayment(body); + } // @Get('OrderDetails/:P_ORDERID') async OrderDetails(@Param() body: GetOrderDetailsDTO) { return this.carnetApplicationService.OrderDetails(body); } - // @Get('GetPaymentHistory/:P_APPLICATIONNAME/:P_USERID') - // async GetPaymentHistory(@Param() body: GetPaymentHistoryDTO) { - // return this.carnetApplicationService.GetPaymentHistory(body); - // } + @Get('GetPaymentHistory/:P_APPLICATIONNAME/:P_USERID') + async GetPaymentHistory(@Param() body: GetPaymentHistoryDTO) { + return this.carnetApplicationService.GetPaymentHistory(body); + } - // @Post('SaveHistory') - // @HttpCode(200) - // async SaveHistory(@Body() body: SaveHistoryDTO) { - // return this.carnetApplicationService.SaveHistory(body); - // } + @Post('SaveHistory') + @HttpCode(200) + async SaveHistory(@Body() body: SaveHistoryDTO) { + return this.carnetApplicationService.SaveHistory(body); + } } diff --git a/src/pg/carnet-application/carnet-application.service.ts b/src/pg/carnet-application/carnet-application.service.ts index 40c7d07..8debe16 100644 --- a/src/pg/carnet-application/carnet-application.service.ts +++ b/src/pg/carnet-application/carnet-application.service.ts @@ -26,12 +26,19 @@ import { import { BadRequestException } from 'src/exceptions/badRequest.exception'; import { PoolClient } from 'pg'; import { PgDBService } from 'src/db/db.service'; -import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper'; +import { checkPgUserDefinedErrors, deleteFilesAsync, fnCounterFoil, fnVochers, generateFinalPDF, generateGL, generateGL1, generateGreenCoverPDF, handlePgError, pdfCarnetData, pdfGLData, releasePgClient, replaceSlashWithDash, ResponseStatus, tnVochers, toUpperCaseKeys, tsCounterFoil, usCounterFoil } from 'src/utils/helper'; +import { InternalServerException } from 'src/exceptions/internalServerError.exception'; +import axios from 'axios'; +import { PaypalService } from 'src/paypal/paypal.service'; +import { NotFoundException } from 'src/exceptions/notFound.exception'; @Injectable() export class CarnetApplicationService { - constructor(private readonly pgDBService: PgDBService) { } + constructor( + private readonly pgDBService: PgDBService, + private readonly payPalService: PaypalService + ) { } // [ CARNETAPPLICATION_PKG ] @@ -1133,11 +1140,239 @@ export class CarnetApplicationService { // [PRINT_PKG] - async getPrintingData(body: PrintCarnetDTO) { } + async getPrintingData(body: PrintCarnetDTO) { - async PrintCarnet(body: PrintCarnetDTO) { } + let client: PoolClient | null = null; - async PrintGL(body: PrintGLDTO) { } + const p_carnetdatacursor = 'p_carnetdatacursor'; + const p_gldatacursor = 'p_gldatacursor'; + + try { + client = await this.pgDBService.getConnection(); + + await client.query('BEGIN'); + + const callProcQuery = ` + CALL "CARNETSYS".print_pkg_printcarnet($1, $2, $3, $4, $5) + `; + await client.query(callProcQuery, [body.P_SPID, body.P_HEADERID, body.P_PRINTGL, p_carnetdatacursor, p_gldatacursor]); + + // 🚫 DON'T quote the cursor name in FETCH + const p_carnetdatacursorResult = await client.query(`FETCH ALL FROM ${p_carnetdatacursor}`); + const p_gldatacursorResult = await client.query(`FETCH ALL FROM ${p_gldatacursor}`); + + // 🚫 DON'T quote the cursor name in CLOSE + await client.query(`CLOSE ${p_carnetdatacursor}`); + await client.query(`CLOSE ${p_gldatacursor}`); + + await client.query('COMMIT'); + + checkPgUserDefinedErrors(p_carnetdatacursorResult); + checkPgUserDefinedErrors(p_gldatacursorResult); + + return { fres: toUpperCaseKeys(p_carnetdatacursorResult.rows), fres1: toUpperCaseKeys(p_gldatacursorResult.rows) } + + } catch (error) { + if (client) await client.query('ROLLBACK'); + handlePgError(error, CarnetApplicationService.name) + } finally { + releasePgClient(client) + } + } + + async PrintCarnet(body: PrintCarnetDTO) { + try { + const { fres, fres1 }: any = await this.getPrintingData(body); + + if (body.P_PRINTGL === 'Y') { + if (fres.length === 0 || !fres[0].CARNETNO || fres1.length === 0) { + throw new BadRequestException("Print failed please check the submitted details"); + } + } + else { + if (fres.length === 0 || !fres[0].CARNETNO) { + throw new BadRequestException("Print failed please check the submitted details"); + } + } + + if (fres.length > 0 && fres[0].ERRORMESG) { + // this.logger.warn(fres[0].ERRORMESG); + console.log(fres[0].ERRORMESG); + throw new BadRequestException(fres[0].ERRORMESG) + } + + try { + const glData: pdfGLData[] = fres1.map((x: any) => { + return { + itemNo: x.ITEMNO, + description: x.ITEMDESCRIPTION, + noOfPieces: x.NOOFPIECES, + weight: x.WEIGHT, + itemValue: x.ITEMVALUE, + countryOfOrigin: x.GOODSORIGINCOUNTRY + }; + }); + + const carnetData: pdfCarnetData = { + carnetNo: fres[0].CARNETNO ?? "", + ISSUEDBY: fres[0].ISSUEDBY ?? "", + ISSUEDATE: fres[0].ISSUEDATE ?? "", + EXPDATE: fres[0].EXPDATE ?? "", + AUTHREP: fres[0].AUTHREP ?? "", + NOOFUSSETS: fres[0].NOOFUSSETS ?? 0, + NOOFFOREIGNSETS: fres[0].NOOFFOREIGNSETS ?? 0, + NOOFTRANSITSETS: fres[0].NOOFTRANSITSETS ?? 0, + PRINTGOODSTOBEEXPORTED: fres[0].PRINTGOODSTOBEEXPORTED ?? "", + HOLDERDATATOPRINT: fres[0].HOLDERDATATOPRINT ?? "", + CONTINUATIONSHEETS: fres[0].CONTINUATIONSHEETS ?? 0, + NEXTUSCFNO: fres[0].NEXTUSCFNO ?? 0, + NEXTFOREIGNCFNO: fres[0].NEXTFOREIGNCFNO ?? 0, + NEXTTRANSITCFNO: fres[0].NEXTTRANSITCFNO ?? 0, + contPageNo: 0 + } + + const p1Status = await generateGreenCoverPDF(carnetData); + + let p2Status: any = ""; + + if (body.P_PRINTGL === 'Y') { + p2Status = await generateGL(glData, carnetData, body); + // console.log("-------- p2 --------", p2Status); + // console.log(typeof p2Status.batch, p2Status.batch); + + if (p2Status.batch % 2 === 0) { + await generateFinalPDF([...p2Status.fileArray, '2GeneralListVOID.pdf'], `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`) + await deleteFilesAsync([...p2Status.fileArray]) + } + else { + await generateFinalPDF([...p2Status.fileArray], `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`) + await deleteFilesAsync([...p2Status.fileArray]) + } + + } else { + p2Status = await generateGL1(carnetData); + if (p2Status === 'p2 done') { + await generateFinalPDF([`${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`, '2GeneralListVOID.pdf'], `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`) + } + } + + const p3Status = await usCounterFoil(carnetData); + const p4Status = await fnCounterFoil(carnetData); + const p5Status = await tsCounterFoil(carnetData); + const p6Status = await fnVochers(carnetData, body); + const p7Status = await tnVochers(carnetData, body); + + const finalArray = [ + ...p3Status, + ...p4Status, + ...p5Status, + ...p6Status, + ...p7Status + ] + + return { finalArray, carnetData } + + } catch (error) { + throw new InternalServerException(error.message) + } + + } + catch (error) { + // if (client) await client.query('ROLLBACK'); + handlePgError(error, CarnetApplicationService.name) + } + } + + async PrintGL(body: PrintGLDTO) { + let newBody: PrintCarnetDTO = { ...body, P_PRINTGL: YON.YES } + + try { + const { fres, fres1 }: any = await this.getPrintingData(newBody); + + if (fres.length === 0 || fres1.length === 0) { + throw new BadRequestException("Print failed please check the submitted details"); + } + + if (fres.length > 0 && fres[0].ERRORMESG) { + // this.logger.warn(fres[0].ERRORMESG); + console.log(fres[0].ERRORMESG); + + throw new BadRequestException(fres[0].ERRORMESG) + } + + try { + const glData: pdfGLData[] = fres1.map(x => { + return { + itemNo: x.ITEMNO, + description: x.ITEMDESCRIPTION, + noOfPieces: x.NOOFPIECES, + weight: x.WEIGHT, + itemValue: x.ITEMVALUE, + countryOfOrigin: x.GOODSORIGINCOUNTRY + }; + }); + + const carnetData: pdfCarnetData = { + carnetNo: fres[0].CARNETNO ?? "", + ISSUEDBY: fres[0].ISSUEDBY ?? "", + ISSUEDATE: fres[0].ISSUEDATE ?? "", + EXPDATE: fres[0].EXPDATE ?? "", + AUTHREP: fres[0].AUTHREP ?? "", + NOOFUSSETS: fres[0].NOOFUSSETS ?? 0, + NOOFFOREIGNSETS: fres[0].NOOFFOREIGNSETS ?? 0, + NOOFTRANSITSETS: fres[0].NOOFTRANSITSETS ?? 0, + PRINTGOODSTOBEEXPORTED: fres[0].PRINTGOODSTOBEEXPORTED ?? "", + HOLDERDATATOPRINT: fres[0].HOLDERDATATOPRINT ?? "", + CONTINUATIONSHEETS: fres[0].CONTINUATIONSHEETS ?? 0, + NEXTUSCFNO: fres[0].NEXTUSCFNO ?? 0, + NEXTFOREIGNCFNO: fres[0].NEXTFOREIGNCFNO ?? 0, + NEXTTRANSITCFNO: fres[0].NEXTTRANSITCFNO ?? 0, + contPageNo: 0 + } + + // const p1Status = await generateGreenCoverPDF(carnetData); + + let p2Status: any = ""; + + p2Status = await generateGL(glData, carnetData, body); + // console.log("-------- p2 --------", p2Status); + // console.log(typeof p2Status.batch, p2Status.batch); + + if (p2Status.batch % 2 === 0) { + await generateFinalPDF([...p2Status.fileArray, '2GeneralListVOID.pdf'], `${body.P_HEADERID}p2.pdf`) + await deleteFilesAsync([...p2Status.fileArray]) + } + else { + await generateFinalPDF([...p2Status.fileArray], `${body.P_HEADERID}p2.pdf`) + await deleteFilesAsync([...p2Status.fileArray]) + } + + // const p3Status = await usCounterFoil(carnetData); + // const p4Status = await fnCounterFoil(carnetData); + // const p5Status = await tsCounterFoil(carnetData); + // const p6Status = await fnVochers(carnetData); + // const p7Status = await tnVochers(carnetData); + + const finalArray = [ + // ...p3Status, + // ...p4Status, + // ...p5Status, + // ...p6Status, + // ...p7Status + ] + + return { finalArray, carnetData } + + } catch (error) { + throw new InternalServerException(error.message) + } + + } + catch (error) { + // if (client) await client.query('ROLLBACK'); + handlePgError(error, CarnetApplicationService.name) + } + } // [payment] @@ -1153,13 +1388,328 @@ export class CarnetApplicationService { return amount.toFixed(2); // Always returns a string with 2 decimal places } - async InitiatePayment(body: InitiatePaymentDTO) { } + async InitiatePayment(body: InitiatePaymentDTO) { + const quantity = 1; + let orderID: string | null = null - async CapturePayment(body: CapturePaymentDTO) { } + const formattedAmount = await this.formatAmount(body.P_PRICE * quantity); - async OrderDetails(body: GetOrderDetailsDTO) { } + try { + const accessToken = await this.payPalService.generateAccessToken(); - async GetPaymentHistory(body: GetPaymentHistoryDTO) { } + const response = await axios({ + url: process.env.PAYPAL_BASE_URL + '/v2/checkout/orders', + method: 'post', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + accessToken + }, + data: JSON.stringify({ + intent: 'CAPTURE', + purchase_units: [ + { + items: [ + { + name: 'Carnet', + description: body.P_DESCRIPTION, + quantity: quantity, + unit_amount: { + currency_code: 'USD', + value: formattedAmount + } + } + ], + amount: { + currency_code: 'USD', + value: formattedAmount, + breakdown: { + item_total: { + currency_code: 'USD', + value: formattedAmount + } + } + } + } + ], + application_context: { + return_url: process.env.BASE_URL + '/complete-order', + cancel_url: process.env.BASE_URL + '/cancel-order', + shipping_preference: 'NO_SHIPPING', + user_action: 'PAY_NOW', + brand_name: 'test sample', + disable_funding: "card" + } + }) + }); - async SaveHistory(body: SaveHistoryDTO) { } + orderID = response?.data?.id; + + const save_result: any = await this.SaveHistory( + { + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: response?.data?.id, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "CREATED", + P_USERID: body.P_USERID + } + ); + + if (save_result.statusCode === 200) { + return { + id: response?.data?.id, href: response?.data?.links?.find(obj => obj.rel === 'approve')?.href + }; + } + else { + throw new InternalServerException(); + } + + } catch (error) { + console.error('Error creating PayPal order:', error.response?.data || error?.message || error); + + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: orderID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "FAILED", + P_USERID: body.P_USERID, + P_PAYMENTERROR: orderID ? error?.message : `Error while creating ORDERID : ${error?.message}` + }); + + throw new InternalServerException(); + } + } + + async CapturePayment(body: CapturePaymentDTO) { + + try { + + const approve_result = await this.OrderDetails({ P_ORDERID: body.P_ORDERID }); + + const formattedAmount = await this.formatAmount(body.P_PRICE); + + if (approve_result.data.id === body.P_ORDERID + && approve_result.data.status === "APPROVED" + && approve_result.data.purchase_units[0]?.amount?.value === formattedAmount + "" + ) { + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: body.P_ORDERID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "APPROVED", + P_USERID: body.P_USERID + // P_PAYMENTERROR: `Error while capturing Payment : ${error?.message}` + }); + + const accessToken = await this.payPalService.generateAccessToken(); + + const response = await axios({ + url: `${process.env.PAYPAL_BASE_URL}/v2/checkout/orders/${body.P_ORDERID}/capture`, + method: 'post', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${accessToken}`, + }, + }); + + const capture = response?.data?.purchase_units?.[0]?.payments?.captures?.[0]; + // console.log(JSON.stringify(response?.data)); + + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: body.P_ORDERID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "COMPLETED", + P_USERID: body.P_USERID + // P_PAYMENTERROR: `Error while capturing Payment : ${error?.message}` + }); + + return { + statusCode: 200, + message: "Payment successful", + amount: `${capture?.amount?.value} ${capture?.amount?.currency_code}`, + }; + } + else { + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: body.P_ORDERID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "FAILED", + P_USERID: body.P_USERID, + P_PAYMENTERROR: `Error while validating user approval` + }); + + throw new InternalServerException("failed to save approved status"); + } + + } catch (error: any) { + const status = error.response?.status || 500; + const message = error.response?.data?.message || "Payment failed due to an unexpected error."; + + // Optional: log full error for debugging + console.error("PayPal Capture Error:", { + status, + message, + details: error.response?.data, + }); + + if (status === 404) { + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: body.P_ORDERID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "FAILED", + P_USERID: body.P_USERID, + P_PAYMENTERROR: `ORDERID NOT FOUND : ${error?.message}` + }); + throw new NotFoundException(error.response?.data?.message || error?.message || "Resource Not Found") + } + + await this.SaveHistory({ + P_APPLICATIONNAME: body.P_APPLICATIONNAME, + P_ORDERID: body.P_ORDERID, + P_PAYMENTAMOUNT: body.P_PRICE, + P_STATUS: "FAILED", + P_USERID: body.P_USERID, + P_PAYMENTERROR: `Error while capturing Payment : ${error?.message}` + }); + + throw new InternalServerException(); + } + } + + async OrderDetails(body: GetOrderDetailsDTO) { + try { + + // Max length of Order ID: 36 characters (UUID) + if (!body.P_ORDERID || body.P_ORDERID.length > 36) { + throw new BadRequestException("Invalid Order ID"); + } + + const accessToken = await this.payPalService.generateAccessToken(); + + const response = await axios({ + url: `${process.env.PAYPAL_BASE_URL}/v2/checkout/orders/${body.P_ORDERID}`, + method: 'get', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${accessToken}`, + }, + }); + + // console.log("PayPal Order Details:", JSON.stringify(response.data)); + + return { + statusCode: 200, + message: "Order details retrieved successfully", + data: response.data, + }; + + } catch (error: any) { + const isAxiosError = error.isAxiosError; + + if (isAxiosError) { + const axiosErrorCode = error.code; + + switch (axiosErrorCode) { + case 'ECONNABORTED': + case 'ETIMEDOUT': + console.error("PayPal request timed out. Please try again later.") + throw new InternalServerException("Service is currently unreachable. Please try again later."); + case 'ENOTFOUND': + case 'ECONNREFUSED': + console.error("PayPal service is currently unavailable. Please try again later.") + throw new InternalServerException("Service is currently unreachable. Please try again later."); + } + } + + const status = error.response?.status || 500; + const message = error.response?.data?.message || "Failed to fetch order details."; + + + console.error("PayPal OrderDetails Error:", { + status, + message, + details: error.response?.data, + }); + + if (status === 404) { + throw new NotFoundException(message); + } + + throw new InternalServerException("A Error Occured while Processing your Request"); + } + } + + async GetPaymentHistory(body: GetPaymentHistoryDTO) { + + let client: PoolClient | null = null; + + const cursorName = 'p_cursor'; + + try { + client = await this.pgDBService.getConnection(); + + await client.query('BEGIN'); + + const callProcQuery = ` + CALL "CARNETSYS".Pay_GetPaymentHistory($1, $2, $3) + `; + await client.query(callProcQuery, [body.P_APPLICATIONNAME, body.P_USERID, cursorName]); + + // 🚫 DON'T quote the cursor name in FETCH + const fetchResult = await client.query(`FETCH ALL FROM ${cursorName}`); + + // 🚫 DON'T quote the cursor name in CLOSE + await client.query(`CLOSE ${cursorName}`); + await client.query('COMMIT'); + + return toUpperCaseKeys(fetchResult.rows); + + } catch (error) { + if (client) await client.query('ROLLBACK'); + handlePgError(error, CarnetApplicationService.name) + } finally { + releasePgClient(client) + } + } + + async SaveHistory(body: SaveHistoryDTO) { + + let client: PoolClient | null = null; + + const cursorName = 'p_cursor'; + + try { + client = await this.pgDBService.getConnection(); + + await client.query('BEGIN'); + + const callProcQuery = ` + CALL "CARNETSYS".Pay_SaveHistory($1, $2, $3, $4, $5, $6, $7) + `; + await client.query(callProcQuery, [body.P_APPLICATIONNAME, body.P_ORDERID, body.P_PAYMENTAMOUNT, body.P_STATUS, body.P_USERID, body.P_PAYMENTERROR, cursorName]); + + // 🚫 DON'T quote the cursor name in FETCH + const fetchResult = await client.query(`FETCH ALL FROM ${cursorName}`); + + // 🚫 DON'T quote the cursor name in CLOSE + await client.query(`CLOSE ${cursorName}`); + await client.query('COMMIT'); + + checkPgUserDefinedErrors(fetchResult); + + return { + statusCode: 200, + message: ResponseStatus.saved, + ...toUpperCaseKeys(fetchResult?.rows)[0] + }; + + } catch (error) { + if (client) await client.query('ROLLBACK'); + handlePgError(error, CarnetApplicationService.name) + } finally { + releasePgClient(client) + } + } } diff --git a/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.controller.ts b/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.controller.ts index c1bc2fb..2485a3e 100644 --- a/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.controller.ts +++ b/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.controller.ts @@ -31,7 +31,7 @@ export class SpContactsController { return this.spContactsService.updateSPContacts(body); } - // @Patch('/InactivateSPContact/:P_SPCONTACTID') + @Patch('/InactivateSPContact/:P_SPCONTACTID') inactivateSPContact(@Param() param: SP_CONTACTID_DTO) { return this.spContactsService.inactivateSPContact(param); } diff --git a/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.service.ts b/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.service.ts index 414762a..c01b414 100644 --- a/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.service.ts +++ b/src/pg/uscib-managed-sp/sp-contacts/sp-contacts.service.ts @@ -150,7 +150,7 @@ export class SpContactsService { await client.query('BEGIN'); const callProcQuery = ` - CALL "CARNETSYS".uscib_managed_pkg_setdefaultcontact($1) + CALL "CARNETSYS".USCIB_Managed_Pkg_InActivateSPContacts($1) `; await client.query(callProcQuery, [body.P_SPCONTACTID]); diff --git a/src/pg/user-maintenance/user-maintenance.controller.ts b/src/pg/user-maintenance/user-maintenance.controller.ts index 190dbed..048be8b 100644 --- a/src/pg/user-maintenance/user-maintenance.controller.ts +++ b/src/pg/user-maintenance/user-maintenance.controller.ts @@ -4,7 +4,7 @@ import { Roles } from 'src/decorators/roles.decorator'; import { JwtAuthGuard } from 'src/guards/jwt-auth.guard'; import { RolesGuard } from 'src/guards/roles.guard'; import { UserMaintenanceService } from './user-maintenance.service'; -import { CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, EMAIL_DTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto'; +import { CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, EMAIL_DTO, GetCarnetDetailsbyCarnetStatusDTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto'; @ApiTags('User Maintenance - PG') @UseGuards(JwtAuthGuard, RolesGuard) @@ -90,4 +90,12 @@ export class UserMaintenanceController { GetCarnetSummaryData(@Param() params: USERID_DTO) { return this.userMaintenanceService.GetCarnetSummaryData(params); } + + // [carnetcontrolcenter_pkg] + + @Get('GetCarnetDetailsbyCarnetStatus/:P_SPID/:P_USERID/:P_CARNETSTATUS') + @Roles('pca', 'psa', 'pua') + GetCarnetDetailsbyCarnetStatus(@Param() params: GetCarnetDetailsbyCarnetStatusDTO) { + return this.userMaintenanceService.GetCarnetDetailsbyCarnetStatus(params); + } } diff --git a/src/pg/user-maintenance/user-maintenance.service.ts b/src/pg/user-maintenance/user-maintenance.service.ts index b703863..c0a4341 100644 --- a/src/pg/user-maintenance/user-maintenance.service.ts +++ b/src/pg/user-maintenance/user-maintenance.service.ts @@ -1,5 +1,5 @@ import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common'; -import { CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, EMAIL_DTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto'; +import { CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, EMAIL_DTO, GetCarnetDetailsbyCarnetStatusDTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto'; import { checkPgUserDefinedErrors, handlePgError, normalizeKeysToUpperCase, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper'; import { PoolClient } from 'pg'; @@ -57,7 +57,7 @@ export class UserMaintenanceService { await client.query(`CLOSE ${userDetailsCursor}`); await client.query('COMMIT'); - + checkPgUserDefinedErrors(roleResult); checkPgUserDefinedErrors(menuResult); checkPgUserDefinedErrors(menuPageResult); @@ -489,6 +489,94 @@ export class UserMaintenanceService { checkPgUserDefinedErrors(fetchResult); + const fres: any = toUpperCaseKeys(fetchResult.rows); + + // Step 1: Replace spaces in keys + const mappedRows = fres.map((obj) => { + const newObj = {}; + for (const key in obj) { + const newKey = key.replace(/ /g, '_'); + newObj[newKey] = obj[key]; + } + return newObj; + }); + + // Step 2: Group and aggregate + const reducedRows = mappedRows.reduce((acc, curr) => { + let existing; + + if (curr.Service_Provider_Name && curr.SPID) { + existing = acc.find( + (item) => + item.Service_Provider_Name === curr.Service_Provider_Name && + item.SPID === curr.SPID + ); + } else if (curr.Preparer_Name && curr.CLIENTID) { + existing = acc.find( + (item) => + item.Preparer_Name === curr.Preparer_Name && + item.CLIENTID === curr.CLIENTID + ); + } + + if (existing) { + existing.CARNETSTATUS.push(curr.CARNETSTATUS); + existing.Carnet_Count.push(curr.Carnet_Count); + } else { + const newItem = { + CARNETSTATUS: [curr.CARNETSTATUS], + Carnet_Count: [curr.Carnet_Count], + }; + + if (curr.Service_Provider_Name && curr.SPID) { + newItem['Service_Provider_Name'] = curr.Service_Provider_Name; + newItem['SPID'] = curr.SPID; + } else if (curr.Preparer_Name && curr.CLIENTID) { + newItem['Preparer_Name'] = curr.Preparer_Name; + newItem['CLIENTID'] = curr.CLIENTID; + } + + acc.push(newItem); + } + + return acc; + }, []); + + return reducedRows; + + } catch (error) { + if (client) await client.query('ROLLBACK'); + handlePgError(error, UserMaintenanceService.name) + } finally { + releasePgClient(client) + } + } + + async GetCarnetDetailsbyCarnetStatus(body: GetCarnetDetailsbyCarnetStatusDTO) { + + let client: PoolClient | null = null; + + const cursorName = 'p_cursor'; + + try { + client = await this.pgDBService.getConnection(); + + await client.query('BEGIN'); + + const callProcQuery = ` + CALL "CARNETSYS".carnetcontrolcenter_pkg_getcarnetdetails($1, $2, $3, $4) + `; + await client.query(callProcQuery, [body.P_SPID, body.P_USERID, body.P_CARNETSTATUS, cursorName]); + + // 🚫 DON'T quote the cursor name in FETCH + const fetchResult = await client.query(`FETCH ALL FROM ${cursorName}`); + + // 🚫 DON'T quote the cursor name in CLOSE + await client.query(`CLOSE ${cursorName}`); + await client.query('COMMIT'); + + checkPgUserDefinedErrors(fetchResult); + return toUpperCaseKeys(fetchResult.rows); } catch (error) {