Compare commits

...

52 Commits

Author SHA1 Message Date
2d6eb77d98 updated holdertype and uscibmemberflag to "" if null 2025-11-15 15:06:51 +00:00
cb74d0a2d1 updated uscib member flag and holder type to required false and allow any length 2025-11-15 15:02:17 +00:00
203caabe5e Added IsOptinal to P_SPCLCOUNTRY 2025-11-12 12:20:32 +00:00
3be2a9c289 Added IsOptional 2025-11-12 12:18:44 +00:00
07839bbc55 Added message to P_SPCLCOMMODITY 2025-11-12 12:14:49 +00:00
36456f7915 Updated SPCLCOMMODITY_DTO and SPCLCOUNTRY_DTO to required: false 2025-11-12 12:10:04 +00:00
9b41ed24a4 updated P_SPCLCOMMODITY and P_SPCLCOUNTRY to "" if null 2025-11-12 11:59:44 +00:00
9f4faf2f0b updated P_SPCLCOMMODITY and P_SPCLCOUNTRY to "" if null 2025-11-12 11:58:21 +00:00
e8864a214f add pua login to createsplogins 2025-11-09 15:34:07 +00:00
97093d9abe Add ua role to createsplogins 2025-11-09 15:33:32 +00:00
6c23cedc4e updated address, bond surety, cargo policy, and cargo surety to "" if null 2025-11-09 15:27:14 +00:00
bf59d29b96 fixed CARNETSTATUS and Carnet_Count 2025-11-07 15:56:33 +00:00
a012287e19 changed fax_no_dto and middle_initial_dto to required: false 2025-11-05 16:35:02 +00:00
d3c029173e changed PartialType(TITLE_DTO) to TITLE_DTO 2025-11-05 16:32:09 +00:00
Kallesh B S
60f59287c6 reverted auth domain 2025-09-30 12:41:34 +05:30
Kallesh B S
16881b9c0a auth bug fix 12 2025-09-30 11:15:23 +05:30
Kallesh B S
7a783994fd auth bug fix 11 2025-09-30 09:52:42 +05:30
Kallesh B S
2e3a506c81 bug fix 10 2025-09-29 16:38:09 +05:30
Kallesh B S
4c92d28496 bug fix 9 2025-09-29 11:33:28 +05:30
Kallesh B S
8050870b0b auth fix 8 2025-09-27 18:43:17 +05:30
Kallesh B S
570037c6d9 auth fix 7 2025-09-27 18:21:36 +05:30
Kallesh B S
1a08f98548 auth fix 6 2025-09-27 18:02:26 +05:30
Kallesh B S
7d27c9a0ff auth fix 5 2025-09-27 17:56:39 +05:30
Kallesh B S
59c51fb817 auth fix 4 2025-09-27 17:44:51 +05:30
Kallesh B S
df5fc86821 auth fix 3 2025-09-27 17:30:42 +05:30
Kallesh B S
82ac15af6f auth fix 2 2025-09-27 16:36:01 +05:30
Kallesh B S
da3051fe5e auth fix 1 2025-09-27 16:09:24 +05:30
Kallesh B S
67173f3a6c auth fix 2025-09-26 15:02:51 +05:30
Kallesh B S
b27fee6ece fix api issues 2025-09-25 16:08:50 +05:30
Kallesh B S
c7d084fa91 pull from dev-v5 2025-09-25 15:04:30 +05:30
b17a94342b Update src/auth/auth.service.ts
domain condition
2025-09-24 16:03:18 +00:00
Kallesh B S
9535f75301 mail domain 2025-09-24 17:22:48 +05:30
Kallesh B S
9a19d9660e mail domain 2025-09-24 16:56:25 +05:30
Kallesh B S
7ea099d611 response aligned to match same as oracle 2025-09-24 16:20:54 +05:30
Kallesh B S
cecfa1030a all api completed 2025-09-23 16:48:58 +05:30
Kallesh B S
8e94cdd97a uppercase all response keys 2025-09-22 17:13:48 +05:30
Kallesh B S
a1fd355171 adding carnet api 2025-09-20 16:52:38 +05:30
Kallesh B S
439c986583 auth for pg 2025-09-20 13:30:57 +05:30
Kallesh B S
19115d50fe adding carnet module 2025-09-19 17:29:05 +05:30
Kallesh B S
3c27de26b9 swag condition added 2025-09-19 15:47:11 +05:30
Kallesh B S
c08b8bb19f db initialize through env flag 2025-09-19 12:13:02 +05:30
Kallesh B S
2a45c0b522 added holders and client 2025-09-18 15:45:53 +05:30
Kallesh B S
72ffa77ba6 api modified for auth and holder template 2025-09-17 16:39:13 +05:30
Kallesh B S
7b8e595a92 api added 2025-09-17 10:18:44 +05:30
Kallesh B S
5fd62322ad auth changes and last pay bug fix 2025-09-17 10:18:08 +05:30
Kallesh B S
36529727a0 api endpoints modified to replace db name to its mapped value 2025-09-05 11:15:17 +05:30
Kallesh B S
c1f03cdf43 28-08-2025 API changes, return specific value in applicationName from login API, payment data persist changes 2025-08-28 17:16:55 +05:30
Kallesh B S
3616b57a73 create login bugs 2025-08-26 17:02:03 +05:30
Kallesh B S
a2c2ed2a68 Added the Payment Data Persistence API 2025-08-25 16:14:25 +05:30
Kallesh B S
45d57cee8d initiate-payment api modified for dynamic amount from UI 2025-08-22 15:16:02 +05:30
Kallesh B S
0e59a652b0 19-08-2025 api modifications 2025-08-19 17:27:14 +05:30
Kallesh B S
75a537aab4 pay 2 2025-08-18 20:34:44 +05:30
80 changed files with 7806 additions and 163 deletions

View File

@ -1,5 +1,9 @@
GET http://192.168.1.96:3006
###
GET http://localhost:3000/oracle/GetRegions/1
###
GET http://localhost:3000/oracle/SearchHolder/1

15
package-lock.json generated
View File

@ -35,7 +35,7 @@
"pdf-lib": "^1.17.1",
"pdf-merger-js": "^5.1.2",
"pdfkit": "^0.17.1",
"pg": "^8.13.3",
"pg": "^8.16.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"typeorm": "^0.3.20",
@ -56,6 +56,7 @@
"@types/mssql": "^9.1.7",
"@types/node": "^22.10.7",
"@types/oracledb": "^6.5.4",
"@types/pg": "^8.15.5",
"@types/supertest": "^6.0.2",
"@types/uuid": "^10.0.0",
"eslint": "^9.31.0",
@ -3873,6 +3874,18 @@
"@types/node": "*"
}
},
"node_modules/@types/pg": {
"version": "8.15.5",
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz",
"integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
"pg-protocol": "*",
"pg-types": "^2.2.0"
}
},
"node_modules/@types/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",

View File

@ -46,7 +46,7 @@
"pdf-lib": "^1.17.1",
"pdf-merger-js": "^5.1.2",
"pdfkit": "^0.17.1",
"pg": "^8.13.3",
"pg": "^8.16.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"typeorm": "^0.3.20",
@ -67,6 +67,7 @@
"@types/mssql": "^9.1.7",
"@types/node": "^22.10.7",
"@types/oracledb": "^6.5.4",
"@types/pg": "^8.15.5",
"@types/supertest": "^6.0.2",
"@types/uuid": "^10.0.0",
"eslint": "^9.31.0",

View File

@ -6,11 +6,13 @@ import { OriginCheckMiddleware } from './middleware/OriginCheck.middleware';
import { ReqBodyKeysToUppercaseMiddleware } from './middleware/reqBodyKeysToUppercase.middleware';
import { ConfigModule } from '@nestjs/config';
import { MailModule } from './mail/mail.module';
import { PaypalModule } from './paypal/paypal.module';
import { PgModule } from './pg/pg.module';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
AuthModule, DbModule, OracleModule, MailModule
AuthModule, PgModule, DbModule, OracleModule, MailModule, PaypalModule
],
controllers: [],
providers: [],

View File

