BE/src/pg/manage-clients/manage-clients.service.ts
2025-09-24 14:40:34 +05:30

643 lines
22 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { ClientContactControlsDTO, CreateClientContactsDTO, CreateClientDataDTO, CreateClientLocationsDTO, GetClientContactByLacationIdDTO, GetClientDTO, GetPreparersDTO, UpdateClientContactsDTO, UpdateClientDTO, UpdateClientLocationsDTO } from 'src/dto/property.dto';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
import { PoolClient } from 'pg';
import { PgDBService } from 'src/db/db.service';
@Injectable()
export class ManageClientsService {
constructor(private readonly pgDBService: PgDBService) { }
CreateClientData = async (body: CreateClientDataDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_createclientdata($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTNAME,
body.P_LOOKUPCODE,
body.P_ADDRESS1,
body.P_ADDRESS2,
body.P_CITY,
body.P_STATE,
body.P_ZIP,
body.P_COUNTRY,
body.P_ISSUINGREGION,
body.P_REVENUELOCATION,
body.P_USERID,
body.P_INDUSTRYTYPE,
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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
UpdateClient = async (body: UpdateClientDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_updateclient($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTID,
body.P_PREPARERNAME,
body.P_ADDRESS1,
body.P_ADDRESS2,
body.P_CITY,
body.P_STATE,
body.P_ZIP,
body.P_COUNTRY,
body.P_REVENUELOCATION,
body.P_USERID,
body.P_INDUSTRYTYPE,
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.updated,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
UpdateClientContacts = async (body: UpdateClientContactsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_updateclientcontacts($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTCONTACTID,
body.P_FIRSTNAME,
body.P_LASTNAME,
body.P_MIDDLEINITIAL,
body.P_TITLE,
body.P_PHONENO,
body.P_FAXNO,
body.P_MOBILENO,
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: 200,
message: ResponseStatus.updated,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
UpdateClientLocations = async (body: UpdateClientLocationsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_updateclientlocations($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTLOCATIONID,
body.P_LOCATIONNAME,
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: 200,
message: ResponseStatus.updated,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
async CreateClientContact(body: CreateClientContactsDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
// Helper to escape special characters for Postgres composite fields
function escapePostgresCompositeField(str: string): string {
if (str == null) return '';
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
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".managepreparer_pkg_createclientcontact($1, $2, $3::"CARNETSYS".contactstable[], $4, $5, $6)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_LOCATIONID,
pgArrayLiteral,
body.P_DEFCONTACTFLAG,
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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
}
SetDefaultClientContacts = async (body: ClientContactControlsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_setdefaultclientcontacts($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTCONTACTID, 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.updated,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
}
InactivateClientContacts = async (body: ClientContactControlsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_inactivateclientcontacts($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTCONTACTID, 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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
}
ReactivateClientContacts = async (body: ClientContactControlsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_reactivateclientcontacts($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTCONTACTID, 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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
}
CreateClientLocation = async (body: CreateClientLocationsDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
function escapePostgresCompositeField(str: string): string {
if (str == null) return '';
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
const addressLiterals = body.P_CLIENTLOCADDRESSTABLE.map(c => {
const fields = [
c.P_NAMEOF || '',
c.P_ADDRESS1 || '',
c.P_ADDRESS2 || '',
c.P_CITY || '',
c.P_STATE || '',
c.P_ZIP || '',
c.P_COUNTRY || '',
].map(field => escapePostgresCompositeField(field)).join(',');
return `"(${fields})"`; // Composite literal wrapped in double quotes
});
const pgArrayLiteral = `{${addressLiterals.join(',')}}`;
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_updateclientlocations($1, $2, $3::"CARNETSYS".addresstable[], $4, $5)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CLIENTID,
pgArrayLiteral,
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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
GetPreparers = async (body: GetPreparersDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_getpreparers($1, $2, $3, $4, $5, $6, $7)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_NAME, body.P_LOOKUPCODE, body.P_CITY, body.P_STATE, body.P_STATUS, 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) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
GetPreparerByClientid = async (body: GetClientDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_getpreparerlocbyclientid($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTID, 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)[0] ?? [];
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
GetPreparerContactsByClientid = async (body: GetClientDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_getpreparercontactsbyclientid($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTID, 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) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
GetPreparerContactsbyClientLocationID = async (body: GetClientContactByLacationIdDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_getpreparercontactsbyclientlocationid($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_LOCATIONID, 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) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
}
GetPreparerLocByClientid = async (body: GetClientDTO) => {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managepreparer_pkg_getpreparerlocbyclientid($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_CLIENTID, 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) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageClientsService.name)
} finally {
releasePgClient(client)
}
};
}