import { Injectable, Logger } from '@nestjs/common'; import { OracleDBService } from 'src/db/db.service'; import * as oracledb from 'oracledb'; import { BadRequestException } from 'src/exceptions/badRequest.exception'; import { InternalServerException } from 'src/exceptions/internalServerError.exception'; import { closeOracleDbConnection, fetchCursor, handleError, setEmptyStringsToNull } from 'src/utils/helper'; import { CLIENTLOCADDRESSTABLE_ROW_DTO, CreateClientContactsDTO, CreateClientDataDTO, CreateClientLocationsDTO, GetPreparerByClientidContactsByClientidLocByClientidDTO, GetPreparersDTO, UpdateClientContactsDTO, UpdateClientDTO, UpdateClientLocationsDTO, CONTACTSTABLE_ROW_DTO } from 'src/dto/property.dto'; import { OracleService } from '../oracle.service'; @Injectable() export class ManageClientsService { private readonly logger = new Logger(ManageClientsService.name); constructor( private readonly oracleDBService: OracleDBService, private readonly oracleService: OracleService ) { } CreateClientData = async (body: CreateClientDataDTO) => { const newBody = { P_SPID: null, P_CLIENTNAME: null, P_LOOKUPCODE: null, P_ADDRESS1: null, P_ADDRESS2: null, P_CITY: null, P_STATE: null, P_ZIP: null, P_COUNTRY: null, P_ISSUINGREGION: null, P_REVENUELOCATION: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: CreateClientDataDTO = { ...newBody, ...reqBody }; let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.CreateClientData( :P_SPID, :P_CLIENTNAME, :P_LOOKUPCODE, :P_ADDRESS1, :P_ADDRESS2, :P_CITY, :P_STATE, :P_ZIP, :P_COUNTRY, :P_ISSUINGREGION, :P_REVENUELOCATION, :P_USERID, :P_CLIENTCURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTNAME: { val: finalBody.P_CLIENTNAME, type: oracledb.DB_TYPE_NVARCHAR }, P_LOOKUPCODE: { val: finalBody.P_LOOKUPCODE, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS1: { val: finalBody.P_ADDRESS1, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS2: { val: finalBody.P_ADDRESS2, type: oracledb.DB_TYPE_NVARCHAR }, P_CITY: { val: finalBody.P_CITY, type: oracledb.DB_TYPE_NVARCHAR }, P_STATE: { val: finalBody.P_STATE, type: oracledb.DB_TYPE_NVARCHAR }, P_ZIP: { val: finalBody.P_ZIP, type: oracledb.DB_TYPE_NVARCHAR }, P_COUNTRY: { val: finalBody.P_COUNTRY, type: oracledb.DB_TYPE_NVARCHAR }, P_ISSUINGREGION: { val: finalBody.P_ISSUINGREGION, type: oracledb.DB_TYPE_NVARCHAR }, P_REVENUELOCATION: { val: finalBody.P_REVENUELOCATION, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CLIENTCURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); await connection.commit(); const outBinds: any = result.outBinds; if (!outBinds?.P_CLIENTCURSOR) { this.logger.error('One or more expected cursors are missing from stored procedure output.'); throw new InternalServerException("Incomplete data received from the database."); } const fres: any = await fetchCursor(outBinds.P_CLIENTCURSOR, ManageClientsService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 201, message: "Created Successfully" }; } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; UpdateClient = async (body: UpdateClientDTO) => { const newBody = { P_SPID: null, P_CLIENTID: null, P_PREPARERNAME: null, P_ADDRESS1: null, P_ADDRESS2: null, P_CITY: null, P_STATE: null, P_ZIP: null, P_COUNTRY: null, P_REVENUELOCATION: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: UpdateClientDTO = { ...newBody, ...reqBody }; let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.UpdateClient( :P_SPID, :P_CLIENTID, :P_PREPARERNAME, :P_ADDRESS1, :P_ADDRESS2, :P_CITY, :P_STATE, :P_ZIP, :P_COUNTRY, :P_REVENUELOCATION, :P_USERID, :P_CURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: finalBody.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, P_PREPARERNAME: { val: finalBody.P_PREPARERNAME, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS1: { val: finalBody.P_ADDRESS1, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS2: { val: finalBody.P_ADDRESS2, type: oracledb.DB_TYPE_NVARCHAR }, P_CITY: { val: finalBody.P_CITY, type: oracledb.DB_TYPE_NVARCHAR }, P_STATE: { val: finalBody.P_STATE, type: oracledb.DB_TYPE_NVARCHAR }, P_ZIP: { val: finalBody.P_ZIP, type: oracledb.DB_TYPE_NVARCHAR }, P_COUNTRY: { val: finalBody.P_COUNTRY, type: oracledb.DB_TYPE_NVARCHAR }, P_REVENUELOCATION: { val: finalBody.P_REVENUELOCATION, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); await connection.commit(); const outBinds: any = 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."); } const fres: any = await fetchCursor(outBinds.P_CURSOR, ManageClientsService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 200, message: "Updated Successfully" }; } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; UpdateClientContacts = async (body: UpdateClientContactsDTO) => { const newBody = { P_SPID: null, P_CLIENTCONTACTID: null, P_FIRSTNAME: null, P_LASTNAME: null, P_MIDDLEINITIAL: null, P_TITLE: null, P_PHONENO: null, P_FAXNO: null, P_MOBILENO: null, P_EMAILADDRESS: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: UpdateClientContactsDTO = { ...newBody, ...reqBody }; let connection; let P_CURSOR_rows: any = []; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.UpdateClientContacts( :P_SPID, :P_CLIENTCONTACTID, :P_FIRSTNAME, :P_LASTNAME, :P_MIDDLEINITIAL, :P_TITLE, :P_PHONENO, :P_FAXNO, :P_MOBILENO, :P_EMAILADDRESS, :P_USERID, :P_CURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTCONTACTID: { val: finalBody.P_CLIENTCONTACTID, type: oracledb.DB_TYPE_NUMBER }, P_FIRSTNAME: { val: finalBody.P_FIRSTNAME, type: oracledb.DB_TYPE_NVARCHAR }, P_LASTNAME: { val: finalBody.P_LASTNAME, type: oracledb.DB_TYPE_NVARCHAR }, P_MIDDLEINITIAL: { val: finalBody.P_MIDDLEINITIAL, type: oracledb.DB_TYPE_NVARCHAR }, P_TITLE: { val: finalBody.P_TITLE, type: oracledb.DB_TYPE_NVARCHAR }, P_PHONENO: { val: finalBody.P_PHONENO, type: oracledb.DB_TYPE_NVARCHAR }, P_FAXNO: { val: finalBody.P_FAXNO, type: oracledb.DB_TYPE_NVARCHAR }, P_MOBILENO: { val: finalBody.P_MOBILENO, type: oracledb.DB_TYPE_NVARCHAR }, P_EMAILADDRESS: { val: finalBody.P_EMAILADDRESS, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); await connection.commit(); const outBinds: any = 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."); } const fres: any = await fetchCursor(outBinds.P_CURSOR, ManageClientsService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 200, message: "Updated Successfully" }; } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; UpdateClientLocations = async (body: UpdateClientLocationsDTO) => { const newBody = { P_SPID: null, P_CLIENTLOCATIONID: null, P_LOCATIONNAME: null, P_ADDRESS1: null, P_ADDRESS2: null, P_CITY: null, P_STATE: null, P_ZIP: null, P_COUNTRY: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: UpdateClientLocationsDTO = { ...newBody, ...reqBody }; let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.UpdateClientLocations( :P_SPID, :P_CLIENTLOCATIONID, :P_LOCATIONNAME, :P_ADDRESS1, :P_ADDRESS2, :P_CITY, :P_STATE, :P_ZIP, :P_COUNTRY, :P_USERID, :P_CURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTLOCATIONID: { val: finalBody.P_CLIENTLOCATIONID, type: oracledb.DB_TYPE_NUMBER }, P_LOCATIONNAME: { val: finalBody.P_LOCATIONNAME, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS1: { val: finalBody.P_ADDRESS1, type: oracledb.DB_TYPE_NVARCHAR }, P_ADDRESS2: { val: finalBody.P_ADDRESS2, type: oracledb.DB_TYPE_NVARCHAR }, P_CITY: { val: finalBody.P_CITY, type: oracledb.DB_TYPE_NVARCHAR }, P_STATE: { val: finalBody.P_STATE, type: oracledb.DB_TYPE_NVARCHAR }, P_ZIP: { val: finalBody.P_ZIP, type: oracledb.DB_TYPE_NVARCHAR }, P_COUNTRY: { val: finalBody.P_COUNTRY, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); await connection.commit(); const outBinds: any = 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."); } const fres: any = await fetchCursor(outBinds.P_CURSOR, ManageClientsService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 200, message: "Updated Successfully" }; } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; async CreateClientContact(body: CreateClientContactsDTO) { const newBody = { P_SPID: null, P_CLIENTID: null, P_CONTACTSTABLE: null, P_DEFCONTACTFLAG: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: CreateClientContactsDTO = { ...newBody, ...reqBody }; let connection; try { connection = await this.oracleDBService.getConnection(); const CONTACTSTABLE_INSTANCE = await this.oracleService.get_CONTACTS_TABLE_INSTANCE(finalBody); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.CreateClientContact( :P_SPID, :P_CLIENTID, :P_CONTACTSTABLE, :P_DEFCONTACTFLAG, :P_USERID, :P_CURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: finalBody.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, P_CONTACTSTABLE: { val: CONTACTSTABLE_INSTANCE, type: oracledb.DB_TYPE_OBJECT }, P_DEFCONTACTFLAG: { val: finalBody.P_DEFCONTACTFLAG, type: oracledb.DB_TYPE_NVARCHAR }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { 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, ManageClientsService.name); } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } } CreateClientLocation = async (body: CreateClientLocationsDTO) => { const newBody = { P_SPID: null, P_CLIENTID: null, p_clientlocaddresstable: null, P_USERID: null, }; const reqBody = JSON.parse(JSON.stringify(body)); setEmptyStringsToNull(reqBody); const finalBody: CreateClientLocationsDTO = { ...newBody, ...reqBody, }; let connection; try { connection = await this.oracleDBService.getConnection(); const CLIENTLOCADDRESSTABLE_INSTANCE = await this.oracleService.get_CLIENTLOCADDRESS_TABLE_INSTANCE(finalBody); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.CreateClientLocation( :P_SPID, :P_CLIENTID, :P_CLIENTLOCADDRESSTABLE, :P_USERID, :P_CURSOR ); END;`, { P_SPID: { val: finalBody.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: finalBody.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, p_clientlocaddresstable: { val: CLIENTLOCADDRESSTABLE_INSTANCE, type: oracledb.DB_TYPE_OBJECT }, P_USERID: { val: finalBody.P_USERID, type: oracledb.DB_TYPE_NVARCHAR }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); await connection.commit(); const outBinds: any = 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."); } const fres: any = await fetchCursor(outBinds.P_CURSOR, ManageClientsService.name); if (fres.length > 0 && fres[0].ERRORMESG) { this.logger.warn(fres[0].ERRORMESG); throw new BadRequestException(fres[0].ERRORMESG) } return { statusCode: 201, message: "Created Successfully" }; } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; GetPreparers = async (body: GetPreparersDTO) => { let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.GetPreparers( :P_SPID, :P_NAME, :P_LOOKUPCODE, :P_CITY, :P_STATE, :P_STATUS, :P_MAINCURSOR ); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_NAME: { val: body.P_NAME, type: oracledb.DB_TYPE_NVARCHAR }, P_LOOKUPCODE: { val: body.P_LOOKUPCODE, type: oracledb.DB_TYPE_NVARCHAR }, P_CITY: { val: body.P_CITY, type: oracledb.DB_TYPE_NVARCHAR }, P_STATE: { val: body.P_STATE, type: oracledb.DB_TYPE_NVARCHAR }, P_STATUS: { val: body.P_STATUS, type: oracledb.DB_TYPE_NVARCHAR }, P_MAINCURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); const outBinds: any = result.outBinds; if (!outBinds?.P_MAINCURSOR) { 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_MAINCURSOR, ManageClientsService.name); } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; GetPreparerByClientid = async (body: GetPreparerByClientidContactsByClientidLocByClientidDTO) => { let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.GetPreparerByClientid( :P_SPID, :P_CLIENTID, :P_CURSOR ); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); const outBinds: any = 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, ManageClientsService.name); } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; GetPreparerContactsByClientid = async (body: GetPreparerByClientidContactsByClientidLocByClientidDTO) => { let connection; try { connection = await this.oracleDBService.getConnection(); const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.GetPreparerContactsByClientid( :P_SPID, :P_CLIENTID, :P_CURSOR ); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); const outBinds: any = 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, ManageClientsService.name); } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; GetPreparerLocByClientid = async (body: GetPreparerByClientidContactsByClientidLocByClientidDTO) => { let connection; try { connection = await this.oracleDBService.getConnection(); if (!connection) { throw new Error('No DB Connected'); } const result = await connection.execute( `BEGIN MANAGEPREPARER_PKG.GetPreparerLocByClientid( :P_SPID, :P_CLIENTID, :P_CURSOR ); END;`, { P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER }, P_CLIENTID: { val: body.P_CLIENTID, type: oracledb.DB_TYPE_NUMBER }, P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { outFormat: oracledb.OUT_FORMAT_OBJECT, }, ); const outBinds: any = 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, ManageClientsService.name); } catch (error) { handleError(error, ManageClientsService.name) } finally { await closeOracleDbConnection(connection, ManageClientsService.name) } }; }