@ -1,13 +1,14 @@
import { Body, Controller, Get, HttpCode, Post, Put, Req, Res, UseGuards, UseInterceptors } from '@nestjs/common';
import { AuthService } from './auth.service';
import { ApiTags } from '@nestjs/swagger';
import { AuthLoginDTO, SendMailDTO } from './auth.dto';
import { AuthLoginDTO, AuthLoginOnlyDTO, SendMailDTO } from './auth.dto';
import { Request, Response } from 'express';
import { LogoutInterceptor } from 'src/interceptors/logout.interceptor';
import { RegisterGuard } from 'src/guards/register.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { extractSubdomain } from 'src/utils/helper';
@ApiTags('Auth')
@Controller()
@ -16,11 +17,11 @@ export class AuthController {
private readonly authService: AuthService,
) { }
@Post('login')
@Post('1/login')
@HttpCode(200)
async loginClient(@Body() body: AuthLoginDTO, @Res({ passthrough: true }) res: Response, @Req() req: Request) {
async loginClienta(@Body() body: AuthLoginOnlyDTO, @Res({ passthrough: true }) res: Response, @Req() req: Request) {
let k: any = await this.authService.loginUser(body.P_EMAILADDR.toLowerCase(), body.P_PASSWORD, req);
let k: any = await this.authService.loginUser(body.P_EMAILADDR.toLowerCase(), body.P_PASSWORD, body.P_APPLICATIONNAME, req, 1);
if (k.access_token) {
res.cookie('access_token', k.access_token, {
@ -41,16 +42,84 @@ export class AuthController {
return { statusCode: 200, message: "Logged-In Successfully", email: k.email }
}
@Post('2/login')
@HttpCode(200)
async loginClientb(@Body() body: AuthLoginOnlyDTO, @Res({ passthrough: true }) res: Response, @Req() req: Request) {
let k: any = await this.authService.loginUser(body.P_EMAILADDR.toLowerCase(), body.P_PASSWORD, body.P_APPLICATIONNAME, req, 2);
if (k.access_token) {
res.cookie('access_token', k.access_token, {
httpOnly: true,
secure: true,
sameSite: 'none'
});
}
if (k.refresh_token) {
res.cookie('refresh_token', k.refresh_token, {
httpOnly: true,
secure: true,
sameSite: 'none'
});
}
// auth domain below
// const hostname = req.hostname;
// const isLocalhost = hostname === 'localhost' || hostname === '127.0.0.1';
// const isDevEnv = isLocalhost || hostname.startsWith('localhost') || hostname.startsWith('127.0.0.1');
// const cookieOptions: any = {
// httpOnly: true,
// secure: true,
// sameSite: 'none'
// };
// if (!isDevEnv) {
// cookieOptions.domain = hostname;
// }
// res.cookie('access_token', k.access_token, {
// ...cookieOptions
// });
// res.cookie('refresh_token', k.refresh_token, {
// ...cookieOptions
// });
return { statusCode: 200, message: "Logged-In Successfully", email: k.email }
}
// @UseGuards(RegisterGuard)
@Post('register')
async register(@Body() body: AuthLoginDTO) {
return this.authService.registerUser(body);
@Post('1/register')
async registera(@Body() body: AuthLoginDTO) {
return this.authService.registerUser(body, 1);
}
@Post('2/register')
async registerb(@Body() body: AuthLoginDTO) {
return this.authService.registerUser(body, 2);
}
@UseGuards(RegisterGuard)
@Put('1/forgot-password')
async forgotPassworda(@Body() body: AuthLoginDTO, @Req() req: Request) {
return this.authService.forgotPassword(body, req);
}
@UseGuards(RegisterGuard)
@Put('2/forgot-password')
async forgotPasswordb(@Body() body: AuthLoginDTO, @Req() req: Request) {
return this.authService.forgotPassword(body, req);
}
@UseInterceptors(LogoutInterceptor)
@HttpCode(200)
@Post('logout')
async logout(@Req() req: any, @Res() res: Response) {
@Post('1/logout')
async logouta(@Req() req: any, @Res() res: Response) {
const refreshToken = req.user?.refreshToken;
let rst: any = await this.authService.logoutUser(refreshToken);
if (rst.statusCode === 200) {
@ -68,14 +137,101 @@ export class AuthController {
res.json({ ...rst })
}
@UseGuards(RegisterGuard)
@Put('forgot-password')
async forgotPassword(@Body() body: AuthLoginDTO, @Req() req: Request) {
return this.authService.forgotPassword(body, req);
@UseInterceptors(LogoutInterceptor)
@HttpCode(200)
@Post('2/logout')
async logoutb(@Req() req: any, @Res() res: Response) {
const refreshToken = req.user?.refreshToken;
let rst: any = await this.authService.logoutUser(refreshToken);
if (rst.statusCode === 200) {
res.clearCookie('access_token', {
httpOnly: true,
secure: true,
sameSite: 'none'
});
res.clearCookie('refresh_token', {
httpOnly: true,
secure: true,
sameSite: 'none'
});
// to enable auth domain
// const hostname = req.hostname;
// const isLocalhost = hostname === 'localhost' || hostname === '127.0.0.1';
// const isDevEnv = isLocalhost || hostname.startsWith('localhost') || hostname.startsWith('127.0.0.1');
// const cookieOptions: any = {
// httpOnly: true,
// secure: true,
// sameSite: 'none'
// };
// if (!isDevEnv) {
// cookieOptions.domain = hostname;
// }
// if (!isDevEnv) {
// res.clearCookie('access_token', {
// httpOnly: true,
// secure: true,
// sameSite: 'none',
// domain: hostname
// });
// res.clearCookie('refresh_token', {
// httpOnly: true,
// secure: true,
// sameSite: 'none',
// domain: hostname
// });
// } else {
// res.clearCookie('access_token', {
// httpOnly: true,
// secure: true,
// sameSite: 'none'
// });
// res.clearCookie('refresh_token', {
// httpOnly: true,
// secure: true,
// sameSite: 'none'
// });
// }
}
res.json({ ...rst })
}
@Get('refresh-tokens')
async getTokenFromRefreshToken(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
@Get('1/refresh-tokens')
async getTokenFromRefreshTokena(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
let k: any = await this.authService.getTokenFromRefreshToken(req)
if (k.access_token) {
res.cookie('access_token', k.access_token, {
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 8 * 60 * 60 * 1000,
path: '/'
});
}
if (k.refresh_token) {
res.cookie('refresh_token', k.refresh_token, {
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 8 * 60 * 60 * 1000,
path: '/'
});
}
return { statusCode: 200, message: "Tokens refreshed successfully" }
}
@Get('2/refresh-tokens')
async getTokenFromRefreshTokenb(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
let k: any = await this.authService.getTokenFromRefreshToken(req)
if (k.access_token) {
@ -102,12 +258,36 @@ export class AuthController {
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa')
@Post('sendmail')
@Roles('ua', 'sa', 'ca')
@Post('1/sendmail')
@HttpCode(200)
async sendMail(@Body() body: SendMailDTO) {
async sendMaila(@Body() body: SendMailDTO, @Req() req: Request) {
// let token = await this.jwtService.generateToken({ email: mail })
return this.authService.sendMail(body);
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
return this.authService.sendMail(body, appDomain);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('pua', 'psa', 'pca')
@Post('2/sendmail')
@HttpCode(200)
async sendMailb(@Body() body: SendMailDTO, @Req() req: Request) {
// let token = await this.jwtService.generateToken({ email: mail })
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
return this.authService.sendMail(body, appDomain);
}
// @Get('checkRoles')

View File

@ -1,6 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';
import { ApiProperty, IntersectionType } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import { IsEmail, IsEnum, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator';
import { APPLICATIONNAME_DTO } from 'src/dto/property.dto';
export class AuthLoginDTO {
@ApiProperty({ required: true })
@ -12,6 +13,8 @@ export class AuthLoginDTO {
P_PASSWORD: string;
}
export class AuthLoginOnlyDTO extends IntersectionType(AuthLoginDTO, APPLICATIONNAME_DTO) { }
export enum MailTypeDTO {
REGISTER_CLIENT = "REGISTER_CLIENT",
REGISTER_SP = "REGISTER_SP",

View File

@ -6,9 +6,10 @@ import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { OracleModule } from 'src/oracle/oracle.module';
import { MailModule } from 'src/mail/mail.module';
import { PgModule } from 'src/pg/pg.module';
@Module({
imports: [DbModule,MailModule, forwardRef(() => OracleModule)],
imports: [DbModule,MailModule, forwardRef(() => OracleModule), forwardRef(() => PgModule)],
providers: [
AuthService,
{

View File

@ -11,9 +11,10 @@ import { UnauthorizedException } from 'src/exceptions/unauthorized.exception';
import { ConflictException } from 'src/exceptions/conflict.exception';
import { BadRequestException } from 'src/exceptions/badRequest.exception';
import { JwtService } from '@nestjs/jwt';
import { UserMaintenanceService } from 'src/oracle/user-maintenance/user-maintenance.service';
import { v4 as uuidv4 } from 'uuid';
import { MailService } from 'src/mail/mail.service';
import { UserMaintenanceService as OracleUserMaintenanceService } from 'src/oracle/user-maintenance/user-maintenance.service';
import { UserMaintenanceService as PgUserMaintenanceService } from 'src/pg/user-maintenance/user-maintenance.service';
interface DecodedToken {
@ -44,7 +45,8 @@ export class AuthService {
private readonly oracleDBService: OracleDBService,
private readonly configService: ConfigService,
private readonly mailService: MailService,
private readonly userMaintenanceService: UserMaintenanceService,
private readonly oracleUserMaintenanceService: OracleUserMaintenanceService,
private readonly pgUserMaintenanceService: PgUserMaintenanceService,
@Inject("REGISTER_SIGN_JWT") readonly REGISTER_SIGN_JWT: JwtService,
@Inject("REGISTER_VERIFY_JWT") readonly REGISTER_VERIFY_JWT: JwtService
) {
@ -245,7 +247,7 @@ export class AuthService {
return verified;
}
async loginUser(username: string, password: string, req: Request): Promise<any> {
async loginUser(username: string, password: string, applicationName: string, req: Request, dbtype: number): Promise<any> {
const access_token = req.cookies?.access_token;
const refresh_token = req.cookies?.refresh_token;
@ -260,7 +262,14 @@ export class AuthService {
try {
const userSession = await this.getUserSession(username)
const emailVerifyResponse: any = await this.userMaintenanceService.ValidateEmail({ P_EMAILADDR: username })
let emailVerifyResponse: any;
if (dbtype === 1) {
emailVerifyResponse = await this.oracleUserMaintenanceService.ValidateEmail({ P_EMAILADDR: username })
}
else if (dbtype === 2) {
emailVerifyResponse = await this.pgUserMaintenanceService.ValidateEmail({ P_EMAILADDR: username })
}
if (Array.isArray(emailVerifyResponse) && emailVerifyResponse[0].ERRORMESG) {
throw new BadRequestException();
@ -269,13 +278,23 @@ export class AuthService {
let ROLE = "";
if (Array.isArray(emailVerifyResponse) && !emailVerifyResponse[0].ERRORMESG) {
switch (emailVerifyResponse[0].SOURCE) {
case "USCIB": ROLE = 'ua'; break;
case "SP": ROLE = 'sa'; break;
case "CLIENT": ROLE = 'ca'; break;
switch ((emailVerifyResponse[0].SOURCE + "".toUpperCase())) {
case "USCIB": ROLE = dbtype === 1 ? 'ua' : dbtype === 2 ? 'pua' : ''; break;
case "SP": ROLE = dbtype === 1 ? 'sa' : dbtype === 2 ? 'psa' : ''; break;
case "CLIENT": ROLE = dbtype === 1 ? 'ca' : dbtype === 2 ? 'pca' : ''; break;
}
}
const isValidCombo =
(applicationName === 'policy' && ROLE === (dbtype === 1 ? 'ua' : dbtype === 2 ? 'pua' : null)) ||
(applicationName === 'service-provider' && ROLE === (dbtype === 1 ? 'sa' : dbtype === 2 ? 'psa' : null)) ||
(applicationName === 'client' && ROLE === (dbtype === 1 ? 'ca' : dbtype === 2 ? 'pca' : null));
if (!isValidCombo) {
throw new UnauthorizedException("Authentication failed")
// console.log(!isValidCombo);
}
// if (ROLE === 'ua' && req.headers.origin !== 'https://policy.alphaomegainfosys.com') {
// throw new BadRequestException("Invalid username or password")
// }
@ -286,22 +305,22 @@ export class AuthService {
// throw new BadRequestException("Invalid username or password")
// }
if (access_token && refresh_token && userSession.length > 0) {
// if (access_token && refresh_token && userSession.length > 0) {
const getSub: any = jwt.decode(refresh_token, { complete: true })
// const getSub: any = jwt.decode(refresh_token, { complete: true })
const user: any = await this.getUserDetailsById(getSub?.payload.sub)
// const user: any = await this.getUserDetailsById(getSub?.payload.sub)
if (user.email !== username) {
throw new UnauthorizedException("Authentication failed")
}
// if (user.email !== username) {
// throw new UnauthorizedException("Authentication failed")
// }
let tokens = await this.getTokenFromRefreshToken(req);
const decoded = jwt.decode(access_token, { complete: true });
const email: any = (decoded && typeof decoded === 'object') ? (decoded as any).payload?.email : undefined;
return { ...tokens, email }
// let tokens = await this.getTokenFromRefreshToken(req);
// const decoded = jwt.decode(access_token, { complete: true });
// const email: any = (decoded && typeof decoded === 'object') ? (decoded as any).payload?.email : undefined;
// return { ...tokens, email, ApplicationName: ROLE }
}
// }
const response = await axios.post(this.TOKEN_URL, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@ -311,6 +330,9 @@ export class AuthService {
return k;
} catch (error) {
if (error instanceof BadRequestException || error instanceof UnauthorizedException) {
throw error
}
throw new BadRequestException('Invalid username or password');
}
}
@ -425,7 +447,6 @@ export class AuthService {
}
}
async forgotPassword(body: AuthLoginDTO, req: Request) {
let det = await req['user'];
@ -499,13 +520,21 @@ export class AuthService {
}
}
async registerUser(body: AuthLoginDTO) {
async registerUser(body: AuthLoginDTO, dbtype: number) {
// let det = await req['user'];
// if (det?.email !== body.P_EMAILADDR) {
// throw new BadRequestException();
// }
const emailVerifyResponse: any = await this.userMaintenanceService.ValidateEmail({ P_EMAILADDR: body.P_EMAILADDR })
let emailVerifyResponse: any;
if (dbtype === 1) {
emailVerifyResponse = await this.oracleUserMaintenanceService.ValidateEmail({ P_EMAILADDR: body.P_EMAILADDR })
}
else if (dbtype === 2) {
emailVerifyResponse = await this.pgUserMaintenanceService.ValidateEmail({ P_EMAILADDR: body.P_EMAILADDR })
}
if (Array.isArray(emailVerifyResponse) && emailVerifyResponse[0].ERRORMESG) {
throw new BadRequestException();
@ -555,10 +584,10 @@ export class AuthService {
if (Array.isArray(emailVerifyResponse) && !emailVerifyResponse[0].ERRORMESG) {
switch (emailVerifyResponse[0].SOURCE) {
case "USCIB": ROLE = 'ua'; break;
case "SP": ROLE = 'sa'; break;
case "CLIENT": ROLE = 'ca'; break;
switch ((emailVerifyResponse[0].SOURCE + "".toUpperCase())) {
case "USCIB": ROLE = dbtype === 1 ? 'ua' : dbtype === 2 ? 'pua' : ''; break;
case "SP": ROLE = dbtype === 1 ? 'sa' : dbtype === 2 ? 'psa' : ''; break;
case "CLIENT": ROLE = dbtype === 1 ? 'ca' : dbtype === 2 ? 'pca' : ''; break;
}
}
@ -705,8 +734,6 @@ export class AuthService {
}
}
async getTokenFromRefreshToken(req: Request) {
const refreshToken = req.cookies['refresh_token'];
@ -815,9 +842,29 @@ export class AuthService {
}
}
async getMailTemplate(body: SendMailDTO, token: string, source: string): Promise<MailTemplateDTO | null> {
async getMailTemplate(body: SendMailDTO, token: string, source: string, appDomain: string): Promise<MailTemplateDTO | null> {
switch (body.P_MAIL_TYPE) {
case MailTypeDTO.REGISTER_USCIB:
return {
to: body.P_TO,
subject: `🔐 Register Your Account`,
templateName: 'a',
variables: {
to: body.P_TO,
url: `https://${appDomain.toLowerCase() === "policy" ? "policy" : appDomain.toLowerCase() === "policy-1" ? "policy-1" : appDomain.toLowerCase() === "policy-2" ? "policy-2" : ""}.alphaomegainfosys.com/register`
}
}
case MailTypeDTO.REGISTER_SP:
return {
to: body.P_TO,
subject: `🔐 Register Your Account`,
templateName: 'a',
variables: {
to: body.P_TO,
url: `https://${appDomain.toLowerCase() === "sp" ? "sp" : appDomain.toLowerCase() === "sp-1" ? "sp-1" : appDomain.toLowerCase() === "sp-2" ? "sp-2" : ""}.alphaomegainfosys.com/register`
}
}
case MailTypeDTO.REGISTER_CLIENT:
return {
to: body.P_TO,
@ -825,7 +872,7 @@ export class AuthService {
templateName: 'a',
variables: {
to: body.P_TO,
url: `https://client.alphaomegainfosys.com/register`
url: `https://${appDomain.toLowerCase() === "sp" ? "client" : appDomain.toLowerCase() === "sp-1" ? "client-1" : appDomain.toLowerCase() === "sp-2" ? "client-2" : ""}.alphaomegainfosys.com/register`
}
}
case MailTypeDTO.FORGOT_PASSWORD:
@ -835,9 +882,15 @@ export class AuthService {
templateName: 'b',
variables: {
to: body.P_TO,
url: `${source === 'ua' ? `https://policy.alphaomegainfosys.com/forgot-password/${token}`
: source === 'sa' ? `https://sp.alphaomegainfosys.com/forgot-password/${token}`
: source === 'ca' ? `https://client.alphaomegainfosys.com/forgot-password/${token}` : ''}`
url: `${appDomain.toLowerCase() === 'policy' ? `https://policy.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'policy-1' ? `https://policy-1.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'policy-2' ? `https://policy-2.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'sp' ? `https://sp.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'sp-1' ? `https://sp-1.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'sp-2' ? `https://sp-2.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'client' ? `https://client.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'client-1' ? `https://client-1.alphaomegainfosys.com/forgot-password/${token}`
: appDomain.toLowerCase() === 'client-2' ? `https://client-2.alphaomegainfosys.com/forgot-password/${token}` : ''}`
}
}
default:
@ -845,7 +898,7 @@ export class AuthService {
}
}
async sendMail(body: SendMailDTO) {
async sendMail(body: SendMailDTO, appDomain: string) {
let token: string;
let ROLE: string = "";
let uuid: string | undefined = undefined;
@ -870,7 +923,7 @@ export class AuthService {
token = await this.generateToken({ P_TO: body.P_TO, uuid: uuid })
const mailTemplate: MailTemplateDTO | null = await this.getMailTemplate(body, token, ROLE);
const mailTemplate: MailTemplateDTO | null = await this.getMailTemplate(body, token, ROLE, appDomain);
if (!mailTemplate) {
throw new BadRequestException();

View File

@ -18,3 +18,28 @@ export const getMssqlConfig = (configService: ConfigService) => ({
encrypt: true,
},
});
interface PgConfig {
user: string;
host: string;
database: string;
password: string;
port: number;
max: number;
idleTimeoutMillis: number;
connectionTimeoutMillis: number;
query_timeout: number;
}
export const getPgConfig = (configService: ConfigService): PgConfig => ({
user: configService.get<string>('PG_USER', ''),
host: configService.get<string>('PG_HOST', ''),
database: configService.get<string>('PG_DB', ''),
password: configService.get<string>('PG_PWD', ''), // Password can be optional, e.g., if using environment variables or other auth
port: parseInt(configService.get<string>('PG_PORT', '5432'), 10),
max: parseInt(configService.get<string>('PG_MAX_CLIENTS_IN_POOL', '10'), 10), // Maximum number of clients in the pool
idleTimeoutMillis: parseInt(configService.get<string>('PG_CLIENT_IDLE', '10000'), 10), // How long a client is allowed to remain idle before being closed
connectionTimeoutMillis: parseInt(configService.get<string>('PG_CONNECTION_TIMEOUT', '0'), 10), // How long to try to establish a new connection before throwing an error
query_timeout: parseInt(configService.get<string>('PG_QUERY_TIMEOUT', '5000'), 10), // Add this line, default 5000ms (5 seconds)
});

View File

@ -1,9 +1,9 @@
import { Global, Module } from '@nestjs/common';
import { MssqlDBService, OracleDBService } from './db.service';
import { MssqlDBService, OracleDBService, PgDBService } from './db.service';
@Global()
@Module({
providers: [OracleDBService, MssqlDBService],
exports: [OracleDBService, MssqlDBService],
providers: [OracleDBService, MssqlDBService, PgDBService],
exports: [OracleDBService, MssqlDBService, PgDBService],
})
export class DbModule { }

View File

@ -1,9 +1,10 @@
import { createPool, Pool, Connection } from 'oracledb';
import { ConnectionPool } from 'mssql';
import { Injectable, Logger } from '@nestjs/common';
import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { ConfigService } from '@nestjs/config';
import { getMssqlConfig, getOracleConfig } from './db.config';
import { getMssqlConfig, getOracleConfig, getPgConfig } from './db.config';
import { Pool as pgPool, PoolClient } from 'pg';
@Injectable()
export class OracleDBService {
@ -11,11 +12,13 @@ export class OracleDBService {
private readonly logger = new Logger(OracleDBService.name);
constructor(private readonly configService: ConfigService) {
if (process.env.DB_TYPE === "ORACLE") {
this.initializePool().catch(err => {
this.logger.error('Error initializing Oracle DB pool', err);
throw new InternalServerException();
});
}
}
private async initializePool(): Promise<void> {
try {
@ -62,6 +65,109 @@ export class OracleDBService {
}
}
@Injectable()
export class PgDBService implements OnModuleDestroy {
private pool: pgPool | null = null;
private readonly logger = new Logger(PgDBService.name);
constructor(private readonly configService: ConfigService) {
if (process.env.DB_TYPE === "PG") {
this.initializePool().catch(err => {
this.logger.error('Error initializing PostgreSQL DB pool', err);
throw new InternalServerException('Failed to initialize database pool');
});
} else {
this.logger.warn('PG pool not initialized because DB_FOR is not PG');
}
}
/**
* Initializes the PostgreSQL connection pool.
* This method is called once when the service is instantiated.
* It attempts to create the pool and test a connection to ensure connectivity.
*/
private async initializePool(): Promise<void> {
try {
const config = getPgConfig(this.configService);
this.pool = new pgPool({
user: config.user,
host: config.host,
database: config.database,
password: config.password,
port: config.port,
max: config.max,
idleTimeoutMillis: config.idleTimeoutMillis,
connectionTimeoutMillis: config.connectionTimeoutMillis,
query_timeout: config.query_timeout
});
// Optional: Add an error listener to the pool.
// This listener catches errors on idle clients that might occur due to database restarts
// or network issues, allowing the pool to recover by discarding the faulty client.
this.pool.on('error', (err: Error, client: PoolClient) => {
this.logger.error('Unexpected error on idle PostgreSQL client', err, client);
// In production, you might want more sophisticated error handling,
// but for an idle client error, the pool usually handles replacing it.
});
// Test connection: Acquire and immediately release a client to confirm the pool is functional.
const client = await this.pool.connect();
client.release(); // Release the client back to the pool after successful test
this.logger.log('PostgreSQL connection pool created and tested successfully');
} catch (error) {
this.logger.error('Failed to create PostgreSQL DB pool:', error);
// Re-throw to propagate the error up to the constructor, which will halt startup
throw error;
}
}
/**
* Retrieves a client from the connection pool.
* This method is used by consumers of the service to get a database connection.
*
* IMPORTANT: The caller is responsible for releasing the client back to the pool
* using `client.release()` in a `finally` block to prevent connection leaks.
*
* @returns A promise that resolves to a PoolClient.
* @throws InternalServerException if the pool is not initialized or if
* it fails to acquire a connection within the configured timeout.
*/
async getConnection(): Promise<PoolClient> {
if (!this.pool) {
this.logger.error('Attempted to get a connection before pool was initialized');
throw new InternalServerException('Database connection pool not initialized');
}
try {
// pool.connect() acquires a client from the pool. If no clients are available
// and the pool is at its max, it will wait until one is released or timeout occurs.
const client = await this.pool.connect();
return client;
} catch (error) {
this.logger.error('Failed to get PostgreSQL DB connection from pool:', error);
throw new InternalServerException('Failed to acquire database connection');
}
}
/**
* Closes the PostgreSQL connection pool gracefully.
* This method is part of the NestJS `OnModuleDestroy` lifecycle hook,
* ensuring that the pool is drained and all connections are closed when the application shuts down.
*/
async onModuleDestroy(): Promise<void> {
if (this.pool) {
try {
await this.pool.end(); // Drains the pool of all active and idle clients, then closes them.
this.logger.log('PostgreSQL DB pool closed successfully');
} catch (error) {
this.logger.error('Error closing PostgreSQL DB pool:', error);
// Rethrowing here will not necessarily stop the shutdown, but logs the error.
throw new InternalServerException('Failed to gracefully close database pool');
}
}
}
}
@Injectable()
export class MssqlDBService {
@ -98,4 +204,3 @@ export class MssqlDBService {
}
}
}

View File

@ -39,6 +39,61 @@ export class CARNETNO_DTO {
P_CARNETNO: string;
}
export class ORDERID_DTO {
@ApiProperty({ required: true, type: String, nullable: true })
@IsString()
@IsDefined({ message: 'Property P_ORDERID is required' })
P_ORDERID: string | null;
}
export class PRICE_DTO {
@ApiProperty({ required: true })
// @Max(999999999, {
// message: 'Property P_PRICE must not exceed 999999999',
// })
@Min(0.01, { message: 'Property P_PRICE must be greater than zero' })
// @IsInt({ message: 'Property P_PRICE allows only whole numbers' })
@IsNumber({}, { message: 'Property P_PRICE must be a number' })
@Transform(({ value }) => Number(value))
@IsDefined({ message: 'Property P_PRICE is required' })
P_PRICE: number;
}
export class PAYMENTAMOUNT_DTO {
@ApiProperty({ required: true })
// @Max(999999999, {
// message: 'Property P_PRICE must not exceed 999999999',
// })
@Min(0.01, { message: 'Property P_PAYMENTAMOUNT must be greater than zero' })
// @IsInt({ message: 'Property P_PRICE allows only whole numbers' })
@IsNumber({}, { message: 'Property P_PAYMENTAMOUNT must be a number' })
@Transform(({ value }) => Number(value))
@IsDefined({ message: 'Property P_PAYMENTAMOUNT is required' })
P_PAYMENTAMOUNT: number;
}
export class PAYMENTSTATUS_DTO {
@ApiProperty({ required: true })
@IsString({ message: 'Property P_STATUS must be a string' })
@IsDefined({ message: 'Property P_STATUS is required' })
P_STATUS: string;
}
export class PAYMENTERROR_DTO {
@ApiProperty({ required: true, type: String, nullable: true })
@IsString({ message: 'Property P_PAYMENTERROR must be a string' })
@IsDefined({ message: 'Property P_PAYMENTERROR is required' })
P_PAYMENTERROR: string | null = null;
}
export class DESCRIPTION_DTO {
@ApiProperty({ required: true })
@IsString()
@IsDefined({ message: 'Property P_DESCRIPTION is required' })
P_DESCRIPTION: string;
}
export class HEADERID_DTO {
@ApiProperty({ required: true })
@Max(999999999, {
@ -60,17 +115,17 @@ export class APPLICATIONNAME_DTO {
}
export class GOODS_PORT_DTO {
@ApiProperty({ required: true })
@ApiProperty({ required: true, type: String, nullable: true })
@IsString({ message: 'Property P_GOODSPORT must be a string' })
@IsDefined({ message: 'Property P_GOODSPORT is required' })
P_GOODSPORT: string;
P_GOODSPORT: string | null = null;
}
export class GOODS_COUNTRY_DTO {
@ApiProperty({ required: true })
@ApiProperty({ required: true, type: String, nullable: true })
@IsString({ message: 'Property P_GOODSCOUNTRY must be a string' })
@IsDefined({ message: 'Property P_GOODSCOUNTRY is required' })
P_GOODSCOUNTRY: string;
P_GOODSCOUNTRY: string | null = null;
}
export class REASON_CODE_DTO {
@ -90,7 +145,7 @@ export class EXTENSION_PERIOD_DTO {
@IsNumber({}, { message: 'Property P_EXTENSIONPERIOD must be a number' })
@Transform(({ value }) => Number(value))
@IsDefined({ message: 'Property P_EXTENSIONPERIOD is required' })
P_EXTENSIONPERIOD: number;
P_EXTENSIONPERIOD: number = 0;
}
export class ORDERTYPE_DTO {
@ -323,7 +378,7 @@ export class USSETS_DTO {
@Transform(({ value }) => Number(value))
@IsNumber({}, { message: 'Property P_USSETS must be a number' })
@IsDefined({ message: 'Property P_USSETS is required' })
P_USSETS: number;
P_USSETS: number = 0;
}
export enum VOT {

View File

@ -3,8 +3,11 @@ import { IntersectionType, PartialType } from "@nestjs/swagger";
import {
APPLICATIONNAME_DTO, AUTHREP_DTO, AUTO_FLAG_DTO, CARNETNO_DTO, COMMERCIAL_SAMPLE_FLAG_DTO,
COUNTRYTABLE_DTO, CUSTCOURIERNO_DTO, DELIVERYMETHOD_DTO, DELIVERYTYPE_DTO,
DESCRIPTION_DTO,
EXIBITIONS_FAIR_FLAG_DTO, EXTENSION_PERIOD_DTO, FORMOFSECURITY_DTO, GLTABLE_DTO, GLTABLE_ITEMNO_OPTIONAL_DTO, GOODS_COUNTRY_DTO, GOODS_PORT_DTO, HEADERID_DTO,
HORSE_FLAG_DTO, INSPROTECTION_DTO, ITEMNO_DTO, LDIPROTECTION_DTO, ORDERTYPE_DTO, PAYMENTMETHOD_DTO,
HORSE_FLAG_DTO, INSPROTECTION_DTO, ITEMNO_DTO, LDIPROTECTION_DTO, ORDERID_DTO, ORDERTYPE_DTO, PAYMENTAMOUNT_DTO, PAYMENTERROR_DTO, PAYMENTMETHOD_DTO,
PAYMENTSTATUS_DTO,
PRICE_DTO,
PRINTGL_DTO,
PROF_EQUIPMENT_FLAG_DTO, REASON_CODE_DTO, REFNO_DTO, SHIPADDRID_DTO, SHIPCONTACTID_DTO, SHIPNAME_DTO, SHIPTOTYPE_DTO, USSETS_DTO
} from "./carnet-application-property.dto";
@ -60,14 +63,19 @@ export class SaveExtensionApplicationDTO extends (IntersectionType(
USERID_DTO,
SPID_DTO,
HEADERID_DTO,
GOODS_PORT_DTO,
GOODS_COUNTRY_DTO,
PartialType(GOODS_PORT_DTO),
PartialType(GOODS_COUNTRY_DTO),
REASON_CODE_DTO,
EXTENSION_PERIOD_DTO
PartialType(EXTENSION_PERIOD_DTO)
)) { }
export class PrintCarnetDTO extends (IntersectionType(SPID_DTO, HEADERID_DTO, PRINTGL_DTO)) { }
export class PrintGLDTO extends (IntersectionType(SPID_DTO, HEADERID_DTO)) { }
export class CapturePaymentDTO extends (IntersectionType(ORDERID_DTO, APPLICATIONNAME_DTO, PRICE_DTO, USERID_DTO)) { }
export class InitiatePaymentDTO extends (IntersectionType(APPLICATIONNAME_DTO, PRICE_DTO, DESCRIPTION_DTO, USERID_DTO)) { }
export class GetOrderDetailsDTO extends (IntersectionType(ORDERID_DTO)) { }
export class GetPaymentHistoryDTO extends (IntersectionType(APPLICATIONNAME_DTO, USERID_DTO)) { }
export class SaveHistoryDTO extends (IntersectionType(APPLICATIONNAME_DTO, ORDERID_DTO, PAYMENTAMOUNT_DTO, PAYMENTSTATUS_DTO, USERID_DTO, PartialType(PAYMENTERROR_DTO))) { }
export class CreateApplicationDTO extends IntersectionType(
SPID_DTO, CLIENTID_DTO, LOCATIONID_DTO, USERID_DTO, APPLICATIONNAME_DTO,
@ -97,7 +105,7 @@ export class DeleteGenerallistItemsDTO extends IntersectionType(
) { }
export class AddCountriesDTO extends IntersectionType(
HEADERID_DTO, USSETS_DTO, COUNTRYTABLE_DTO, USERID_DTO
HEADERID_DTO, PartialType(USSETS_DTO), COUNTRYTABLE_DTO, USERID_DTO
) { }
export class UpdateShippingDetailsDTO extends IntersectionType(

View File

@ -60,6 +60,13 @@ export class CLIENTNAME_DTO {
P_CLIENTNAME: string;
}
export class INDUSTRY_TYPE_DTO {
@ApiProperty({ required: true })
@IsString({ message: 'Property P_INDUSTRYTYPE must be a string' })
@IsDefined({ message: 'Property P_INDUSTRYTYPE is required' })
P_INDUSTRYTYPE: string;
}
export class REVENUELOCATION_DTO {
@ApiProperty({ required: true })
@Length(0, 2, {

View File

@ -9,7 +9,7 @@ import {
import {
CLIENT_CONTACTID_DTO, CLIENTID_DTO, CLIENTLOCADDRESSTABLE_DTO, CLIENTLOCATIONID_DTO,
CLIENTNAME_DTO, LOCATIONNAME_DTO, NAMEOF_DTO, PREPARERNAME_DTO, REVENUELOCATION_DTO, STATUS_DTO
CLIENTNAME_DTO, INDUSTRY_TYPE_DTO, LOCATIONNAME_DTO, NAMEOF_DTO, PREPARERNAME_DTO, REVENUELOCATION_DTO, STATUS_DTO
} from "./manage-clients-property.dto";
import {
@ -34,7 +34,8 @@ export class CreateClientDataDTO extends IntersectionType(
PartialType(COUNTRY_DTO),
ISSUING_REGION_DTO,
REVENUELOCATION_DTO,
USERID_DTO
USERID_DTO,
INDUSTRY_TYPE_DTO
) { }
@ -49,7 +50,8 @@ export class UpdateClientDTO extends IntersectionType(
ZIP_DTO,
COUNTRY_DTO,
REVENUELOCATION_DTO,
USERID_DTO
USERID_DTO,
INDUSTRY_TYPE_DTO
) { }
export class UpdateClientContactsDTO extends IntersectionType(

View File

@ -1,5 +1,12 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsNumber, IsString } from "class-validator";
import { IsNumber, IsString, IsOptional } from "class-validator";
export class PCT_VALUE_DTO {
@ApiProperty({ required: true })
@IsString()
P_PCT_VALUE: string;
}
export class EFFDATE_DTO {
@ApiProperty({ required: true })
@ -14,15 +21,17 @@ export class FEES_DTO {
}
export class SPCLCOMMODITY_DTO {
@ApiProperty({ required: true })
@IsString()
P_SPCLCOMMODITY: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString({ message: 'Property P_SPCLCOMMODITY must be a string' })
P_SPCLCOMMODITY?: string | null;
}
export class SPCLCOUNTRY_DTO {
@ApiProperty({ required: true })
@IsString()
P_SPCLCOUNTRY: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString({ message: 'Property P_SPCLCOUNTRY must be a string' })
P_SPCLCOUNTRY?: string | null;
}
export class RATE_DTO {

View File

@ -6,7 +6,7 @@ import { HOLDERTYPE_DTO, USCIBMEMBERFLAG_DTO } from "../manage-holders/manage-ho
import {
BASICFEESETUPID_DTO, BONDRATESETUPID_DTO, CARGORATESETUPID_DTO, CFFEESETUPID_DTO,
COMMRATE_DTO, CSFEESETUPID_DTO, CUSTOMERTYPE_DTO, EFFDATE_DTO, EFFEESETUPID_DTO, ENDSETS_DTO,
ENDTIME_DTO, FEECOMMID_DTO, FEES_DTO, RATE_DTO, SPCLCOMMODITY_DTO, SPCLCOUNTRY_DTO,
ENDTIME_DTO, FEECOMMID_DTO, FEES_DTO, PCT_VALUE_DTO, RATE_DTO, SPCLCOMMODITY_DTO, SPCLCOUNTRY_DTO,
STARTSETS_DTO, STARTTIME_DTO, TIMEZONE_DTO
} from "./manage-fee-property.dto";
@ -36,7 +36,8 @@ export class CreateBondRateDTO extends IntersectionType(
SPCLCOUNTRY_DTO,
EFFDATE_DTO,
RATE_DTO,
USERID_DTO
USERID_DTO,
PCT_VALUE_DTO
) { }
export class CreateCargoRateDTO extends IntersectionType(
@ -100,7 +101,8 @@ export class UpdateBondRateDTO extends IntersectionType(
BONDRATESETUPID_DTO,
RATE_DTO,
EFFDATE_DTO,
USERID_DTO
USERID_DTO,
PCT_VALUE_DTO
) { }
export class UpdateCargoRateDTO extends IntersectionType(

View File

@ -18,11 +18,9 @@ export class GOVAGENCYFLAG_DTO {
}
export class USCIBMEMBERFLAG_DTO {
@ApiProperty({ required: true })
@Length(0, 1, { message: 'Property P_USCIBMEMBERFLAG must be between 0 to 1 character' })
@ApiProperty({ required: false })
@IsString({ message: 'Property P_USCIBMEMBERFLAG must be a string' })
@IsDefined({ message: 'Property P_USCIBMEMBERFLAG is required' })
P_USCIBMEMBERFLAG: string;
P_USCIBMEMBERFLAG: string | null;
}
export class LOCATIONID_DTO {
@ -58,11 +56,9 @@ export class HOLDERNO_DTO {
}
export class HOLDERTYPE_DTO {
@ApiProperty({ required: true })
@Length(0, 4, { message: 'Property P_HOLDERTYPE must be between 0 to 6 characters' })
@ApiProperty({ required: false })
@IsString({ message: 'Property P_HOLDERTYPE must be a string' })
@IsDefined({ message: 'Property P_HOLDERTYPE is required' })
P_HOLDERTYPE: string;
P_HOLDERTYPE: string | null;
}
export class HOLDERNAME_DTO {
@ -95,12 +91,14 @@ export class CONTACTSTABLE_ROW_DTO extends IntersectionType(
FIRSTNAME_DTO,
LASTNAME_DTO,
PartialType(MIDDLE_INITIAL_DTO),
PartialType(TITLE_DTO),
TITLE_DTO,
EMAIL_ADDRESS_DTO,
PHONE_NO_DTO,
MOBILE_NO_DTO,
PartialType(FAX_NO_DTO)
) { }
) {
FAX_NO: null;
}
export class CONTACTSTABLE_DTO {
@ApiProperty({ required: true, type: () => [CONTACTSTABLE_ROW_DTO] })

View File

@ -1,7 +1,7 @@
import { IntersectionType } from '@nestjs/swagger';
import { REGION_CODE_DTO, REGIONID_DTO } from './region-property.dto';
import { NAME_DTO } from '../../property.dto';
import { NAME_DTO, SPID_DTO } from '../../property.dto';
export class InsertRegionsDto extends IntersectionType(REGION_CODE_DTO, NAME_DTO) { }
export class InsertRegionsDto extends IntersectionType(REGION_CODE_DTO, NAME_DTO, SPID_DTO) { }
export class UpdateRegionDto extends IntersectionType(REGIONID_DTO, NAME_DTO) { }

View File

@ -40,7 +40,7 @@ export class LASTNAME_DTO {
}
export class MIDDLE_INITIAL_DTO {
@ApiProperty({ required: true })
@ApiProperty({ required: false })
@Length(0, 3, { message: 'Property P_MIDDLEINITIAL must be between 0 to 3 characters' })
@IsString({ message: 'Property P_MIDDLEINITIAL must be a string' })
P_MIDDLEINITIAL: string;
@ -70,7 +70,7 @@ export class MOBILE_NO_DTO {
}
export class FAX_NO_DTO {
@ApiProperty({ required: true })
@ApiProperty({ required: false })
@Length(0, 20, { message: 'Property FAXNO must be between 0 to 20 characters' })
@IsString({ message: 'Property FAXNO must be a string' })
P_FAXNO: string;

View File

@ -0,0 +1,19 @@
import { HttpException, HttpStatus } from '@nestjs/common';
export class NotFoundException extends HttpException {
constructor(
message = 'Not Found',
// errorCode = 'INTERNAL_ERROR',
// data: any = null,
) {
super(
{
statusCode: HttpStatus.NOT_FOUND ,
message,
// errorCode,
// data,
},
HttpStatus.NOT_FOUND,
);
}
}

View File

@ -37,7 +37,7 @@ export class RolesGuard implements CanActivate {
try {
const decoded: any = jwt.decode(token);
const roles: string[] = decoded?.resource_access?.['carnet-app']?.roles || [];
const roles: string[] = decoded?.resource_access?.[process.env.CLIENT_ID || '']?.roles || [];
const hasRole = requiredRoles.some(role => roles.includes(role));
if (!hasRole) {
@ -46,7 +46,7 @@ export class RolesGuard implements CanActivate {
return true;
} catch (err: any) {
throw new UnauthorizedException('Authentication Failed');
throw new UnauthorizedException('Unauthorized : Please Request Access for this Resource');
}
}
}

View File

@ -20,7 +20,12 @@ async function bootstrap() {
'http://localhost:5173',
'https://policy.alphaomegainfosys.com',
'https://sp.alphaomegainfosys.com',
'https://client.alphaomegainfosys.com'
'https://policy-2.alphaomegainfosys.com',
'https://client-2.alphaomegainfosys.com',
'https://sp-2.alphaomegainfosys.com',
'https://policy-1.alphaomegainfosys.com',
'https://client-1.alphaomegainfosys.com',
'https://sp-1.alphaomegainfosys.com',
],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
preflightContinue: false,
@ -77,20 +82,43 @@ async function bootstrap() {
);
// app.useGlobalPipes(new ValidationPipe({ exceptionFactory:customExceptionFactory, whitelist: true, forbidNonWhitelisted: true, transform: true }));
const config = new DocumentBuilder()
.setTitle('API')
.setDescription('API description')
.setVersion('1.0')
.addServer(
'https://dev.alphaomegainfosys.com/test-api',
`https://dev.alphaomegainfosys.com/${process.env.DB_TYPE === "ORACLE" ? "test-api-1" : process.env.DB_TYPE === "PG" ? "test-api-2" : "test-api"}`,
'Development Server 2',
)
.addServer('http://localhost:3000', 'Development Server 1')
.build();
const options: SwaggerDocumentOptions = { autoTagControllers: false };
const documentFactory = () => SwaggerModule.createDocument(app, config, options);
SwaggerModule.setup('api', app, documentFactory);
// const documentFactory = () => SwaggerModule.createDocument(app, config, options);
// SwaggerModule.setup('api', app, documentFactory);
const document = SwaggerModule.createDocument(app, config, options);
// 2. Remove all paths starting with /1 or exactly /1 if not PG
if (process.env.DB_TYPE === 'PG') {
for (const path of Object.keys(document.paths)) {
if (path === '/1' || path.startsWith('/1/')) {
delete document.paths[path];
}
}
}
if (process.env.DB_TYPE === 'ORACLE') {
for (const path of Object.keys(document.paths)) {
if (path === '/2' || path.startsWith('/2/')) {
delete document.paths[path];
}
}
}
// 3. Setup Swagger with the modified document
SwaggerModule.setup('api', app, document);
app.use('/api-json', (req, res) => {
res.setHeader('Content-Type', 'application/json');

View File

@ -7,7 +7,8 @@ import {
AddCountriesDTO,
AddGenerallistItemsDTO,
CA_UpdateHolderDTO,
CarnetProcessingCenterDTO, CarnetProcessingCenterDTO2, CopyCarnetDTO, CreateApplicationDTO, DeleteGenerallistItemsDTO, EditGenerallistItemsDTO, GetCarnetControlCenterDTO, GetExtendedSectionDTO, PrintCarnetDTO, PrintGLDTO, SaveCarnetApplicationDTO, SaveExtensionApplicationDTO, TransmitApplicationtoProcessDTO,
CapturePaymentDTO,
CarnetProcessingCenterDTO, CarnetProcessingCenterDTO2, CopyCarnetDTO, CreateApplicationDTO, DeleteGenerallistItemsDTO, EditGenerallistItemsDTO, GetCarnetControlCenterDTO, GetExtendedSectionDTO, GetOrderDetailsDTO, GetPaymentHistoryDTO, InitiatePaymentDTO, PrintCarnetDTO, PrintGLDTO, SaveCarnetApplicationDTO, SaveExtensionApplicationDTO, SaveHistoryDTO, TransmitApplicationtoProcessDTO,
UpdateExpGoodsAuthRepDTO,
UpdateShippingDetailsDTO
} from 'src/dto/property.dto';
@ -25,7 +26,7 @@ import { InternalServerException } from 'src/exceptions/internalServerError.exce
@ApiTags('Carnet Application - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ca', 'sa')
@Controller('oracle')
@Controller('1')
export class CarnetApplicationController {
constructor(private readonly carnetApplicationService: CarnetApplicationService) { }
@ -271,4 +272,33 @@ export class CarnetApplicationController {
}
}
//[payment]
@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);
}
// @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);
}
@Post('SaveHistory')
@HttpCode(200)
async SaveHistory(@Body() body: SaveHistoryDTO) {
return this.carnetApplicationService.SaveHistory(body);
}
}

View File

@ -20,10 +20,18 @@ import {
CopyCarnetDTO,
GetExtendedSectionDTO,
SaveExtensionApplicationDTO,
CarnetProcessingCenterDTO2
CarnetProcessingCenterDTO2,
CapturePaymentDTO,
InitiatePaymentDTO,
GetOrderDetailsDTO,
GetPaymentHistoryDTO,
SaveHistoryDTO
} from 'src/dto/property.dto';
import { OracleService } from '../oracle.service';
import { BadRequestException } from 'src/exceptions/badRequest.exception';
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
import { PaypalService } from 'src/paypal/paypal.service';
import { NotFoundException } from 'src/exceptions/notFound.exception';
@Injectable()
export class CarnetApplicationService {
@ -32,7 +40,8 @@ export class CarnetApplicationService {
constructor(
private readonly oracleDBService: OracleDBService,
private readonly oracleService: OracleService
private readonly oracleService: OracleService,
private readonly payPalService: PaypalService
) { }
// [ CARNETAPPLICATION_PKG ]
@ -960,7 +969,7 @@ export class CarnetApplicationService {
}
// return { statusCode: 200, message: "Extended successfully", ...fres[0] };
return fres;
return fres.length > 0 ? fres[0] : [];
} catch (error) {
handleError(error, CarnetApplicationService.name)
} finally {
@ -1582,4 +1591,376 @@ export class CarnetApplicationService {
}
}
// [payment]
async formatAmount(amount) {
if (typeof amount !== 'number' || isNaN(amount)) {
throw new Error('Amount must be a valid number');
}
if (amount < 0) {
throw new BadRequestException('Amount must be non-negative');
}
return amount.toFixed(2); // Always returns a string with 2 decimal places
}
async InitiatePayment(body: InitiatePaymentDTO) {
// console.log(body);
const quantity = 1;
let orderID: string | null = null
const formattedAmount = await this.formatAmount(body.P_PRICE * quantity);
try {
const accessToken = await this.payPalService.generateAccessToken();
// return {
// id: "6CU709471L678832M",
// href: "https://www.sandbox.paypal.com/checkoutnow?token=6CU709471L678832M"
// }
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"
}
})
});
orderID = response?.data?.id;
// console.log('PayPal create order response headers:', response.headers);
// console.log('PayPal create order response data:', response.data);
const save_result = 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
// "P_PAYMENTERROR": {}
}
);
if (save_result.statusCode === 200) {
return {
id: response?.data?.id, href: response?.data?.links?.find(obj => obj.rel === 'approve')?.href
};
}
else {
throw new InternalServerException();
}
// return { id: response.data.id };
} 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 connection;
try {
connection = await this.oracleDBService.getConnection();
const result = await connection.execute(
`BEGIN
Pay_GetPaymentHistory(
:P_APPLICATIONNAME, :P_USERID, :P_CURSOR
);
END;`,
{
P_APPLICATIONNAME: { val: body.P_APPLICATIONNAME, type: oracledb.DB_TYPE_NVARCHAR },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR },
// 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.");
}
const fres: any = await fetchCursor(outBinds.P_CURSOR, CarnetApplicationService.name);
if (fres.length > 0 && fres[0].ERRORMESG) {
this.logger.warn(fres[0].ERRORMESG);
throw new BadRequestException(fres[0].ERRORMESG)
}
return fres.length > 0 ? fres[0] : {}
} catch (error) {
handleError(error, CarnetApplicationService.name)
} finally {
await closeOracleDbConnection(connection, CarnetApplicationService.name)
}
}
async SaveHistory(body: SaveHistoryDTO) {
let connection;
try {
connection = await this.oracleDBService.getConnection();
const result = await connection.execute(
`BEGIN
Pay_SaveHistory(
:P_APPLICATIONNAME, :P_ORDERID, :P_PAYMENTAMOUNT, :P_STATUS, :P_USERID, :P_PAYMENTERROR, :P_CURSOR
);
END;`,
{
P_APPLICATIONNAME: { val: body.P_APPLICATIONNAME, type: oracledb.DB_TYPE_NVARCHAR },
P_ORDERID: { val: body.P_ORDERID, type: oracledb.DB_TYPE_NVARCHAR },
P_PAYMENTAMOUNT: { val: body.P_PAYMENTAMOUNT, type: oracledb.DB_TYPE_NUMBER },
P_STATUS: { val: body.P_STATUS, type: oracledb.DB_TYPE_NVARCHAR },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_PAYMENTERROR: { val: body.P_PAYMENTERROR, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR },
// 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.");
}
const fres: any = await fetchCursor(outBinds.P_CURSOR, CarnetApplicationService.name);
if (fres.length > 0 && fres[0].ERRORMESG) {
this.logger.warn(fres[0].ERRORMESG);
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 200, message: "Saved Successfully", ...fres[0] };
} catch (error) {
handleError(error, CarnetApplicationService.name)
} finally {
await closeOracleDbConnection(connection, CarnetApplicationService.name)
}
}
}

View File

@ -20,11 +20,12 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('HomePage - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ca', 'sa', 'ua')
@Controller('oracle')
@Controller('1')
export class HomePageController {
constructor(private readonly homePageService: HomePageService) { }
// NOT USED
@Get('GetHomePageData/:P_SPID')
GetHomePageData(@Param() params: SPID_DTO) {
return this.homePageService.GetHomePageData(params);

View File

@ -18,6 +18,7 @@ export class HomePageService {
constructor(private readonly oracleDBService: OracleDBService) { }
// NOT USED
async GetHomePageData(params: SPID_DTO) {
let connection;

View File

@ -17,7 +17,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Manage Clients - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa')
@Controller('oracle')
@Controller('1')
export class ManageClientsController {
constructor(private readonly manageClientsService: ManageClientsService) { }

View File

@ -39,6 +39,7 @@ export class ManageClientsService {
P_ISSUINGREGION: null,
P_REVENUELOCATION: null,
P_USERID: null,
P_INDUSTRYTYPE: null
};
const reqBody = JSON.parse(JSON.stringify(body));
@ -58,6 +59,7 @@ export class ManageClientsService {
: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_INDUSTRYTYPE,
:P_CLIENTCURSOR
);
END;`,
@ -74,6 +76,7 @@ export class ManageClientsService {
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_INDUSTRYTYPE: { val: finalBody.P_INDUSTRYTYPE, type: oracledb.DB_TYPE_NVARCHAR },
P_CLIENTCURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{
@ -118,6 +121,7 @@ export class ManageClientsService {
P_COUNTRY: null,
P_REVENUELOCATION: null,
P_USERID: null,
P_INDUSTRYTYPE: null
};
const reqBody = JSON.parse(JSON.stringify(body));
@ -135,7 +139,8 @@ export class ManageClientsService {
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
:P_COUNTRY, :P_REVENUELOCATION, :P_USERID, :P_INDUSTRYTYPE,
:P_CURSOR
);
END;`,
{
@ -150,6 +155,7 @@ export class ManageClientsService {
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_INDUSTRYTYPE: { val: finalBody.P_INDUSTRYTYPE, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{

View File

@ -14,7 +14,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Manage Fee - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa','ua')
@Controller('oracle')
@Controller('1')
export class ManageFeeController {
constructor(private readonly manageFeeService: ManageFeeService) { }

View File

@ -195,6 +195,7 @@ export class ManageFeeService {
MANAGEFEE_SETUP_PKG.CREATEBONDRATE(
:P_SPID, :P_HOLDERTYPE, :P_USCIBMEMBERFLAG, :P_SPCLCOMMODITY,
:P_SPCLCOUNTRY, :P_EFFDATE, :P_RATE, :P_USERID,
:P_PCT_VALUE,
:P_CURSOR
);
END;`,
@ -202,11 +203,12 @@ export class ManageFeeService {
P_SPID: { val: body.P_SPID, type: oracledb.DB_TYPE_NUMBER },
P_HOLDERTYPE: { val: body.P_HOLDERTYPE, type: oracledb.DB_TYPE_VARCHAR },
P_USCIBMEMBERFLAG: { val: body.P_USCIBMEMBERFLAG, type: oracledb.DB_TYPE_VARCHAR },
P_SPCLCOMMODITY: { val: body.P_SPCLCOMMODITY, type: oracledb.DB_TYPE_VARCHAR },
P_SPCLCOUNTRY: { val: body.P_SPCLCOUNTRY, type: oracledb.DB_TYPE_VARCHAR },
P_SPCLCOMMODITY: { val: body.P_SPCLCOMMODITY ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_SPCLCOUNTRY: { val: body.P_SPCLCOUNTRY ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_EFFDATE: { val: body.P_EFFDATE, type: oracledb.DB_TYPE_VARCHAR },
P_RATE: { val: body.P_RATE, type: oracledb.DB_TYPE_NUMBER },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_VARCHAR },
P_PCT_VALUE: { val: body.P_PCT_VALUE, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{
@ -238,7 +240,7 @@ export class ManageFeeService {
const result = await connection.execute(
`BEGIN
MANAGEFEE_SETUP_PKG.UPDATEBONDRATE(
:P_BONDRATESETUPID, :P_RATE, :P_EFFDATE, :P_USERID,
:P_BONDRATESETUPID, :P_RATE, :P_EFFDATE, :P_USERID, :P_PCT_VALUE,
:P_CURSOR
);
END;`,
@ -247,6 +249,7 @@ export class ManageFeeService {
P_RATE: { val: body.P_RATE, type: oracledb.DB_TYPE_NUMBER },
P_EFFDATE: { val: body.P_EFFDATE, type: oracledb.DB_TYPE_NVARCHAR },
P_USERID: { val: body.P_USERID, type: oracledb.DB_TYPE_NVARCHAR },
P_PCT_VALUE: { val: body.P_PCT_VALUE, type: oracledb.DB_TYPE_NVARCHAR },
P_CURSOR: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{

View File

@ -26,7 +26,7 @@ import { BadRequestException } from 'src/exceptions/badRequest.exception';
@ApiTags('Manage Holders - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ca', 'sa')
@Controller('oracle')
@Controller('1')
export class ManageHoldersController {
constructor(private readonly manageHoldersService: ManageHoldersService) { }

View File

@ -10,11 +10,13 @@ import { UserMaintenanceModule } from './user-maintenance/user-maintenance.modul
import { CarnetApplicationModule } from './carnet-application/carnet-application.module';
import { OracleService } from './oracle.service';
import { AuthModule } from 'src/auth/auth.module';
import { PaypalModule } from 'src/paypal/paypal.module';
@Global()
@Module({
imports: [
DbModule,
PaypalModule,
CarnetApplicationModule,
UserMaintenanceModule,
HomePageModule,

View File

@ -13,7 +13,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Param Table - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa', 'ua')
@Controller('oracle')
@Controller('1')
export class ParamTableController {
constructor(private readonly paramTableService: ParamTableService) { }

View File

@ -175,7 +175,7 @@ export class ParamTableService {
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 201, message: "Createdted Successfully", ...fres[0] };
return { statusCode: 201, message: "Created Successfully", ...fres[0] };
} catch (error) {
handleError(error, ParamTableService.name)
@ -230,7 +230,7 @@ export class ParamTableService {
throw new BadRequestException(fres[0].ERRORMESG)
}
return { statusCode: 201, message: "Createdted Successfully", ...fres[0] };
return { statusCode: 201, message: "Created Successfully", ...fres[0] };
} catch (error) {
handleError(error, ParamTableService.name)

View File

@ -10,7 +10,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Carnet Sequence - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa', 'ua')
@Controller('oracle')
@Controller('1')
export class CarnetSequenceController {
constructor(private readonly carnetSequenceService: CarnetSequenceService) { }

View File

@ -1,18 +1,18 @@
import { RegionService } from './region.service';
import { Get, Post, Body, Controller, Patch, UseGuards } from '@nestjs/common';
import { Get, Post, Body, Controller, Patch, UseGuards, Param } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Roles } from 'src/decorators/roles.decorator';
import { InsertRegionsDto, UpdateRegionDto } from 'src/dto/property.dto';
import { InsertRegionsDto, SPID_DTO, UpdateRegionDto } from 'src/dto/property.dto';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Regions - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa', 'ua')
@Controller('oracle')
@Controller('1')
export class RegionController {
constructor(private readonly regionService: RegionService) { }
@ -26,9 +26,9 @@ export class RegionController {
return this.regionService.updateRegions(body);
}
@Get('/GetRegions')
getRegions() {
return this.regionService.getRegions();
@Get('/GetRegions/:P_SPID')
getRegions(@Param() param: SPID_DTO) {
return this.regionService.getRegions(param);
}
}

View File

@ -5,7 +5,7 @@ import { BadRequestException } from 'src/exceptions/badRequest.exception';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { closeOracleDbConnection, fetchCursor, handleError } from 'src/utils/helper';
import { InsertRegionsDto, UpdateRegionDto } from 'src/dto/property.dto';
import { InsertRegionsDto, SPID_DTO, UpdateRegionDto } from 'src/dto/property.dto';
@Injectable()
export class RegionService {
@ -21,11 +21,12 @@ export class RegionService {
const result = await connection.execute(
`BEGIN
USCIB_Managed_Pkg.InsertNewRegion(:P_REGION,:P_NAME,:P_CURSOR);
USCIB_Managed_Pkg.InsertNewRegion(:P_REGION, :P_NAME, :P_SPID, :P_CURSOR);
END;`,
{
P_REGION: { val: body.P_REGION, type: oracledb.DB_TYPE_VARCHAR },
P_NAME: { val: body.P_NAME, type: oracledb.DB_TYPE_VARCHAR },
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 }
@ -95,16 +96,17 @@ export class RegionService {
}
}
async getRegions() {
async getRegions(body: SPID_DTO) {
let connection;
try {
connection = await this.oracleDBService.getConnection();
const result = await connection.execute(
`BEGIN
USCIB_Managed_Pkg.GetRegions(:P_CURSOR);
USCIB_Managed_Pkg.GetRegions(: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 }

View File

@ -14,7 +14,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('SPContacts - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa', 'ua')
@Controller('oracle')
@Controller('1')
export class SpContactsController {
constructor(private readonly spContactsService: SpContactsService) { }

View File

@ -13,7 +13,7 @@ import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('SP - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('sa', 'ua')
@Controller('oracle')
@Controller('1')
export class SpController {
constructor(private readonly spService: SpService) { }

View File

@ -59,16 +59,16 @@ export class SpService {
P_NAME: { val: finalBody.P_NAME, type: oracledb.DB_TYPE_VARCHAR },
P_LOOKUPCODE: { val: finalBody.P_LOOKUPCODE, type: oracledb.DB_TYPE_VARCHAR },
P_ADDRESS1: { val: finalBody.P_ADDRESS1, type: oracledb.DB_TYPE_VARCHAR },
P_ADDRESS2: { val: finalBody.P_ADDRESS2, type: oracledb.DB_TYPE_VARCHAR },
P_ADDRESS2: { val: finalBody.P_ADDRESS2 ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_CITY: { val: finalBody.P_CITY, type: oracledb.DB_TYPE_VARCHAR },
P_STATE: { val: finalBody.P_STATE, type: oracledb.DB_TYPE_VARCHAR },
P_ZIP: { val: finalBody.P_ZIP, type: oracledb.DB_TYPE_VARCHAR },
P_COUNTRY: { val: finalBody.P_COUNTRY, type: oracledb.DB_TYPE_VARCHAR },
P_ISSUINGREGION: { val: finalBody.P_ISSUINGREGION, type: oracledb.DB_TYPE_VARCHAR },
P_REPLACEMENTREGION: { val: finalBody.P_REPLACEMENTREGION, type: oracledb.DB_TYPE_VARCHAR },
P_BONDSURETY: { val: finalBody.P_BONDSURETY, type: oracledb.DB_TYPE_VARCHAR },
P_CARGOPOLICYNO: { val: finalBody.P_CARGOPOLICYNO, type: oracledb.DB_TYPE_VARCHAR },
P_CARGOSURETY: { val: finalBody.P_CARGOSURETY, type: oracledb.DB_TYPE_VARCHAR },
P_BONDSURETY: { val: finalBody.P_BONDSURETY ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_CARGOPOLICYNO: { val: finalBody.P_CARGOPOLICYNO ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_CARGOSURETY: { val: finalBody.P_CARGOSURETY ?? "", type: oracledb.DB_TYPE_VARCHAR },
P_USER_ID: { val: finalBody.P_USER_ID, type: oracledb.DB_TYPE_VARCHAR },
P_NOTES: { val: finalBody.P_NOTES, type: oracledb.DB_TYPE_VARCHAR },
P_FILEIDS: { val: finalBody.P_FILEIDS, type: oracledb.DB_TYPE_VARCHAR },

View File

@ -1,4 +1,4 @@
import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Patch, Post, Query, Req, UseGuards } from '@nestjs/common';
import { UserMaintenanceService } from './user-maintenance.service';
import { ApiTags } from '@nestjs/swagger';
@ -10,11 +10,12 @@ import {
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { Request } from 'express';
@ApiTags('User Maintenance - Oracle')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ca', 'sa', 'ua')
@Controller('oracle')
@Controller('1')
export class UserMaintenanceController {
constructor(private readonly userMaintenanceService: UserMaintenanceService) { }
@ -53,7 +54,7 @@ export class UserMaintenanceController {
}
@Post('CreateSPLogins')
@Roles('sa')
@Roles('sa','ua')
async CreateSPLogins(@Body() body: CreateSPLoginsDTO) {
return await this.userMaintenanceService.CreateSPLogins(body);
}
@ -74,8 +75,8 @@ export class UserMaintenanceController {
@Post('CreateClientLogins')
@Roles('sa')
async CreateClientLogins(@Body() body: CreateClientLoginsDTO) {
return await this.userMaintenanceService.CreateClientLogins(body);
async CreateClientLogins(@Body() body: CreateClientLoginsDTO, @Req() req: Request) {
return await this.userMaintenanceService.CreateClientLogins(body, req);
}
// validate email

View File

@ -7,6 +7,6 @@ import { AuthModule } from 'src/auth/auth.module';
imports: [forwardRef(() => AuthModule)],
controllers: [UserMaintenanceController],
providers: [UserMaintenanceService],
exports: [UserMaintenanceService, AuthModule]
exports: [UserMaintenanceService]
})
export class UserMaintenanceModule { }

View File

@ -2,7 +2,7 @@ import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
import { OracleDBService } from 'src/db/db.service';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import * as oracledb from 'oracledb';
import { closeOracleDbConnection, fetchCursor, handleError } from 'src/utils/helper';
import { closeOracleDbConnection, extractSubdomain, fetchCursor, handleError } from 'src/utils/helper';
import {
SPID_DTO,
@ -12,6 +12,7 @@ import {
import { BadRequestException } from 'src/exceptions/badRequest.exception';
import { AuthService } from 'src/auth/auth.service';
import { MailTypeDTO } from 'src/auth/auth.dto';
import { Request } from 'express';
interface RoleDetail { [key: string]: any; }
@ -356,7 +357,7 @@ export class UserMaintenanceService {
}
async CreateClientLogins(body: CreateClientLoginsDTO) {
async CreateClientLogins(body: CreateClientLoginsDTO, req: Request) {
let connection;
try {
connection = await this.oracleDBService.getConnection();
@ -392,10 +393,18 @@ export class UserMaintenanceService {
throw new BadRequestException(fres[0].ERRORMESG)
}
const mailRes = await this.authService.sendMail({ P_TO: body.P_USERID, P_MAIL_TYPE: MailTypeDTO.REGISTER_CLIENT })
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
const mailRes = await this.authService.sendMail({ P_TO: body.P_USERID, P_MAIL_TYPE: MailTypeDTO.REGISTER_CLIENT }, appDomain)
if (mailRes.statusCode !== 200) {
return new InternalServerException();
throw new InternalServerException();
}
return { statusCode: 201, message: "Client registration initiated successfully", ...fres[0] };

View File

@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';
@Controller('paypal')
export class PaypalController {}

View File

@ -0,0 +1,10 @@
import { Global, Module } from '@nestjs/common';
import { PaypalController } from './paypal.controller';
import { PaypalService } from './paypal.service';
@Global()
@Module({
providers: [PaypalService],
exports: [PaypalService]
})
export class PaypalModule { }

View File

@ -0,0 +1,69 @@
// paypal.service.ts
import { Injectable, Logger } from '@nestjs/common';
import axios from 'axios';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
@Injectable()
export class PaypalService {
private accessToken: string | null = null;
private tokenExpiresAt: number = 0; // Unix timestamp in milliseconds
private readonly clientId = process.env.PAYPAL_CLIENT_ID;
private readonly clientSecret = process.env.PAYPAL_CLIENT_SECRET;
private readonly baseUrl = process.env.PAYPAL_BASE_URL; // or live URL
private readonly logger = new Logger(PaypalService.name);
async generateAccessToken(): Promise<any> {
// return process.env.PAYPAL_AT
const now = Date.now();
// Check if token is still valid
if (this.accessToken && now < this.tokenExpiresAt - 60_000) {
return this.accessToken;
}
// Fetch new token
const auth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64');
try {
const tokenUrl = process.env.PAYPAL_BASE_URL + '/v1/oauth2/token';
const params = new URLSearchParams();
params.append('grant_type', 'client_credentials');
const response = await axios.post(
tokenUrl,
params.toString(), // or use `params` directly
{
auth: {
username: process.env.PAYPAL_CLIENT_ID!,
password: process.env.PAYPAL_SECRET!,
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
);
const { access_token, expires_in } = response.data;
this.accessToken = access_token;
this.tokenExpiresAt = now + expires_in * 1000; // convert seconds to ms
// this.logger.warn(`Fetched new PayPal access token, expires in ${access_token} seconds`);
// console.log(access_token);
if (this.accessToken) {
return this.accessToken;
}
throw new InternalServerException("Error while getting paypal access token")
} catch (error) {
this.logger.error('Failed to fetch PayPal access token', error);
throw new InternalServerException('PayPal token fetch failed');
}
}
}

View File

@ -0,0 +1,308 @@
import { Body, Controller, Delete, Get, HttpCode, Param, Patch, Post, Put, Res, StreamableFile, UseGuards } from '@nestjs/common';
import { CarnetApplicationService } from './carnet-application.service';
import {
AddCountriesDTO,
AddGenerallistItemsDTO,
CA_UpdateHolderDTO,
CapturePaymentDTO,
CarnetProcessingCenterDTO, CarnetProcessingCenterDTO2, CopyCarnetDTO, CreateApplicationDTO, DeleteGenerallistItemsDTO, EditGenerallistItemsDTO, GetCarnetControlCenterDTO, GetCarnetDetailsbyCarnetStatusDTO, GetExtendedSectionDTO, GetOrderDetailsDTO, GetPaymentHistoryDTO, InitiatePaymentDTO, PrintCarnetDTO, PrintGLDTO, SaveCarnetApplicationDTO, SaveExtensionApplicationDTO, SaveHistoryDTO, TransmitApplicationtoProcessDTO,
UpdateExpGoodsAuthRepDTO,
UpdateShippingDetailsDTO
} from 'src/dto/property.dto';
import { Roles } from 'src/decorators/roles.decorator';
import { deleteFilesAsync, generateFinalPDF, replaceSlashWithDash } from 'src/utils/helper';
import { Response } from 'express';
import { join } from 'path';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { BadRequestException } from 'src/exceptions/badRequest.exception';
import { createReadStream } from 'fs';
import { BadRequestException as BR } from 'src/exceptions/badRequest.exception';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { ApiExcludeController, ApiTags } from '@nestjs/swagger';
@ApiTags('Carnet Application - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('pca', 'psa')
@Controller('2')
export class CarnetApplicationController {
constructor(private readonly carnetApplicationService: CarnetApplicationService) { }
// [ CARNETAPPLICATION_PKG ]
// not used
// @Post('SaveCarnetApplication')
// async CreateClientData(@Body() body: SaveCarnetApplicationDTO) {
// return this.carnetApplicationService.SaveCarnetApplication(body);
// }
@Post('TransmitApplicationtoProcess')
@Roles('pca')
TransmitApplicationtoProcess(@Body() body: TransmitApplicationtoProcessDTO) {
return this.carnetApplicationService.TransmitApplicationtoProcess(body);
}
@Post('CreateApplication')
@Roles('pca')
CreateApplication(@Body() body: CreateApplicationDTO) {
return this.carnetApplicationService.CreateApplication(body);
}
@Patch('update-holder')
UpdateHolder(@Body() body: CA_UpdateHolderDTO) {
return this.carnetApplicationService.UpdateHolder(body);
}
@Patch('UpdateExpGoodsAuthRep')
UpdateExpGoodsAuthRep(@Body() body: UpdateExpGoodsAuthRepDTO) {
return this.carnetApplicationService.UpdateExpGoodsAuthRep(body);
}
@Post('AddGenerallistItems')
AddGenerallistItems(@Body() body: AddGenerallistItemsDTO) {
return this.carnetApplicationService.AddGenerallistItems(body);
}
@Put('EditGenerallistItems')
EditGenerallistItems(@Body() body: EditGenerallistItemsDTO) {
return this.carnetApplicationService.EditGenerallistItems(body);
}
@Delete('DeleteGenerallistItems')
DeleteGenerallistItems(@Body() body: DeleteGenerallistItemsDTO) {
return this.carnetApplicationService.DeleteGenerallistItems(body);
}
@Post('AddCountries')
AddCountries(@Body() body: AddCountriesDTO) {
return this.carnetApplicationService.AddCountries(body);
}
@Patch('UpdateShippingDetails')
UpdateShippingDetails(@Body() body: UpdateShippingDetailsDTO) {
return this.carnetApplicationService.UpdateShippingDetails(body);
}
@Get('EstimatedFees/:P_SPID/:P_USERID/:P_HEADERID')
EstimatedFees(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.EstimatedFees(body);
}
// // processing [ PROCESSINGCENTER_PKG ]
@Patch('ProcessCarnet')
ProcessCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.ProcessCarnet(body);
}
@Patch('UpdatePrintCarnet')
UpdatePrintCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.UpdatePrintCarnet(body);
}
@Patch('VoidCarnet')
@Roles('psa')
VoidCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.VoidCarnet(body);
}
@Patch('CopyCarnet')
CopyCarnet(@Body() body: CopyCarnetDTO) {
return this.carnetApplicationService.CopyCarnet(body);
}
@Patch('DuplicateCarnet')
DuplicateCarnet(@Body() body: CarnetProcessingCenterDTO2) {
return this.carnetApplicationService.DuplicateCarnet(body);
}
@Patch('AddlSets')
AddlSets(@Body() body: CarnetProcessingCenterDTO2) {
return this.carnetApplicationService.AddlSets(body);
}
@Patch('ExtendCarnet')
ExtendCarnet(@Body() body: CarnetProcessingCenterDTO2) {
return this.carnetApplicationService.ExtendCarnet(body);
}
@Get('GetExtendedSection/:P_SPID/:P_HEADERID')
GetExtendedSection(@Param() body: GetExtendedSectionDTO) {
return this.carnetApplicationService.GetExtendedSection(body);
}
@Post('SaveExtensionApplication')
@HttpCode(200)
SaveExtensionApplication(@Body() body: SaveExtensionApplicationDTO) {
return this.carnetApplicationService.SaveExtensionApplication(body);
}
@Patch('CloseCarnet')
@Roles('psa')
CloseCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.CloseCarnet(body);
}
@Patch('ResetCarnet')
@Roles('psa')
ResetCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.ResetCarnet(body);
}
@Delete('DeleteCarnet')
DeleteCarnet(@Body() body: CarnetProcessingCenterDTO) {
return this.carnetApplicationService.DeleteCarnet(body);
}
// [ CARNETCONTROLCENTER_PKG ]
@Get('GetHolderstoEdit/:P_SPID/:P_USERID/:P_HEADERID')
GetHolderstoEdit(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.GetHolderstoEdit(body);
}
@Get('GetGoodsDetailstoEdit/:P_SPID/:P_USERID/:P_HEADERID')
GetGoodsDetailstoEdit(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.GetGoodsDetailstoEdit(body);
}
@Get('GetGoodsItemstoEdit/:P_SPID/:P_USERID/:P_HEADERID')
GetGoodsItemstoEdit(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.GetGoodsItemstoEdit(body);
}
@Get('GetCountryDetailstoEdit/:P_SPID/:P_USERID/:P_HEADERID')
GetCountryDetailstoEdit(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.GetCountryDetailstoEdit(body);
}
@Get('GetShipPaymentDetailstoEdit/:P_SPID/:P_USERID/:P_HEADERID')
GetShipPaymentDetailstoEdit(@Param() body: GetCarnetControlCenterDTO) {
return this.carnetApplicationService.GetShipPaymentDetailstoEdit(body);
}
@Get('GetCarnetDetailsbyCarnetStatus/:P_SPID/:P_USERID/:P_CARNETSTATUS')
@Roles('pca', 'psa', 'pua')
GetCarnetDetailsbyCarnetStatus(@Param() params: GetCarnetDetailsbyCarnetStatusDTO) {
return this.carnetApplicationService.GetCarnetDetailsbyCarnetStatus(params);
}
// [PRINT_PKG]
@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')
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`;
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
console.log(filePath);
// console.log(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]);
});
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);
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`;
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
// console.log(filePath);
// console.log(filePath);
const stream = createReadStream(filePath);
// 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");
}
}
}
//[payment]
@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);
}
// @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);
}
@Post('SaveHistory')
@HttpCode(200)
async SaveHistory(@Body() body: SaveHistoryDTO) {
return this.carnetApplicationService.SaveHistory(body);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { CarnetApplicationController } from './carnet-application.controller';
import { CarnetApplicationService } from './carnet-application.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [CarnetApplicationController],
providers: [CarnetApplicationService]
})
export class CarnetApplicationModule {}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
import { Body, Controller, Get, Param, Patch, Post, Put, Query, UseGuards } from '@nestjs/common';
import { ClientContactControlsDTO, CreateClientContactsDTO, CreateClientDataDTO, CreateClientLocationsDTO, GetClientContactByLacationIdDTO, GetClientDTO, GetPreparersParamDTO, GetPreparersQueryDTO, UpdateClientContactsDTO, UpdateClientDTO, UpdateClientLocationsDTO } from 'src/dto/property.dto';
import { ManageClientsService } from './manage-clients.service';
import { Roles } from 'src/decorators/roles.decorator';
import { ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Manage Clients - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa')
@Controller('2')
export class ManageClientsController {
constructor(private readonly manageClientsService: ManageClientsService) { }
@Post('CreateNewClients')
async CreateClientData(@Body() body: CreateClientDataDTO) {
return this.manageClientsService.CreateClientData(body);
}
@Put('UpdateClient')
async UpdateClient(@Body() body: UpdateClientDTO) {
return this.manageClientsService.UpdateClient(body);
}
@Put('UpdateClientContacts')
@Roles('pca', 'psa')
UpdateClientContacts(@Body() body: UpdateClientContactsDTO) {
return this.manageClientsService.UpdateClientContacts(body);
}
@Put('UpdateClientLocations')
@Roles('pca', 'psa')
UpdateClientLocations(@Body() body: UpdateClientLocationsDTO) {
return this.manageClientsService.UpdateClientLocations(body);
}
@Post('CreateClientContacts')
@Roles('pca', 'psa')
CreateClientContact(@Body() body: CreateClientContactsDTO) {
return this.manageClientsService.CreateClientContact(body);
}
@Patch('SetDefaultClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
SetDefaultClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.SetDefaultClientContacts(param);
}
@Patch('InactivateClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
InactivateClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.InactivateClientContacts(param);
}
@Patch('ReactivateClientContacts/:P_SPID/:P_CLIENTCONTACTID/:P_USERID')
ReactivateClientContacts(@Param() param: ClientContactControlsDTO) {
return this.manageClientsService.ReactivateClientContacts(param);
}
@Post('CreateClientLocations')
@Roles('pca', 'psa')
CreateClientLocation(@Body() body: CreateClientLocationsDTO) {
return this.manageClientsService.CreateClientLocation(body);
}
@Get('GetPreparers/:P_SPID/:P_STATUS')
async GetPreparers(@Param() param: GetPreparersParamDTO, @Query() query: GetPreparersQueryDTO) {
return await this.manageClientsService.GetPreparers({ ...param, ...query });
}
@Get('GetPreparerByClientid/:P_SPID/:P_CLIENTID')
GetPreparerByClientid(@Param() body: GetClientDTO) {
return this.manageClientsService.GetPreparerByClientid(body);
}
@Get('GetPreparerContactsByClientid/:P_SPID/:P_CLIENTID')
@Roles('pca', 'psa')
GetPreparerContactsByClientid(@Param() body: GetClientDTO) {
return this.manageClientsService.GetPreparerContactsByClientid(body);
}
@Get('GetPreparerContactsbyClientLocationID/:P_SPID/:P_LOCATIONID')
@Roles('pca', 'psa')
GetPreparerContactsbyClientLocationID(@Param() body: GetClientContactByLacationIdDTO) {
return this.manageClientsService.GetPreparerContactsbyClientLocationID(body);
}
@Get('GetPreparerLocByClientid/:P_SPID/:P_CLIENTID')
@Roles('pca', 'psa')
GetPreparerLocByClientid(@Param() body: GetClientDTO) {
return this.manageClientsService.GetPreparerLocByClientid(body);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { ManageClientsController } from './manage-clients.controller';
import { ManageClientsService } from './manage-clients.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [ManageClientsController],
providers: [ManageClientsService]
})
export class ManageClientsModule {}

View File

@ -0,0 +1,642 @@
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_createclientlocation($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_GetPreparerByClientid($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)
}
};
}

View File

@ -0,0 +1,139 @@
import { Body, Controller, Get, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { ManageFeeService } from './manage-fee.service';
import { ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { Roles } from 'src/decorators/roles.decorator';
import { CreateBasicFeeDTO, CreateBondRateDTO, CreateCargoRateDTO, CreateCfFeeDTO, CreateCsFeeDTO, CreateEfFeeDTO, CreateFeeCommDTO, GetFeeGeneralDTO, UpdateBasicFeeDTO, UpdateBondRateDTO, UpdateCargoRateDTO, UpdateCfFeeDTO, UpdateCsFeeDTO, UpdateEfFeeDTO, UpdateFeeCommDTO } from 'src/dto/property.dto';
@ApiTags('Manage Fee - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class ManageFeeController {
constructor(private readonly manageFeeService: ManageFeeService) { }
@Get('/GetBasicFeeRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETBASICFEERATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETBASICFEERATES(body);
}
@Post('/CreateBasicFee')
CREATEBASICFEE(@Body() body: CreateBasicFeeDTO) {
return this.manageFeeService.CREATEBASICFEE(body);
}
@Patch('/UpdateBasicFee')
UPDATEBASICFEE(@Body() body: UpdateBasicFeeDTO) {
return this.manageFeeService.UPDATEBASICFEE(body);
}
// bond rate
@Get('/GetBondRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETBONDRATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETBONDRATES(body);
}
@Post('/CreateBondRate')
CREATEBONDRATE(@Body() body: CreateBondRateDTO) {
return this.manageFeeService.CREATEBONDRATE(body);
}
@Patch('/UpdateBondRate')
UPDATEBONDRATE(@Body() body: UpdateBondRateDTO) {
return this.manageFeeService.UPDATEBONDRATE(body);
}
// cargo rate
@Get('/GetCargoRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETCARGORATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETCARGORATES(body);
}
@Post('/CreateCargoRate')
CREATECARGORATE(@Body() body: CreateCargoRateDTO) {
return this.manageFeeService.CREATECARGORATE(body);
}
@Patch('/UpdateCargoRate')
UPDATECARGORATE(@Body() body: UpdateCargoRateDTO) {
return this.manageFeeService.UPDATECARGORATE(body);
}
// cf fee rate
@Get('/GetCfFeeRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETCFFEERATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETCFFEERATES(body);
}
@Post('/CreateCfFee')
CREATECFFEE(@Body() body: CreateCfFeeDTO) {
return this.manageFeeService.CREATECFFEE(body);
}
@Patch('/UpdateCfFee')
UPDATECFFEE(@Body() body: UpdateCfFeeDTO) {
return this.manageFeeService.UPDATECFFEE(body);
}
// cs fee rate
@Get('/GetCsFeeRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETCSFEERATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETCSFEERATES(body);
}
@Post('/CreateCsFee')
CREATECSFEE(@Body() body: CreateCsFeeDTO) {
return this.manageFeeService.CREATECSFEE(body);
}
@Patch('/UpdateCsFee')
UPDATECSFEE(@Body() body: UpdateCsFeeDTO) {
return this.manageFeeService.UPDATECSFEE(body);
}
// ef fee rate
@Get('/GetEfFeeRates/:P_SPID/:P_ACTIVE_INACTIVE')
GETEFFEERATES(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETEFFEERATES(body);
}
@Post('/CreateEfFee')
CREATEEFFEE(@Body() body: CreateEfFeeDTO) {
return this.manageFeeService.CREATEEFFEE(body);
}
@Patch('/UpdateEfFee')
UPDATEEFFEE(@Body() body: UpdateEfFeeDTO) {
return this.manageFeeService.UPDATEEFFEE(body);
}
// fee comm
@Get('/GetFeeComm/:P_SPID/:P_ACTIVE_INACTIVE')
GETFEECOMM(@Param() body: GetFeeGeneralDTO) {
return this.manageFeeService.GETFEECOMM(body);
}
@Post('/CreateFeeComm')
CREATEFEECOMM(@Body() body: CreateFeeCommDTO) {
return this.manageFeeService.CREATEFEECOMM(body);
}
@Patch('/UpdateFeeComm')
UPDATEFEECOMM(@Body() body: UpdateFeeCommDTO) {
return this.manageFeeService.UPDATEFEECOMM(body);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { ManageFeeController } from './manage-fee.controller';
import { ManageFeeService } from './manage-fee.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [ManageFeeController],
providers: [ManageFeeService]
})
export class ManageFeeModule {}

View File

@ -0,0 +1,947 @@
import { Injectable } from '@nestjs/common';
import { PgDBService } from 'src/db/db.service';
import { CreateBasicFeeDTO, CreateBondRateDTO, CreateCargoRateDTO, CreateCfFeeDTO, CreateCsFeeDTO, CreateEfFeeDTO, CreateFeeCommDTO, GetFeeGeneralDTO, UpdateBasicFeeDTO, UpdateBondRateDTO, UpdateCargoRateDTO, UpdateCfFeeDTO, UpdateCsFeeDTO, UpdateEfFeeDTO, UpdateFeeCommDTO } from 'src/dto/property.dto';
import { PoolClient } from 'pg';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class ManageFeeService {
constructor(private readonly pgDBService: PgDBService) { }
async GETBASICFEERATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getbasicfeerates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATEBASICFEE(body: CreateBasicFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createbasicfee($1, $2, $3, $4, $5, $6, $7)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_STARTNUMBER,
body.P_ENDNUMBER,
body.P_EFFDATE,
body.P_FEES,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATEBASICFEE(body: UpdateBasicFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatebasicfee($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_BASICFEESETUPID,
body.P_FEES,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// bond rate
async GETBONDRATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getbondrates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATEBONDRATE(body: CreateBondRateDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createbondrate($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_HOLDERTYPE ?? "",
body.P_USCIBMEMBERFLAG ?? "",
body.P_SPCLCOMMODITY ?? "",
body.P_SPCLCOUNTRY ?? "",
body.P_EFFDATE,
body.P_RATE,
body.P_USERID,
body.P_PCT_VALUE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATEBONDRATE(body: UpdateBondRateDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatebondrate($1, $2, $3, $4, $5, $6)
`;
await client.query(callProcQuery,
[
body.P_BONDRATESETUPID,
body.P_RATE,
body.P_EFFDATE,
body.P_USERID,
body.P_PCT_VALUE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// cargo rate
async GETCARGORATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getcargorates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATECARGORATE(body: CreateCargoRateDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createcargorate($1, $2, $3, $4, $5, $6, $7, $8)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CARNETTYPE,
body.P_STARTSETS,
body.P_ENDSETS,
body.P_EFFDATE,
body.P_RATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATECARGORATE(body: UpdateCargoRateDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatecargorate($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_CARGORATESETUPID,
body.P_RATE,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// counter foil
async GETCFFEERATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getcffeerates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATECFFEE(body: CreateCfFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createcffee($1, $2, $3, $4, $5, $6, $7, $8, $9)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_STARTSETS,
body.P_ENDSETS,
body.P_EFFDATE,
body.P_CUSTOMERTYPE,
body.P_CARNETTYPE,
body.P_RATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATECFFEE(body: UpdateCfFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatecffee($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_CFFEESETUPID,
body.P_RATE,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// continuation sheet
async GETCSFEERATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getcsfeerates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATECSFEE(body: CreateCsFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createcsfee($1, $2, $3, $4, $5, $6, $7)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CUSTOMERTYPE,
body.P_CARNETTYPE,
body.P_EFFDATE,
body.P_RATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATECSFEE(body: UpdateCsFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatecsfee($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_CSFEESETUPID,
body.P_RATE,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// expedited fee
async GETEFFEERATES(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_geteffeerates($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATEEFFEE(body: CreateEfFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createeffee($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_CUSTOMERTYPE,
body.P_DELIVERYTYPE,
body.P_STARTTIME,
body.P_ENDTIME,
body.P_TIMEZONE,
body.P_EFFDATE,
body.P_FEES,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATEEFFEE(body: UpdateEfFeeDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updateeffee($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_EFFEESETUPID,
body.P_FEES,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
// fee comm
async GETFEECOMM(body: GetFeeGeneralDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_getfeecomm($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_ACTIVE_INACTIVE, 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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async CREATEFEECOMM(body: CreateFeeCommDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_createfeecomm($1, $2, $3, $4, $5, $6)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_PARAMID,
body.P_COMMRATE,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
async UPDATEFEECOMM(body: UpdateFeeCommDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".managefee_setup_pkg_updatefeecomm($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_FEECOMMID,
body.P_RATE,
body.P_EFFDATE,
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, ManageFeeService.name)
} finally {
releasePgClient(client)
}
}
}

View File

@ -0,0 +1,109 @@
import { Body, Controller, Get, Param, Patch, Post, Put, Query, UseGuards } from '@nestjs/common';
import { ApiQuery, ApiTags } from '@nestjs/swagger';
import { CreateHolderContactsDTO, CreateHoldersDTO, GetHolderDTO, HolderActivateOrInactivateDTO, HolderContactActivateOrInactivateDTO, UpdateHolderContactDTO, UpdateHolderDTO } from 'src/dto/property.dto';
import { BadRequestException } from 'src/exceptions/badRequest.exception';
import { ManageHolderService } from './manage-holder.service';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Manage Holders - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('pca', 'psa')
@Controller('2')
export class ManageHolderController {
constructor(private readonly manageHoldersService: ManageHolderService) { }
@Get('SearchHolder/:P_SPID/:P_USERID')
@ApiQuery({ name: "P_HOLDERNAME", type: String, required: false, description: "Optional" })
@ApiQuery({ name: "P_HOLDERID", type: Number, required: false, description: "Optional" })
SearchHolder(
@Param('P_SPID') P_SPID: number,
@Param('P_USERID') P_USERID: string,
@Query('P_HOLDERID') P_HOLDERID?: number,
@Query('P_HOLDERNAME') P_HOLDERNAME?: string | null | undefined,
) {
if (!P_USERID) {
throw new BadRequestException('User ID is required');
}
// Sanitize holder name
let rawHolderName: string | null = null;
if (typeof P_HOLDERNAME === 'string') {
const trimmed = P_HOLDERNAME.trim().replace(/^['"]|['"]$/g, '');
rawHolderName = trimmed === '' || trimmed.toLowerCase() === 'null' ? null : trimmed;
}
// Validate and coerce P_HOLDERID
let holderId: number | null = null;
if (P_HOLDERID !== undefined && P_HOLDERID !== null) {
const parsed = Number(P_HOLDERID);
if (isNaN(parsed)) {
throw new BadRequestException('Invalid holder ID');
}
holderId = parsed;
}
const body = {
P_SPID,
P_USERID,
P_HOLDERID: holderId,
P_HOLDERNAME: rawHolderName,
};
return this.manageHoldersService.SearchHolder(body)
}
@Post('/CreateHolderData')
CreateHolders(@Body() body: CreateHoldersDTO) {
return this.manageHoldersService.CreateHolders(body);
}
@Post('CreateHoldercontact')
CreateHoldercontact(@Body() body: CreateHolderContactsDTO) {
return this.manageHoldersService.CreateHoldercontact(body);
}
@Put('/UpdateHolder')
UpdateHolder(@Body() body: UpdateHolderDTO) {
return this.manageHoldersService.UpdateHolder(body);
}
@Get('/GetHolderRecord/:P_SPID/:P_HOLDERID')
GetHolderRecord(@Param() body: GetHolderDTO) {
return this.manageHoldersService.GetHolderRecord(body);
}
@Put('/UpdateHolderContact')
UpdateHolderContact(@Body() body: UpdateHolderContactDTO) {
return this.manageHoldersService.UpdateHolderContact(body);
}
@Get('/GetHolderContacts/:P_SPID/:P_HOLDERID')
GetHolderContacts(@Param() body: GetHolderDTO) {
return this.manageHoldersService.GetHolderContacts(body);
}
@Patch('/InactivateHolder/:P_SPID/:P_HOLDERID/:P_USERID')
InactivateHolder(@Param() body: HolderActivateOrInactivateDTO) {
return this.manageHoldersService.InactivateHolder(body);
}
@Patch('/ReactivateHolder/:P_SPID/:P_HOLDERID/:P_USERID')
ReactivateHolder(@Param() body: HolderActivateOrInactivateDTO) {
return this.manageHoldersService.ReactivateHolder(body);
}
@Patch('/InactivateHolderContact/:P_SPID/:P_HOLDERCONTACTID/:P_USERID')
InactivateHolderContact(@Param() body: HolderContactActivateOrInactivateDTO) {
return this.manageHoldersService.InactivateHolderContact(body);
}
@Patch('/ReactivateHolderContact/:P_SPID/:P_HOLDERCONTACTID/:P_USERID')
ReactivateHolderContact(@Param() body: HolderContactActivateOrInactivateDTO) {
return this.manageHoldersService.ReactivateHolderContact(body);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { ManageHolderController } from './manage-holder.controller';
import { ManageHolderService } from './manage-holder.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [ManageHolderController],
providers: [ManageHolderService]
})
export class ManageHolderModule {}

View File

@ -0,0 +1,499 @@
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, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class ManageHolderService {
constructor(private readonly pgDBService: PgDBService) { }
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 toUpperCaseKeys(fetchResult.rows);
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
}
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,
...toUpperCaseKeys(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,
...toUpperCaseKeys(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: 200,
message: ResponseStatus.updated,
...toUpperCaseKeys(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 toUpperCaseKeys(fetchResult.rows)[0]??[];
} 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_updateholdercontacts($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: 200,
message: ResponseStatus.updated,
...toUpperCaseKeys(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 toUpperCaseKeys(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,
...toUpperCaseKeys(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,
...toUpperCaseKeys(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,
...toUpperCaseKeys(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,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ManageHolderService.name)
} finally {
releasePgClient(client)
}
};
}

View File

@ -0,0 +1,86 @@
import { Body, Controller, Get, Param, Patch, Post, Put, Query, UseGuards } from '@nestjs/common';
import { ApiQuery, ApiTags } from '@nestjs/swagger';
import { ParamTableService } from './param-table.service';
import {
ActivateOrInactivateParamRecordDTO, CreateParamRecordDTO, CreateTableRecordDTO,
getParamValuesDTO, SPID_DTO, UpdateParamRecordDTO
} from 'src/dto/property.dto';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
@ApiTags('Param Table - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class ParamTableController {
constructor(private readonly paramTableService: ParamTableService) { }
@Get('/GetParamValues')
@Roles('pca', 'psa', 'pua')
@ApiQuery({
name: 'P_SPID',
required: false,
type: Number,
description: 'The ID of the parameter',
})
@ApiQuery({
name: 'P_PARAMTYPE',
required: false,
type: String,
description: 'The type of the parameter',
})
GETPARAMVALUES(@Query() body: getParamValuesDTO) {
return this.paramTableService.GETPARAMVALUES(body);
}
@Get('/GetAllParamValues')
@ApiQuery({
name: 'P_SPID',
required: false,
type: Number,
description: 'The ID of the parameter',
})
@ApiQuery({
name: 'P_PARAMTYPE',
required: false,
type: String,
description: 'The type of the parameter',
})
GETALLPARAMVALUES(@Query() body: getParamValuesDTO) {
return this.paramTableService.GETALLPARAMVALUES(body);
}
@Get('GetCountriesAndMessages/:P_SPID')
@Roles('pca', 'psa', 'pua')
GET_COUNTRIES_AND_MESSAGES(@Param() body: SPID_DTO) {
return this.paramTableService.GET_COUNTRIES_AND_MESSAGES(body);
}
@Post('/CreateTableRecord')
CREATETABLERECORD(@Body() body: CreateTableRecordDTO) {
return this.paramTableService.CREATETABLERECORD(body);
}
@Post('/CreateParamRecord')
CREATEPARAMRECORD(@Body() body: CreateParamRecordDTO) {
return this.paramTableService.CREATEPARAMRECORD(body);
}
@Patch('/UpdateParamRecord')
UPDATEPARAMRECORD(@Body() body: UpdateParamRecordDTO) {
return this.paramTableService.UPDATEPARAMRECORD(body);
}
@Patch('/InActivateParamRecord')
INACTIVATEPARAMRECORD(@Body() body: ActivateOrInactivateParamRecordDTO) {
return this.paramTableService.INACTIVATEPARAMRECORD(body);
}
@Patch('/ReActivateParamRecord')
REACTIVATEPARAMRECORD(@Body() body: ActivateOrInactivateParamRecordDTO) {
return this.paramTableService.REACTIVATEPARAMRECORD(body);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { ParamTableController } from './param-table.controller';
import { ParamTableService } from './param-table.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [ParamTableController],
providers: [ParamTableService]
})
export class ParamTableModule { }

View File

@ -0,0 +1,312 @@
import { Injectable, Logger } from '@nestjs/common';
import { PoolClient } from 'pg';
import { PgDBService } from 'src/db/db.service';
import { ActivateOrInactivateParamRecordDTO, CreateParamRecordDTO, CreateTableRecordDTO, getParamValuesDTO, SPID_DTO, UpdateParamRecordDTO } from 'src/dto/property.dto';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class ParamTableService {
private readonly logger = new Logger(ParamTableService.name);
constructor(private readonly pgDBService: PgDBService) { }
async GETPARAMVALUES(body: getParamValuesDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_getparamvalues($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_PARAMTYPE, 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, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async GETALLPARAMVALUES(body: getParamValuesDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_getallparamvalues($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_PARAMTYPE, 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, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async GET_COUNTRIES_AND_MESSAGES(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_getcountriesandmessages($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async CREATETABLERECORD(body: CreateTableRecordDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_createtablerecord($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_USERID, body.P_TABLEFULLDESC, 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);
let fr: any = toUpperCaseKeys(fetchResult?.rows)
// return fetchResult.rows;
return { statusCode: 201, message: ResponseStatus.created, ...fr[0] };
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async CREATEPARAMRECORD(body: CreateParamRecordDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
// Call the stored procedure
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_createparamrecord(
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12
)
`;
await client.query(callProcQuery, [
body.P_SPID,
body.P_PARAMTYPE,
body.P_PARAMDESC,
body.P_PARAMVALUE,
body.P_ADDLPARAMVALUE1,
body.P_ADDLPARAMVALUE2,
body.P_ADDLPARAMVALUE3,
body.P_ADDLPARAMVALUE4,
body.P_ADDLPARAMVALUE5,
body.P_SORTSEQ,
body.P_USERID,
cursorName
]);
// ✅ Correct: quote the cursor name when using it in SQL
const fetchResult = await client.query(`FETCH ALL FROM "${cursorName}"`);
// ✅ Always close the cursor
await client.query(`CLOSE "${cursorName}"`);
await client.query('COMMIT');
checkPgUserDefinedErrors(fetchResult);
let fr: any = toUpperCaseKeys(fetchResult?.rows)
// Return response
return {
statusCode: 201,
message: ResponseStatus.created,
...fr[0] || {}
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async UPDATEPARAMRECORD(body: UpdateParamRecordDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_updateparamrecord(
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11
)
`;
await client.query(callProcQuery, [
body.P_SPID,
body.P_PARAMID,
body.P_PARAMDESC,
body.P_ADDLPARAMVALUE1,
body.P_ADDLPARAMVALUE2,
body.P_ADDLPARAMVALUE3,
body.P_ADDLPARAMVALUE4,
body.P_ADDLPARAMVALUE5,
body.P_SORTSEQ,
body.P_USERID,
cursorName
]);
// ✅ Correct: quote the cursor name when using it in SQL
const fetchResult = await client.query(`FETCH ALL FROM "${cursorName}"`);
// ✅ Always close the cursor
await client.query(`CLOSE "${cursorName}"`);
await client.query('COMMIT');
checkPgUserDefinedErrors(fetchResult);
// Return response
return {
statusCode: 200,
message: ResponseStatus.updated,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async INACTIVATEPARAMRECORD(body: ActivateOrInactivateParamRecordDTO) {
let client: PoolClient | null = null;
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_inactivateparamrecord($1, $2)
`;
await client.query(callProcQuery, [body.P_PARAMID, body.P_USERID]);
await client.query('COMMIT');
return {
statusCode: 200,
message: ResponseStatus.inActivate
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
async REACTIVATEPARAMRECORD(body: ActivateOrInactivateParamRecordDTO) {
let client: PoolClient | null = null;
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".manageparamtable_pkg_reactivateparamrecord($1, $2)
`;
await client.query(callProcQuery, [body.P_PARAMID, body.P_USERID]);
await client.query('COMMIT');
return {
statusCode: 200,
message: ResponseStatus.reActivate
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, ParamTableService.name)
} finally {
releasePgClient(client)
}
}
}

17
src/pg/pg.module.ts Normal file
View File

@ -0,0 +1,17 @@
import { Global, Module } from '@nestjs/common';
import { ParamTableModule } from './param-table/param-table.module';
import { DbModule } from 'src/db/db.module';
import { UscibManagedSpModule } from './uscib-managed-sp/uscib-managed-sp.module';
import { UserMaintenanceModule } from './user-maintenance/user-maintenance.module';
import { ManageFeeModule } from './manage-fee/manage-fee.module';
import { ManageHolderModule } from './manage-holder/manage-holder.module';
import { ManageClientsModule } from './manage-clients/manage-clients.module';
import { CarnetApplicationModule } from './carnet-application/carnet-application.module';
@Global()
@Module({
imports: [DbModule, ParamTableModule, UscibManagedSpModule, UserMaintenanceModule, ManageFeeModule, ManageHolderModule, ManageClientsModule, CarnetApplicationModule],
providers: [],
exports: [UserMaintenanceModule]
})
export class PgModule { }

View File

@ -0,0 +1,25 @@
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { CarnetSequenceService } from './carnet-sequence.service';
import { CreateCarnetSequenceDTO, SPID_DTO } from 'src/dto/property.dto';
import { ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { Roles } from 'src/decorators/roles.decorator';
@ApiTags('Carnet Sequence - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class CarnetSequenceController {
constructor(private readonly carnetSequenceService: CarnetSequenceService) { }
@Post('/CreateCarnetSequence/')
createCarnetSequence(@Body() body: CreateCarnetSequenceDTO) {
return this.carnetSequenceService.createCarnetSequence(body);
}
@Get('/GetCarnetSequence/:P_SPID')
getCarnetSequence(@Param() params: SPID_DTO) {
return this.carnetSequenceService.getCarnetSequence(params);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { CarnetSequenceController } from './carnet-sequence.controller';
import { CarnetSequenceService } from './carnet-sequence.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [CarnetSequenceController],
providers: [CarnetSequenceService]
})
export class CarnetSequenceModule {}

View File

@ -0,0 +1,81 @@
import { Injectable, Logger } from '@nestjs/common';
import { PgDBService } from 'src/db/db.service';
import { CreateCarnetSequenceDTO, SPID_DTO } from 'src/dto/property.dto';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { PoolClient } from 'pg';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class CarnetSequenceService {
private readonly logger = new Logger(CarnetSequenceService.name);
constructor(private readonly pgDBService: PgDBService) { }
async createCarnetSequence(body: CreateCarnetSequenceDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_createcarnetsequence($1, $2, $3, $4, $5, $6)
`;
await client.query(callProcQuery, [body.P_SPID, body.P_REGIONID, body.P_STARTNUMBER, body.P_ENDNUMBER, body.P_CARNETTYPE, 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, CarnetSequenceService.name)
} finally {
releasePgClient(client)
}
}
async getCarnetSequence(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getcarnetsequence($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, CarnetSequenceService.name)
} finally {
releasePgClient(client)
}
}
}

View File

@ -0,0 +1,30 @@
import { Body, Controller, Get, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { RegionService } from './region.service';
import { InsertRegionsDto, SPID_DTO, UpdateRegionDto } from 'src/dto/property.dto';
@ApiTags('Regions - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class RegionController {
constructor(private readonly regionService: RegionService) { }
@Post('/InsertRegions')
insertRegions(@Body() body: InsertRegionsDto) {
return this.regionService.insertRegions(body);
}
@Patch('/UpdateRegion')
updateRegions(@Body() body: UpdateRegionDto) {
return this.regionService.updateRegions(body);
}
@Get('/GetRegions/:P_SPID')
getRegions(@Param() param: SPID_DTO) {
return this.regionService.getRegions(param);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { RegionController } from './region.controller';
import { RegionService } from './region.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [RegionController],
providers: [RegionService]
})
export class RegionModule { }

View File

@ -0,0 +1,120 @@
import { Injectable, Logger } from '@nestjs/common';
import { PgDBService } from 'src/db/db.service';
import { InsertRegionsDto, SPID_DTO, UpdateRegionDto } from 'src/dto/property.dto';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { PoolClient } from 'pg';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class RegionService {
private readonly logger = new Logger(RegionService.name);
constructor(private readonly pgDBService: PgDBService) { }
async insertRegions(body: InsertRegionsDto) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_insertnewregion($1, $2, $3, $4)
`;
await client.query(callProcQuery, [body.P_REGION, body.P_NAME, body.P_SPID, 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, RegionService.name)
} finally {
releasePgClient(client)
}
}
async updateRegions(body: UpdateRegionDto) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_updateregion($1, $2, $3)
`;
await client.query(callProcQuery, [body.P_REGIONID, body.P_NAME, 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, RegionService.name)
} finally {
releasePgClient(client)
}
}
async getRegions(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getregions($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, RegionService.name)
} finally {
releasePgClient(client)
}
}
}

View File

@ -0,0 +1,48 @@
import { Body, Controller, Get, Param, Patch, Post, Put, UseGuards } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { SpContactsService } from './sp-contacts.service';
import { InsertSPContactsDTO, SP_CONTACTID_DTO, SPID_DTO, UpdateSPContactsDTO } from 'src/dto/property.dto';
@ApiTags('SPContacts - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class SpContactsController {
constructor(private readonly spContactsService: SpContactsService) { }
@Post('/InsertSPContacts')
insertSPContacts(@Body() body: InsertSPContactsDTO) {
return this.spContactsService.insertSPContacts(body);
}
@Patch('/SetSPDefaultContact/:P_SPCONTACTID')
@Roles('pua')
setSPDefaultcontact(@Param() param: SP_CONTACTID_DTO) {
return this.spContactsService.setSPDefaultcontact(param);
}
@Put('/UpdateSPContacts')
updateSPContacts(@Body() body: UpdateSPContactsDTO) {
return this.spContactsService.updateSPContacts(body);
}
@Patch('/InactivateSPContact/:P_SPCONTACTID')
inactivateSPContact(@Param() param: SP_CONTACTID_DTO) {
return this.spContactsService.inactivateSPContact(param);
}
@Get('/GetSPDefaultContact/:P_SPID')
getSPDefaultcontacts(@Param() param: SPID_DTO) {
return this.spContactsService.getSPDefaultcontacts(param);
}
@Get('/GetSPAllContacts/:P_SPID')
getSPAllContacts(@Param() param: SPID_DTO) {
return this.spContactsService.getSPAllContacts(param);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { SpContactsController } from './sp-contacts.controller';
import { SpContactsService } from './sp-contacts.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [SpContactsController],
providers: [SpContactsService]
})
export class SpContactsModule {}

View File

@ -0,0 +1,240 @@
import { Injectable } from '@nestjs/common';
import { InsertSPContactsDTO, SP_CONTACTID_DTO, SPID_DTO, UpdateSPContactsDTO } from 'src/dto/property.dto';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { PoolClient } from 'pg';
import { PgDBService } from 'src/db/db.service';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class SpContactsService {
constructor(private readonly pgDBService: PgDBService) { }
async insertSPContacts(body: InsertSPContactsDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_insertspcontacts($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_DEFCONTACTFLAG,
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_USER_ID,
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, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
async setSPDefaultcontact(body: SP_CONTACTID_DTO) {
let client: PoolClient | null = null;
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_setdefaultcontact($1)
`;
await client.query(callProcQuery, [body.P_SPCONTACTID]);
await client.query('COMMIT');
return { statusCode: 200, message: ResponseStatus.defaultSpContactAdded };
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
async updateSPContacts(body: UpdateSPContactsDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_updatespcontacts($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
`;
await client.query(callProcQuery,
[
body.P_SPCONTACTID,
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_USER_ID,
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, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
async inactivateSPContact(body: SP_CONTACTID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".USCIB_Managed_Pkg_InActivateSPContacts($1)
`;
await client.query(callProcQuery, [body.P_SPCONTACTID]);
// 🚫 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 { statusCode: 200, message: ResponseStatus.inActivate };
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
async getSPDefaultcontacts(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getspdefaultcontacts($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
async getSPAllContacts(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getspallcontacts($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, SpContactsService.name)
} finally {
releasePgClient(client)
}
}
}

View File

@ -0,0 +1,37 @@
import { Body, Controller, Get, Param, Post, Put, UseGuards } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Roles } from 'src/decorators/roles.decorator';
import { JwtAuthGuard } from 'src/guards/jwt-auth.guard';
import { RolesGuard } from 'src/guards/roles.guard';
import { SpService } from './sp.service';
import { InsertNewServiceProviderDTO, SPID_DTO, UpdateServiceProviderDTO } from 'src/dto/property.dto';
@ApiTags('SP - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('psa', 'pua')
@Controller('2')
export class SpController {
constructor(private readonly spService: SpService) { }
@Post('/InsertNewServiceProvider')
@Roles('pua')
insertNewServiceProvider(@Body() body: InsertNewServiceProviderDTO) {
return this.spService.insertNewServiceProvider(body);
}
@Put('/UpdateServiceProvider')
updateServiceProvider(@Body() body: UpdateServiceProviderDTO) {
return this.spService.updateServiceProvider(body);
}
@Get('/GetAllServiceproviders')
@Roles('pua')
getAllServiceproviders() {
return this.spService.getAllServiceproviders();
}
@Get('/GetSelectedServiceprovider/:P_SPID')
getServiceproviderByID(@Param() param: SPID_DTO) {
return this.spService.getServiceproviderByID(param);
}
}

View File

@ -0,0 +1,11 @@
import { forwardRef, Module } from '@nestjs/common';
import { SpController } from './sp.controller';
import { SpService } from './sp.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [SpController],
providers: [SpService]
})
export class SpModule {}

View File

@ -0,0 +1,205 @@
import { Injectable, Logger } from '@nestjs/common';
import { PgDBService } from 'src/db/db.service';
import { InsertNewServiceProviderDTO, SPID_DTO, UpdateServiceProviderDTO } from 'src/dto/property.dto';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { PoolClient } from 'pg';
import { checkPgUserDefinedErrors, handlePgError, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
@Injectable()
export class SpService {
private readonly logger = new Logger(SpService.name);
constructor(private readonly pgDBService: PgDBService) { }
async insertNewServiceProvider(body: InsertNewServiceProviderDTO) {
console.log(" i got executed here ....");
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
console.log(" pg connection successfull ..... ");
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_insertnewsp($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
`;
await client.query(callProcQuery,
[
body.P_NAME,
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_REPLACEMENTREGION,
body.P_BONDSURETY,
body.P_CARGOPOLICYNO,
body.P_CARGOSURETY,
body.P_USER_ID,
body.P_NOTES,
body.P_FILEIDS,
cursorName
]);
console.log("Procedure called");
// 🚫 DON'T quote the cursor name in FETCH
const fetchResult = await client.query(`FETCH ALL FROM ${cursorName}`);
console.log("Fetch done", fetchResult?.rows);
// 🚫 DON'T quote the cursor name in CLOSE
await client.query(`CLOSE ${cursorName}`);
console.log("Cursor closed");
await client.query('COMMIT');
console.log("Transaction committed");
checkPgUserDefinedErrors(fetchResult);
return { statusCode: 201, message: ResponseStatus.created, ...toUpperCaseKeys(fetchResult?.rows)[0] || {} };
} catch (error) {
if (client) await client.query('ROLLBACK');
console.log(" i went through here ... ");
handlePgError(error, SpService.name)
} finally {
releasePgClient(client)
}
}
async updateServiceProvider(body: UpdateServiceProviderDTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_updatesp($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_NAME,
body.P_LOOKUPCODE,
body.P_ADDRESS1,
body.P_ADDRESS2,
body.P_CITY,
body.P_STATE,
body.P_ZIP,
body.P_COUNTRY,
body.P_BONDSURETY,
body.P_CARGOPOLICYNO,
body.P_CARGOSURETY,
body.P_REPLACEMENTREGION,
body.P_ISSUINGREGION,
body.P_USER_ID,
body.P_NOTES,
body.P_FILEIDS,
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, SpService.name)
} finally {
releasePgClient(client)
}
}
async getAllServiceproviders() {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getallsps($1)
`;
await client.query(callProcQuery, [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, SpService.name)
} finally {
releasePgClient(client)
}
}
async getServiceproviderByID(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".uscib_managed_pkg_getspbyspid($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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)[0]??[];
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, SpService.name)
} finally {
releasePgClient(client)
}
}
}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { CarnetSequenceModule } from './carnet-sequence/carnet-sequence.module';
import { RegionModule } from './region/region.module';
import { SpModule } from './sp/sp.module';
import { SpContactsModule } from './sp-contacts/sp-contacts.module';
@Module({
imports: [CarnetSequenceModule, RegionModule, SpModule, SpContactsModule]
})
export class UscibManagedSpModule {}

View File

@ -0,0 +1,95 @@
import { Body, Controller, Get, Param, Patch, Post, Req, UseGuards } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
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, GetCarnetDetailsbyCarnetStatusDTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto';
import { Request } from 'express';
@ApiTags('User Maintenance - PG')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('pca', 'psa', 'pua')
@Controller('2')
export class UserMaintenanceController {
constructor(private readonly userMaintenanceService: UserMaintenanceService) { }
// SP_USER_DETAILS
// [spclientuser_pkg]
@Get('GetUserDetails/:P_USERID')
async GetSPUserDetails(@Param() params: USERID_DTO) {
return await this.userMaintenanceService.GetSPUserDetails(params);
}
// [userlogin_pkg]
@Patch('LockUserAccount')
async LockUserAccount(@Body() body: SPID_EMAIL_DTO) {
return await this.userMaintenanceService.LockUserAccount(body);
}
// USCIB_LOGINS
@Get('GetUSCIBLogins')
@Roles('pua')
async GetUSCIBLogins() {
return await this.userMaintenanceService.GetUSCIBLogins();
}
@Post('CreateUSCIBLogins')
@Roles('pua')
async CreateUSCIBLogins(@Body() body: CreateUSCIBLoginsDTO, @Req() req: Request) {
return await this.userMaintenanceService.CreateUSCIBLogins(body, req);
}
// SP LOGINS
@Get('GetSPLogins/:P_SPID')
@Roles('psa')
async GetSPLogins(@Param() params: SPID_DTO) {
return await this.userMaintenanceService.GetSPLogins(params);
}
@Post('CreateSPLogins')
@Roles('psa','pua')
async CreateSPLogins(@Body() body: CreateSPLoginsDTO, @Req() req: Request) {
return await this.userMaintenanceService.CreateSPLogins(body, req);
}
// CLIENT LOGINS
@Get('GetClientloginsBySPID/:P_SPID')
@Roles('psa')
async GetClientloginsBySPID(@Param() params: SPID_DTO) {
return await this.userMaintenanceService.GetClientloginsBySPID(params);
}
@Get('GetClientloginsByClientID/:P_SPID/:P_CLIENTID')
@Roles('psa')
async GetClientloginsByClientID(@Param() params: SPID_CLIENTID_DTO) {
return await this.userMaintenanceService.GetClientloginsByClientID(params);
}
@Post('CreateClientLogins')
@Roles('psa')
async CreateClientLogins(@Body() body: CreateClientLoginsDTO, @Req() req: Request) {
return await this.userMaintenanceService.CreateClientLogins(body, req);
}
// validate email
@Get('ValidateEmail/:P_EMAILADDR')
async ValidateEmail(@Param() params: EMAIL_DTO) {
return await this.userMaintenanceService.ValidateEmail(params);
}
// get carnet summary data
@Get('GetCarnetSummaryData/:P_USERID')
GetCarnetSummaryData(@Param() params: USERID_DTO) {
return this.userMaintenanceService.GetCarnetSummaryData(params);
}
}

View File

@ -0,0 +1,12 @@
import { forwardRef, Module } from '@nestjs/common';
import { UserMaintenanceController } from './user-maintenance.controller';
import { UserMaintenanceService } from './user-maintenance.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [forwardRef(() => AuthModule)],
controllers: [UserMaintenanceController],
providers: [UserMaintenanceService],
exports: [UserMaintenanceService]
})
export class UserMaintenanceModule { }

View File

@ -0,0 +1,595 @@
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
import { CreateClientLoginsDTO, CreateSPLoginsDTO, CreateUSCIBLoginsDTO, EMAIL_DTO, GetCarnetDetailsbyCarnetStatusDTO, SPID_CLIENTID_DTO, SPID_DTO, SPID_EMAIL_DTO, USERID_DTO } from 'src/dto/property.dto';
import { checkPgUserDefinedErrors, extractSubdomain, handlePgError, normalizeKeysToUpperCase, releasePgClient, ResponseStatus, toUpperCaseKeys } from 'src/utils/helper';
import { PoolClient } from 'pg';
import { PgDBService } from 'src/db/db.service';
import { InternalServerException } from 'src/exceptions/internalServerError.exception';
import { AuthService } from 'src/auth/auth.service';
import { MailTypeDTO } from 'src/auth/auth.dto';
import { Request } from 'express';
@Injectable()
export class UserMaintenanceService {
private readonly logger = new Logger(UserMaintenanceService.name);
constructor(
private readonly pgDBService: PgDBService,
@Inject(forwardRef(() => AuthService))
private readonly authService: AuthService
) { }
async GetSPUserDetails(body: USERID_DTO): Promise<any> {
let client: PoolClient | null = null;
// Assign unique names to each cursor
const roleCursor = 'role_cursor';
const menuCursor = 'menu_cursor';
const menuPageCursor = 'menu_page_cursor';
const userDetailsCursor = 'user_details_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".spclientuser_pkg_getspuserdetails($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery, [
body.P_USERID,
roleCursor,
menuCursor,
menuPageCursor,
userDetailsCursor
]);
// Fetch all data from each cursor
const roleResult = await client.query(`FETCH ALL FROM ${roleCursor}`);
const menuResult = await client.query(`FETCH ALL FROM ${menuCursor}`);
const menuPageResult = await client.query(`FETCH ALL FROM ${menuPageCursor}`);
const userDetailsResult = await client.query(`FETCH ALL FROM ${userDetailsCursor}`);
// Close all cursors
await client.query(`CLOSE ${roleCursor}`);
await client.query(`CLOSE ${menuCursor}`);
await client.query(`CLOSE ${menuPageCursor}`);
await client.query(`CLOSE ${userDetailsCursor}`);
await client.query('COMMIT');
// no need for this api
// checkPgUserDefinedErrors(roleResult);
// checkPgUserDefinedErrors(menuResult);
// checkPgUserDefinedErrors(menuPageResult);
// checkPgUserDefinedErrors(userDetailsResult);
return {
roleDetails: toUpperCaseKeys(roleResult.rows).map(x => x.ROLENAME),
menuDetails: toUpperCaseKeys(menuResult.rows).map(x => x.MENUNAME),
menuPageDetails: toUpperCaseKeys(menuPageResult.rows),
userDetails: toUpperCaseKeys(userDetailsResult.rows)[0],
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, 'getSpUserDetails');
} finally {
releasePgClient(client);
}
}
async LockUserAccount(body: SPID_EMAIL_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_lockuseraccount($1, $2, $3)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_EMAILADDR,
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.lockedUserDone,
// ...toUpperCaseKeys(fetchResult?.rows)[0]
// };
return toUpperCaseKeys(fetchResult?.rows)
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
// USCIB_LOGINS
async GetUSCIBLogins() {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_getusciblogins($1)
`;
await client.query(callProcQuery, [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, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
async CreateUSCIBLogins(body: CreateUSCIBLoginsDTO, req: Request) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_createusciblogins($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_USERID,
body.P_EMAILADDR,
body.P_LOOKUPCODE,
body.P_ENABLEPASSWORDPOLICY,
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);
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
const mailRes = await this.authService.sendMail({ P_TO: body.P_USERID, P_MAIL_TYPE: MailTypeDTO.REGISTER_USCIB }, appDomain)
if (mailRes.statusCode !== 200) {
throw new InternalServerException();
}
return {
statusCode: 201,
message: ResponseStatus.created,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
// SP LOGINS
async GetSPLogins(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_getsplogins($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
async CreateSPLogins(body: CreateSPLoginsDTO, req: Request) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_createsplogins($1, $2, $3, $4, $5, $6, $7)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_USERID,
body.P_DOMAIN,
body.P_EMAILADDR,
body.P_LOOKUPCODE,
body.P_ENABLEPASSWORDPOLICY,
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);
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
const mailRes = await this.authService.sendMail({ P_TO: body.P_USERID, P_MAIL_TYPE: MailTypeDTO.REGISTER_SP }, appDomain)
if (mailRes.statusCode !== 200) {
throw new InternalServerException();
}
return {
statusCode: 201,
message: ResponseStatus.created,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
// CLIENT LOGINS
async GetClientloginsBySPID(body: SPID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_getclientloginsbyspid($1, $2)
`;
await client.query(callProcQuery, [body.P_SPID, 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, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
async GetClientloginsByClientID(body: SPID_CLIENTID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_getclientloginsbyclientid($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, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
async CreateClientLogins(body: CreateClientLoginsDTO, req: Request) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_createclientlogins($1, $2, $3, $4, $5)
`;
await client.query(callProcQuery,
[
body.P_SPID,
body.P_USERID,
body.P_CLIENTCONTACTID,
body.P_ENABLEPASSWORDPOLICY,
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);
let appDomain;
if (req.headers.origin) {
appDomain = extractSubdomain(req.headers.origin)
}
else {
appDomain = ""
}
const mailRes = await this.authService.sendMail({ P_TO: body.P_USERID, P_MAIL_TYPE: MailTypeDTO.REGISTER_CLIENT }, appDomain)
if (mailRes.statusCode !== 200) {
throw new InternalServerException();
}
return {
statusCode: 201,
message: ResponseStatus.clientRegistrationDone,
...toUpperCaseKeys(fetchResult?.rows)[0]
};
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
// validate email
async ValidateEmail(body: EMAIL_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_validateemail($1, $2)
`;
await client.query(callProcQuery, [body.P_EMAILADDR, 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);
if (fetchResult?.rows.length > 0) {
return toUpperCaseKeys(fetchResult.rows)
}
else {
return [];
}
} catch (error) {
if (client) await client.query('ROLLBACK');
handlePgError(error, UserMaintenanceService.name)
} finally {
releasePgClient(client)
}
}
//carnet summary data
async GetCarnetSummaryData(body: USERID_DTO) {
let client: PoolClient | null = null;
const cursorName = 'p_cursor';
try {
client = await this.pgDBService.getConnection();
await client.query('BEGIN');
const callProcQuery = `
CALL "CARNETSYS".userlogin_pkg_getcarnetsummarydata($1, $2)
`;
await client.query(callProcQuery, [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);
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 = { };
if (curr.CARNETSTATUS == null){
newItem['CARNETSTATUS'] = [];
newItem['Carnet_Count'] = [];
}
else{
newItem['CARNETSTATUS'] = [curr.CARNETSTATUS];
newItem['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)
}
}
}

View File

@ -17,6 +17,89 @@ import { PrintCarnetDTO, PrintGLDTO } from 'src/dto/property.dto';
const logger = new Logger('Helper');
export enum ResponseStatus {
created = 'Created Successfully',
updated = 'Updated Successfully',
defaultSpContactAdded = "Default contact was added successfully for SP",
inActivate = 'Inactivated Successfully',
reActivate = 'Reactivated Successfully',
clientRegistrationDone = 'Client registration initiated successfully',
lockedUserDone = 'Locked Successfully',
transmitted = 'Transmitted Successfully',
added = 'Added Successfully',
deleted = 'Deleted Successfully',
processed = 'Processed Successfully',
voided = 'Voided Successfully',
copied = 'Coppied Successfully',
duplicated = 'Duplicated Successfully',
addl_completed = 'Additional sets completed',
extended = 'Extended Successfully',
saved = 'Saved Successfully',
closed = 'Closed Successfully',
reset_successfull = 'Reset Successfull'
}
export function extractSubdomain(domain: string): string | null {
try {
const url = new URL(domain);
const hostname = url.hostname; // e.g., "der.asd.com", "localhost", "121.1.21.123"
// Return the full hostname if it's an IP address or 'localhost'
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname) || hostname === 'localhost') {
return hostname;
}
const parts = hostname.split('.');
if (parts.length < 3) {
// Not enough parts to have a subdomain (e.g., "asd.com")
return null;
}
// Return the subdomain (leftmost part)
return parts[0];
} catch (e) {
console.error('Invalid domain:', domain, e);
return null;
}
}
export function parsePGNumericFields(row) {
const keysToConvert = [
'BASICFEE', 'CFFEE', 'CSFEE', 'EFFEE', 'SHIPFEE',
'SECURITYAMOUNT', 'BONDPREMIUM', 'INSUREDVALUE',
'CARGOPREMIUM', 'LDIPREMIUM'
];
const parsed = { ...row };
for (const key of keysToConvert) {
if (parsed[key] !== null && parsed[key] !== undefined) {
parsed[key] = Number(parsed[key]);
}
}
return parsed;
}
export function normalizeKeysToUpperCase(obj) {
return Object.keys(obj).reduce((acc, key) => {
acc[key.toUpperCase()] = obj[key];
return acc;
}, {});
}
export function toUpperCaseKeys(rows: Record<string, any>[]): Record<string, any>[] {
return rows.map(row => {
const transformedRow: Record<string, any> = {};
for (const key in row) {
transformedRow[key.toUpperCase()] = row[key];
}
return transformedRow;
});
}
export const handleError = (error: any, context: string = 'UnknownService'): never => {
if (error instanceof BadRequestException || error instanceof BR) {
logger.warn(`[${context}] ${error.message}`);
@ -37,6 +120,32 @@ export const handleError = (error: any, context: string = 'UnknownService'): nev
throw new InternalServerErrorException(error.message || 'Internal error');
};
export const handlePgError = (error: any, context: string = 'UnknownService'): never => {
if (error instanceof BadRequestException || error instanceof BR) {
logger.warn(`[${context}] ${error.message}`);
throw error;
}
logger.error(`[${context}] Unexpected error:`, error.message);
throw new InternalServerErrorException(error.message || 'Internal error');
}
export function releasePgClient(client: any) {
if (client && typeof client.release === 'function') {
try {
client.release();
} catch (err) {
console.error('Error releasing client:', err);
}
}
}
export const checkPgUserDefinedErrors = (fetchResult: any) => {
if (fetchResult?.rows?.[0]?.errormesg) {
throw new BadRequestException(fetchResult?.rows?.[0]?.errormesg);
}
}
export const closeOracleDbConnection = async (connection: any, context: string = 'UnknownService'): Promise<void> => {
if (connection) {
try {
@ -1201,8 +1310,8 @@ export async function processGlDataInBatches(
let totalItemValue = 0;
for (const item of glDataArray) {
if (typeof item.itemValue === 'number') {
totalItemValue += item.itemValue;
if (typeof Number(item.itemValue) === 'number') {
totalItemValue += Number(item.itemValue);
} else {
console.warn(`Non-numeric itemValue encountered for itemNo: ${item.itemNo}. Skipping value.`);
}