import { Injectable, Logger } from '@nestjs/common'; import * as oracledb from 'oracledb'; import { OracleDBService } from 'src/db/db.service'; import { BadRequestException } from 'src/exceptions/badRequest.exception'; import { InternalServerException } from 'src/exceptions/internalServerError.exception'; import { closeOracleDbConnection, fetchCursor, handleError } from 'src/utils/helper'; import { SPID_DTO, CreateCarnetSequenceDTO } from 'src/dto/property.dto'; @Injectable() export class CarnetSequenceService { private readonly logger = new Logger(CarnetSequenceService.name); constructor(private readonly oracleDBService: OracleDBService) { } async createCarnetSequenceX(body: CreateCarnetSequenceDTO) { let connection; try { connection = await this.oracleDBService.getConnection(); if (!connection) { throw new InternalServerException(); } const result = await connection.execute( `BEGIN USCIB_Managed_Pkg.CreateCarnetSequence( :P_SPID, :P_REGIONID, :P_STARTNUMBER, :P_ENDNUMBER, :P_CARNETTYPE, :P_CURSOR); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER, }, P_REGIONID: { val: body.P_REGIONID, type: oracledb.DB_TYPE_NUMBER, }, P_STARTNUMBER: { val: body.P_STARTNUMBER, type: oracledb.DB_TYPE_NUMBER, }, P_ENDNUMBER: { val: body.P_ENDNUMBER, type: oracledb.DB_TYPE_NUMBER, }, P_CARNETTYPE: { val: body.P_CARNETTYPE, type: oracledb.DB_TYPE_VARCHAR, }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT, }, }, { outFormat: oracledb.OUT_FORMAT_OBJECT, } ); await connection.commit(); const fres = await result.outBinds.P_CURSOR.getRows(); await result.outBinds.P_CURSOR.close(); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 201, message: "Createdted Successfully", ...fres[0] }; } catch (error) { if (error instanceof BadRequestException) { this.logger.warn(error.message); throw error; } this.logger.error('createCarnetSequence failed', error.stack || error); throw new InternalServerException(); } finally { if (connection) { try { await connection.close(); } catch (closeErr) { this.logger.error('Failed to close DB connection', closeErr); } } } } async createCarnetSequence(body: CreateCarnetSequenceDTO) { let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN CARNETAPPLICATION_PKG.SaveCarnetApplication( :P_SPID, :P_REGIONID, :P_STARTNUMBER, :P_ENDNUMBER, :P_CARNETTYPE, :P_CURSOR ); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_REGIONID: { val: body.P_REGIONID, type: oracledb.DB_TYPE_NUMBER }, P_STARTNUMBER: { val: body.P_STARTNUMBER, type: oracledb.DB_TYPE_NUMBER }, P_ENDNUMBER: { val: body.P_ENDNUMBER, type: oracledb.DB_TYPE_NUMBER }, P_CARNETTYPE: { val: body.P_CARNETTYPE, type: oracledb.DB_TYPE_VARCHAR }, P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR } }, { outFormat: oracledb.OUT_FORMAT_OBJECT } ); await connection.commit(); const outBinds = result.outBinds; if (!outBinds?.P_CURSOR) { this.logger.error('One or more expected cursors are missing from stored procedure output.'); throw new InternalServerException("Incomplete data received from the database."); } let fres: any = await fetchCursor(outBinds.P_CURSOR, CarnetSequenceService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 201, message: "Createdted Successfully", ...fres[0] }; } catch (error) { handleError(error, CarnetSequenceService.name) } finally { await closeOracleDbConnection(connection, CarnetSequenceService.name) } } async getCarnetSequenceX(body: SPID_DTO) { let connection; let rows = []; try { // Connect to the Oracle database using oracledb connection = await this.oracleDBService.getConnection(); if (!connection) { throw new InternalServerException(); } const result = await connection.execute( `BEGIN USCIB_Managed_Pkg.GetCarnetSequence(: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, }, ); if (result.outBinds && result.outBinds.P_CURSOR) { const cursor = result.outBinds.P_CURSOR; let rowsBatch; do { rowsBatch = await cursor.getRows(100); rows = rows.concat(rowsBatch); } while (rowsBatch.length > 0); await cursor.close(); } else { throw new BadRequestException(); } return rows; } catch (error) { if (error instanceof BadRequestException) { this.logger.warn(error.message); throw error; } else if (error.message === "NJS-107: invalid cursor") { this.logger.warn(error.message); throw new BadRequestException(); } this.logger.error('getCarnetSequence failed', error.stack || error); throw new InternalServerException(); } finally { if (connection) { try { await connection.close(); } catch (closeErr) { this.logger.error('Failed to close DB connection', closeErr); } } } } async getCarnetSequence(body: SPID_DTO) { let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN USCIB_Managed_Pkg.GetCarnetSequence(:P_SPID,:P_CURSOR); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR } }, { outFormat: oracledb.OUT_FORMAT_OBJECT } ); await connection.commit(); const outBinds = result.outBinds; if (!outBinds?.P_CURSOR) { this.logger.error('One or more expected cursors are missing from stored procedure output.'); throw new InternalServerException("Incomplete data received from the database."); } return await fetchCursor(outBinds.P_CURSOR, CarnetSequenceService.name); } catch (error) { handleError(error, CarnetSequenceService.name) } finally { await closeOracleDbConnection(connection, CarnetSequenceService.name) } } }