BE/src/pg/manage-holder/manage-holder.service.ts
2025-09-18 15:45:53 +05:30

499 lines
17 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { PgDBService } from 'src/db/db.service';
import { CONTACTSTABLE_ROW_DTO, CreateHolderContactsDTO, CreateHoldersDTO, GetHolderDTO, HolderActivateOrInactivateDTO, HolderContactActivateOrInactivateDTO, UpdateHolderContactDTO, UpdateHolderDTO } from 'src/dto/property.dto';
import { PoolClient } from 'pg';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus } from 'src/utils/helper';
@Injectable()
export class ManageHolderService {
constructor(private readonly pgDBService: PgDBService) { }
async CreateHolders(body: CreateHoldersDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_createholderdata($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTLOCATIONID,
body.P_HOLDERNO,
body.P_HOLDERTYPE,
body.P_USCIBMEMBERFLAG,
body.P_GOVAGENCYFLAG,
body.P_HOLDERNAME,
body.P_NAMEQUALIFIER,
body.P_ADDLNAME,
body.P_ADDRESS1,
body.P_ADDRESS2,
body.P_CITY,
body.P_STATE,
body.P_ZIP,
body.P_COUNTRY,
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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 201,
message: ResponseStatus.created,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
}
async CreateHoldercontact(body: CreateHolderContactsDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
// Helper to escape special characters for Postgres composite fields
function escapePostgresCompositeField(str: string): string {
if (str == null) return '';
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const contactLiterals = body.P_CONTACTSTABLE.map(c => {
const fields = [
c.P_FIRSTNAME || '',
c.P_LASTNAME || '',
c.P_MIDDLEINITIAL || '',
c.P_TITLE || '',
c.P_EMAILADDRESS || '',
c.P_PHONENO || '',
c.P_MOBILENO || '',
c.P_FAXNO || '',
].map(field => escapePostgresCompositeField(field)).join(',');
return `"(${fields})"`; // Composite literal wrapped in double quotes
});
const pgArrayLiteral = `{${contactLiterals.join(',')}}`;
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_createholdercontact($1, $2, $3::"CARNETSYS".contactstable[], $4, $5)
`;
await client.query(callProcQuery, [
body.P_SPID,
body.P_HOLDERID,
pgArrayLiteral,
body.P_USERID,
cursorName,
]);
// Fetch results from cursor (do NOT quote cursor name)
const fetchResult = await client.query(`FETCH ALL FROM ${cursorName}`);
// Close cursor
await client.query(`CLOSE ${cursorName}`);
await client.query('COMMIT');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 201,
message: ResponseStatus.created,
...fetchResult?.rows?.[0] || {},
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name);
} finally {
releasePgClient(client);
}
}
UpdateHolder = async (body: UpdateHolderDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_updateholder($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
`;
await client.query(callProcQuery,
[
body.P_HOLDERID,
body.P_SPID,
body.P_LOCATIONID,
body.P_HOLDERNO,
body.P_HOLDERTYPE,
body.P_USCIBMEMBERFLAG,
body.P_GOVAGENCYFLAG,
body.P_HOLDERNAME,
body.P_NAMEQUALIFIER,
body.P_ADDLNAME,
body.P_ADDRESS1,
body.P_ADDRESS2,
body.P_CITY,
body.P_STATE,
body.P_ZIP,
body.P_COUNTRY,
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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 201,
message: ResponseStatus.updated,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
GetHolderRecord = async (body: GetHolderDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_getholdermaster($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERID, 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 fetchResult?.rows ? fetchResult?.rows : []
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
UpdateHolderContact = async (body: UpdateHolderContactDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_updateholder($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
`;
await client.query(callProcQuery,
[
body.P_HOLDERCONTACTID,
body.P_SPID,
body.P_FIRSTNAME,
body.P_LASTNAME,
body.P_MIDDLEINITIAL,
body.P_TITLE,
body.P_PHONENO,
body.P_MOBILENO,
body.P_FAXNO,
body.P_EMAILADDRESS,
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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 201,
message: ResponseStatus.updated,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
GetHolderContacts = async (body: GetHolderDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_getholdercontacts($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERID, 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 fetchResult?.rows ? fetchResult?.rows : []
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
InactivateHolder = async (body: HolderActivateOrInactivateDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_inactivateholder($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERID, 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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 200,
message: ResponseStatus.inActivate,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
ReactivateHolder = async (body: HolderActivateOrInactivateDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_reactivateholder($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERID, 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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 200,
message: ResponseStatus.reActivate,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
InactivateHolderContact = async (body: HolderContactActivateOrInactivateDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_inactivateholdercontact($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERCONTACTID, 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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 200,
message: ResponseStatus.inActivate,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
ReactivateHolderContact = async (body: HolderContactActivateOrInactivateDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_reactivateholdercontact($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERCONTACTID, 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');
checkPgUserDefinedErrors(fetchResult);
return {
statusCode: 200,
message: ResponseStatus.reActivate,
...fetchResult?.rows?.[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
SearchHolder = async (body: { P_SPID: number, P_USERID: string, P_HOLDERID: number | null, P_HOLDERNAME: string | null }) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageholder_pkg_searchholder($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_HOLDERID, body.P_HOLDERNAME, 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');
checkPgUserDefinedErrors(fetchResult);
return fetchResult?.rows ? fetchResult?.rows : []
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
}
}