init push
commit
12765d00c2
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js'],
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,109 @@
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
# movie-bucket-project-api
|
||||
|
||||
Online Movie Show Management and Ticket Booking API
|
||||
@ -0,0 +1,113 @@
|
||||
server:
|
||||
port: 3500
|
||||
db:
|
||||
type: 'postgres'
|
||||
port: '5432'
|
||||
sid: 'artnouveau'
|
||||
oraclesid: 'tbnkdb'
|
||||
oracleport: '1521'
|
||||
|
||||
jwt:
|
||||
expiresIn: 3600
|
||||
|
||||
otp:
|
||||
expiresIn: 5
|
||||
|
||||
crypto:
|
||||
accessToken: 'accessToken@#123'
|
||||
refreshToken: 'refreshToken@#123'
|
||||
commonKey: 'commonKey@#123'
|
||||
|
||||
google:
|
||||
clientID: '42183132451-b2p8fit0okhec8dq8d15ddgu6msa4mro.apps.googleusercontent.com'
|
||||
clientSecret: 'EZvk3XK4_C1mhVXHm_izCDX6'
|
||||
callbackURL : 'https://myfin.api.teorainfotech.com/api/v1/auth/google/callback'
|
||||
succesRedirectURL : 'https://myfin.teorainfotech.com/#/auth/google'
|
||||
failRedirectURL: 'https://myfin.teorainfotech.com/login/failure'
|
||||
|
||||
facebook:
|
||||
appId: 2250938211710092
|
||||
appSecret: 4eabf9e73c1871a84645d1fffeb07c39
|
||||
callbackURL: 'https://myfin.api.teorainfotech.com/api/v1/auth/facebook/redirect'
|
||||
|
||||
mail:
|
||||
fromMail: 'tenderartnouveau@gmail.com'
|
||||
user: 'tenderartnouveau@gmail.com'
|
||||
pass: 'tvrhahtabrwfjshn'
|
||||
|
||||
cron:
|
||||
scheduler: false
|
||||
|
||||
body:
|
||||
from: 'Nexmo'
|
||||
text: 'Test Message from innovations cochin'
|
||||
to: '+9181390 12392'
|
||||
api_key: '6b8c19bc'
|
||||
api_secret: 'BWbmroBtJfX0HPQ1'
|
||||
|
||||
smsPhoneNumberArgName:
|
||||
phoneno: 'to'
|
||||
message: 'text'
|
||||
|
||||
url:
|
||||
url: "https://www.thrickodithanamscb.in/#"
|
||||
|
||||
bodyWay2SMS:
|
||||
apikey: "CKDG9HL5KYFLLILRMX3QX1CPKOIP8QF1"
|
||||
secret: "N373LNKAAJ079JY7"
|
||||
usetype: "stage"
|
||||
phone: "8139012392"
|
||||
message: "Haiii..."
|
||||
senderid: "WAYSMS"
|
||||
|
||||
smsPhoneNumberArgNameWay2SMS:
|
||||
phoneno: 'phone'
|
||||
messsgae: 'message'
|
||||
|
||||
urlWay2SMS:
|
||||
url: "http://www.way2sms.com/api/v1/sendCampaign"
|
||||
|
||||
sms-headers:
|
||||
headers: { "content-type": "application/json" }
|
||||
|
||||
phonepe-gateway:
|
||||
salt : "f53ab68c-456e-4850-9ff6-ebd6139a8959"
|
||||
merchantId : "M224VO4ETK6Z8"
|
||||
indexKey : 1
|
||||
url : "https://api.phonepe.com/apis/hermes/pg/v1/pay"
|
||||
redirectUrlT : "https://tender.artnouveau.in/#/dashboard"
|
||||
redirectUrlE : "https://tender.artnouveau.in/#/tender-upload"
|
||||
callbackUrl : "https://tenderapi.artnouveau.in/api/v1/phonepe-payment-gateway/payment-status"
|
||||
statusUrl : "https://api.phonepe.com/apis/hermes/pg/v1/status"
|
||||
testing : true
|
||||
|
||||
|
||||
payment-gateway:
|
||||
successRedirectUrl: "/tender-view"
|
||||
failureRedirectUrl: "/tender-view"
|
||||
successRedirectUrlStudent: "/student/payment-redirection"
|
||||
failureRedirectUrlStudent: "/student/payment-redirection"
|
||||
successRedirectUrlStudentInternal: "/transaction/student-fee"
|
||||
failureRedirectUrlStudentInternal: "/transaction/student-fee"
|
||||
successRedirectUrlAcceptance: "/student/application"
|
||||
failureRedirectUrlAcceptance: "/student/application"
|
||||
successRedirectUrlAcceptancePublic: "/auth/public/admission-form"
|
||||
failureRedirectUrlAcceptancePublic: "auth/public/admission-form"
|
||||
furl: "https://tenderapi.simssoftware.in/api/v1/payment-gateway/failure"
|
||||
surl: "https://tenderapi.simssoftware.in/api/v1/payment-gateway/success"
|
||||
key : "MY3BX1lo"
|
||||
salt : "9BISuuPeit"
|
||||
testing : true
|
||||
|
||||
sms-merabt:
|
||||
url: "http://reseller.smschub.com/api/sms/format/json"
|
||||
peId: "1201160336050556744"
|
||||
# peTemplateId: 1207163341521627472
|
||||
peTemplateId: "1207164196662343521"
|
||||
apiKey: "b6bf2ebf9bb6e74d9538892569f7e9cc"
|
||||
urlEncd: "Y"
|
||||
sender: "TRISCB"
|
||||
|
||||
default-bank:
|
||||
id: "acc1"
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
db:
|
||||
host: '3.110.164.8'
|
||||
username: 'postgres'
|
||||
password: 'inv123'
|
||||
sid: 'artnouveau'
|
||||
synchronize: false
|
||||
oraclehost: '59.94.179.105'
|
||||
oracleusername: 'simsmobapp'
|
||||
oraclepassword: 'simsmobapp'
|
||||
oraclesid: 'pacs'
|
||||
oracleType: 'oracle'
|
||||
|
||||
jwt:
|
||||
secret: 'topSecret51'
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src"
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
{
|
||||
"name": "artnouveau-api",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nest-modules/mailer": "^1.3.22",
|
||||
"@nestjs/axios": "^3.0.0",
|
||||
"@nestjs/common": "^9.4.3",
|
||||
"@nestjs/core": "^9.4.3",
|
||||
"@nestjs/jwt": "^10.0.3",
|
||||
"@nestjs/passport": "^9.0.3",
|
||||
"@nestjs/platform-express": "^9.4.3",
|
||||
"@nestjs/schedule": "^3.0.2",
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@types/passport-jwt": "^3.0.8",
|
||||
"archiver": "^5.3.1",
|
||||
"bcrypt": "^5.1.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"config": "^3.3.9",
|
||||
"crypto-js": "^4.1.1",
|
||||
"i": "^0.3.7",
|
||||
"js-sha512": "^0.8.0",
|
||||
"jspdf": "^2.5.1",
|
||||
"jspdf-autotable": "^3.5.31",
|
||||
"node-forge": "^1.3.1",
|
||||
"npm": "^9.8.1",
|
||||
"otp-generator": "^4.0.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"payu": "^0.0.1",
|
||||
"payumoney_nodejs": "^2.0.4",
|
||||
"payumoney-node": "^2.0.1",
|
||||
"pg": "^8.10.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.2.0",
|
||||
"typeorm": "^0.3.16",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^9.5.0",
|
||||
"@nestjs/schematics": "^9.2.0",
|
||||
"@nestjs/testing": "^9.4.3",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/jest": "28.1.8",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/supertest": "^2.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "28.1.3",
|
||||
"prettier": "^2.3.2",
|
||||
"source-map-support": "^0.5.20",
|
||||
"supertest": "^6.1.3",
|
||||
"ts-jest": "28.0.8",
|
||||
"ts-loader": "^9.2.3",
|
||||
"ts-node": "^10.0.0",
|
||||
"tsconfig-paths": "4.1.0",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { typeOrmConfig } from './config/typeorm.config';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { FileUploadModule } from './file-upload/file-upload.module';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { TenderDetailsModule } from './tables/tender-master/tender-details.module';
|
||||
import { FormOfContractModule } from './tables/form-of-contract/form-of-contract.module';
|
||||
import { PaymentModeModule } from './tables/payment-mode/payment-mode.module';
|
||||
import { TenderTypeModule } from './tables/tender-type/tender-type.module';
|
||||
import { basicCategoryModule } from './tables/category/category.module';
|
||||
import { TenderCategoryModule } from './tables/tender-category/tender-category.module';
|
||||
import { EmdFeeTypeModule } from './tables/emd-fee-type/emd-fee-type.module';
|
||||
import { TenderModule } from './transactions/tender/tender.module';
|
||||
import { TenderDocModule } from './tables/tender-documents/tender-doc.module';
|
||||
import { DocumentTypeModule } from './tables/document-type/document-type.module';
|
||||
import { CoversLovModule } from './tables/covers-lov/covers-lov.module';
|
||||
import { FileFormatLovModule } from './tables/file-format-lov/file-format-lov.module';
|
||||
import { CoversMasterModule } from './tables/covers-master/covers-master.module';
|
||||
import { PaymentGatewayModule } from './payment-gateway/payment-gateway.module';
|
||||
import { PayuTransactionListModule } from './tables/payu-transaction-list/payu-transaction-list.module';
|
||||
import { PaymentStatusModule } from './tables/payment-status/payment-status.module';
|
||||
import { PaymentMasterModule } from './tables/payment-master/payment-master.module';
|
||||
import { CommonModule } from './tables/common/common.module';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { ReportAuthenticationModule } from './tables/report-authentication/report-authentication.module';
|
||||
import { TenderSubcategoryModule } from './tables/tender-subcategory/tender-subcategory.module';
|
||||
import { TenderSubcategoryMasterModule } from './tables/tender-subcategory-master/tender-subcategory-master.module';
|
||||
import { ClosedTenderUsersModule } from './tables/closed-tender-users/closed-tender-users.module';
|
||||
import { galleryModule } from './tables/gallery/gallery.module';
|
||||
import { SubGalleryModule } from './tables/sub-gallery/sub-gallery.module';
|
||||
import { ImagesService } from './transactions/images/images.service';
|
||||
import { ImagesModule } from './transactions/images/images.module';
|
||||
import { galleryRepository } from './tables/gallery/gallery.repository';
|
||||
import { subGalleryRepository } from './tables/sub-gallery/sub-gallery.repository';
|
||||
import { CategoryModule } from './tables/userCategory-master/category.module';
|
||||
import { PhonepeTransactionListModule } from './tables/phonepe-transaction-list/phonepe-transaction-list.module';
|
||||
import { RevisedTenderModule } from './tables/revised-tender/revised-tender.module';
|
||||
import { UserSubcategoryMasterModule } from './tables/user-subcategory-master/user-subcategory-master.module';
|
||||
|
||||
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ScheduleModule.forRoot(),
|
||||
TypeOrmModule.forRoot(typeOrmConfig),
|
||||
FileUploadModule,
|
||||
AuthModule,
|
||||
TenderDetailsModule,
|
||||
FormOfContractModule,
|
||||
PaymentModeModule,
|
||||
TenderTypeModule,
|
||||
basicCategoryModule,
|
||||
TenderCategoryModule,
|
||||
EmdFeeTypeModule,
|
||||
TenderModule,
|
||||
TenderDocModule,
|
||||
DocumentTypeModule,
|
||||
CoversLovModule,
|
||||
FileFormatLovModule,
|
||||
CoversMasterModule,
|
||||
PaymentGatewayModule,
|
||||
PayuTransactionListModule,
|
||||
PaymentStatusModule,
|
||||
PaymentMasterModule,
|
||||
CommonModule,
|
||||
ReportAuthenticationModule,
|
||||
TenderSubcategoryModule,
|
||||
TenderSubcategoryMasterModule,
|
||||
ClosedTenderUsersModule,
|
||||
galleryModule,
|
||||
SubGalleryModule,
|
||||
ImagesModule,
|
||||
CategoryModule,
|
||||
PhonepeTransactionListModule,
|
||||
RevisedTenderModule,
|
||||
UserSubcategoryMasterModule
|
||||
|
||||
],
|
||||
providers: [ImagesService,galleryRepository,subGalleryRepository],
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(private dataSource: DataSource) {}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
import { Controller, Get, UseGuards, Res, Req, Body, ValidationPipe, Post, HttpCode, Ip, HostParam, HttpStatus, Put, Param, Patch, Delete, Query } from '@nestjs/common';
|
||||
|
||||
import { TokenDto } from './dto/token.dto';
|
||||
|
||||
import * as config from 'config';
|
||||
import { AuthCreadentialsDto } from './dto/auth-credentials.dto';
|
||||
import { AuthService } from './auth.service';
|
||||
import { TempSignUpDto } from './dto/temp-sign-up.dto';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { GetUser } from './dto/get-user.decorator';
|
||||
import { Pcduser } from './pcduser.entity';
|
||||
import { PcduserDto } from './dto/pcd-user.dto';
|
||||
import { Cron } from '@nestjs/schedule';
|
||||
import { ChangePasswordDto } from './dto/change-password.dto';
|
||||
import { UserBankDto } from './dto/user-bank.dto';
|
||||
import { FindManyOptions } from 'typeorm';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(
|
||||
private authService: AuthService
|
||||
) { }
|
||||
|
||||
// @Get('user-data')
|
||||
// async userData() {
|
||||
// return this.authService.getAll()
|
||||
// }
|
||||
// @Get('users')
|
||||
// async usersData() {
|
||||
// return this.authService.getusers()
|
||||
// }
|
||||
// @Get('user-data/:id')
|
||||
// async userDataById(
|
||||
// @Param('id') id:string
|
||||
// ) {
|
||||
// return this.authService.getbyUserId(id)
|
||||
// }
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Put('user-data/:id')
|
||||
async editUser(
|
||||
@Param('id') id:string,
|
||||
@Body() body : PcduserDto,
|
||||
@GetUser() user:PcduserDto
|
||||
){
|
||||
return await this.authService.editUser(id,body,user)
|
||||
}
|
||||
|
||||
// @Delete('user-data/:id')
|
||||
// async deleteUser(
|
||||
// @Param('id') id:string,
|
||||
|
||||
// ){
|
||||
// return await this.authService.deleteUser(id)
|
||||
// }
|
||||
|
||||
@Post('/user-info')
|
||||
async userInfo(@Body() authCredentialDto: AuthCreadentialsDto) {
|
||||
return this.authService.userInfo(authCredentialDto)
|
||||
}
|
||||
|
||||
|
||||
@Post('/signin')
|
||||
async signIn(@Body(ValidationPipe)
|
||||
authCredentialDto: AuthCreadentialsDto,
|
||||
@Req() req): Promise<TokenDto> {
|
||||
return this.authService.signIn(authCredentialDto, req.ip);
|
||||
}
|
||||
|
||||
@Get()
|
||||
async getall() {
|
||||
return this.authService
|
||||
}
|
||||
|
||||
@Post('/signup')
|
||||
async signUp(@Body() pcdUserDto: PcduserDto): Promise<any> {
|
||||
// request.connection.remoteAddress
|
||||
console.log("hello");
|
||||
|
||||
return this.authService.tempSignUp(pcdUserDto);
|
||||
}
|
||||
|
||||
@Post('/forgot-password')
|
||||
async forgotPassword(
|
||||
@Body() body: { pass: string, email: string, otp: string },
|
||||
): Promise<any> {
|
||||
return await this.authService.forgotPassword(body);
|
||||
}
|
||||
|
||||
@Post('/otp/:flag')
|
||||
async sendOtp(
|
||||
@Body() body: { email: string, custName: string, tenderName?: string, bidOpenDate?: string },
|
||||
@Param('flag') flag: string
|
||||
): Promise<void> {
|
||||
console.log("helo==========================");
|
||||
|
||||
return await this.authService.sendOtp(body, flag);
|
||||
}
|
||||
|
||||
// @Post('/resend-otp/:flag')
|
||||
// async resendOtp(
|
||||
// @Body() body: { code?: string | number, email?: string, mobile: string },
|
||||
// @Param('flag') flag: string
|
||||
// ): Promise<void> {
|
||||
// return await this.authService.resendOtp(body,flag);
|
||||
// }
|
||||
|
||||
@Post('/verifyOtp/:flag')
|
||||
async verifyOtp(
|
||||
@Body() body: { otp: string, email: string },
|
||||
@Param('flag') flag: string
|
||||
): Promise<any> {
|
||||
return await this.authService.verifyOtp(body, flag);
|
||||
}
|
||||
|
||||
@Get('statusVerify')
|
||||
async statusVerify(
|
||||
){
|
||||
return this.authService.statusVerify();
|
||||
}
|
||||
|
||||
@Post('reqUser')
|
||||
async reqUser(
|
||||
@Body() body: {status :string,userId:any },
|
||||
// @GetUser() user: PcduserDto
|
||||
|
||||
){
|
||||
console.log(body.status);
|
||||
|
||||
return await this.authService.reqUser(body)
|
||||
}
|
||||
}
|
||||
@UseGuards(AuthGuard())
|
||||
@Controller('admin')
|
||||
export class AdminAuthController {
|
||||
constructor(
|
||||
private authService: AuthService
|
||||
) { }
|
||||
|
||||
@Get('user-data')
|
||||
async userData(
|
||||
@GetUser() user:PcduserDto
|
||||
) {
|
||||
return this.authService.getAll(user)
|
||||
}
|
||||
@Get('users')
|
||||
async usersData(
|
||||
@Query() filter: FindManyOptions,
|
||||
@GetUser() user:PcduserDto
|
||||
) {
|
||||
return await this.authService.getusers(user,filter)
|
||||
}
|
||||
@Get('user-data/:id')
|
||||
async userDataById(
|
||||
@Param('id') id:string,
|
||||
@GetUser() user:PcduserDto
|
||||
) {
|
||||
return await this.authService.getbyUserId(id,user)
|
||||
}
|
||||
|
||||
@Put('user-data/:id')
|
||||
async editUser(
|
||||
@Param('id') id:string,
|
||||
@Body() body : PcduserDto,
|
||||
@GetUser() user:PcduserDto
|
||||
){
|
||||
return await this.authService.editUser(id,body,user)
|
||||
}
|
||||
|
||||
@Delete('user-data/:id')
|
||||
async deleteUser(
|
||||
@Param('id') id:string,
|
||||
@GetUser() user:PcduserDto
|
||||
){
|
||||
return await this.authService.deleteUser(id,user)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AdminAuthController, AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
import * as config from 'config';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { CryptoService } from './crypto.service';
|
||||
import { JwtStrategy } from './jwt.stategy';
|
||||
import { PcduserRepository } from './pcduser.repository';
|
||||
import { PcdotpRepository } from './pcdotp.repository';
|
||||
import { EmailService } from 'src/email/email.service';
|
||||
import { EmailModule } from 'src/email/email.module';
|
||||
import { Pcduser } from './pcduser.entity';
|
||||
import { Pcdotp } from './pcdotp.entity';
|
||||
import { categoryRepository } from 'src/tables/userCategory-master/category.repository';
|
||||
import { TenderMasterRepository } from 'src/tables/tender-master/tender-master.repository';
|
||||
import { userSubCategoryMasterRepo } from 'src/tables/user-subcategory-master/user-subcategory-master.repository';
|
||||
|
||||
|
||||
const jwtConfig = config.get('jwt');
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PassportModule.register({ defaultStrategy: 'jwt' }),
|
||||
JwtModule.register({
|
||||
secret: process.env.JWT_SECRET || jwtConfig.secret,
|
||||
signOptions: {
|
||||
expiresIn: jwtConfig.expiresIn,
|
||||
}
|
||||
}),
|
||||
TypeOrmModule.forFeature([
|
||||
Pcduser,
|
||||
Pcdotp,
|
||||
|
||||
]),EmailModule,AuthModule
|
||||
],
|
||||
controllers: [AuthController,AdminAuthController],
|
||||
providers: [
|
||||
AuthService,
|
||||
CryptoService,
|
||||
JwtStrategy,
|
||||
PcdotpRepository,
|
||||
PcduserRepository,
|
||||
categoryRepository,
|
||||
TenderMasterRepository,
|
||||
userSubCategoryMasterRepo
|
||||
|
||||
|
||||
],
|
||||
exports: [
|
||||
JwtStrategy,
|
||||
JwtModule,
|
||||
PassportModule,
|
||||
CryptoService
|
||||
],
|
||||
})
|
||||
export class AuthModule { }
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import * as CryptoJS from 'crypto-js';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class CryptoService {
|
||||
constructor() { }
|
||||
|
||||
//The set method is use for encrypt the value.
|
||||
set(keys, value) {
|
||||
var key = CryptoJS.enc.Utf8.parse(keys);
|
||||
var iv = CryptoJS.enc.Utf8.parse(keys);
|
||||
var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(value.toString()), key,
|
||||
{
|
||||
keySize: 128 / 8,
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
return encrypted.toString();
|
||||
}
|
||||
|
||||
//The get method is used for decrypt the value.
|
||||
get(keys, value) {
|
||||
var key = CryptoJS.enc.Utf8.parse(keys);
|
||||
var iv = CryptoJS.enc.Utf8.parse(keys);
|
||||
var decrypted = CryptoJS.AES.decrypt(value, key, {
|
||||
keySize: 128 / 8,
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
|
||||
//encryption method
|
||||
encryptAesB64(value) {
|
||||
let b64 = CryptoJS.AES.encrypt(value.toString(), 'etarucca').toString();
|
||||
let e64 = CryptoJS.enc.Base64.parse(b64);
|
||||
let encryptedCode = e64.toString(CryptoJS.enc.Hex);
|
||||
return { "data": encryptedCode };
|
||||
}
|
||||
|
||||
//decryption method
|
||||
decryptAesB64(value) {
|
||||
var reb64 = CryptoJS.enc.Hex.parse(value);
|
||||
var bytes = reb64.toString(CryptoJS.enc.Base64);
|
||||
var decrypt = CryptoJS.AES.decrypt(bytes, 'etarucca');
|
||||
var dycryptedCode = decrypt.toString(CryptoJS.enc.Utf8);
|
||||
return dycryptedCode
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import { IsNotEmpty, IsString, MaxLength, maxLength, MinLength } from "class-validator";
|
||||
|
||||
export class AuthCreadentialsDto {
|
||||
|
||||
|
||||
@IsString()
|
||||
@MinLength(2)
|
||||
@MaxLength(100)
|
||||
username: string;
|
||||
|
||||
password: string;
|
||||
|
||||
module?: string;
|
||||
|
||||
custId: string;
|
||||
|
||||
email: string;
|
||||
|
||||
secuLevel: any;
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import { IsString, MaxLength, MinLength } from "class-validator";
|
||||
|
||||
export class ChangePasswordDto{
|
||||
|
||||
// @MinLength(4)
|
||||
// @Matches(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/,
|
||||
// { message: 'password is too weak' }
|
||||
// )
|
||||
currentPwd:string;
|
||||
|
||||
// @MinLength(4)
|
||||
pass: string;
|
||||
|
||||
|
||||
tpass?: string;
|
||||
|
||||
deviceId?:string;
|
||||
|
||||
mobNo? : string
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
|
||||
import {Pcduser} from "src/auth/pcduser.entity";
|
||||
|
||||
export const GetUser = createParamDecorator(
|
||||
(data: unknown, ctx: ExecutionContext):Pcduser => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
|
||||
return request.user;
|
||||
},
|
||||
);
|
||||
@ -0,0 +1,15 @@
|
||||
export class GoogleProfileDto{
|
||||
displayName: string;
|
||||
|
||||
name: { familyName: string, givenName: string};
|
||||
|
||||
emails: {value: string, verified: true}[];
|
||||
|
||||
photos: {value: string}[];
|
||||
|
||||
provider: string;
|
||||
|
||||
_row: { sub: string, name: string, given_name: string, family_name: string, picture: string, email: string, email_verified: boolean, locale: string};
|
||||
|
||||
_json: { sub: string, name: string, given_name: string, family_name: string, picture: string, email: string, email_verified: boolean };
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
import { userSubCategoryDto } from "src/dto/user-subcategory-master.dto";
|
||||
|
||||
export class PcduserDto {
|
||||
|
||||
userId: string;
|
||||
|
||||
userName: string;
|
||||
|
||||
groupOrUser: string;
|
||||
|
||||
pass: string | null;
|
||||
|
||||
salt: string | null;
|
||||
|
||||
secuLevel: string | null;
|
||||
|
||||
pwdExpDays: number | null;
|
||||
|
||||
email: string;
|
||||
|
||||
mobileNumber: string;
|
||||
|
||||
userImagePath: string;
|
||||
|
||||
refreshtoken: string;
|
||||
|
||||
memberNo: string;
|
||||
|
||||
custId: string;
|
||||
|
||||
status: string;
|
||||
|
||||
bankId: string;
|
||||
|
||||
tPass: string | null;
|
||||
|
||||
tSalt: string | null;
|
||||
|
||||
deviceId:string;
|
||||
|
||||
otp?:string;
|
||||
|
||||
subCategory?:any
|
||||
|
||||
active: boolean;
|
||||
|
||||
employee:boolean;
|
||||
|
||||
maxAmount : number
|
||||
|
||||
companyProfile:string
|
||||
|
||||
projectCompletedCert:string
|
||||
|
||||
Category? : any
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { PcdBaseDto } from "src/framework/custom/pcd-dto.custom";
|
||||
|
||||
export class PcdotpDto extends PcdBaseDto{
|
||||
|
||||
code: number;
|
||||
|
||||
otp: string;
|
||||
|
||||
refCode: string;
|
||||
|
||||
usedFor: string;
|
||||
|
||||
status: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
import { IsNotEmpty } from "class-validator";
|
||||
|
||||
export class RtgsDto {
|
||||
|
||||
rtgsId: string;
|
||||
|
||||
brCode: string;
|
||||
|
||||
dayDt: string;
|
||||
|
||||
code: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
accNo: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
toAccNo: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
toParti: string;
|
||||
|
||||
toEmail: null;
|
||||
|
||||
toMobile: null;
|
||||
|
||||
@IsNotEmpty()
|
||||
toBank: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
toBranch: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
ifscCode: string;
|
||||
|
||||
cashAdj: string;
|
||||
|
||||
payMode: string;
|
||||
|
||||
remarks: string;
|
||||
|
||||
uploadStatus: string;
|
||||
|
||||
credit: null;
|
||||
|
||||
@IsNotEmpty()
|
||||
debit: number;
|
||||
|
||||
slipNo: number;
|
||||
|
||||
clerk: string;
|
||||
|
||||
cashier: string;
|
||||
|
||||
manager: string;
|
||||
|
||||
clerkId: number;
|
||||
|
||||
mgrId: number;
|
||||
|
||||
cashierId: null;
|
||||
|
||||
rejectReason: null;
|
||||
|
||||
entryTime: string;
|
||||
|
||||
appScr: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
commAmt: number;
|
||||
|
||||
chNo: null;
|
||||
|
||||
chDate: null;
|
||||
|
||||
dayDate: any;
|
||||
|
||||
@IsNotEmpty()
|
||||
depType: any;
|
||||
|
||||
dayBeginDt: any;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
import { IsString, MinLength, MaxLength, Matches, IsNotEmpty, IsNumber, IsIn } from "class-validator";
|
||||
|
||||
export class TempSignUpDto {
|
||||
|
||||
// @IsString()
|
||||
// @MinLength(0)
|
||||
// @MaxLength(12)
|
||||
// @IsNotEmpty()
|
||||
email: string;
|
||||
|
||||
|
||||
|
||||
@IsString()
|
||||
@MinLength(2)
|
||||
@MaxLength(20)
|
||||
username: string;
|
||||
|
||||
|
||||
@IsString()
|
||||
@MinLength(4)
|
||||
@MaxLength(20)
|
||||
password: string;
|
||||
|
||||
tpassword?: string;
|
||||
|
||||
mobile?:string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
export class TokenDto {
|
||||
|
||||
accessToken: string;
|
||||
|
||||
refreshToken: string;
|
||||
|
||||
emailId: string;
|
||||
|
||||
module: string;
|
||||
|
||||
changePassword?:string
|
||||
|
||||
secuLevel?:string
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
|
||||
export class UserBankDto {
|
||||
custId:string;
|
||||
|
||||
custName:string;
|
||||
|
||||
mobile:string;
|
||||
|
||||
mPin:string;
|
||||
|
||||
tPin:string;
|
||||
|
||||
email:string;
|
||||
|
||||
bankId:string;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
export interface JwtPayload {
|
||||
|
||||
userId: string;
|
||||
|
||||
emailId: string;
|
||||
|
||||
userName: string;
|
||||
|
||||
sessionId: string;
|
||||
|
||||
module: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Strategy, ExtractJwt } from 'passport-jwt';
|
||||
import { Injectable, UnauthorizedException, Logger, Inject, Scope } from '@nestjs/common';
|
||||
import { JwtPayload } from './jwt-payload.interface';
|
||||
import * as config from 'config';
|
||||
import { DataSource, getConnection } from 'typeorm';
|
||||
import { PcduserRepository } from './pcduser.repository';
|
||||
import { PcduserDto } from 'src/auth/dto/pcd-user.dto';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
|
||||
private logger = new Logger('Jwt Strategy'); // for logging
|
||||
|
||||
constructor(
|
||||
@InjectRepository(PcduserRepository)
|
||||
private pcduserRepository: PcduserRepository,
|
||||
) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: true,
|
||||
secretOrKey: process.env.JWT_SECRET || config.get('jwt').secret,
|
||||
})
|
||||
}
|
||||
|
||||
async validate(payload: JwtPayload) {
|
||||
const { userId, userName, emailId, module } = payload;
|
||||
this.logger.log(`Payload ${JSON.stringify(payload)}`);
|
||||
|
||||
let connect = DataSource;
|
||||
const repo = this.pcduserRepository;
|
||||
const user:PcduserDto = await repo.findOne({where:{userId:userId}});
|
||||
delete user.pass;
|
||||
delete user.salt;
|
||||
if (!user) {
|
||||
this.logger.log(` Unauthorized `);
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
user["payload"] = payload;
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { Entity, PrimaryColumn, Column, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { PcdBaseEntity } from "../framework/custom/pcd-entity.custom";
|
||||
|
||||
@Entity('pcdotp')
|
||||
export class Pcdotp extends PcdBaseEntity {
|
||||
|
||||
@PrimaryGeneratedColumn({
|
||||
name: 'code',
|
||||
})
|
||||
code: number;
|
||||
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
name: 'otp',
|
||||
length: 6,
|
||||
nullable: false,
|
||||
})
|
||||
otp: string;
|
||||
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
name: 'ref_code',
|
||||
nullable: true,
|
||||
})
|
||||
refCode: string;
|
||||
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
name: 'used_for',
|
||||
length: 500,
|
||||
nullable: true,
|
||||
})
|
||||
usedFor: string;
|
||||
|
||||
@Column({
|
||||
type: 'char',
|
||||
name: 'status',
|
||||
length: 1,
|
||||
nullable: false,
|
||||
})
|
||||
status: string;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { DataSource, Repository } from "typeorm";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { Pcdotp } from "./pcdotp.entity";
|
||||
import * as config from 'config';
|
||||
|
||||
@Injectable()
|
||||
export class PcdotpRepository extends Repository<Pcdotp>{
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(Pcdotp, dataSource.createEntityManager());
|
||||
}
|
||||
private logger = new Logger('PcdotpRepository'); // for logging
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,227 @@
|
||||
import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom";
|
||||
import { Column, Entity, OneToMany, PrimaryColumn } from "typeorm";
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { BadRequestException } from "@nestjs/common";
|
||||
import { TenderDoc } from "src/tables/tender-documents/tender-doc.entity";
|
||||
import { PaymentMaster } from "src/tables/payment-master/payment-master.entity";
|
||||
import { category } from "src/tables/userCategory-master/category.entity";
|
||||
import { closedTenderUsers } from "src/tables/closed-tender-users/closed-tender-users.entity";
|
||||
import { PaymentStatus } from "src/tables/payment-status/payment-status.entity";
|
||||
import { revisedTender } from "src/tables/revised-tender/revised-tender.entity";
|
||||
import { userSubcategoryMaster } from "src/tables/user-subcategory-master/user-subcategory-master.entity";
|
||||
|
||||
@Entity('pcduser')
|
||||
export class Pcduser extends PcdBaseEntity {
|
||||
@PrimaryColumn({
|
||||
name: "user_id",
|
||||
primary: true,
|
||||
type: "varchar",
|
||||
length: 12,
|
||||
})
|
||||
userId: string;
|
||||
@Column({
|
||||
name: "user_name",
|
||||
type: "varchar",
|
||||
length: 100
|
||||
})
|
||||
userName: string;
|
||||
|
||||
@Column({
|
||||
name: "group_or_user",
|
||||
type: "char",
|
||||
length: 1,
|
||||
default: () => "'U'",
|
||||
})
|
||||
groupOrUser: string;
|
||||
|
||||
@Column({
|
||||
name: "pass",
|
||||
type: "varchar",
|
||||
length: 500
|
||||
})
|
||||
pass: string | null;
|
||||
|
||||
|
||||
@Column({
|
||||
name: "salt",
|
||||
type: "varchar",
|
||||
nullable: true,
|
||||
length: 50
|
||||
})
|
||||
salt: string | null;
|
||||
|
||||
|
||||
@Column({
|
||||
name: "secu_level",
|
||||
type: "varchar",
|
||||
nullable: true,
|
||||
length: 50
|
||||
})
|
||||
secuLevel: string | null;
|
||||
|
||||
@Column({
|
||||
name: "pwd_exp_days",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
default: () => "(0)"
|
||||
})
|
||||
pwdExpDays: number | null;
|
||||
|
||||
@Column({
|
||||
name: 'email',
|
||||
type: 'varchar',
|
||||
length: 500,
|
||||
// unique: true,
|
||||
nullable: true
|
||||
})
|
||||
email: string;
|
||||
|
||||
@Column({
|
||||
name: 'mobile_number',
|
||||
type: 'varchar',
|
||||
length: 100,
|
||||
nullable: true,
|
||||
unique: false
|
||||
})
|
||||
mobileNumber: string;
|
||||
|
||||
@Column({
|
||||
name: 'refresh_token',
|
||||
type: 'varchar',
|
||||
nullable: true,
|
||||
length: 100,
|
||||
})
|
||||
refreshtoken: string;
|
||||
|
||||
@Column({
|
||||
name: 'user_image_path',
|
||||
type: 'varchar',
|
||||
length: 500,
|
||||
nullable: true
|
||||
})
|
||||
userImagePath: string;
|
||||
|
||||
@Column({
|
||||
name: 'member_no',
|
||||
type: 'varchar',
|
||||
length: 20,
|
||||
nullable: true
|
||||
})
|
||||
memberNo: string;
|
||||
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
name: "cust_id",
|
||||
nullable: true,
|
||||
length: 20,
|
||||
})
|
||||
custId: string;
|
||||
|
||||
@Column({
|
||||
name: "device_id",
|
||||
type: "varchar",
|
||||
nullable: true,
|
||||
})
|
||||
deviceId:string;
|
||||
|
||||
@Column({
|
||||
type: 'char',
|
||||
name: "status",
|
||||
nullable: true,
|
||||
length: 1
|
||||
})
|
||||
status: string;
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
name: "bank_id",
|
||||
nullable: true,
|
||||
unique: true,
|
||||
length: 20,
|
||||
})
|
||||
bankId: string;
|
||||
@Column({
|
||||
nullable:true,
|
||||
name: "t_pass",
|
||||
type: "varchar",
|
||||
length: 500
|
||||
})
|
||||
tPass: string | null;
|
||||
|
||||
@Column({
|
||||
name: "t_salt",
|
||||
type: "varchar",
|
||||
nullable: true,
|
||||
length: 50
|
||||
})
|
||||
tSalt: string | null;
|
||||
|
||||
@Column({
|
||||
name: "active",
|
||||
type: "boolean",
|
||||
|
||||
})
|
||||
active: boolean;
|
||||
|
||||
@Column({
|
||||
name:"employee",
|
||||
type:"boolean"
|
||||
})
|
||||
employee:boolean
|
||||
|
||||
@Column({
|
||||
name:"max_amount",
|
||||
type:"numeric",
|
||||
nullable:true
|
||||
})
|
||||
maxAmount:number
|
||||
|
||||
@Column({
|
||||
name:"company_profile",
|
||||
type:"varchar",
|
||||
nullable:true
|
||||
})
|
||||
companyProfile:string
|
||||
|
||||
@Column({
|
||||
name:"project_compl_cert",
|
||||
type:"varchar",
|
||||
nullable:true
|
||||
})
|
||||
projectCompletedCert:string
|
||||
|
||||
@OneToMany(() => PaymentMaster, (paymentMaster) => paymentMaster.pcduserD)
|
||||
paymentMaster : PaymentMaster[]
|
||||
|
||||
|
||||
@OneToMany(() => TenderDoc, (tenderDoc) => tenderDoc.userD )
|
||||
tenderDoc:TenderDoc[]
|
||||
async validatePassword(password: string,user ): Promise<boolean> {
|
||||
const hash = await bcrypt.hash(password, this.salt);
|
||||
return hash === this.pass;
|
||||
}
|
||||
|
||||
|
||||
@OneToMany(() => category, (category) => category.userD )
|
||||
category:category[]
|
||||
|
||||
@OneToMany(() => closedTenderUsers, (closedTenderUsers) => closedTenderUsers.userD )
|
||||
closedTenderUsers:closedTenderUsers[]
|
||||
|
||||
// async validateTransactionPassword(password: string): Promise<boolean> {
|
||||
// const hash = await bcrypt.hash(password, this.tSalt);
|
||||
// return hash === this.tPass;
|
||||
|
||||
// }
|
||||
|
||||
@OneToMany(() => PaymentStatus, (PaymentStatus) => PaymentStatus.userD )
|
||||
paymentStatusD:PaymentStatus[]
|
||||
|
||||
@OneToMany(() => revisedTender, (revisedTender) => revisedTender.userD )
|
||||
revisedTenderD:revisedTender[]
|
||||
|
||||
@OneToMany(() => userSubcategoryMaster, (userSubcategoryMaster) => userSubcategoryMaster.userD)
|
||||
userSubcategoryMaster: userSubcategoryMaster[]
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
||||
import { DataSource, ILike, Like, Repository } from "typeorm";
|
||||
import { TempSignUpDto } from "./dto/temp-sign-up.dto";
|
||||
import { Pcduser } from "./pcduser.entity";
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { AuthCreadentialsDto } from "./dto/auth-credentials.dto";
|
||||
import { PcduserDto } from "src/auth/dto/pcd-user.dto";
|
||||
|
||||
@Injectable()
|
||||
export class PcduserRepository extends Repository<Pcduser>{
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(Pcduser, dataSource.createEntityManager());
|
||||
}
|
||||
private logger = new Logger('Pcduser Repo'); // for logging
|
||||
async updateRefreshToken(userId: string, refreshToken: string) {
|
||||
const user = await this.findOne({where:{ userId: userId }});
|
||||
user.refreshtoken = refreshToken;
|
||||
this.save(user);
|
||||
}
|
||||
|
||||
async signUp(authCredentials: TempSignUpDto, customerMobileNo, memberNo?, bankId?, secuLevel?): Promise<any> {
|
||||
|
||||
const salt = await bcrypt.genSalt();
|
||||
const tsalt = await bcrypt.genSalt();
|
||||
const user = new Pcduser();
|
||||
// user.userId = authCredentials.userId;
|
||||
let maxCode: number = 10001;
|
||||
const maxRow: PcduserDto = await this.findOne({
|
||||
where: { userId: Like('1%') },
|
||||
order: {
|
||||
"userId": "DESC"
|
||||
}
|
||||
});
|
||||
|
||||
if (maxRow) {
|
||||
maxCode = parseInt(maxRow.userId) + 1;
|
||||
}
|
||||
if (!customerMobileNo) {
|
||||
user.status = 'V';
|
||||
}
|
||||
else {
|
||||
user.status = 'N';
|
||||
user.mobileNumber = customerMobileNo;
|
||||
}
|
||||
user.userId = maxCode.toString();
|
||||
user.userName = authCredentials.username;
|
||||
|
||||
user.email = authCredentials.email;
|
||||
user.createdBy = "SYSTEM";
|
||||
user.modifiedBy = "SYSTEM";
|
||||
user.groupOrUser = 'U';
|
||||
|
||||
user.secuLevel = secuLevel;
|
||||
user.salt = salt;
|
||||
user.pass = await this.hashPassword(authCredentials.password, salt);
|
||||
user.tSalt = tsalt;
|
||||
user.tPass = await this.hashPassword(authCredentials.tpassword, tsalt);
|
||||
user.bankId = bankId;
|
||||
try {
|
||||
return await user.save();
|
||||
} catch (error) {
|
||||
// if(error.code==23505) not working in orcale
|
||||
throw new BadRequestException(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getEagerColumns(): Promise<string[]> {
|
||||
/*
|
||||
For getting Eager true columns having Many to One relations.
|
||||
We need to remove the eager columns before insertions or updations or it will not allow to save data (But save message will show, but data not updated)
|
||||
*/
|
||||
const COLUMNS: string[] = [];
|
||||
for (let columnProperty of this.metadata.eagerRelations) {
|
||||
COLUMNS.push(columnProperty.propertyName);
|
||||
}
|
||||
return COLUMNS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async encryptPassword(password: string, salt: string): Promise<string> {
|
||||
return await this.hashPassword(password, salt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async hashPassword(password: string, salt: string): Promise<string> {
|
||||
return await bcrypt.hash(password, salt);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import { TypeOrmModuleOptions } from "@nestjs/typeorm";
|
||||
import * as config from 'config'
|
||||
|
||||
//const dbConfig = config.get('db');
|
||||
|
||||
export const typeOrmConfig: TypeOrmModuleOptions = {
|
||||
type:'postgres',
|
||||
host:'3.110.164.8',
|
||||
port:5432,
|
||||
username:'postgres',
|
||||
password:'inv123',
|
||||
database:'artnouveau',
|
||||
entities: [__dirname + '/../**/*.entity.{js,ts}'],
|
||||
synchronize:true,
|
||||
logging:false
|
||||
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
export class basicCategoryDto {
|
||||
|
||||
id:number;
|
||||
|
||||
productCategory:string;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
export class categoryDto{
|
||||
id?:number
|
||||
|
||||
category : number
|
||||
|
||||
userId? : number
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class closedTenderUsersDto{
|
||||
|
||||
tenderId : number
|
||||
|
||||
userId : number
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export class CommonDto{
|
||||
marquee : string
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
export class CoverMasterDto{
|
||||
|
||||
tenderId:number;
|
||||
|
||||
coverType:string;
|
||||
|
||||
Description:string;
|
||||
|
||||
fileFormat:string
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
export class coverTypeDto{
|
||||
|
||||
id:number
|
||||
|
||||
coverType:string
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class DocumentTypeDto{
|
||||
id:number;
|
||||
|
||||
documentType:string;
|
||||
|
||||
docCategory:string
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
export class EmdFeeTypeDto {
|
||||
id:number;
|
||||
|
||||
emdFeeType:string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
export class FileFormatLovDto{
|
||||
id:number;
|
||||
|
||||
fileFormat:string;
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
export class FormOfContractDto {
|
||||
id: number;
|
||||
formOfContract: string;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
export class galleryDto{
|
||||
|
||||
id?:number
|
||||
|
||||
category : string
|
||||
|
||||
imageUrl : string
|
||||
|
||||
title: string
|
||||
|
||||
description:string
|
||||
|
||||
projectType:string
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
export class MailConfigDto {
|
||||
|
||||
smtpUserName: string;
|
||||
|
||||
smtpId: number;
|
||||
|
||||
smtpPassword: string;
|
||||
|
||||
smtpHost: string;
|
||||
|
||||
encryptionType: string;
|
||||
|
||||
smtpPort: string;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
export class MenuDto {
|
||||
|
||||
menuId: number;
|
||||
|
||||
menuName: string;
|
||||
|
||||
moduleId: number;
|
||||
|
||||
menuIcon: string;
|
||||
|
||||
menuOrder: number;
|
||||
|
||||
routerLink: string;
|
||||
|
||||
menuParentId: number;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
export class PaymentMasterDto {
|
||||
|
||||
userId:string
|
||||
|
||||
tenderId:number
|
||||
|
||||
transId:number
|
||||
|
||||
status?:string
|
||||
|
||||
finalBidAmt?:number
|
||||
|
||||
notificationViewed?:string
|
||||
|
||||
message?:string
|
||||
|
||||
emdFeeStatus?:string
|
||||
|
||||
emdFeetxnId?:number
|
||||
|
||||
emdFeeType:string
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class PaymentModeDto{
|
||||
|
||||
id:number ;
|
||||
|
||||
paymentMode:string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
import { PcdBaseDto } from "src/framework/custom/pcd-dto.custom";
|
||||
|
||||
export class PaymentStatusDto extends PcdBaseDto {
|
||||
|
||||
id: number;
|
||||
|
||||
paymentDate: Date;
|
||||
|
||||
paymentOption: string;
|
||||
|
||||
paymentCardDetails: string;
|
||||
|
||||
status: string;
|
||||
|
||||
type: string
|
||||
|
||||
email: string;
|
||||
|
||||
mobile: string;
|
||||
|
||||
application: number;
|
||||
|
||||
paymentId: number;
|
||||
|
||||
billingAddress1: string;
|
||||
|
||||
billingAddress2: string;
|
||||
|
||||
billingAddress3: string;
|
||||
|
||||
billingAddress4: string;
|
||||
|
||||
amount: number;
|
||||
|
||||
remarks: string;
|
||||
|
||||
txnid: number;
|
||||
|
||||
identifier: string;
|
||||
|
||||
userId : string
|
||||
|
||||
tenderId : number
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
export class PaymentDto {
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
email: string;
|
||||
phone: number;
|
||||
amount: number;
|
||||
productinfo: string;
|
||||
txnid: number;
|
||||
surl: string;
|
||||
furl: string;
|
||||
service_provider: string;
|
||||
|
||||
constructor() {
|
||||
this.furl = 'http://localhost:3100/api/v1/payment-gateway/failure';
|
||||
this.surl = 'http://localhost:3100/api/v1/payment-gateway/success';
|
||||
|
||||
// this.furl = 'https://flexdata.api.teorainfotech.com/API/V1/payment-gateway/failure';
|
||||
// this.surl = 'https://flexdata.api.teorainfotech.com/API/V1/payment-gateway/success';
|
||||
|
||||
this.txnid = this.getRandomInt();
|
||||
}
|
||||
|
||||
getRandomInt() {
|
||||
return Math.floor(100000 + Math.random() * 900000);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
export class PayuTransactionListDto {
|
||||
|
||||
id: string
|
||||
|
||||
status: string
|
||||
|
||||
key: string
|
||||
|
||||
merchantname: string
|
||||
|
||||
firstname: string
|
||||
|
||||
lastname: string
|
||||
|
||||
addedon: Date
|
||||
|
||||
bank_name: string
|
||||
|
||||
payment_gateway: string
|
||||
|
||||
phone: number | any
|
||||
|
||||
email: string
|
||||
|
||||
transaction_fee: number
|
||||
|
||||
amount: number | any
|
||||
|
||||
discount: number | any
|
||||
|
||||
additional_charges: number | any
|
||||
|
||||
productinfo: string
|
||||
|
||||
error_code: string
|
||||
|
||||
bank_ref_no: number | any
|
||||
|
||||
ibibo_code: string
|
||||
|
||||
mode: string
|
||||
|
||||
ip: string
|
||||
|
||||
card_no: number | any
|
||||
|
||||
cardtype: string
|
||||
|
||||
offer_key: string
|
||||
|
||||
field0: string
|
||||
|
||||
field1: string
|
||||
|
||||
field2: string
|
||||
|
||||
field3: string
|
||||
|
||||
field4: string
|
||||
|
||||
field5: string
|
||||
|
||||
field6: string
|
||||
|
||||
field7: string
|
||||
|
||||
field8: string
|
||||
|
||||
field9: string
|
||||
|
||||
udf1: string
|
||||
|
||||
udf2: string
|
||||
|
||||
udf3: string
|
||||
|
||||
udf4: string
|
||||
|
||||
udf5: string
|
||||
|
||||
address2: string
|
||||
|
||||
city: string
|
||||
|
||||
zipcode: string
|
||||
|
||||
pg_mid: string
|
||||
|
||||
issuing_bank: string
|
||||
|
||||
offer_type: string
|
||||
|
||||
failure_reason: string
|
||||
|
||||
mer_service_fee: string
|
||||
|
||||
mer_service_tax: string
|
||||
|
||||
txnid: string;
|
||||
|
||||
gateway: string;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
export class phonepeTransactionDto {
|
||||
merchantId: string
|
||||
merchantTransactionId: number
|
||||
transactionId: string
|
||||
amount: number
|
||||
code: string
|
||||
message: string
|
||||
state: string
|
||||
responseCode: string
|
||||
paymentType: string
|
||||
success: boolean
|
||||
txnDate: Date
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
|
||||
export class PurchaseDto {
|
||||
|
||||
amount: number;
|
||||
|
||||
application: string;
|
||||
|
||||
mobile: string;
|
||||
|
||||
email: string;
|
||||
|
||||
type: string;
|
||||
|
||||
menuId?: string;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
export class reportAuthenticationDto{
|
||||
|
||||
id:number;
|
||||
|
||||
adminUsers:string
|
||||
|
||||
key:number[]
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
export class revisedTenderDto{
|
||||
|
||||
userId : string
|
||||
|
||||
tenderId : number
|
||||
|
||||
revisedDocument : string
|
||||
|
||||
requotedOrder : number
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class subGalleryDto{
|
||||
|
||||
gallery_id : number
|
||||
|
||||
imageUrl : string
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
export class TenderCategoryDto{
|
||||
|
||||
tenderCategory:string;
|
||||
|
||||
active : boolean
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
export class TenderDocumentDto{
|
||||
|
||||
tenderId:number;
|
||||
|
||||
docName:string;
|
||||
|
||||
description:string;
|
||||
|
||||
docType:string;
|
||||
|
||||
documentSize:number;
|
||||
|
||||
documentCategory:string;
|
||||
|
||||
userId?:string
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
export class TenderDetailDto {
|
||||
createdBy: string;
|
||||
createdDate: string;
|
||||
modifiedBy: string;
|
||||
modifiedDate: string;
|
||||
versionNo: number;
|
||||
sessionNo: number;
|
||||
id: number;
|
||||
orgChain: string;
|
||||
tenderRefNo: string;
|
||||
tenderId: string;
|
||||
allowTechEval: string;
|
||||
paymentMode: number;
|
||||
allowWithdraw: string;
|
||||
noOfCovers: number;
|
||||
itemwiseTechEval: string;
|
||||
allowTwoStageBid: string;
|
||||
tenderFee: number;
|
||||
feePayableTo: string;
|
||||
feePayableAt: string;
|
||||
tenderFeeExemption: number;
|
||||
emdAmt: number;
|
||||
emdPayableTo: string;
|
||||
allowEmdBgOrSt: string;
|
||||
emdPercentage: number;
|
||||
emdPayableAt: string;
|
||||
title: string;
|
||||
workDesc: string;
|
||||
ndaPreQualification: string;
|
||||
remarks: string;
|
||||
tenderValue: number;
|
||||
contractType: string;
|
||||
location: string;
|
||||
preBidMeetAdd: string;
|
||||
allowNdaTender: string;
|
||||
productCategory: number;
|
||||
bidValidity: number;
|
||||
pincode: number;
|
||||
preBidDate: Date;
|
||||
allowPreferencialBidder: string;
|
||||
subCategory: string;
|
||||
periodOfWork: number;
|
||||
preBidMeetPlace: string;
|
||||
bidOpeningPlace: string;
|
||||
publishDate: Date;
|
||||
saleStartDate: Date;
|
||||
clarificationStartDate: Date;
|
||||
bidSubStartDate: Date;
|
||||
bidOpenDate: Date;
|
||||
saleEndDate: Date;
|
||||
clarificationEndDate: Date;
|
||||
bidSubEndDate: Date;
|
||||
tenderInvName: string;
|
||||
tenderInvAddess: string;
|
||||
tenderType: number;
|
||||
tenderCategory: number;
|
||||
formOfContract: number;
|
||||
emdFeeType: string;
|
||||
activeYn: string;
|
||||
sendReport: string;
|
||||
bidOpenAddress: string
|
||||
emdFeeApplied: boolean
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
export class tenderSubcategoryMasterDto{
|
||||
|
||||
tenderId : number
|
||||
|
||||
subCategoryId : number
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class tenderSubCategoryDto{
|
||||
|
||||
tenderSubCategory:string;
|
||||
|
||||
active : boolean
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
export class TenderTypeDto{
|
||||
|
||||
id:number;
|
||||
|
||||
tenderType:string;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
export class userSubCategoryDto{
|
||||
id?:string
|
||||
|
||||
Category:number
|
||||
|
||||
subCategory:number
|
||||
|
||||
userId:number
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
|
||||
import { EmailService } from './email.service';
|
||||
|
||||
@Controller('email')
|
||||
export class EmailController {
|
||||
|
||||
constructor(
|
||||
private service: EmailService
|
||||
) { }
|
||||
|
||||
@Post('report/:id')
|
||||
sendReport(
|
||||
@Param('id') id:string,
|
||||
@Body() body : {toMail : string[]}
|
||||
){
|
||||
return this.service.pdfReport(id,body.toMail)
|
||||
}
|
||||
|
||||
@Post()
|
||||
sendMail(@Body() body){
|
||||
console.log("===here===")
|
||||
console.log(body);
|
||||
|
||||
return this.service.sendmailManually(body.toMail,body.subject,body.content);
|
||||
}
|
||||
|
||||
// @Get('create-new')
|
||||
// sendNewTenderMail(){
|
||||
// console.log("===here===")
|
||||
|
||||
// return this.service.tenderPublishEmail();
|
||||
// }
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { EmailController } from './email.controller';
|
||||
import { EmailService } from './email.service';
|
||||
import { HandlebarsAdapter, MailerModule } from '@nest-modules/mailer';
|
||||
import * as config from 'config';
|
||||
import { TenderMasterRepository } from 'src/tables/tender-master/tender-master.repository';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { tenderDocRepository } from 'src/tables/tender-documents/tender-doc.repository';
|
||||
import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository';
|
||||
import { tenderSubCategoryMasterRepository } from 'src/tables/tender-subcategory-master/tender-subcategory-master.repository';
|
||||
import { tenderSubCategoryRepository } from 'src/tables/tender-subcategory/tender-subcategory.repository';
|
||||
import { PcduserRepository } from 'src/auth/pcduser.repository';
|
||||
import { categoryRepository } from 'src/tables/userCategory-master/category.repository';
|
||||
import { closedTenderUsersRepository } from 'src/tables/closed-tender-users/closed-tender-users.repository';
|
||||
import { TenderMaster } from 'src/tables/tender-master/tender-master.entity';
|
||||
import { PaymentMaster } from 'src/tables/payment-master/payment-master.entity';
|
||||
import { tenderSubCategoryMaster } from 'src/tables/tender-subcategory-master/tender-subcategory-master.entity';
|
||||
import { tenderSubCategory } from 'src/tables/tender-subcategory/tender-subcategory.entity';
|
||||
import { Pcduser } from 'src/auth/pcduser.entity';
|
||||
import { category } from 'src/tables/userCategory-master/category.entity';
|
||||
import { closedTenderUsers } from 'src/tables/closed-tender-users/closed-tender-users.entity';
|
||||
import { userSubCategoryMasterRepo } from 'src/tables/user-subcategory-master/user-subcategory-master.repository';
|
||||
import { userSubcategoryMaster } from 'src/tables/user-subcategory-master/user-subcategory-master.entity';
|
||||
|
||||
const emailConfig = config.get('mail');
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MailerModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
// remember to turn-on the Less secure app access in the gmail security
|
||||
transport: {
|
||||
host: 'smtp.gmail.com',
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: emailConfig.user,
|
||||
pass: emailConfig.pass
|
||||
},
|
||||
tls: { rejectUnauthorized: false }
|
||||
},
|
||||
|
||||
}),
|
||||
}),
|
||||
TypeOrmModule.forFeature([TenderMaster,PaymentMaster,
|
||||
tenderSubCategoryMaster,tenderSubCategory,Pcduser,
|
||||
category,closedTenderUsers,userSubcategoryMaster]),
|
||||
],
|
||||
controllers: [EmailController],
|
||||
providers: [EmailService,TenderMasterRepository,PaymentMasterRepository,
|
||||
tenderSubCategoryMasterRepository,tenderSubCategoryRepository,PcduserRepository,categoryRepository,
|
||||
closedTenderUsersRepository,userSubCategoryMasterRepo
|
||||
],
|
||||
exports: [
|
||||
MailerModule,
|
||||
EmailService
|
||||
]
|
||||
})
|
||||
export class EmailModule { }
|
||||
@ -0,0 +1,728 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { MailerService } from '@nest-modules/mailer';
|
||||
import * as config from 'config';
|
||||
import { TenderMasterRepository } from 'src/tables/tender-master/tender-master.repository';
|
||||
import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository';
|
||||
import { log } from 'console';
|
||||
import * as nodemailer from 'nodemailer';
|
||||
import { createFolders } from 'src/file-upload/file-upload.controller';
|
||||
const mail = config.get('mail');
|
||||
import jsPDF from 'jspdf';
|
||||
import autoTable from 'jspdf-autotable';
|
||||
import { promisify } from 'util';
|
||||
const emailConfig = config.get('mail');
|
||||
import axios from 'axios';
|
||||
import { Between, Not } from 'typeorm';
|
||||
import { categoryRepository } from 'src/tables/userCategory-master/category.repository';
|
||||
import { tenderSubCategoryMasterRepository } from 'src/tables/tender-subcategory-master/tender-subcategory-master.repository';
|
||||
import { tenderSubCategoryRepository } from 'src/tables/tender-subcategory/tender-subcategory.repository';
|
||||
import { PcduserRepository } from 'src/auth/pcduser.repository';
|
||||
import { Cron } from '@nestjs/schedule';
|
||||
import { closedTenderUsersRepository } from 'src/tables/closed-tender-users/closed-tender-users.repository';
|
||||
import { userSubCategoryMasterRepo } from 'src/tables/user-subcategory-master/user-subcategory-master.repository';
|
||||
@Injectable()
|
||||
export class EmailService {
|
||||
reportArray: any;
|
||||
constructor(
|
||||
private readonly mailerService: MailerService,
|
||||
private tenderMasterRepository: TenderMasterRepository,
|
||||
private paymentMasterRepository: PaymentMasterRepository,
|
||||
private tenderSubCategoryMasterRepository: tenderSubCategoryMasterRepository,
|
||||
private tenderSubCategoryRepo: tenderSubCategoryRepository,
|
||||
private pcdRepo: PcduserRepository,
|
||||
private userCategoryRepo: categoryRepository,
|
||||
private closedTenderRepo: closedTenderUsersRepository,
|
||||
private userSubCategoryMasterRepo : userSubCategoryMasterRepo
|
||||
) { }
|
||||
// documenation : https://www.npmjs.com/package/@nest-modules/mailer
|
||||
|
||||
async pdfReport(id,toMail) {
|
||||
let query = `SELECT tm.id , tm.title ,tm.send_report,tm.bid_open_date FROM tender_master tm WHERE tm.id = ${id}
|
||||
`
|
||||
let reportNotSend = await this.tenderMasterRepository.query(query)
|
||||
|
||||
let query1 = `SELECT "PaymentMaster"."id" AS "id",
|
||||
"PaymentMaster"."user_id" AS "userId",
|
||||
tm.tender_id AS "tenderId",
|
||||
"PaymentMaster"."trans_id" AS "transId",
|
||||
"PaymentMaster"."final_bid_amt" AS "finalBidAmt",
|
||||
"PaymentMaster_pcduserD"."user_name" AS "userName",
|
||||
"PaymentMaster_pcduserD"."email" AS "email",
|
||||
"PaymentMaster_pcduserD"."mobile_number" AS "mobileNumber"
|
||||
FROM "payment-master" "PaymentMaster"
|
||||
LEFT JOIN "pcduser" "PaymentMaster_pcduserD" ON"PaymentMaster_pcduserD"."user_id"="PaymentMaster"."user_id"
|
||||
LEFT join "tender_master" "tm" on "tm"."id" = "PaymentMaster"."tender_id"
|
||||
WHERE "PaymentMaster"."tender_id" = ${id}
|
||||
and "PaymentMaster"."status"= 'S'
|
||||
AND "PaymentMaster"."final_bid_amt" IS NOT NULL;`
|
||||
let report = await this.paymentMasterRepository.query(query1);
|
||||
|
||||
if (report.length == 0) {
|
||||
throw new NotFoundException('Document entry not found.');
|
||||
}
|
||||
|
||||
return this.generateReport(report, id ,toMail)
|
||||
|
||||
}
|
||||
|
||||
|
||||
async generateReport(report, id ,toMail) {
|
||||
|
||||
const enq = await report;
|
||||
|
||||
const doc = new jsPDF('landscape');
|
||||
let headers = (['id', 'userId', 'tenderId', 'transId', 'finalBidAmt', 'userName', 'email', 'mobileNumber']);
|
||||
|
||||
// Prepare the data in the required format for autoTable
|
||||
let data = [];
|
||||
enq.forEach((item) => {
|
||||
data.push([
|
||||
item.id,
|
||||
item.userId,
|
||||
item.tenderId,
|
||||
item.transId,
|
||||
item.finalBidAmt,
|
||||
item.userName,
|
||||
item.email,
|
||||
item.mobileNumber
|
||||
]);
|
||||
});
|
||||
|
||||
// Create the table in the PDF document
|
||||
|
||||
|
||||
autoTable(doc, {
|
||||
startY: 1, // Adjust the starting position of the table (Y coordinate)
|
||||
head: [headers],
|
||||
body: data,
|
||||
});
|
||||
|
||||
// Save the PDF
|
||||
const filePath: string = './uploads/Report';
|
||||
createFolders(filePath);
|
||||
doc.save(`${filePath}/${id}.pdf`);
|
||||
console.log(id);
|
||||
const pdfFileName = `${id}.pdf`;
|
||||
const filePathReport: string = './uploads/Report/';
|
||||
|
||||
// Update pdfStatus
|
||||
let pdfStatus = await this.tenderMasterRepository.findOne({ where: { id: id } });
|
||||
pdfStatus.sendReport = 'Y'
|
||||
this.tenderMasterRepository.save(pdfStatus)
|
||||
|
||||
// Send email with attachment
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: 'smtp.gmail.com',
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: emailConfig.user,
|
||||
pass: emailConfig.pass
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
});
|
||||
|
||||
const mailOptions = {
|
||||
from: emailConfig.user,
|
||||
to: emailConfig.user,
|
||||
subject: `Generated PDF Report for ID: ${report[0].tenderId}`,
|
||||
text: 'Attached PDF report.',
|
||||
headers: {
|
||||
bcc: toMail, // BCC recipients
|
||||
//bcc: ["joshjohn212@gmail.com","atlejs47@gmail.com"] , // BCC recipients
|
||||
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
filename: pdfFileName,
|
||||
path: `${filePathReport}${pdfFileName}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const sendMail = promisify(transporter.sendMail.bind(transporter));
|
||||
|
||||
try {
|
||||
await sendMail(mailOptions);
|
||||
console.log('Email sent successfully');
|
||||
return { data: "Email sent successfully" }
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error);
|
||||
return { data: "Error sending email:", error }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async sendmailManually(email, subject, content) {
|
||||
let content1 = `
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>OTP</title>
|
||||
<meta name="description" content="New Account Email Template.">
|
||||
<style type="text/css">
|
||||
a:hover {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
/* Other styles */
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body marginheight="0" topmargin="0" marginwidth="0" style="margin: 0px; background-color: #f2f3f8;" leftmargin="0">
|
||||
<!-- 100% body table -->
|
||||
<table cellspacing="0" border="0" cellpadding="0" width="100%" bgcolor="#f2f3f8"
|
||||
style="@import url(https://fonts.googleapis.com/css?family=Rubik:300,400,500,700|Open+Sans:300,400,600,700); font-family: 'Open Sans', sans-serif;">
|
||||
<tr>
|
||||
<td>
|
||||
<table style="background-color: #f2f3f8; max-width:800px; margin:0 auto;" width="100%" border="0"
|
||||
align="center" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<a href="https://artnouveau.in/" title="" target="_blank">
|
||||
<img width="60" src="https://tender.artnouveau.in/assets/img/Art-n-Artiect-removebg-preview.png" title="logo" alt="logo">
|
||||
</a>
|
||||
<h3 style="font-family: "Lucida Console", "Courier New", monospace;">Artnouveau Architects</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width="95%" border="0" align="center" cellpadding="0" cellspacing="0"
|
||||
style="max-width:670px; background:#fff; border-radius:3px; text-align:center;-webkit-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);-moz-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);box-shadow:0 6px 18px 0 rgba(0,0,0,.06);">
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 35px;">
|
||||
|
||||
<p style="font-size:15px; color:#455056; margin:8px 0 0; line-height:24px;">
|
||||
Dear customer , <br>
|
||||
<strong>
|
||||
${content} <br>
|
||||
|
||||
For any inquiries or clarifications, please contact <br><br>
|
||||
|
||||
<br>
|
||||
|
||||
<div style="">
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Subash</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> subash@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 94469 64558</p>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Boncy</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> boncy@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 85473 42848</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
Best regards,<br>
|
||||
Artnouveau Architects</strong></p>
|
||||
<span
|
||||
style="display:inline-block; vertical-align:middle; margin:29px 0 26px; border-bottom:1px solid #cecece; width:100px;"></span>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<p style="font-size:14px; color:rgba(69, 80, 86, 0.7411764705882353); line-height:18px; margin:0 0 0;">©<strong> <a href="https://www.artnouveau.in/" >www.artnouveau.in</a></strong> </p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--/100% body table-->
|
||||
</body>
|
||||
|
||||
</html> `;
|
||||
let subject1 = subject
|
||||
|
||||
await this.sendMailManually(email, subject1, content1, content1);
|
||||
}
|
||||
|
||||
async sendMailManually(toMail: string[], subject: string, bodyText: string, htmlText: string) {
|
||||
|
||||
this.mailerService.sendMail({
|
||||
to: '', // sender address
|
||||
subject: subject, // Subject line
|
||||
text: bodyText, // plaintext body
|
||||
html: htmlText,// HTML body content
|
||||
headers: {
|
||||
bcc: toMail, // BCC recipients
|
||||
//bcc: ["joshjohn212@gmail.com","atlejs47@gmail.com"] , // BCC recipients
|
||||
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
console.log("==== here==res==", res)
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("=====err====", err);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async sendMail(toMail: string, subject: string, bodyText: string, htmlText: string) {
|
||||
this.mailerService.sendMail({
|
||||
to: toMail, // sender address
|
||||
subject: subject, // Subject line
|
||||
text: bodyText, // plaintext body
|
||||
html: htmlText, // HTML body content
|
||||
|
||||
})
|
||||
.then((res) => {
|
||||
console.log("==== here==res==", res)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("=====err====", err);
|
||||
});
|
||||
}
|
||||
// @Cron('* * * * *', { name: 'send-mail' })
|
||||
@Cron('1 0 * * *', { name: 'send-mail'})
|
||||
async tenderMail() {
|
||||
await this.tenderPublishEmail()
|
||||
await this.closedTenderPublishEmail()
|
||||
}
|
||||
|
||||
async tenderPublishEmail() {
|
||||
let date = new Date()
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are zero-based
|
||||
const year = date.getFullYear();
|
||||
|
||||
let convertedDate = `${year}-${month}-${day}`;
|
||||
|
||||
const startDate = new Date(convertedDate + 'T00:00:00.000');
|
||||
const endDate = new Date(convertedDate + 'T23:59:59.999');
|
||||
console.log(convertedDate);
|
||||
|
||||
let tendersToday = await this.tenderMasterRepository.find({
|
||||
where: {
|
||||
publishDate: Between(startDate, endDate), activeYn: 'Y', tenderType: Not(7),
|
||||
}
|
||||
})
|
||||
|
||||
// console.log("uigiuygu",tendersToday.length);
|
||||
|
||||
let tenderSubCategroyArray = []
|
||||
let emailArray = []
|
||||
|
||||
for (let t of tendersToday) {
|
||||
|
||||
let tenderSubCategory = await this.tenderSubCategoryMasterRepository.find({
|
||||
where: {
|
||||
tenderId: t.id
|
||||
}
|
||||
})
|
||||
for (let s of tenderSubCategory) {
|
||||
tenderSubCategroyArray.push(s.subCategoryId)
|
||||
}
|
||||
// for (let s of tenderSubCategory) {
|
||||
// let tenderCategory = await this.tenderSubCategoryRepo.find({ where: { id: s.subCategoryId } })
|
||||
// for (let t of tenderCategory) {
|
||||
// tenderCategroyArray.push(t.tenderCategory)
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//User Category -------->
|
||||
|
||||
let users = await this.pcdRepo.find({
|
||||
where: {
|
||||
secuLevel: 'User', active: true
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
for (let u of users) {
|
||||
let userCategory = await this.userSubCategoryMasterRepo.find({
|
||||
where: {
|
||||
userId: parseInt(u.userId)
|
||||
}
|
||||
})
|
||||
for (let c of userCategory) {
|
||||
if (tenderSubCategroyArray.includes(c.subCategory)) {
|
||||
if(!emailArray.includes(u.email)){
|
||||
emailArray.push(u.email)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let date = new Date(t.publishDate);
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are zero-based
|
||||
const year = date.getFullYear();
|
||||
let hours = date.getHours();
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
// Determine AM or PM
|
||||
const ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
|
||||
// Convert to 12-hour format
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // If hours is 0, set it to 12
|
||||
|
||||
const publishDate = `${day}-${month}-${year} ${hours}:${minutes} ${ampm}`;
|
||||
console.log(publishDate);
|
||||
|
||||
let html = `
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>OTP</title>
|
||||
<meta name="description" content="New Account Email Template.">
|
||||
<style type="text/css">
|
||||
a:hover {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
/* Other styles */
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body marginheight="0" topmargin="0" marginwidth="0" style="margin: 0px; background-color: #f2f3f8;" leftmargin="0">
|
||||
<!-- 100% body table -->
|
||||
<table cellspacing="0" border="0" cellpadding="0" width="100%" bgcolor="#f2f3f8"
|
||||
style="@import url(https://fonts.googleapis.com/css?family=Rubik:300,400,500,700|Open+Sans:300,400,600,700); font-family: 'Open Sans', sans-serif;">
|
||||
<tr>
|
||||
<td>
|
||||
<table style="background-color: #f2f3f8; max-width:800px; margin:0 auto;" width="100%" border="0"
|
||||
align="center" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<a href="https://artnouveau.in/" title="" target="_blank">
|
||||
<img width="60" src="https://tender.artnouveau.in/assets/img/Art-n-Artiect-removebg-preview.png" title="logo" alt="logo">
|
||||
</a>
|
||||
<h3 style="font-family: "Lucida Console", "Courier New", monospace;">Artnouveau Architects</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width="95%" border="0" align="center" cellpadding="0" cellspacing="0"
|
||||
style="max-width:670px; background:#fff; border-radius:3px; text-align:center;-webkit-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);-moz-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);box-shadow:0 6px 18px 0 rgba(0,0,0,.06);">
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 35px;">
|
||||
|
||||
<p style="font-size:15px; color:#455056; margin:8px 0 0; line-height:24px;">
|
||||
Dear Customer , <br>
|
||||
<strong> We are excited to inform you that a <a style="color:red;">${t.title}</a> tender in the <a style="color:red;">${t.tenderCategoryD['productCategory']}</a> category will been added on our ArtNouveau website.<br><br>
|
||||
You can view the details on <a style="color:red;">${publishDate}</a> and submit your bids by visiting the website at <strong> <a href="tender.artnouveau.in/#/auth/login" >tender.artnouveau.in</a></strong> <br><br>
|
||||
|
||||
For any inquiries or clarifications, please contact <br><br>
|
||||
<br>
|
||||
|
||||
<div style="">
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Subash</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> subash@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 94469 64558</p>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Boncy</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> boncy@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 85473 42848</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
Best regards,<br>
|
||||
Artnouveau Architects</strong></p>
|
||||
<span
|
||||
style="display:inline-block; vertical-align:middle; margin:29px 0 26px; border-bottom:1px solid #cecece; width:100px;"></span>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<p style="font-size:14px; color:rgba(69, 80, 86, 0.7411764705882353); line-height:18px; margin:0 0 0;">©<strong> <a href="https://www.artnouveau.in/" >www.artnouveau.in</a></strong> </p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--/100% body table-->
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
let subject = `New Tender Added in ${t.tenderCategoryD['productCategory']} Category on ArtNouveau Website`
|
||||
|
||||
emailArray = this.removeDuplicates(emailArray);
|
||||
// console.log(emailArray);
|
||||
|
||||
await this.sendMailManually(emailArray, subject, html, html)
|
||||
tenderSubCategroyArray = []
|
||||
emailArray = []
|
||||
}
|
||||
}
|
||||
|
||||
removeDuplicates<T>(arr: T[]): T[] {
|
||||
return arr.filter((value, index, self) => self.indexOf(value) === index);
|
||||
}
|
||||
|
||||
async closedTenderPublishEmail() {
|
||||
let date = new Date()
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are zero-based
|
||||
const year = date.getFullYear();
|
||||
|
||||
let convertedDate = `${year}-${month}-${day}`;
|
||||
|
||||
const startDate = new Date(convertedDate + 'T00:00:00.000');
|
||||
const endDate = new Date(convertedDate + 'T23:59:59.999');
|
||||
console.log("startDate",startDate,"endDate",endDate);
|
||||
let tendersToday = await this.tenderMasterRepository.find({
|
||||
where: {
|
||||
publishDate: Between(startDate, endDate), activeYn: 'Y', tenderType: 7,
|
||||
}
|
||||
})
|
||||
console.log(tendersToday.length);
|
||||
|
||||
let closedTenderUsers = []
|
||||
for (let t of tendersToday) {
|
||||
// console.log(t);
|
||||
let users = await this.closedTenderRepo.find({
|
||||
where: {
|
||||
tenderId: t.id
|
||||
}
|
||||
})
|
||||
for (let u of users) {
|
||||
console.log("11111111", u.userId);
|
||||
|
||||
let user = await this.pcdRepo.findOne({
|
||||
where: {
|
||||
userId: u.userId.toString()
|
||||
}
|
||||
})
|
||||
closedTenderUsers.push(user.email)
|
||||
}
|
||||
let date = new Date(t.publishDate);
|
||||
const day = date.getDate().toString().padStart(2, '0');
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are zero-based
|
||||
const year = date.getFullYear();
|
||||
let hours = date.getHours();
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
// Determine AM or PM
|
||||
const ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
|
||||
// Convert to 12-hour format
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // If hours is 0, set it to 12
|
||||
|
||||
const publishDate = `${day}-${month}-${year} ${hours}:${minutes} ${ampm}`;
|
||||
console.log(publishDate);
|
||||
let html = `
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<title>OTP</title>
|
||||
<meta name="description" content="New Account Email Template.">
|
||||
<style type="text/css">
|
||||
a:hover {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
/* Other styles */
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body marginheight="0" topmargin="0" marginwidth="0" style="margin: 0px; background-color: #f2f3f8;" leftmargin="0">
|
||||
<!-- 100% body table -->
|
||||
<table cellspacing="0" border="0" cellpadding="0" width="100%" bgcolor="#f2f3f8"
|
||||
style="@import url(https://fonts.googleapis.com/css?family=Rubik:300,400,500,700|Open+Sans:300,400,600,700); font-family: 'Open Sans', sans-serif;">
|
||||
<tr>
|
||||
<td>
|
||||
<table style="background-color: #f2f3f8; max-width:800px; margin:0 auto;" width="100%" border="0"
|
||||
align="center" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<a href="https://artnouveau.in/" title="" target="_blank">
|
||||
<img width="60" src="https://tender.artnouveau.in/assets/img/Art-n-Artiect-removebg-preview.png" title="logo" alt="logo">
|
||||
</a>
|
||||
<h3 style="font-family: "Lucida Console", "Courier New", monospace;">Artnouveau Architects</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width="95%" border="0" align="center" cellpadding="0" cellspacing="0"
|
||||
style="max-width:670px; background:#fff; border-radius:3px; text-align:center;-webkit-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);-moz-box-shadow:0 6px 18px 0 rgba(0,0,0,.06);box-shadow:0 6px 18px 0 rgba(0,0,0,.06);">
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:0 35px;">
|
||||
|
||||
<p style="font-size:15px; color:#455056; margin:8px 0 0; line-height:24px;">
|
||||
Dear Customer , <br>
|
||||
<strong> We are excited to inform you that a <a style="color:red;">${t.title}</a> closed tender in the <a style="color:red;">${t.tenderCategoryD['productCategory']}</a> category will been added on our ArtNouveau website.<br><br>
|
||||
You can view the details on <a style="color:red;">${publishDate}</a> and submit your bids by visiting the website at <strong> <a href="tender.artnouveau.in/#/auth/login" >tender.artnouveau.in</a></strong> <br><br>
|
||||
|
||||
For any inquiries or clarifications, please contact <br><br>
|
||||
|
||||
<br>
|
||||
|
||||
<div style="">
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Subash</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> subash@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 94469 64558</p>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div style="text-align: center; width:95%">
|
||||
<p style="text-align: start;"><strong>Name:</strong>Boncy</p>
|
||||
<p style="text-align: start;"><strong>Email:</strong> boncy@artnouveau.in</p>
|
||||
<p style="text-align: start;"><strong>Phone:</strong> +91 85473 42848</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
Best regards,<br>
|
||||
Artnouveau Architects</strong></p>
|
||||
<span
|
||||
style="display:inline-block; vertical-align:middle; margin:29px 0 26px; border-bottom:1px solid #cecece; width:100px;"></span>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:40px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:20px;"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center;">
|
||||
<p style="font-size:14px; color:rgba(69, 80, 86, 0.7411764705882353); line-height:18px; margin:0 0 0;">©<strong> <a href="https://www.artnouveau.in/" >www.artnouveau.in</a></strong> </p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:80px;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--/100% body table-->
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
let subject = `New Tender Added in ${t.tenderCategoryD['productCategory']} Category on ArtNouveau Website`
|
||||
// console.log(closedTenderUsers);
|
||||
await this.sendMailManually(closedTenderUsers, subject, html, html)
|
||||
closedTenderUsers = []
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,859 @@
|
||||
import { BadRequestException, Controller, Delete, Get, NotFoundException, Param, Post, Req, Res, UploadedFile, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { diskStorage } from 'multer';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { GetUser } from 'src/auth/dto/get-user.decorator';
|
||||
import { FileUploadService } from './file-upload.service';
|
||||
import * as fs from 'fs';
|
||||
import * as archiver from 'archiver';
|
||||
import * as path from 'path';
|
||||
import { join, extname } from 'path';
|
||||
import { tenderDocRepository } from 'src/tables/tender-documents/tender-doc.repository';
|
||||
import { TenderDocumentDto } from 'src/dto/tender-document.dto';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { log } from 'console';
|
||||
|
||||
export function createFolders(filePath: string) {
|
||||
|
||||
|
||||
const splitPath = filePath.split('/');
|
||||
splitPath.reduce((path, subPath) => {
|
||||
let currentPath;
|
||||
if (subPath != '.') {
|
||||
currentPath = path + '/' + subPath;
|
||||
|
||||
if (!existsSync(currentPath)) {
|
||||
mkdirSync(currentPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentPath = subPath;
|
||||
}
|
||||
return currentPath
|
||||
|
||||
}, '')
|
||||
}
|
||||
|
||||
|
||||
@Controller('file-upload')
|
||||
export class FileUploadController {
|
||||
constructor(
|
||||
@InjectRepository(tenderDocRepository)
|
||||
private readonly tenderDocRepository: tenderDocRepository,
|
||||
|
||||
private iservice: FileUploadService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@Post('user-documents/:id/:userId')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
destination: (req, res, cb) => {
|
||||
const parentFolder: string = './uploads/userDocuments/' + req.params.id;
|
||||
createFolders(parentFolder);
|
||||
const childFolder: string = parentFolder + '/' + req.params.userId;
|
||||
createFolders(childFolder);
|
||||
return cb(null, childFolder);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Use the original filename instead of generating a random name
|
||||
return cb(null, `${file.originalname}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
userDoc(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
// To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post('Bank-documents/:id')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
|
||||
|
||||
const filePath: string = './uploads/BankDocuments/' + req.params.id;
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Use the original filename instead of generating a random name
|
||||
return cb(null, `${file.originalname}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
bankDoc(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post('drawings/:id')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/Drawings/' + req.params.id;
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Use the original filename instead of generating a random name
|
||||
return cb(null, `${file.originalname}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
drawings(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('R-drawing/:id/:filename')
|
||||
async deleteDrawing(
|
||||
@Param('filename') filename: string,
|
||||
@Param('id') id: string): Promise<any> {
|
||||
const filePath = './uploads/Drawings/' + id + '/' + filename;
|
||||
try {
|
||||
console.log("deleted=====", id, filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename, id: id };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, tenderId: parseInt(id), documentCategory: 'D' } });
|
||||
if (deletedEntry) {
|
||||
console.log('helloooooo');
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Delete('R-userDoc/:id/:userId/:filename')
|
||||
async deleteUserDoc(
|
||||
@Param('userId') userId: string,
|
||||
@Param('filename') filename: string,
|
||||
@Param('id') id: string,
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/userDocuments/' + id + '/' + userId + '/' + filename;
|
||||
try {
|
||||
console.log("deleted=====", userId, filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, tenderId: parseInt(id), userId: parseInt(userId), documentCategory: 'USERD' } });
|
||||
if (deletedEntry) {
|
||||
console.log('helloooooo');
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('R-bankDoc/:id/:filename')
|
||||
async deleteBankDoc(
|
||||
@Param('filename') filename: string,
|
||||
@Param('id') id: string): Promise<any> {
|
||||
const filePath = './uploads/BankDocuments/' + id + '/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", id, filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, tenderId: parseInt(id), documentCategory: 'WID' } });
|
||||
if (deletedEntry) {
|
||||
console.log('helloooooo');
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('R-notice/:id/:filename')
|
||||
async deleteNotice(
|
||||
@Param('filename') filename: string,
|
||||
@Param('id') id: string): Promise<any> {
|
||||
const filePath = './uploads/Notice/' + id + '/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", id, filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, tenderId: parseInt(id), documentCategory: 'NIT' } });
|
||||
if (deletedEntry) {
|
||||
console.log('helloooooo');
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post('notice/:id')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/Notice/' + req.params.id;
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Use the original filename instead of generating a random name
|
||||
return cb(null, `${file.originalname}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
notice(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
|
||||
@Get('notice/:id/:imgpath')
|
||||
getNotice(
|
||||
@Param('imgpath') image: string,
|
||||
@Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
return res.sendFile(image, { root: './uploads/Notice/' + id }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Get('Bank-Documents/:id/:imgpath')
|
||||
getBankDocuments(
|
||||
@Param('imgpath') image: string,
|
||||
@Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
|
||||
) {
|
||||
return res.sendFile(image, { root: './uploads/BankDocuments/' + id }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@Get('user-Documents/:id/:userId/:imgpath')
|
||||
getUserDocuments(
|
||||
@Param('imgpath') image: string,
|
||||
@Param('userId') userId: string,
|
||||
@Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
|
||||
) {
|
||||
return res.sendFile(image, { root: './uploads/userDocuments/' + id + '/' + userId }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Get('Bank-Documents-Arc/:id')
|
||||
async getBankDocumentsAsZip(
|
||||
@Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
const folderPath = path.join('./uploads/BankDocuments', id);
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
res.status(404).send({ error: 'File not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
//Uncomment when we want tender id as the zip file name
|
||||
//const zipFileName = id + '.zip';
|
||||
const zipFileName = 'tenderDocuments.zip';
|
||||
const zipPath = path.join('./uploads/BankDocuments', zipFileName);
|
||||
|
||||
// Create a new archive
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Set compression level (optional)
|
||||
});
|
||||
|
||||
// Create a write stream to the zip file
|
||||
const output = fs.createWriteStream(zipPath);
|
||||
|
||||
// Pipe the archive to the write stream
|
||||
archive.pipe(output);
|
||||
|
||||
// Add the entire folder to the archive
|
||||
archive.directory(folderPath, id);
|
||||
|
||||
// Finalize the archive
|
||||
await archive.finalize();
|
||||
|
||||
// Set the appropriate headers for downloading the zip file
|
||||
res.attachment(zipFileName);
|
||||
res.setHeader('Content-Type', 'application/zip');
|
||||
|
||||
// Stream the zip file to the response
|
||||
const readStream = fs.createReadStream(zipPath);
|
||||
readStream.pipe(res);
|
||||
|
||||
// Remove the temporary zip file once it's streamed
|
||||
readStream.on('end', () => {
|
||||
fs.unlinkSync(zipPath);
|
||||
});
|
||||
|
||||
// Handle any errors that occur during the archiving process
|
||||
archive.on('error', function (err) {
|
||||
console.log(err);
|
||||
res.status(500).send({ error: 'Failed to create the zip file' });
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Get('Drawings-Arc/:id')
|
||||
async getDrawingsAsZip(
|
||||
@Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
const folderPath = path.join('./uploads/Drawings', id);
|
||||
console.log(folderPath);
|
||||
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
console.log(
|
||||
"helloo"
|
||||
);
|
||||
|
||||
res.status(404).send({ error: 'File not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
//Uncomment when we want tender id as the zip file name
|
||||
//const zipFileName = id + '.zip';
|
||||
const zipFileName = 'Drawings.zip';
|
||||
const zipPath = path.join('./uploads/Drawings', zipFileName);
|
||||
|
||||
// Create a new archive
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Set compression level (optional)
|
||||
});
|
||||
|
||||
// Create a write stream to the zip file
|
||||
const output = fs.createWriteStream(zipPath);
|
||||
|
||||
// Pipe the archive to the write stream
|
||||
archive.pipe(output);
|
||||
|
||||
// Add the entire folder to the archive
|
||||
archive.directory(folderPath, id);
|
||||
|
||||
// Finalize the archive
|
||||
await archive.finalize();
|
||||
|
||||
// Set the appropriate headers for downloading the zip file
|
||||
res.attachment(zipFileName);
|
||||
res.setHeader('Content-Type', 'application/zip');
|
||||
|
||||
// Stream the zip file to the response
|
||||
const readStream = fs.createReadStream(zipPath);
|
||||
readStream.pipe(res);
|
||||
|
||||
// Remove the temporary zip file once it's streamed
|
||||
readStream.on('end', () => {
|
||||
fs.unlinkSync(zipPath);
|
||||
});
|
||||
|
||||
// Handle any errors that occur during the archiving process
|
||||
archive.on('error', function (err) {
|
||||
console.log(err);
|
||||
res.status(500).send({ error: 'Failed to create the zip file' });
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Get('user-doc-arc/:id/:userId')
|
||||
async getUserDocsAsZip(
|
||||
@Param('id') id: string,
|
||||
@Param('userId') userId: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
const folderPath = path.join('./uploads/userDocuments' + '/' + id + '/' + userId);
|
||||
|
||||
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
res.status(404).send({ error: 'File not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
//Uncomment when we want tender id as the zip file name
|
||||
//const zipFileName = id + '.zip';
|
||||
const zipFileName = 'userDocuments.zip';
|
||||
const zipPath = path.join('./uploads/userDocuments', zipFileName);
|
||||
|
||||
// Create a new archive
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Set compression level (optional)
|
||||
});
|
||||
|
||||
// Create a write stream to the zip file
|
||||
const output = fs.createWriteStream(zipPath);
|
||||
|
||||
// Pipe the archive to the write stream
|
||||
archive.pipe(output);
|
||||
|
||||
// Add the entire folder to the archive
|
||||
archive.directory(folderPath, id);
|
||||
|
||||
// Finalize the archive
|
||||
await archive.finalize();
|
||||
|
||||
// Set the appropriate headers for downloading the zip file
|
||||
res.attachment(zipFileName);
|
||||
res.setHeader('Content-Type', 'application/zip');
|
||||
|
||||
// Stream the zip file to the response
|
||||
const readStream = fs.createReadStream(zipPath);
|
||||
readStream.pipe(res);
|
||||
|
||||
// Remove the temporary zip file once it's streamed
|
||||
readStream.on('end', () => {
|
||||
fs.unlinkSync(zipPath);
|
||||
});
|
||||
|
||||
// Handle any errors that occur during the archiving process
|
||||
archive.on('error', function (err) {
|
||||
console.log(err);
|
||||
res.status(500).send({ error: 'Failed to create the zip file' });
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Post('picture')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/Pictures';
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Useing a random name
|
||||
const randomName = uuidv4();
|
||||
const fileExtension = file.originalname.split('.').pop();
|
||||
return cb(null, `${randomName}.${fileExtension}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
pictures(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@Get('picture/:imgpath')
|
||||
getPicture(
|
||||
@Param('imgpath') image: string,
|
||||
// @Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
console.log("filegettt");
|
||||
|
||||
return res.sendFile(image, { root: './uploads/Pictures' }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Delete('picture/:filename')
|
||||
async deletePicture(
|
||||
@Param('filename') filename: string,
|
||||
// @Param('id') id:string
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/Pictures/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, documentCategory: 'WEBSITE' } });
|
||||
if (deletedEntry) {
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post('dd')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/DD';
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Useing a random name
|
||||
const randomName = uuidv4();
|
||||
const fileExtension = file.originalname.split('.').pop();
|
||||
return cb(null, `${randomName}.${fileExtension}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
DD(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@Get('dd/:imgpath')
|
||||
getDD(
|
||||
@Param('imgpath') image: string,
|
||||
// @Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
console.log("filegettt");
|
||||
|
||||
return res.sendFile(image, { root: './uploads/DD' }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('dd/:filename')
|
||||
async deleteDD(
|
||||
@Param('filename') filename: string,
|
||||
// @Param('id') id:string
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/DD/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, documentCategory: 'DD' } });
|
||||
if (deletedEntry) {
|
||||
await this.tenderDocRepository.remove(deletedEntry);
|
||||
console.log('Entry deleted successfully.');
|
||||
}
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Post('company-profile')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/company';
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Useing a random name
|
||||
const randomName = uuidv4();
|
||||
const fileExtension = file.originalname.split('.').pop();
|
||||
return cb(null, `${randomName}.${fileExtension}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
companyProfile(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@Get('company-profile/:imgpath')
|
||||
getCompanyProfile(
|
||||
@Param('imgpath') image: string,
|
||||
// @Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
console.log("filegettt");
|
||||
|
||||
return res.sendFile(image, { root: './uploads/company' }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Delete('company-profile/:filename')
|
||||
async deleteCompanyProfile(
|
||||
@Param('filename') filename: string,
|
||||
// @Param('id') id:string
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/company/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
// const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, documentCategory: 'DD' } });
|
||||
// if (deletedEntry) {
|
||||
// await this.tenderDocRepository.remove(deletedEntry);
|
||||
// console.log('Entry deleted successfully.');
|
||||
// }
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Post('project-complete_cert')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/company';
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Useing a random name
|
||||
const randomName = uuidv4();
|
||||
const fileExtension = file.originalname.split('.').pop();
|
||||
return cb(null, `${randomName}.${fileExtension}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
projectCompletionCert(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@Get('project-complete_cert/:imgpath')
|
||||
getprojectCompletionCert(
|
||||
@Param('imgpath') image: string,
|
||||
// @Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
console.log("filegettt");
|
||||
|
||||
return res.sendFile(image, { root: './uploads/company' }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @UseGuards(AuthGuard())
|
||||
@Delete('project-complete_cert/:filename')
|
||||
async deleteprojectCompletionCert(
|
||||
@Param('filename') filename: string,
|
||||
// @Param('id') id:string
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/company/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
// const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, documentCategory: 'DD' } });
|
||||
// if (deletedEntry) {
|
||||
// await this.tenderDocRepository.remove(deletedEntry);
|
||||
// console.log('Entry deleted successfully.');
|
||||
// }
|
||||
return { message: 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post('quoted-tender')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// destination: './uploads/cars',
|
||||
destination: (req, res, cb) => {
|
||||
// console.log(req);
|
||||
|
||||
const filePath: string = './uploads/QuotedTender';
|
||||
createFolders(filePath);
|
||||
return cb(null, filePath);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
// Useing a random name
|
||||
const randomName = uuidv4();
|
||||
const fileExtension = file.originalname.split('.').pop();
|
||||
return cb(null, `${randomName}.${fileExtension}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
QuotedTender(@UploadedFile() file) {
|
||||
if (!file) {
|
||||
return { error: 'No file uploaded.' };
|
||||
}
|
||||
//To return the size of the document in kb
|
||||
const fileSizeKB = Math.ceil(file.size / 1024);
|
||||
return { fileName: file.filename, filePath: file.path, fileSizeKB };
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Get('quoted-tender/:imgpath')
|
||||
GetQuotedTender(
|
||||
@Param('imgpath') image: string,
|
||||
// @Param('id') id: string,
|
||||
@Res() res,
|
||||
@Req() req,
|
||||
) {
|
||||
console.log("filegettt");
|
||||
|
||||
return res.sendFile(image, { root: './uploads/QuotedTender' }, function (err) {
|
||||
if (err) {
|
||||
console.log(err.status);
|
||||
res.status(err.status).end();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('quoted-tender/:filename')
|
||||
async deleteQuotedTender(
|
||||
@Param('filename') filename: string,
|
||||
// @Param('id') id:string
|
||||
): Promise<any> {
|
||||
const filePath = './uploads/QuotedTender/' + filename;
|
||||
console.log("filepath===", filePath);
|
||||
try {
|
||||
console.log("deleted=====", filename);
|
||||
|
||||
await fs.promises.unlink(filePath);
|
||||
const filter = { docName: filename };
|
||||
// const deletedEntry = await this.tenderDocRepository.findOne({ where: { docName: filename, documentCategory: 'DD' } });
|
||||
// if (deletedEntry) {
|
||||
// await this.tenderDocRepository.remove(deletedEntry);
|
||||
// console.log('Entry deleted successfully.');
|
||||
// }
|
||||
return { message : 'File and entry deleted successfully.' };
|
||||
} catch (err) {
|
||||
throw new NotFoundException('File or entry not found.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { FileUploadController } from './file-upload.controller';
|
||||
import { FileUploadService } from './file-upload.service';
|
||||
import { MulterModule } from '@nestjs/platform-express';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { tenderDocRepository } from 'src/tables/tender-documents/tender-doc.repository';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { TenderDoc } from 'src/tables/tender-documents/tender-doc.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MulterModule.register({
|
||||
dest: './uploads'
|
||||
}),
|
||||
TypeOrmModule.forFeature([
|
||||
TenderDoc
|
||||
]),
|
||||
AuthModule,
|
||||
],
|
||||
controllers: [FileUploadController],
|
||||
providers: [FileUploadService,tenderDocRepository
|
||||
]
|
||||
})
|
||||
export class FileUploadModule { }
|
||||
@ -0,0 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class FileUploadService {}
|
||||
@ -0,0 +1,63 @@
|
||||
import { Body, DefaultValuePipe, Delete, Get, Logger, Param, ParseIntPipe, Post, Put, Query, UsePipes, ValidationPipe } from "@nestjs/common";
|
||||
import { GetUser } from "src/auth/dto/get-user.decorator";
|
||||
import { PcduserDto } from "src/auth/dto/pcd-user.dto";
|
||||
import { FindManyOptions } from "typeorm";
|
||||
import { PcdFormGridService } from "./pcd-form-grid.service";
|
||||
import { AuthGuard } from "@nestjs/passport";
|
||||
import { AuthModule } from "src/auth/auth.module";
|
||||
|
||||
export class PcdFormGridController<T>{
|
||||
private logger = new Logger('PcdFormGridController'); // for logging
|
||||
constructor(
|
||||
private service: PcdFormGridService<T>
|
||||
) {
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(
|
||||
@Query() filter: FindManyOptions,
|
||||
@GetUser() user: PcduserDto
|
||||
): Promise<any[]> {
|
||||
return await this.service.findAll(filter, user);
|
||||
}
|
||||
|
||||
|
||||
@Get('/:id')
|
||||
async getOne(
|
||||
@Query() filterDto: FindManyOptions,
|
||||
@Param('id') id: string,
|
||||
@GetUser() user: PcduserDto,
|
||||
): Promise<any> {
|
||||
|
||||
return await this.service.findOne(filterDto, id, user);
|
||||
}
|
||||
|
||||
@UsePipes(ValidationPipe)
|
||||
@Post()
|
||||
async createOne(
|
||||
@Body() body: T,
|
||||
@GetUser() user: PcduserDto
|
||||
): Promise<any> {
|
||||
|
||||
return await this.service.createOne(body, user);
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
async updateOne(
|
||||
@Body(ValidationPipe) body: any,
|
||||
@Param('id') id: number,
|
||||
@GetUser() user: PcduserDto
|
||||
) {
|
||||
return await this.service.updateOne(body, id, user);
|
||||
}
|
||||
|
||||
@Delete('/:id')
|
||||
async deleteOne(
|
||||
@Query() filter: FindManyOptions,
|
||||
@Param('id') id: string,
|
||||
@GetUser() user: PcduserDto,
|
||||
): Promise<any> {
|
||||
return await this.service.deleteOne(filter, id, user);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,278 @@
|
||||
import { BadRequestException, ConflictException, HttpException, InternalServerErrorException, NotAcceptableException } from '@nestjs/common';
|
||||
import { PcduserDto } from 'src/auth/dto/pcd-user.dto';
|
||||
import { FindManyOptions, Not, Repository } from 'typeorm';
|
||||
import { PcdFormGridInterface } from '../interface/pcd-form-grid.interface';
|
||||
|
||||
|
||||
export class PcdFormGridService<T> implements PcdFormGridInterface {
|
||||
MAIN_KEY: string = 'id';
|
||||
CUSTID: string = '';
|
||||
MANDATORY_FEILDS: string[] = [];
|
||||
DUPLICATE_CHK: string[] = [];
|
||||
FK_FEILDS: { column: string, relation: Repository<any> }[] = [];
|
||||
ROW_COUNT: string = '';
|
||||
constructor(
|
||||
// @Inject(TENANT_CONNECTION) conn:Connection,
|
||||
private repo: Repository<any>
|
||||
) { }
|
||||
async preFindAll(filter: FindManyOptions, user: PcduserDto): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
async findAll(filter: FindManyOptions, user: PcduserDto): Promise<any[]> {
|
||||
if (!filter.where) filter.where = {};
|
||||
|
||||
if (!await this.preFindAll(filter, user))
|
||||
throw new BadRequestException(`Unepected Error Occured in findAll`);
|
||||
// console.log("====1==== filter===", filter);
|
||||
const result = await this.repo.find(filter);
|
||||
// console.log("====2==== result===", result);
|
||||
return await this.postFindAll(filter, user, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
async postFindAll(filter: FindManyOptions, user: PcduserDto, result: T[]): Promise<T[]> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async preFindOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async findOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<any> {
|
||||
if (!filter.where) filter.where = {};
|
||||
|
||||
filter.where[this.MAIN_KEY] = id;
|
||||
|
||||
if (!await this.preFindOne(filter, id, user))
|
||||
throw new BadRequestException(`Unepected Error Occured in findAll`);
|
||||
|
||||
const result = await this.repo.findOne(filter);
|
||||
|
||||
return await this.postFindOne(filter, id, user, result);
|
||||
}
|
||||
|
||||
async postFindOne(filter: FindManyOptions, id: string | number, user: PcduserDto, result: T): Promise<T> {
|
||||
return result;
|
||||
}
|
||||
async preCreateOne(body: T, user: PcduserDto): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
async createOne(body: any, user: PcduserDto): Promise<any> {
|
||||
for (let colMan of this.MANDATORY_FEILDS) {
|
||||
if (!body[colMan] || body[colMan].toString().trim() == "") {
|
||||
throw new BadRequestException(`${colMan} field Cannot be Blank`);
|
||||
}
|
||||
}
|
||||
console.log("==this.DUPLICATE_CHK===", this.DUPLICATE_CHK);
|
||||
|
||||
for (let dupCol of this.DUPLICATE_CHK) {
|
||||
const dupfilter = { where: {} };
|
||||
// if (!dupCol.isSl || (user.coCodeD.secondryLangauge && user.coCodeD.multiLanguageYn == 'Y' && dupCol.isSl)) {
|
||||
// if (dupCol && isArray(dupCol) && dupCol.column.length > 0) {
|
||||
// dupCol.forEach(element => {
|
||||
// console.log("===element====", element);
|
||||
dupfilter.where[dupCol] = body[dupCol];
|
||||
// })
|
||||
// }
|
||||
// else
|
||||
// dupfilter.where[dupCol.column] = body[dupCol.column];
|
||||
// }
|
||||
// else
|
||||
// continue;
|
||||
console.log("===dupRec filter====", dupfilter);
|
||||
|
||||
let dupRec = await this.repo.findOne(dupfilter);
|
||||
if (dupRec)
|
||||
throw new BadRequestException(`Duplication not allowed for ${dupCol}`);
|
||||
}
|
||||
|
||||
console.log("==user.userId==", user);
|
||||
if (user ) {
|
||||
body["createdBy"] = user.userId;
|
||||
body["modifiedBy"] = user.userId;
|
||||
// body[this.CUSTID] = user.custId;
|
||||
}
|
||||
|
||||
if (!await this.preCreateOne(body, user))
|
||||
throw new BadRequestException(`Unexpected Error Occured in create`);
|
||||
for (let eagerCol of await this.getEagerColumns()) {
|
||||
delete body[eagerCol];
|
||||
}
|
||||
try {
|
||||
await this.repo.save(body);
|
||||
const filter: FindManyOptions = await this.getFilterWithPrimaryKey(body);
|
||||
const result = await this.findOne(filter, body[this.MAIN_KEY], user);
|
||||
|
||||
return await this.postCreateOne(body, user, result);
|
||||
} catch (err) {
|
||||
console.log("==err==", err);
|
||||
throw new InternalServerErrorException(err);
|
||||
}
|
||||
}
|
||||
async postCreateOne(body: T, user: PcduserDto, result: T): Promise<T> {
|
||||
return result;
|
||||
}
|
||||
async preUpdateOne(body: T, id: string | number, user: PcduserDto): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
async updateOne(body: any, id: string | number, user: PcduserDto): Promise<any> {
|
||||
|
||||
for (let colMan of this.MANDATORY_FEILDS) {
|
||||
|
||||
if (!body[colMan] || body[colMan].toString().trim() == "") {
|
||||
throw new BadRequestException(`${colMan} field Cannot be Blank`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let dupCol of this.DUPLICATE_CHK) {
|
||||
const dupfilter = { where: {} };
|
||||
dupfilter.where[this.MAIN_KEY] = Not(body[this.MAIN_KEY]);
|
||||
|
||||
// if (!dupCol.isSl || (user.coCodeD.secondryLangauge && user.coCodeD.multiLanguageYn == 'Y' && dupCol.isSl)) {
|
||||
// if (dupCol.column && isArray(dupCol.column) && dupCol.column.length > 0) {
|
||||
// dupCol.column.forEach(element => {
|
||||
// dupfilter.where[element] = body[element];
|
||||
// })
|
||||
// }
|
||||
// else
|
||||
dupfilter.where[dupCol] = body[dupCol];
|
||||
// }
|
||||
// else
|
||||
// continue;
|
||||
|
||||
let dupRec = await this.repo.findOne(dupfilter);
|
||||
if (dupRec)
|
||||
throw new BadRequestException(`Duplication not allowed for ${dupCol}`);
|
||||
|
||||
}
|
||||
const filter: FindManyOptions = await this.getFilterWithPrimaryKey(body);
|
||||
const updateRow = await this.getOne(filter, body[this.MAIN_KEY], user);
|
||||
console.log("====updateRow====", updateRow);
|
||||
|
||||
for (let eagerCol of await this.getEagerColumns()) {
|
||||
delete body[eagerCol];
|
||||
}
|
||||
// updateRow["coCode"] = user.coCode;
|
||||
const COLUMNS = await this.getAllColumns();
|
||||
const PRIMARY_KEYS = await this.getPrimaryKeys();
|
||||
|
||||
COLUMNS.forEach((row) => {
|
||||
if (!PRIMARY_KEYS.includes(row))
|
||||
updateRow[row] = body[row];
|
||||
});
|
||||
console.log("====update row 1 ====", updateRow);
|
||||
await this.repo.save(updateRow);
|
||||
// const filter: FindManyOptions = await this.getFilterWithPrimaryKey(body);
|
||||
const result = await this.findOne(filter, body[this.MAIN_KEY], user);
|
||||
return await this.postUpdateOne(body, id, user, result);
|
||||
}
|
||||
|
||||
async postUpdateOne(body: T, id: string | number, user: PcduserDto, result: T): Promise<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async preDeleteOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<boolean> {
|
||||
for (let fkRel of this.FK_FEILDS) {
|
||||
const fkFilter = { where: {} };
|
||||
fkFilter.where[fkRel.column] = id;
|
||||
const result = await fkRel.relation.findOne(fkFilter);
|
||||
if (result)
|
||||
throw new ConflictException(`Can't delete Record. Detail Records Exists.`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
async deleteOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<any> {
|
||||
if (!filter.where) filter.where = {};
|
||||
filter.where[this.MAIN_KEY] = id;
|
||||
if (this.CUSTID)
|
||||
filter.where[this.CUSTID] = user.custId;
|
||||
if (!await this.preDeleteOne(filter, id, user))
|
||||
throw new BadRequestException(`Unexpected Error Occured in delete`);
|
||||
|
||||
const delFilter = await this.getDeleteFilter(filter);
|
||||
|
||||
if (!delFilter[this.MAIN_KEY])
|
||||
throw new NotAcceptableException(`Please select a data to delete`);
|
||||
try {
|
||||
const result = await this.repo.delete(delFilter);
|
||||
return await this.postDeleteOne(filter, id, user, result);
|
||||
} catch (err) {
|
||||
if (err.status) throw new HttpException(err.message, err.status);
|
||||
|
||||
throw new InternalServerErrorException(`${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async postDeleteOne(filter: FindManyOptions, id: string | number, user: PcduserDto, result: any): Promise<any> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getDeleteFilter(whereFilter: FindManyOptions): Promise<any> {
|
||||
const filter: FindManyOptions = {};
|
||||
const PRIMARY_KEYS = await this.getPrimaryKeys();
|
||||
await PRIMARY_KEYS.forEach((column) => {
|
||||
filter[column] = whereFilter.where[column];
|
||||
});
|
||||
return filter;
|
||||
}
|
||||
|
||||
async getOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<any> {
|
||||
if (!filter.where) filter.where = {};
|
||||
if (this.CUSTID)
|
||||
filter.where[this.CUSTID] = user.custId;
|
||||
filter.where[this.MAIN_KEY] = id;
|
||||
|
||||
const result = await this.repo.findOne(filter);
|
||||
|
||||
return result;
|
||||
}
|
||||
async getAllColumns(): Promise<string[]> {
|
||||
const COLUMNS: string[] = [];
|
||||
for (let columnProperty in this.repo.metadata.propertiesMap) {
|
||||
COLUMNS.push(this.repo.metadata.propertiesMap[columnProperty]);
|
||||
}
|
||||
// in the below method it will not take the forignKey columns Like modelD etc..
|
||||
// await this.repo.metadata.columns.forEach((row) => {
|
||||
// COLUMNS.push(row.propertyName);
|
||||
// });
|
||||
return COLUMNS;
|
||||
}
|
||||
|
||||
async getPrimaryKeys(): Promise<string[]> {
|
||||
const PRIMARY_KEYS: string[] = [];
|
||||
await this.repo.metadata.primaryColumns.forEach((row) => {
|
||||
PRIMARY_KEYS.push(row.propertyName);
|
||||
});
|
||||
return PRIMARY_KEYS;
|
||||
}
|
||||
|
||||
async getFilterWithPrimaryKey(body: T): Promise<FindManyOptions> {
|
||||
const filter: FindManyOptions = { where: {} };
|
||||
const PRIMARY_KEYS = await this.getPrimaryKeys();
|
||||
await PRIMARY_KEYS.forEach((column) => {
|
||||
filter.where[column] = body[column];
|
||||
});
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
async getEagerColumns(): Promise<string[]> {
|
||||
/*
|
||||
For getting Eager true columns having Many to One relations.
|
||||
We need to remove the eager columns before insertions or updations or it will not allow to save data (But save message will show, but data not updated)
|
||||
*/
|
||||
const COLUMNS: string[] = [];
|
||||
for (let columnProperty of this.repo.metadata.eagerRelations) {
|
||||
COLUMNS.push(columnProperty.propertyName);
|
||||
}
|
||||
return COLUMNS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { Logger, Get, Query, Delete, Post, Body, Param, UseGuards } from "@nestjs/common";
|
||||
import { AuthGuard } from "@nestjs/passport";
|
||||
import { AuthModule } from "src/auth/auth.module";
|
||||
import { FindManyOptions } from "typeorm";
|
||||
import { PcdTransactionService } from "./pcd-transaction.service";
|
||||
import { GetUser } from "src/auth/dto/get-user.decorator";
|
||||
import { PcduserDto } from "src/auth/dto/pcd-user.dto";
|
||||
|
||||
export class PcdTransactionController<T> {
|
||||
|
||||
private logger = new Logger('PcdTransactionController'); // for logging
|
||||
|
||||
constructor(
|
||||
private service: PcdTransactionService<T>
|
||||
) { }
|
||||
|
||||
@Get()
|
||||
async findList(@Query() filter: FindManyOptions,
|
||||
@GetUser() user: PcduserDto
|
||||
): Promise<T[]> {
|
||||
return await this.service.findList(filter, user);
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
async findOne(@Query() filter: FindManyOptions, @Param('id') id: string,): Promise<T> {
|
||||
return await this.service.findOne(filter, id);
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Post()
|
||||
async createOne(@Body() body: T,
|
||||
@GetUser() user: PcduserDto): Promise<T> {
|
||||
return await this.service.createOne(body, user);
|
||||
}
|
||||
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Delete('/:id')
|
||||
async delete(@Query() filter: FindManyOptions, @Param('id') id: string,): Promise<any> {
|
||||
return await this.service.deleteOne(filter, id,);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,357 @@
|
||||
import { PcdtTransactionInterface } from "../interface/pcd-transaction.interface";
|
||||
import { FindManyOptions, Repository, getConnection, QueryRunner, Connection, DataSource, FindOneOptions } from "typeorm";
|
||||
import { BadRequestException, NotAcceptableException, UnauthorizedException, InternalServerErrorException, MethodNotAllowedException, HttpException, Inject } from "@nestjs/common";
|
||||
import { TransactionDetailDto } from "src/framework/custom/transaction-detail.dto";
|
||||
import { PcduserDto } from "src/auth/dto/pcd-user.dto";
|
||||
//import { TENANT_CONNECTION } from "src/tenant/tenant.module";
|
||||
// import { IintDto } from "../../dto/iint.dto";
|
||||
// import { IintvrnoDto } from "../../dto/iintvrno.dto";
|
||||
// import { IintService } from "../../tables/iint/iint.service";
|
||||
|
||||
export class PcdTransactionService<T> implements PcdtTransactionInterface {
|
||||
|
||||
MAIN_KEY: string = "id";
|
||||
TXN_TYPE: string = "";
|
||||
|
||||
DETAIL_DATA_FORMAT: TransactionDetailDto[] = [];
|
||||
|
||||
constructor(
|
||||
private connection: DataSource,
|
||||
private repo: Repository<any>
|
||||
) { }
|
||||
|
||||
async preFindList(filter: FindManyOptions, user: PcduserDto): Promise<boolean> {
|
||||
return true
|
||||
}
|
||||
|
||||
async findList(filter: FindManyOptions, user: PcduserDto): Promise<T[]> {
|
||||
if (!filter.where) filter.where = {};
|
||||
if (this.TXN_TYPE) filter.where[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
// if (!filter.where[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName])
|
||||
// return;
|
||||
|
||||
if (!await this.preFindList(filter, user))
|
||||
throw new BadRequestException(`Unexpected Error Occured in findList`);
|
||||
let result: T[] = await this.repo.find(filter);
|
||||
|
||||
return await this.postFindList(filter, result);
|
||||
}
|
||||
|
||||
async postFindList(filter: FindManyOptions, result: T[]): Promise<T[]> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async preFindOne(filter: FindManyOptions,): Promise<boolean> {
|
||||
return true
|
||||
}
|
||||
|
||||
async findOne(filter: FindOneOptions, id: string | number,): Promise<T> {
|
||||
if (!filter.where) filter.where = {};
|
||||
if (this.TXN_TYPE) filter.where[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
let orgFilter = Object.create(filter);
|
||||
|
||||
filter.where[this.MAIN_KEY] = id;
|
||||
|
||||
if (!await this.preFindOne(filter))
|
||||
throw new BadRequestException(`Unepected Error Occured in findOne`);
|
||||
//branch right check();
|
||||
|
||||
|
||||
let result: T = await this.repo.findOne(filter);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
result = await this.getDetailData(result, orgFilter, this.DETAIL_DATA_FORMAT);
|
||||
|
||||
return await this.postFindOne(filter, result);
|
||||
}
|
||||
|
||||
async postFindOne(filter: FindManyOptions, result: T): Promise<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async preDeleteOne(filter: FindManyOptions, id: string | number,): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async deleteOne(filter: any, id: string | number,): Promise<any> {
|
||||
if (!filter || !filter.where) filter.where = {};
|
||||
if (this.TXN_TYPE) filter.where[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
filter.where[this.MAIN_KEY] = id;
|
||||
|
||||
const delFilter = await this.getDeleteFilter(filter);
|
||||
if (!delFilter[this.MAIN_KEY])
|
||||
throw new NotAcceptableException(`Please select a record`);
|
||||
if (!await this.preDeleteOne(filter, id,))
|
||||
throw new BadRequestException(`Unepected Error Occured in deleteOne`);
|
||||
const queryRunner = this.connection.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
try {
|
||||
await queryRunner.startTransaction();
|
||||
await this.deleteDetailDataTabels(id, this.DETAIL_DATA_FORMAT, queryRunner);
|
||||
const result = await queryRunner.manager.delete(this.repo.metadata.name, id);
|
||||
await queryRunner.commitTransaction();
|
||||
return await this.postDeleteOne(filter, result);
|
||||
} catch (err) {
|
||||
if (queryRunner.isTransactionActive)
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw new InternalServerErrorException(`${err.message}`);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
// const result = await this.repo.delete(delFilter);
|
||||
|
||||
}
|
||||
|
||||
async postDeleteOne(filter: FindManyOptions, result: any): Promise<any> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async preCreateOne(body: T,user): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async beforeCreateOne(body: T, queryRunner: QueryRunner): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async createOne(body: T, user: PcduserDto): Promise<T> {
|
||||
//console.log('--- incoming = ', body);
|
||||
|
||||
if (this.TXN_TYPE) body[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
if (!await this.preCreateOne(body,user))
|
||||
throw new BadRequestException(`Unexpected Error Occured in CreateOne`);
|
||||
for (let eagerCol of await this.getEagerColumns()) {
|
||||
delete body[eagerCol];
|
||||
}
|
||||
const queryRunner = this.connection.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
try {
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
if (this.TXN_TYPE) body[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
// await this.checkAndSetVrNo(body, user, queryRunner);
|
||||
|
||||
// for deleting deleted details from the angular
|
||||
for (let row of this.DETAIL_DATA_FORMAT) {
|
||||
body[row.detailName] = await this.deleteDetailData(body[row.detailName], row, queryRunner);
|
||||
}
|
||||
|
||||
|
||||
body["createdBy"] = 'SYSTEM';
|
||||
body["modifiedBy"] = 'SYSTEM';
|
||||
if (!await this.beforeCreateOne(body, queryRunner))
|
||||
throw new BadRequestException(`Unepected Error Occured in CreateOne`);
|
||||
|
||||
const data = await queryRunner.manager.save(this.repo.metadata.name, body);
|
||||
await this.insertDetailData(body, this.DETAIL_DATA_FORMAT, queryRunner, data);
|
||||
|
||||
await this.afterCreateOne(body);
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
|
||||
const filter: FindManyOptions = await this.getFilterWithPrimaryKey(body);
|
||||
const result = await this.findOne(filter, data[this.MAIN_KEY]);
|
||||
|
||||
return await this.postCreateOne(body, result);
|
||||
|
||||
} catch (err) {
|
||||
// since we have errors lets rollback changes we made
|
||||
console.log('--- err --', err);
|
||||
console.log('QueryFailedError', err.QueryFailedError);
|
||||
console.log('*******err name*****', err.name);
|
||||
console.log('-- message------', err.message);
|
||||
console.log('-- code------', err.code);
|
||||
|
||||
console.log('--- err.status --', err.status);
|
||||
console.log("===is active===", queryRunner.isTransactionActive);
|
||||
if (queryRunner.isTransactionActive)
|
||||
await queryRunner.rollbackTransaction();
|
||||
console.log("heree===afterrollback");
|
||||
if (err.status && err.status == '401') throw new MethodNotAllowedException(`${err.message.message}`);
|
||||
if (!(err.name == "QueryFailedError")) if (queryRunner.isTransactionActive) await queryRunner.rollbackTransaction();
|
||||
//console.log("====after rollback====");
|
||||
if (err.name == "QueryFailedError") {
|
||||
if (err.precedingErrors && err.precedingErrors.length > 0 && err.precedingErrors[0].originalError)
|
||||
throw new BadRequestException(`${err.precedingErrors[0].originalError}`);
|
||||
if (err.originalError)
|
||||
throw new BadRequestException(`${err.originalError}`);
|
||||
}
|
||||
if (err.status && err.status == 500) throw new HttpException(err.message.error, err.message.statusCode);
|
||||
if (err.status) throw new HttpException(err.message, err.status);
|
||||
|
||||
throw new InternalServerErrorException(`${err.message}`);
|
||||
}
|
||||
finally {
|
||||
console.log('--- finally --- ');
|
||||
await queryRunner.release();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async afterCreateOne(body: T): Promise<void> {
|
||||
}
|
||||
|
||||
async postCreateOne(body: T, result: T): Promise<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
async insertDetailData(body: T, detailData: TransactionDetailDto[], queryRunner: QueryRunner, insertedData: T): Promise<void> {
|
||||
|
||||
for (let row of detailData) {
|
||||
await this.insertDetailData2ndLevel(body[row.detailName], row, queryRunner, insertedData, insertedData);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDetailDataTabels(id: string | number, detailDataFormat: TransactionDetailDto[], queryRunner: QueryRunner): Promise<any> {
|
||||
for (let row of detailDataFormat) {
|
||||
await this.deleteDetailTableData(id, row, queryRunner);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDetailTableData(id: string | number, detailData: TransactionDetailDto, queryRunner: QueryRunner): Promise<any> {
|
||||
if (detailData.childDetail && detailData.childDetail.length > 0) {
|
||||
for (let child of detailData.childDetail) {
|
||||
await this.deleteDetailTableData(id, child, queryRunner);
|
||||
}
|
||||
}
|
||||
if (id) {
|
||||
let filter = {};
|
||||
if (detailData.foreignKeyColumnName) {
|
||||
filter[detailData.foreignKeyColumnName] = id;
|
||||
|
||||
} else {
|
||||
filter[detailData.foreignKeyAssignmentColumnName.columnName] = id;
|
||||
}
|
||||
await queryRunner.manager.delete(detailData.repo.metadata.name, filter);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteDetailData(body: T[], detailData: TransactionDetailDto, queryRunner: QueryRunner): Promise<T[]> {
|
||||
if (detailData.childDetail && detailData.childDetail.length > 0) {
|
||||
for (let child of detailData.childDetail) {
|
||||
if (body && body.length > 0) {
|
||||
for (let row of body) {
|
||||
if (row["crud"] == "D") {
|
||||
for (let detData of row[child.detailName]) {
|
||||
detData["crud"] = "D";
|
||||
}
|
||||
}
|
||||
row[child.detailName] = await this.deleteDetailData(row[child.detailName], child, queryRunner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (body) {
|
||||
await queryRunner.manager.remove(detailData.repo.metadata.name, body.filter((row: any) => row.crud == 'D'));
|
||||
body = body.filter((row: any) => row["crud"] != 'D');
|
||||
return body;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async insertDetailData2ndLevel(body: T[], detailData: TransactionDetailDto, queryRunner: QueryRunner, headerData: T, detailHeaderData: T): Promise<void> {
|
||||
|
||||
let deatilInsResult: any;
|
||||
let eagerCols: any = await this.getEagerColumns(detailData.repo);
|
||||
if (body) {
|
||||
for (let row of body) {
|
||||
for (let col of eagerCols) {
|
||||
delete row[col];
|
||||
}
|
||||
if (this.TXN_TYPE) row[this.DETAIL_DATA_FORMAT[0].transactionTypeColumnName] = this.TXN_TYPE;
|
||||
if (detailData.foreignKeyColumnName) {
|
||||
row[detailData.foreignKeyColumnName] = headerData[this.MAIN_KEY];
|
||||
} else {
|
||||
|
||||
row[detailData.foreignKeyAssignmentColumnName.columnName]
|
||||
= detailHeaderData[detailData.foreignKeyAssignmentColumnName.headerColumn];
|
||||
}
|
||||
row["createdBy"] = 'SYSTEM';
|
||||
row["modifiedBy"] = 'SYSTEM';
|
||||
if (detailData.addtionalSettingOfRowsInInsertion && detailData.addtionalSettingOfRowsInInsertion.length > 0) {
|
||||
for (let addRow of detailData.addtionalSettingOfRowsInInsertion) {
|
||||
row[addRow.columnName] = detailHeaderData[addRow.headerColumn];
|
||||
}
|
||||
}
|
||||
|
||||
deatilInsResult = await queryRunner.manager.save(detailData.repo.metadata.name, row);
|
||||
if (detailData.childDetail && detailData.childDetail.length > 0) {
|
||||
for (let child of detailData.childDetail) {
|
||||
if (body && body.length > 0) {
|
||||
await this.insertDetailData2ndLevel(row[child.detailName], child, queryRunner, headerData, deatilInsResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async getDetailData(result: any, filter: FindManyOptions, detailData: TransactionDetailDto[]): Promise<any> {
|
||||
for (let row of detailData) {
|
||||
result[row.detailName] = [];
|
||||
let filterDetail: FindManyOptions = Object.assign({}, filter);
|
||||
if (!filterDetail.where) filterDetail.where = {};
|
||||
for (let filterRow of row.filter) {
|
||||
filterDetail.where[filterRow.columnName] = filterRow.headerColumn ? result[filterRow.headerColumn] : filterRow.value;
|
||||
};
|
||||
if (row.orderByColumn) {
|
||||
if (!filterDetail.order) filterDetail["order"] = {};
|
||||
filterDetail.order[row.orderByColumn.columnName] = row.orderByColumn.sort;
|
||||
}
|
||||
result[row.detailName] = await row.repo.find(filterDetail);
|
||||
if (row.childDetail && row.childDetail.length > 0) {
|
||||
for (let detailRows of result[row.detailName])
|
||||
detailRows = await this.getDetailData(detailRows, filter, row.childDetail);
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*-- To get the filter using primary key --*/
|
||||
async getFilterWithPrimaryKey(body: T): Promise<FindManyOptions> {
|
||||
const filter: FindManyOptions = { where: {} };
|
||||
const PRIMARY_KEYS = await this.getPrimaryKeys();
|
||||
await PRIMARY_KEYS.forEach((column) => {
|
||||
filter.where[column] = body[column];
|
||||
});
|
||||
return filter;
|
||||
}
|
||||
|
||||
/*-- To get the filter for delete --*/
|
||||
async getDeleteFilter(whereFilter: FindManyOptions): Promise<any> {
|
||||
const filter: FindManyOptions = {};
|
||||
const PRIMARY_KEYS = await this.getPrimaryKeys();
|
||||
await PRIMARY_KEYS.forEach((column) => {
|
||||
filter[column] = whereFilter.where[column];
|
||||
});
|
||||
return filter;
|
||||
}
|
||||
|
||||
/*-- To get the Primary Keys of the entity --*/
|
||||
async getPrimaryKeys(): Promise<string[]> {
|
||||
const PRIMARY_KEYS: string[] = [];
|
||||
await this.repo.metadata.primaryColumns.forEach((row) => {
|
||||
PRIMARY_KEYS.push(row.propertyName);
|
||||
});
|
||||
return PRIMARY_KEYS;
|
||||
}
|
||||
|
||||
async getEagerColumns(repoDetail?: any): Promise<string[]> {
|
||||
/*
|
||||
For getting Eager true columns having Many to One relations.
|
||||
We need to remove the eager columns before insertions or updations or it will not allow to save data (But save message will show, but data not updated)
|
||||
*/
|
||||
const COLUMNS: string[] = [];
|
||||
for (let columnProperty of (repoDetail ? repoDetail.metadata.eagerRelations : this.repo.metadata.eagerRelations)) { //AJ
|
||||
COLUMNS.push(columnProperty.propertyName);
|
||||
}
|
||||
return COLUMNS;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
export class PcdBaseDto {
|
||||
|
||||
createdBy: string;
|
||||
|
||||
createdDate: Date;
|
||||
|
||||
modifiedBy: string;
|
||||
|
||||
modifiedDate: Date;
|
||||
|
||||
versionNo: number;
|
||||
|
||||
sessionNo: number;
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
import { CreateDateColumn, Column, UpdateDateColumn, VersionColumn, BaseEntity, Entity } from "typeorm";
|
||||
|
||||
export abstract class PcdBaseEntity extends BaseEntity {
|
||||
|
||||
@Column({
|
||||
name: "created_by",
|
||||
type: "varchar",
|
||||
length: 12,
|
||||
default:() => "'SYSTEM'",
|
||||
})
|
||||
createdBy: string;
|
||||
|
||||
// @Column({
|
||||
// name: "created_country",
|
||||
// type: "numeric",
|
||||
// nullable: true
|
||||
// })
|
||||
// createdCountry: string;
|
||||
|
||||
@CreateDateColumn({
|
||||
name: "created_date",
|
||||
default:() => "CURRENT_TIMESTAMP",
|
||||
})
|
||||
createdDate: Date;
|
||||
|
||||
@Column({
|
||||
name: "modified_by",
|
||||
type: "varchar",
|
||||
length: 12,
|
||||
default:() => "'SYSTEM'",
|
||||
})
|
||||
modifiedBy: string;
|
||||
|
||||
// @Column({
|
||||
// name: "modified_country",
|
||||
// type: "numeric",
|
||||
// nullable: true
|
||||
// })
|
||||
// modifiedCountry: string;
|
||||
|
||||
@UpdateDateColumn({
|
||||
name: "modified_date",
|
||||
default:() => "CURRENT_TIMESTAMP",
|
||||
})
|
||||
modifiedDate: Date;
|
||||
|
||||
@VersionColumn({
|
||||
name: "version_no",
|
||||
type: "number",
|
||||
nullable: true
|
||||
})
|
||||
versionNo: number
|
||||
|
||||
@VersionColumn({
|
||||
name: "session_no",
|
||||
type: "number",
|
||||
nullable: true
|
||||
})
|
||||
sessionNo: number
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { BaseEntity, Column } from "typeorm";
|
||||
|
||||
export class PcdViewEntity extends BaseEntity {
|
||||
|
||||
@Column("string",{
|
||||
name:"CREATED_BY"
|
||||
})
|
||||
createdBy:string;
|
||||
|
||||
@Column("date",{
|
||||
name:"CREATED_DATE"
|
||||
})
|
||||
createdDate:Date;
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import { Repository } from "typeorm";
|
||||
|
||||
export class TransactionDetailDto {
|
||||
|
||||
detailName: string;
|
||||
|
||||
foreignKeyColumnName?: string;
|
||||
|
||||
foreignKeyAssignmentColumnName?: {columnName:string,headerColumn:string};
|
||||
|
||||
repo: Repository<any>;
|
||||
|
||||
filter: { columnName: string, value?: any, headerColumn?: string }[];
|
||||
|
||||
childDetail: TransactionDetailDto[];
|
||||
|
||||
addtionalSettingOfRowsInInsertion?: { columnName: string, value?: any, headerColumn?: string }[];
|
||||
|
||||
transactionTypeColumnName?:string;
|
||||
|
||||
orderByColumn?: {columnName : string, sort : "DESC" | "ASC" };
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { FindManyOptions } from "typeorm";
|
||||
import { PcduserDto } from "src/auth/dto/pcd-user.dto";
|
||||
|
||||
export interface PcdFormGridInterface {
|
||||
|
||||
findAll(filter: FindManyOptions, user: PcduserDto): Promise<any[]>;
|
||||
|
||||
findOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<any>;
|
||||
|
||||
createOne(body: any, user: PcduserDto): Promise<any>
|
||||
|
||||
updateOne(body: any, id: string | number, user: PcduserDto): Promise<any>;
|
||||
|
||||
deleteOne(filter: FindManyOptions, id: string | number, user: PcduserDto): Promise<any>;
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
import { PcduserDto,} from "src/auth/dto/pcd-user.dto";
|
||||
import { FindManyOptions } from "typeorm";
|
||||
|
||||
export interface PcdtTransactionInterface {
|
||||
|
||||
findList(filter: FindManyOptions, user: PcduserDto): Promise<any[]>;
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import * as config from 'config';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import * as bodyParser from 'body-parser';
|
||||
import { urlencoded, json } from 'express';
|
||||
|
||||
|
||||
async function bootstrap() {
|
||||
|
||||
const serverConfig = config.get('server');
|
||||
// const whiteIp = config.get('whiteIp')
|
||||
const logger = new Logger('bootstrap');
|
||||
const app = await NestFactory.create(AppModule, { cors: true });
|
||||
const port = process.env.PORT || serverConfig.port; // for logging and config
|
||||
app.setGlobalPrefix('api/v1');
|
||||
app.enableCors();
|
||||
app.use(json({ limit: '50mb' }));
|
||||
app.use(urlencoded({ extended: true, limit: '50mb' }));
|
||||
await app.listen(port);
|
||||
|
||||
logger.log(`Application listing on port ${port}`) // for logging
|
||||
}
|
||||
// Cluster.register(4, bootstrap);
|
||||
bootstrap()
|
||||
@ -0,0 +1,323 @@
|
||||
import { Body, Controller, Get, Param, Post, Query, Req, Res, UseGuards } from '@nestjs/common';
|
||||
import { FreeChargePaymentGatewayService, PaymentGatewayService, phonepeGatewayService } from './payment-gateway.service';
|
||||
import * as config from 'config';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { GetUser } from 'src/auth/dto/get-user.decorator';
|
||||
import { PcduserDto } from 'src/auth/dto/pcd-user.dto';
|
||||
import { PurchaseDto } from 'src/dto/purchase.dto';
|
||||
import { FindManyOptions } from 'typeorm';
|
||||
import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository';
|
||||
|
||||
@Controller('payment-gateway')
|
||||
export class PaymentGatewayController {
|
||||
constructor(
|
||||
private paymentGatewayService: PaymentGatewayService,
|
||||
private paymentMasterRepo : PaymentMasterRepository
|
||||
) { }
|
||||
|
||||
@Post()
|
||||
@UseGuards(AuthGuard())
|
||||
createPayment(
|
||||
@Req() req,
|
||||
@Res() res,
|
||||
@GetUser() user: PcduserDto
|
||||
): void {
|
||||
// console.log('=============',user);
|
||||
|
||||
try {
|
||||
const paymentBody: PurchaseDto = req.body;
|
||||
paymentBody.amount = req.body.amount;
|
||||
paymentBody.email = req.body.email;
|
||||
paymentBody['user'] = user.userId;
|
||||
paymentBody.mobile = req.body.mobile;
|
||||
paymentBody.application = `${req.body.application}ESC${user.userId}`;
|
||||
paymentBody.type = req.body.type;
|
||||
this.paymentGatewayService.makePayment(req.body, (error, result) => {
|
||||
if (error) {
|
||||
res.status(error.code).send(error)
|
||||
//res.send (error);
|
||||
} else {
|
||||
res.send(result);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Exception in creating User Data . ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('public')
|
||||
createPaymentPublic(
|
||||
@Req() req,
|
||||
@Res() res,
|
||||
): void {
|
||||
// console.log('=============',user);
|
||||
|
||||
try {
|
||||
const paymentBody: PurchaseDto = req.body;
|
||||
paymentBody.amount = req.body.amount;
|
||||
paymentBody.email = req.body.email;
|
||||
paymentBody['user'] = 'system';
|
||||
paymentBody.mobile = req.body.mobile;
|
||||
paymentBody.application = req.body.application;
|
||||
paymentBody.type = req.body.type;
|
||||
paymentBody.menuId = 'PUBLIC';
|
||||
this.paymentGatewayService.makePayment(req.body, (error, result) => {
|
||||
if (error) {
|
||||
res.status(error.code).send(error)
|
||||
//res.send (error);
|
||||
} else {
|
||||
res.send(result);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Exception in creating User Data . ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('success')
|
||||
async paymentSuccess(
|
||||
@Req() req,
|
||||
@Res() res,
|
||||
): Promise<void> {
|
||||
console.log("==req====", req.body);
|
||||
try {
|
||||
const paymentSuccessBody = req.body;
|
||||
console.log(paymentSuccessBody);
|
||||
const userId = paymentSuccessBody.lastname.split('ESC')[1];
|
||||
const tenderId = paymentSuccessBody.lastname.split('ESC')[0];
|
||||
let user = await this.paymentMasterRepo.findOne({where:{ userId: userId , tenderId:tenderId}});
|
||||
console.log(user);
|
||||
|
||||
this.paymentGatewayService.paymentSuccess(paymentSuccessBody, (error, result) => {
|
||||
const prodInfo = paymentSuccessBody.productinfo.split('ESC');
|
||||
console.log(prodInfo, '#####');
|
||||
console.log('*************', config.get('payment-gateway'));
|
||||
|
||||
if (error) {
|
||||
let redirectUrl
|
||||
redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrl + `/${req.body.lastname.split('ESC')[0]}/f`;
|
||||
user.status = 'F'
|
||||
this.paymentMasterRepo.save(user);
|
||||
console.log("==redirectUrl====", redirectUrl);
|
||||
res.redirect(redirectUrl);
|
||||
// res.send(error);
|
||||
} else {
|
||||
let redirectUrl
|
||||
redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${req.body.lastname.split('ESC')[0]}/s`;
|
||||
user.status = 'S'
|
||||
this.paymentMasterRepo.save(user);
|
||||
console.log("==redirectUrl====", redirectUrl);
|
||||
res.redirect(redirectUrl);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.log("Exception in creating User Data . ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('failure')
|
||||
async paymentFailure(
|
||||
@Req() req,
|
||||
@Res() res,
|
||||
): Promise<void> {
|
||||
console.log(req.body, 'request body');
|
||||
try {
|
||||
const paymentFailureBody = req.body;
|
||||
const userId = paymentFailureBody.lastname.split('ESC')[1];
|
||||
const tenderId = paymentFailureBody.lastname.split('ESC')[0];
|
||||
let user = await this.paymentMasterRepo.findOne({where:{ userId: userId , tenderId:tenderId}});
|
||||
console.log(user);
|
||||
this.paymentGatewayService.paymentFailure(paymentFailureBody, (error, result) => {
|
||||
console.log(paymentFailureBody);
|
||||
console.log(config.get('payment-gateway'));
|
||||
|
||||
|
||||
|
||||
if (error) {
|
||||
res.send(error);
|
||||
user.status = 'F'
|
||||
this.paymentMasterRepo.save(user);
|
||||
} else {
|
||||
// Redirect to payment failure page
|
||||
let redirectUrl
|
||||
redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrl + `${req.body.lastname.split('ESC')[0]}/f`;
|
||||
user.status = 'F'
|
||||
this.paymentMasterRepo.save(user);
|
||||
res.redirect(redirectUrl);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Exception in creating User Data . ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Controller('payment-gateway-fc')
|
||||
// export class FreeChargePaymentGatewayController {
|
||||
// constructor(
|
||||
// private freeChargePaymentGatewayService: FreeChargePaymentGatewayService
|
||||
// ) { }
|
||||
|
||||
// @Post('status')
|
||||
// async checkPaymentStatus(
|
||||
// @Body() body: any,
|
||||
// @GetUser() user: PcduserDto
|
||||
// ): Promise<any> {
|
||||
// console.log("===dd===", body);
|
||||
// return await this.freeChargePaymentGatewayService.checkPaymentStatus(body, user);
|
||||
// }
|
||||
|
||||
// @Post('refund')
|
||||
// async refundPayment(
|
||||
// @Body() body: any,
|
||||
// @GetUser() user: PcduserDto
|
||||
// ): Promise<any> {
|
||||
// console.log("===dd===", body);
|
||||
// return await this.freeChargePaymentGatewayService.refundPayment(body, user);
|
||||
// }
|
||||
|
||||
|
||||
// @Post()
|
||||
// @UseGuards(AuthGuard())
|
||||
// createPayment(
|
||||
// @Req() req,
|
||||
// @Res() res,
|
||||
// @GetUser() user: PcduserDto
|
||||
// ): void {
|
||||
// // console.log('=============',user);
|
||||
|
||||
// try {
|
||||
// const paymentBody: PurchaseDto = req.body;
|
||||
// paymentBody.amount = req.body.amount;
|
||||
// paymentBody.email = req.body.email;
|
||||
// paymentBody['user'] = user.userId;
|
||||
// paymentBody.mobile = req.body.mobile;
|
||||
// paymentBody.application = req.body.application;
|
||||
// paymentBody.type = req.body.type;
|
||||
// this.freeChargePaymentGatewayService.makePayment(paymentBody, (error, result) => {
|
||||
// if (error) {
|
||||
// // console.log(error,'err here');
|
||||
|
||||
// res.status(error.status).send()
|
||||
// //res.send (error);
|
||||
// } else {
|
||||
// res.send(result);
|
||||
// }
|
||||
// });
|
||||
// } catch (e) {
|
||||
// console.log("Exception in creating User Data . ", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// @Post('success')
|
||||
// paymentSuccess(
|
||||
// @Req() req,
|
||||
// @Res() res,
|
||||
// ): void {
|
||||
// console.log("==req====", req.body);
|
||||
// try {
|
||||
|
||||
// console.log(req.body);
|
||||
// if (req.body.statusCode == "SPG-0000") {
|
||||
// const paymentSuccessBody = req.body;
|
||||
// this.freeChargePaymentGatewayService.paymentSuccess(paymentSuccessBody, (error, result) => {
|
||||
// if (error) {
|
||||
// console.log(error, 'error test');
|
||||
|
||||
// let redirectUrl
|
||||
// if (paymentSuccessBody.productinfo == 'F') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentSuccessBody.lastname}?payment=Y`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'S') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudent + `?id=${paymentSuccessBody.lastname}&status=Y`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'A') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlAcceptance + `/${paymentSuccessBody.lastname}?status=N`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'I') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudentInternal + `?rollNo=${paymentSuccessBody.lastname}&status=N`;
|
||||
// }
|
||||
|
||||
|
||||
// res.redirect(redirectUrl);
|
||||
// // res.send(error);
|
||||
// } else {
|
||||
// console.log('success test', paymentSuccessBody.productinfo);
|
||||
|
||||
// let redirectUrl
|
||||
// if (paymentSuccessBody.productinfo == 'F') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentSuccessBody.lastname}?payment=Y`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'S') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlStudent + `?id=${paymentSuccessBody.lastname}&status=Y`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'A') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlAcceptance + `/${paymentSuccessBody.lastname}?status=Y`;
|
||||
// } else if (paymentSuccessBody.productinfo == 'I') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrlStudentInternal + `?rollNo=${paymentSuccessBody.lastname}&studentId=${paymentSuccessBody.studentId}&status=Y`;
|
||||
// }
|
||||
// console.log(redirectUrl, 'red');
|
||||
// res.redirect(redirectUrl);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// else if (req.body.statusCode == "SPG-0001") {
|
||||
// const paymentFailureBody = req.body;
|
||||
// this.freeChargePaymentGatewayService.paymentFailure(paymentFailureBody, (error, result) => {
|
||||
// if (error) {
|
||||
// res.send(error);
|
||||
// } else {
|
||||
// // Redirect to payment failure page
|
||||
// let redirectUrl
|
||||
// if (paymentFailureBody.productinfo.split('ESC')[1] == 'F') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').successRedirectUrl + `/${paymentFailureBody.lastname}?payment=N`;
|
||||
// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'S') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudent + `?id=${paymentFailureBody.lastname}&status=N`;
|
||||
// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'A') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlAcceptance + `/${paymentFailureBody.lastname}?status=N`;
|
||||
// } else if (paymentFailureBody.productinfo.split('ESC')[1] == 'I') {
|
||||
// redirectUrl = config.get('url').url + config.get('payment-gateway').failureRedirectUrlStudentInternal + `?rollNo=${paymentFailureBody.lastname}&status=N`;
|
||||
// }
|
||||
|
||||
// res.redirect(redirectUrl);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// } catch (e) {
|
||||
// console.log("Exception in creating User Data . ", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@Controller('phonepe-payment-gateway')
|
||||
export class phonepePaymentGatewayController {
|
||||
constructor(
|
||||
private phonepeGatewayService: phonepeGatewayService
|
||||
) { }
|
||||
|
||||
@Post()
|
||||
@UseGuards(AuthGuard())
|
||||
async createOrder(
|
||||
@Body() body:{ name:string,mobile:number,amount:number,type:string,tenderId:number,emdFeeType?:string
|
||||
},
|
||||
@GetUser() user : PcduserDto
|
||||
){
|
||||
let result = await this.phonepeGatewayService.createOrder(body,user)
|
||||
return result
|
||||
}
|
||||
|
||||
@Post('payment-status/:userId/:tenderId/:type')
|
||||
async paymentStatus(
|
||||
@Req() req,
|
||||
@Res() res,
|
||||
@Param('userId') userId:number,
|
||||
@Param('tenderId') tenderId:number,
|
||||
@Param('type') type:number
|
||||
){
|
||||
let result = await this.phonepeGatewayService.paymentStatus(req,res,tenderId,userId,type)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { CryptoService } from 'src/auth/crypto.service';
|
||||
import { PcduserRepository } from 'src/auth/pcduser.repository';
|
||||
import { EmailModule } from 'src/email/email.module';
|
||||
import { PaymentStatusRepository } from 'src/tables/payment-status/payment-status.repository';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
|
||||
import { PaymentGatewayController, phonepePaymentGatewayController } from './payment-gateway.controller';
|
||||
import { PaymentGatewayService, phonepeGatewayService } from './payment-gateway.service';
|
||||
import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository';
|
||||
import { PhonepeTransactionListRepository } from 'src/tables/phonepe-transaction-list/phonepe-transaction-list.repository';
|
||||
import { PcdotpRepository } from 'src/auth/pcdotp.repository';
|
||||
import { categoryRepository } from 'src/tables/userCategory-master/category.repository';
|
||||
import { TenderMasterRepository } from 'src/tables/tender-master/tender-master.repository';
|
||||
import { userSubCategoryMasterRepo } from 'src/tables/user-subcategory-master/user-subcategory-master.repository';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
||||
TypeOrmModule.forFeature([
|
||||
PaymentStatusRepository,
|
||||
PaymentMasterRepository,
|
||||
PhonepeTransactionListRepository
|
||||
|
||||
]), AuthModule,
|
||||
HttpModule.register({
|
||||
timeout: 5000,
|
||||
maxRedirects: 5,
|
||||
}),
|
||||
|
||||
EmailModule,
|
||||
],
|
||||
controllers: [PaymentGatewayController,phonepePaymentGatewayController],
|
||||
providers: [PaymentGatewayService,phonepeGatewayService,AuthService,
|
||||
CryptoService,PaymentStatusRepository,PaymentMasterRepository,
|
||||
PhonepeTransactionListRepository,PcduserRepository,PcdotpRepository,categoryRepository,
|
||||
TenderMasterRepository,userSubCategoryMasterRepo
|
||||
]
|
||||
})
|
||||
export class PaymentGatewayModule { }
|
||||
@ -0,0 +1,859 @@
|
||||
import { BadRequestException, HttpException, Injectable, InternalServerErrorException, Logger, MethodNotAllowedException, Req, Res } from '@nestjs/common';
|
||||
import { PaymentDto } from '../dto/payment.dto';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { Connection, FindManyOptions, getConnection } from 'typeorm';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
//import { generate } from 'generate-password';
|
||||
import * as config from 'config';
|
||||
import { CryptoService } from 'src/auth/crypto.service';
|
||||
import { PcduserRepository } from 'src/auth/pcduser.repository';
|
||||
import { PaymentStatusRepository } from 'src/tables/payment-status/payment-status.repository';
|
||||
import { PurchaseDto } from 'src/dto/purchase.dto';
|
||||
import { PaymentStatusDto } from 'src/dto/payment-status.dto';
|
||||
import { convertDate } from 'src/pipe/pcd-date.pipe';
|
||||
var crypto = require('crypto')
|
||||
|
||||
import { PayuTransactionListDto } from 'src/dto/payu-transaction-list.dto';
|
||||
import { PayuTransactionListRepository } from 'src/tables/payu-transaction-list/payu-transaction-list.repository';
|
||||
import { PcduserDto } from 'src/auth/dto/pcd-user.dto';
|
||||
import { PaymentMasterDto } from 'src/dto/payment-master.dto';
|
||||
import { Console } from 'console';
|
||||
import { PaymentMasterRepository } from 'src/tables/payment-master/payment-master.repository';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { phonepeTransactionDto } from 'src/dto/phonepeTransaction.dto';
|
||||
import { PhonepeTransactionListRepository } from 'src/tables/phonepe-transaction-list/phonepe-transaction-list.repository';
|
||||
import { TenderMasterRepository } from 'src/tables/tender-master/tender-master.repository';
|
||||
|
||||
|
||||
|
||||
const payUMoney = require("payumoney_nodejs");
|
||||
const querystring = require('querystring');
|
||||
|
||||
const paymentGatewayConf = config.get('payment-gateway');
|
||||
const phonepeGatewayConf = config.get('phonepe-gateway')
|
||||
const paymentGatewayMethod: "DHOFAR" | "PAYU" = paymentGatewayConf.method;
|
||||
|
||||
@Injectable()
|
||||
export class PaymentGatewayService {
|
||||
|
||||
private logger = new Logger('PaymentGatewayService'); // for logging
|
||||
|
||||
|
||||
constructor(
|
||||
private readonly http: HttpService,
|
||||
// private authService: AuthService,
|
||||
private paymentStatusRepo: PaymentStatusRepository,
|
||||
private paymentMasterRepo: PaymentMasterRepository,
|
||||
|
||||
private crypto: CryptoService,
|
||||
|
||||
) {
|
||||
// Set you MERCHANT_KEY, MERCHANT_SALT_KEY, PAYUMONEY_AUTHORIZATION_HEADER
|
||||
// for both Production and Sandox Account
|
||||
payUMoney.setProdKeys(paymentGatewayConf.key, paymentGatewayConf.salt, "ylb6+TCDC20wlyTooZbYM9wDw4abjaOVV9KiHFzGPgw=");
|
||||
payUMoney.setSandboxKeys(paymentGatewayConf.key, paymentGatewayConf.salt, "ylb6+TCDC20wlyTooZbYM9wDw4abjaOVV9KiHFzGPgw=");
|
||||
payUMoney.isProdMode(true);
|
||||
}
|
||||
|
||||
public async makePayment(paymentBody: PurchaseDto, callback: (error: any, response: any) => void) {
|
||||
// let total = 0;
|
||||
// let tax = 0;
|
||||
// let totalAmount = 0;
|
||||
// let minAmount = paymentBody.amount;
|
||||
// key : "crvbe4"
|
||||
// salt : "wIVuIkieIBBrSYtXP3aVw5uFH7eFe2nM"
|
||||
|
||||
let date = new Date()
|
||||
let paymentStatus = new PaymentStatusDto()
|
||||
paymentStatus.createdBy = paymentBody["user"];
|
||||
paymentStatus.modifiedBy = paymentBody["user"];
|
||||
paymentStatus.email = paymentBody.email;
|
||||
paymentStatus.type = paymentBody.type;
|
||||
paymentStatus.status = 'U';
|
||||
paymentStatus.paymentOption = 'P'; //F - FreeCharge | P - PayU
|
||||
|
||||
let paymentModel = new PaymentDto();
|
||||
paymentModel.txnid = Date.now();
|
||||
paymentStatus.txnid = paymentModel.txnid;
|
||||
paymentModel.firstname = 'Admin';
|
||||
paymentModel.lastname = paymentBody.application.toString();
|
||||
paymentModel.email = paymentBody.email;
|
||||
paymentModel.service_provider = 'payu_paisa';
|
||||
paymentModel.furl = config.get('payment-gateway').furl;
|
||||
paymentModel.surl = config.get('payment-gateway').surl;
|
||||
paymentModel.amount = 1;
|
||||
|
||||
let paymentMaster = new PaymentMasterDto();
|
||||
paymentMaster.userId = paymentModel.lastname.split('ESC')[1];
|
||||
paymentMaster.tenderId = parseInt(paymentModel.lastname.split('ESC')[0]);
|
||||
paymentMaster.transId = paymentStatus.txnid;
|
||||
paymentMaster.status = 'P';
|
||||
console.log('paymentmasterDto======', paymentMaster);
|
||||
|
||||
const paymentMas = this.paymentMasterRepo.save(paymentMaster);
|
||||
|
||||
|
||||
// if (paymentBody.type == 'F') {
|
||||
// let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application);
|
||||
// if (!application)
|
||||
// throw new BadRequestException('application not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = application.receiptAmount;
|
||||
// paymentStatus.application = application.id;
|
||||
// paymentModel.phone = parseInt(application.motherPhoneNo);
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentModel.amount = 1;
|
||||
// else
|
||||
// paymentModel.amount = application.receiptAmount;
|
||||
// }
|
||||
// if (paymentBody.type == 'S') {
|
||||
// let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application);
|
||||
// if (!payment)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = payment.paidAmount;
|
||||
// paymentStatus.paymentId = payment.id;
|
||||
// paymentModel.phone = payment.contactPhone;
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentModel.amount = 1;
|
||||
// else
|
||||
// paymentModel.amount = payment.paidAmount;
|
||||
|
||||
// }
|
||||
// if (paymentBody.type == 'I') {
|
||||
// let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application);
|
||||
// if (!payment)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = payment.paidAmount;
|
||||
// paymentStatus.paymentId = payment.id;
|
||||
// paymentModel.phone = payment.contactPhone;
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentModel.amount = 1;
|
||||
// else
|
||||
// paymentModel.amount = payment.paidAmount;
|
||||
|
||||
// }
|
||||
// if (paymentBody.type == 'A') {
|
||||
// let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application);
|
||||
// let courseFee = await this.sisFeeRepository.findOne({ where: { id: application.acceptance } })
|
||||
// if (!application)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// let date = new Date()
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = parseInt(courseFee.feeCharge);
|
||||
// paymentStatus.application = application.id;
|
||||
// paymentStatus.identifier = 'A';
|
||||
// paymentModel.phone = parseInt(application.motherPhoneNo);
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentModel.amount = 1;
|
||||
// else
|
||||
// paymentModel.amount = parseInt(courseFee.feeCharge);
|
||||
|
||||
// }
|
||||
const pay = await this.paymentStatusRepo.save(paymentStatus);
|
||||
paymentModel.productinfo = `${pay.id}ESC${paymentBody.type}`;
|
||||
console.log(paymentModel);
|
||||
|
||||
{
|
||||
payUMoney.pay(paymentModel, (error: any, response: any) => {
|
||||
if (error) {
|
||||
console.error("makePayment error : " + error);
|
||||
callback(error, null);
|
||||
} else {
|
||||
console.log("Payment Redirection link " + response + '===' + error);
|
||||
callback(error, { url: response });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async paymentSuccess(paymentBody: any, callback: (error: any, response: any) => void) {
|
||||
// console.log("===payment body===", paymentBody);
|
||||
let code;
|
||||
let paymentSuccessBody;
|
||||
let receiptNo;
|
||||
let receiptNoPrefix;
|
||||
|
||||
paymentSuccessBody = paymentBody;
|
||||
code = paymentSuccessBody.txnid;
|
||||
console.log(paymentSuccessBody, 'successbody');
|
||||
|
||||
let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "id": paymentSuccessBody.productinfo.split('ESC')[0] } });
|
||||
paymentStatus.status = 'S';
|
||||
await this.paymentStatusRepo.save(paymentStatus);
|
||||
|
||||
// const queryRunner = getConnection().createQueryRunner();
|
||||
// await queryRunner.connect();
|
||||
// await queryRunner.startTransaction();
|
||||
// try {
|
||||
// let productData
|
||||
// // if (paymentStatus.type == 'F' || paymentStatus.type == 'A') {
|
||||
// // productData = await this.sisAdmissionFormRepository.findOne({ where: { id: paymentStatus.application }, select: ['id', 'sessionId'] })
|
||||
// // } else {
|
||||
// // productData = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'sessionId'] })
|
||||
// // }
|
||||
|
||||
// // const session = await this.sisSessionRepository.findOne({ where: { id: productData.sessionId } });
|
||||
// // receiptNoPrefix = session.sessionCode;
|
||||
// // receiptNo = parseInt(session.receiptSeq.toString()) + 1;
|
||||
|
||||
// // await queryRunner.manager.query(`update sis_session set receipt_seq = ${receiptNo} where id = ${session.id}`);
|
||||
// // if (paymentStatus.type == 'F')
|
||||
// // await queryRunner.manager.query(`update sis_admission_form set payment_stat ='S',receipt_no_prefix='${receiptNoPrefix}',receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`)
|
||||
// // if (paymentStatus.type == 'S') {
|
||||
// // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`)
|
||||
// // }
|
||||
// // if (paymentStatus.type == 'I') {
|
||||
// // await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`)
|
||||
// // const data = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'studentId'] });
|
||||
// // const student = await this.sisStudentRepository.findOne({ where: { id: data.studentId }, select: ['id', 'rollNo', 'sessionId'] });
|
||||
// // paymentBody.lastname = student.rollNo;
|
||||
// // paymentBody['studentId'] = student.id;
|
||||
// // paymentBody['sessionId'] = student.sessionId;
|
||||
|
||||
// // }
|
||||
// // if (paymentStatus.type == 'A') {
|
||||
// // await queryRunner.manager.query(`update sis_admission_form set acceptance_fee_stat ='S',acceptance_receipt_no_prefix='${receiptNoPrefix}',acceptance_receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`)
|
||||
// // }
|
||||
// queryRunner.commitTransaction()
|
||||
|
||||
|
||||
callback(null, { status: "Payment Success", id: code });
|
||||
// } catch (error) {
|
||||
// queryRunner.rollbackTransaction()
|
||||
// } finally {
|
||||
// queryRunner.release()
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public async paymentFailure(paymentBody: any, callback: (error: any, response: any) => void) {
|
||||
let paymentFailureBody;
|
||||
let code;
|
||||
console.log("Payment Failure");
|
||||
paymentFailureBody = paymentBody;
|
||||
|
||||
|
||||
let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "txnid": paymentFailureBody.txnid } });
|
||||
paymentStatus.status = 'F';
|
||||
await this.paymentStatusRepo.save(paymentStatus);
|
||||
|
||||
code = paymentFailureBody.txnid;
|
||||
|
||||
// await this.authService.updateHeader(code, 2, paymentFailureBody);
|
||||
callback(null, { status: "Payment Failed" });
|
||||
}
|
||||
|
||||
async insertPaymentStatus() {
|
||||
|
||||
}
|
||||
|
||||
// PAYU SECTION END DONT ADD PAYU RELATED CODE BELOW
|
||||
|
||||
|
||||
|
||||
}
|
||||
@Injectable()
|
||||
export class FreeChargePaymentGatewayService {
|
||||
|
||||
constructor(
|
||||
private readonly http: HttpService,
|
||||
private paymentStatusRepo: PaymentStatusRepository,
|
||||
private crypto: CryptoService,
|
||||
private PayuTransactionListRepository: PayuTransactionListRepository
|
||||
) { }
|
||||
|
||||
async getUrl() {
|
||||
if (config.get('payment-gateway-freecharge').production) {
|
||||
return config.get('payment-gateway-freecharge').prodUrl;
|
||||
} else {
|
||||
return config.get('payment-gateway-freecharge').sandUrl;
|
||||
}
|
||||
}
|
||||
|
||||
async makePayment(paymentBody: PurchaseDto, callback: (error: any, response: any) => void) {
|
||||
let date = new Date()
|
||||
|
||||
let paymentStatus = new PaymentStatusDto()
|
||||
paymentStatus.createdBy = paymentBody["user"];
|
||||
paymentStatus.modifiedBy = paymentBody["user"];
|
||||
paymentStatus.email = paymentBody.email;
|
||||
paymentStatus.type = paymentBody.type;
|
||||
paymentStatus.status = 'U';
|
||||
paymentStatus.paymentOption = 'F'; //F - FreeCharge | P - PayU
|
||||
|
||||
|
||||
let paymentJson = {
|
||||
merchantId: config.get('payment-gateway-freecharge').merchantId,
|
||||
callbackUrl: config.get('payment-gateway-freecharge').callBackUrl,
|
||||
merchantTxnId: null,
|
||||
merchantTxnAmount: paymentBody.amount,
|
||||
currency: config.get('payment-gateway-freecharge').currency,
|
||||
customerEmailId: paymentBody.email,
|
||||
customerMobileNo: paymentBody.mobile,
|
||||
timestamp: date.getTime(),
|
||||
udf1: null
|
||||
}
|
||||
paymentStatus.txnid = paymentJson.timestamp;
|
||||
paymentJson.merchantTxnId = paymentJson.timestamp;
|
||||
|
||||
// if (paymentBody.type == 'F') {
|
||||
// let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application);
|
||||
// if (!application)
|
||||
// throw new BadRequestException('application not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = application.receiptAmount;
|
||||
// paymentStatus.application = application.id;
|
||||
// paymentJson.customerMobileNo = application.motherPhoneNo;
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentJson.merchantTxnAmount = 1;
|
||||
// else
|
||||
// paymentJson.merchantTxnAmount = application.receiptAmount;
|
||||
// }
|
||||
// if (paymentBody.type == 'S') {
|
||||
// let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application);
|
||||
// if (!payment)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = payment.paidAmount;
|
||||
// paymentStatus.paymentId = payment.id;
|
||||
// paymentJson.customerMobileNo = payment.contactPhone.toString();
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentJson.merchantTxnAmount = 1;
|
||||
// else
|
||||
// paymentJson.merchantTxnAmount = payment.paidAmount;
|
||||
|
||||
// }
|
||||
// if (paymentBody.type == 'I') {
|
||||
// let payment = await this.sisFeePaymentOnlineRepository.findOne(paymentBody.application);
|
||||
// if (!payment)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = payment.paidAmount;
|
||||
// paymentStatus.paymentId = payment.id;
|
||||
// paymentJson.merchantTxnAmount = payment.contactPhone;
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentJson.merchantTxnAmount = 1;
|
||||
// else
|
||||
// paymentJson.merchantTxnAmount = payment.paidAmount;
|
||||
|
||||
// }
|
||||
// if (paymentBody.type == 'A') {
|
||||
// let application = await this.sisAdmissionFormRepository.findOne(paymentBody.application);
|
||||
// let courseFee = await this.sisFeeRepository.findOne({ where: { id: application.acceptance } })
|
||||
// if (!application)
|
||||
// throw new BadRequestException('payment not generated')
|
||||
// let date = new Date()
|
||||
// paymentStatus.paymentDate = new Date();
|
||||
// paymentStatus.amount = parseInt(courseFee.feeCharge);
|
||||
// paymentStatus.application = application.id;
|
||||
// paymentStatus.identifier = 'A';
|
||||
// paymentJson.customerMobileNo = application.motherPhoneNo;
|
||||
// if (paymentGatewayConf.testing == true)
|
||||
// paymentJson.merchantTxnAmount = 1;
|
||||
// else
|
||||
// paymentJson.merchantTxnAmount = parseInt(courseFee.feeCharge);
|
||||
|
||||
// }
|
||||
const pay = await this.paymentStatusRepo.save(paymentStatus);
|
||||
paymentJson.udf1 = `${pay.id}ESC${paymentBody.type}`;
|
||||
|
||||
const ordered = Object.keys(paymentJson).sort().reduce(
|
||||
(obj, key) => {
|
||||
obj[key] = paymentJson[key];
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
console.log(ordered)
|
||||
|
||||
let string = ''
|
||||
|
||||
for (const [key, value] of Object.entries(ordered)) {
|
||||
if (value)
|
||||
string = string + value
|
||||
}
|
||||
string = string + config.get('payment-gateway-freecharge').key
|
||||
console.log(string);
|
||||
|
||||
const hash = crypto.createHash('sha256').update(string).digest('hex');
|
||||
|
||||
console.log(hash);
|
||||
paymentJson['signature'] = hash
|
||||
callback(null, { paymentBody: paymentJson, url: `${await this.getUrl()}/payment/v1/checkout` })
|
||||
}
|
||||
|
||||
public async paymentSuccess(paymentBody: any, callback: (error: any, response: any) => void) {
|
||||
// console.log("===payment body===", paymentBody);
|
||||
let code;
|
||||
let paymentSuccessBody;
|
||||
let receiptNo;
|
||||
let receiptNoPrefix;
|
||||
|
||||
paymentSuccessBody = paymentBody;
|
||||
|
||||
console.log(paymentSuccessBody, 'successbody');
|
||||
|
||||
|
||||
let paymentStatus = await this.paymentStatusRepo.findOne({ where: { txnid: paymentBody.merchantTxnId } });
|
||||
await this.insertPaymentRecord(paymentStatus, paymentSuccessBody);
|
||||
if (paymentStatus.application) {
|
||||
paymentSuccessBody.lastname = paymentStatus.application;
|
||||
} else if (paymentStatus.paymentId) {
|
||||
paymentSuccessBody.lastname = paymentStatus.paymentId
|
||||
}
|
||||
code = paymentStatus.txnid;
|
||||
paymentStatus.status = 'S';
|
||||
paymentStatus.txnrefid = paymentSuccessBody.txnReferenceId;
|
||||
paymentSuccessBody.productinfo = paymentStatus.type;
|
||||
await this.paymentStatusRepo.save(paymentStatus);
|
||||
|
||||
const queryRunner = getConnection().createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
let productData
|
||||
// if (paymentStatus.type == 'F' || paymentStatus.type == 'A') {
|
||||
// productData = await this.sisAdmissionFormRepository.findOne({ where: { id: paymentStatus.application }, select: ['id', 'sessionId'] })
|
||||
// } else {
|
||||
// productData = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'sessionId'] })
|
||||
// }
|
||||
|
||||
// const session = await this.sisSessionRepository.findOne({ where: { id: productData.sessionId } });
|
||||
// receiptNoPrefix = session.sessionCode;
|
||||
// receiptNo = parseInt(session.receiptSeq.toString()) + 1;
|
||||
|
||||
// await queryRunner.manager.query(`update sis_session set receipt_seq = ${receiptNo} where id = ${session.id}`);
|
||||
// if (paymentStatus.type == 'F')
|
||||
// await queryRunner.manager.query(`update sis_admission_form set payment_stat ='S',receipt_no_prefix='${receiptNoPrefix}',receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`)
|
||||
// if (paymentStatus.type == 'S') {
|
||||
// await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`)
|
||||
// }
|
||||
// if (paymentStatus.type == 'I') {
|
||||
// await queryRunner.manager.query(`update sis_fee_payment_online set payment_stat ='S',txnid = '${code}',receipt_no_prefix='${receiptNoPrefix}',receipt_no = ${receiptNo} where id = ${paymentStatus.paymentId}`)
|
||||
// const data = await this.sisFeePaymentOnlineRepository.findOne({ where: { id: paymentStatus.paymentId }, select: ['id', 'studentId'] });
|
||||
// const student = await this.sisStudentRepository.findOne({ where: { id: data.studentId }, select: ['id', 'rollNo', 'sessionId'] });
|
||||
// paymentBody.lastname = student.rollNo;
|
||||
// paymentBody['studentId'] = student.id;
|
||||
// paymentBody['sessionId'] = student.sessionId;
|
||||
|
||||
// }
|
||||
if (paymentStatus.type == 'A') {
|
||||
await queryRunner.manager.query(`update sis_admission_form set acceptance_fee_stat ='S',acceptance_receipt_no_prefix='${receiptNoPrefix}',acceptance_receipt_no = '${receiptNo}' where id = ${paymentStatus.application}`)
|
||||
}
|
||||
queryRunner.commitTransaction()
|
||||
|
||||
|
||||
callback(null, { status: "Payment Success", id: code });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
queryRunner.rollbackTransaction()
|
||||
} finally {
|
||||
queryRunner.release()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async insertPaymentRecord(paymentStatus: PaymentStatusDto, paymentSuccessBody: any) {
|
||||
let PayuTransaction = new PayuTransactionListDto();
|
||||
PayuTransaction.addedon = paymentStatus.paymentDate;
|
||||
PayuTransaction.amount = paymentSuccessBody.amount;
|
||||
PayuTransaction.txnid = paymentSuccessBody.merchantTxnId;
|
||||
PayuTransaction.status = 'success';
|
||||
PayuTransaction.gateway = 'FreeCharge';
|
||||
PayuTransaction.transaction_fee = paymentSuccessBody.amount;
|
||||
PayuTransaction.mer_service_fee = paymentSuccessBody.handlingFee;
|
||||
PayuTransaction.mer_service_tax = paymentSuccessBody.taxAmount;
|
||||
PayuTransaction.id = paymentSuccessBody.txnReferenceId;
|
||||
await this.PayuTransactionListRepository.save(PayuTransaction)
|
||||
}
|
||||
|
||||
|
||||
async checkPaymentStatus(body: any, user: PcduserDto) {
|
||||
let paymentBody = {
|
||||
"merchantId": `${config.get('payment-gateway-freecharge').merchantId}`,
|
||||
"merchantTxnId": `${body.merchantTxnId}`
|
||||
}
|
||||
let string = ''
|
||||
for (const [key, value] of Object.entries(paymentBody)) {
|
||||
if (value)
|
||||
string = string + value
|
||||
}
|
||||
string = string + config.get('payment-gateway-freecharge').key
|
||||
console.log(string);
|
||||
|
||||
const hash = crypto.createHash('sha256').update(string).digest('hex');
|
||||
paymentBody['signature'] = hash;
|
||||
return this.http.post(`${await this.getUrl()}/payment/v1/txn/status`, paymentBody).toPromise().then((res) => {
|
||||
console.log("===res====", res.data);
|
||||
return res.data;
|
||||
}, (err) => {
|
||||
console.log("===errr====", err);
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
async refundPayment(body: any, user: PcduserDto) {
|
||||
let date = new Date()
|
||||
let paymentBody = {
|
||||
"merchantId": `${config.get('payment-gateway-freecharge').merchantId}`,
|
||||
"merchantRefundTxnId": date.getTime(),
|
||||
"txnReferenceId": body.txnReferenceId,
|
||||
"refundAmount": body.amount,
|
||||
"currency": "INR"
|
||||
}
|
||||
const ordered = Object.keys(paymentBody).sort().reduce(
|
||||
(obj, key) => {
|
||||
obj[key] = paymentBody[key];
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
let string = ''
|
||||
for (const [key, value] of Object.entries(ordered)) {
|
||||
if (value)
|
||||
string = string + value
|
||||
}
|
||||
string = string + config.get('payment-gateway-freecharge').key;
|
||||
const hash = crypto.createHash('sha256').update(string).digest('hex');
|
||||
paymentBody['signature'] = hash;
|
||||
return this.http.post(`${await this.getUrl()}/payment/v1/refund`, paymentBody).toPromise().then((res) => {
|
||||
console.log("===res====", res.data);
|
||||
return res.data;
|
||||
}, (err) => {
|
||||
console.log("===errr====", err);
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
public async paymentFailure(paymentBody: any, callback: (error: any, response: any) => void) {
|
||||
let paymentFailureBody;
|
||||
let code;
|
||||
|
||||
paymentFailureBody = paymentBody;
|
||||
let paymentStatus = await this.paymentStatusRepo.findOne({ where: { "txnid": paymentFailureBody.merchantTxnId } });
|
||||
paymentFailureBody.productinfo = paymentStatus.type;
|
||||
if (paymentStatus.application) {
|
||||
paymentFailureBody.lastname = paymentStatus.application;
|
||||
} else if (paymentStatus.paymentId) {
|
||||
paymentFailureBody.lastname = paymentStatus.paymentId
|
||||
}
|
||||
|
||||
paymentStatus.status = 'F';
|
||||
await this.paymentStatusRepo.save(paymentStatus);
|
||||
|
||||
code = paymentFailureBody.merchantTxnId;
|
||||
|
||||
// await this.authService.updateHeader(code, 2, paymentFailureBody);
|
||||
callback(null, { status: "Payment Failed" });
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////// PHONEPE INTEGRATION //////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class phonepeGatewayService {
|
||||
|
||||
constructor(
|
||||
private readonly http: HttpService,
|
||||
private paymentStatusRepo: PaymentStatusRepository,
|
||||
private paymentMasterRepo: PaymentMasterRepository,
|
||||
private phonepetxnRepo: PhonepeTransactionListRepository,
|
||||
private crypto: CryptoService,
|
||||
private authservice: AuthService,
|
||||
private pcdUserRepo: PcduserRepository,
|
||||
private tenderMasterRepo: TenderMasterRepository
|
||||
|
||||
) { }
|
||||
|
||||
//merchantId:'PGTESTPAYUAT'
|
||||
//key: '695d0547-3728-4b1c-825d-99647913361'
|
||||
// keyIndex: 1
|
||||
|
||||
|
||||
async createOrder(body, user) {
|
||||
console.log(body);
|
||||
console.log(phonepeGatewayConf);
|
||||
|
||||
let currentDate = new Date();
|
||||
let year = currentDate.getFullYear();
|
||||
let month = (currentDate.getMonth() + 1).toString().padStart(2, '0'); // Adding 1 because months are zero-based
|
||||
let day = currentDate.getDate().toString().padStart(2, '0');
|
||||
let formattedDate = `${year}-${month}-${day}`;
|
||||
let TxnId = Date.now().toString()
|
||||
|
||||
let redirectUrl
|
||||
|
||||
if (body.type == 'T') {
|
||||
redirectUrl = phonepeGatewayConf.redirectUrlT
|
||||
} else if (body.type == 'E') {
|
||||
redirectUrl = phonepeGatewayConf.redirectUrlE + '/' + body.tenderId
|
||||
}
|
||||
|
||||
let callbackUrl = phonepeGatewayConf.callbackUrl + '/' + user.userId + '/' + body.tenderId + '/' + body.type
|
||||
console.log("redirectUrl======,", callbackUrl);
|
||||
let amount
|
||||
if (phonepeGatewayConf.testing == true) {
|
||||
amount = 100
|
||||
} else {
|
||||
amount = body.amount * 100
|
||||
}
|
||||
|
||||
const data = {
|
||||
merchantId: phonepeGatewayConf.merchantId,
|
||||
merchantTransactionId: TxnId,
|
||||
merchantUserId: body.name,
|
||||
amount: amount,
|
||||
redirectUrl: redirectUrl,
|
||||
redirectMode: "REDIRECT",
|
||||
mobileNumber: body.mobile,
|
||||
callbackUrl: callbackUrl,
|
||||
paymentInstrument: {
|
||||
type: "PAY_PAGE"
|
||||
}
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
|
||||
const payload = JSON.stringify(data);
|
||||
const payloadMain = Buffer.from(payload).toString('base64');
|
||||
let key = phonepeGatewayConf.salt
|
||||
let index = phonepeGatewayConf.indexKey
|
||||
// console.log("payloadMain========", payloadMain);
|
||||
|
||||
const string = payloadMain + '/pg/v1/pay' + key
|
||||
const sha256 = crypto.createHash('sha256').update(string).digest('hex')
|
||||
|
||||
const checkSum = sha256 + '###' + index
|
||||
// console.log("checkSum=========", checkSum);
|
||||
|
||||
let url = phonepeGatewayConf.url
|
||||
let response = ''
|
||||
const decodedString = Buffer.from(response, 'base64').toString('utf-8');
|
||||
console.log("decodedString", decodedString);
|
||||
|
||||
|
||||
const axios = require('axios');
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-VERIFY': checkSum
|
||||
},
|
||||
data: {
|
||||
request: payloadMain
|
||||
}
|
||||
};
|
||||
let res = await axios
|
||||
.request(options)
|
||||
.then(function (response) {
|
||||
console.log(response.data);
|
||||
|
||||
|
||||
return response.data
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error(error);
|
||||
|
||||
});
|
||||
let paymentStatus = new PaymentStatusDto
|
||||
paymentStatus.amount = body.amount;
|
||||
paymentStatus.txnid = parseInt(TxnId);
|
||||
paymentStatus.mobile = user.mobileNumber;
|
||||
paymentStatus.email = user.email;
|
||||
paymentStatus.status = 'U';
|
||||
paymentStatus.paymentOption = 'P';
|
||||
paymentStatus.type = body.type;
|
||||
paymentStatus.userId = user.userId
|
||||
paymentStatus.tenderId = body.tenderId
|
||||
paymentStatus.paymentDate = new Date(formattedDate);
|
||||
console.log(paymentStatus);
|
||||
await this.paymentStatusRepo.save(paymentStatus)
|
||||
// this.paymentStatus(body.tenderId,user.userId,body.type)
|
||||
return res
|
||||
|
||||
}
|
||||
//
|
||||
async paymentStatus(req, res, tenderId, userId, type) {
|
||||
// console.log("inside payment Status",res.req.body);
|
||||
let keyIndex = phonepeGatewayConf.indexKey
|
||||
let key = phonepeGatewayConf.salt
|
||||
let response = res.req.body.response
|
||||
const encoded = Buffer.from(response, 'base64').toString('utf-8');
|
||||
// console.log("decodedString",encoded);
|
||||
const decodedString = JSON.parse(encoded);
|
||||
let txnId = decodedString.data.merchantTransactionId
|
||||
let merchantId = decodedString.data.merchantId
|
||||
console.log("res=========", txnId, merchantId);
|
||||
|
||||
// console.log("paymentStstus===",res.body);
|
||||
let key1 = {
|
||||
"keyIndex": keyIndex,
|
||||
"key": key
|
||||
}
|
||||
|
||||
|
||||
|
||||
const string = '/pg/v1/status/' + merchantId + '/' + txnId + key
|
||||
const sha256 = crypto.createHash('sha256').update(string).digest('hex')
|
||||
|
||||
const checkSum = sha256 + '###' + keyIndex
|
||||
console.log("checkSum=========", checkSum);
|
||||
|
||||
let url = phonepeGatewayConf.statusUrl + '/' + merchantId + '/' + txnId
|
||||
|
||||
const axios = require('axios');
|
||||
const options = {
|
||||
method: 'get',
|
||||
url: url,
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-VERIFY': checkSum,
|
||||
'X-MERCHANT-ID': merchantId
|
||||
},
|
||||
|
||||
};
|
||||
let result = await axios
|
||||
.request(options)
|
||||
.then(function (response) {
|
||||
console.log(response.data);
|
||||
return response.data
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
if (result.code == 'PAYMENT_SUCCESS') {
|
||||
return this.paymentSuccess(result, tenderId, userId, type)
|
||||
} else {
|
||||
return this.paymentFailed(result, tenderId, userId)
|
||||
}
|
||||
}
|
||||
async paymentSuccess(res, tenderId, userId, type) {
|
||||
|
||||
let phonepeTrans = new phonepeTransactionDto
|
||||
phonepeTrans.success = res.success
|
||||
phonepeTrans.message = res.message
|
||||
phonepeTrans.code = res.code
|
||||
phonepeTrans.merchantId = res.data.merchantId
|
||||
phonepeTrans.merchantTransactionId = res.data.merchantTransactionId
|
||||
phonepeTrans.transactionId = res.data.transactionId
|
||||
phonepeTrans.amount = res.data.amount / 100
|
||||
phonepeTrans.state = res.data.state
|
||||
phonepeTrans.paymentType = res.data.paymentInstrument.type
|
||||
phonepeTrans.txnDate = await this.newDate()
|
||||
phonepeTrans.responseCode = res.data.responseCode
|
||||
await this.phonepetxnRepo.save(phonepeTrans)
|
||||
|
||||
let pamentStatus = await this.paymentStatusRepo.findOne({ where: { txnid: parseInt(res.data.merchantTransactionId) } })
|
||||
if (pamentStatus) {
|
||||
pamentStatus.status = 'S'
|
||||
await this.paymentStatusRepo.save(pamentStatus)
|
||||
}
|
||||
console.log("type=====", type);
|
||||
|
||||
if (type == 'T') {
|
||||
let paymentMaster = new PaymentMasterDto
|
||||
paymentMaster.transId = parseInt(res.data.merchantTransactionId)
|
||||
paymentMaster.userId = userId
|
||||
paymentMaster.tenderId = tenderId
|
||||
paymentMaster.notificationViewed = 'N'
|
||||
paymentMaster.status = 'S'
|
||||
console.log(paymentMaster);
|
||||
|
||||
await this.paymentMasterRepo.save(paymentMaster)
|
||||
}else if(type == 'E'){
|
||||
let paymentMaster = await this.paymentMasterRepo.findOne({where:{tenderId : tenderId , userId : userId}})
|
||||
if(paymentMaster){
|
||||
paymentMaster.emdFeetxnId = parseInt(res.data.merchantTransactionId)
|
||||
paymentMaster.emdFeeType = 'PhonePe'
|
||||
paymentMaster.emdFeeStatus = res.code
|
||||
await this.paymentMasterRepo.save(paymentMaster)
|
||||
}
|
||||
|
||||
}
|
||||
await this.sendPaymentEmail(userId, tenderId)
|
||||
return { data: "Payment Success" }
|
||||
|
||||
}
|
||||
|
||||
async paymentFailed(res, tenderId, userId) {
|
||||
|
||||
let phonepeTrans = new phonepeTransactionDto
|
||||
phonepeTrans.success = res.success
|
||||
phonepeTrans.message = res.message
|
||||
phonepeTrans.code = res.code
|
||||
phonepeTrans.merchantId = res.data.merchantId
|
||||
phonepeTrans.merchantTransactionId = res.data.merchantTransactionId
|
||||
phonepeTrans.transactionId = res.data.transactionId
|
||||
phonepeTrans.amount = res.data.amount / 100
|
||||
phonepeTrans.state = res.data.state
|
||||
phonepeTrans.paymentType = res.data.paymentInstrument.type ?? null
|
||||
phonepeTrans.responseCode = res.data.responseCode ?? null
|
||||
phonepeTrans.txnDate = await this.newDate()
|
||||
|
||||
await this.phonepetxnRepo.save(phonepeTrans)
|
||||
let pamentStatus = await this.paymentStatusRepo.findOne({ where: { txnid: parseInt(res.data.merchantTransactionId) } })
|
||||
if (pamentStatus) {
|
||||
pamentStatus.status = 'F'
|
||||
await this.paymentStatusRepo.save(pamentStatus)
|
||||
}
|
||||
|
||||
return { data: "Payment Failed" }
|
||||
}
|
||||
|
||||
async newDate() {
|
||||
let currentDate = new Date();
|
||||
let year = currentDate.getFullYear();
|
||||
let month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
|
||||
let day = currentDate.getDate().toString().padStart(2, '0');
|
||||
let formattedDate = `${year}-${month}-${day}`;
|
||||
return new Date(formattedDate)
|
||||
}
|
||||
|
||||
async sendPaymentEmail(userId, tenderId) {
|
||||
let user = await this.pcdUserRepo.findOne({ where: { userId: userId } })
|
||||
let tender = await this.tenderMasterRepo.findOne({ where: { id: tenderId } })
|
||||
let bidopenDAte = await this.formattedNewDate(tender.bidOpenDate)
|
||||
|
||||
let body ={
|
||||
email : user.email,
|
||||
custName : user.userName,
|
||||
tenderName : tender.title,
|
||||
bidOpenDate : bidopenDAte.toString()
|
||||
}
|
||||
console.log("mailbody=========",body);
|
||||
|
||||
await this.authservice.sendOtp(body,'CP')
|
||||
}
|
||||
|
||||
async formattedNewDate(date) {
|
||||
let currentDate = date
|
||||
let year = currentDate.getFullYear();
|
||||
let month = (currentDate.getMonth() + 1).toString().padStart(2, '0');
|
||||
let day = currentDate.getDate().toString().padStart(2, '0');
|
||||
let formattedDate = `${day}/${month}/${year}`;
|
||||
return new Date(formattedDate)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
export function convertDate(date: Date, format?: string): Date {
|
||||
if (!date || date.toString() == "" || date.toString() == "null")
|
||||
return null;
|
||||
|
||||
date = new Date(date);
|
||||
if (!format)
|
||||
format = "yyyy-MM-dd";
|
||||
let day = ('0' + date.getDate()).slice(-2);
|
||||
let month = ('0' + (date.getMonth() + 1)).slice(-2);
|
||||
let year = date.getFullYear();
|
||||
let hours = ('0' + date.getHours() || '00').slice(-2);
|
||||
let minutes = ('0' + date.getMinutes() || '00').slice(-2);
|
||||
let seconds = ('0' + date.getSeconds() || '00').slice(-2);
|
||||
let stringDt = format;
|
||||
if (format.includes("yyyy")) stringDt = stringDt.replace("yyyy", year.toString());
|
||||
if (format.includes("MM")) stringDt = stringDt.replace("MM", month.toString());
|
||||
if (format.includes("dd")) stringDt = stringDt.replace("dd", day.toString());
|
||||
if (format.includes("hh")) stringDt = stringDt.replace("hh", hours.toString());
|
||||
if (format.includes("mm")) stringDt = stringDt.replace("mm", minutes.toString());
|
||||
if (format.includes("ss")) stringDt = stringDt.replace("ss", seconds.toString());
|
||||
|
||||
let convDate = new Date(stringDt);
|
||||
|
||||
return convDate;
|
||||
}
|
||||
|
||||
export function convertDateString(date: Date, format?: string): string {
|
||||
if (!date || date.toString() == "null")
|
||||
return null;
|
||||
|
||||
date = new Date(date);
|
||||
|
||||
if (!format)
|
||||
format = "yyyy-MM-dd";
|
||||
let day = ('0' + date.getDate()).slice(-2);
|
||||
let month = ('0' + (date.getMonth() + 1)).slice(-2);
|
||||
let year = date.getFullYear();
|
||||
let hours = ('0' + date.getHours() || '00').slice(-2);
|
||||
let minutes = ('0' + date.getMinutes() || '00').slice(-2);
|
||||
let seconds = ('0' + date.getSeconds() || '00').slice(-2);
|
||||
|
||||
let stringDt = format;
|
||||
if (format.includes("yyyy")) stringDt = stringDt.replace("yyyy", year.toString());
|
||||
if (format.includes("MM")) stringDt = stringDt.replace("MM", month.toString());
|
||||
if (format.includes("dd")) stringDt = stringDt.replace("dd", day.toString());
|
||||
if (format.includes("hh")) stringDt = stringDt.replace("hh", hours.toString());
|
||||
if (format.includes("mm")) stringDt = stringDt.replace("mm", minutes.toString());
|
||||
if (format.includes("ss")) stringDt = stringDt.replace("ss", seconds.toString());
|
||||
if (format.includes("MON")) stringDt = stringDt.replace("MON", shortMonth[parseInt(month.toString()) - 1]);
|
||||
if (format.includes("MONTH")) stringDt = stringDt.replace("MONTH", month[parseInt(month.toString()) - 1]);
|
||||
|
||||
|
||||
return stringDt;
|
||||
}
|
||||
|
||||
const month = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
|
||||
|
||||
const shortMonth = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
|
||||
@ -0,0 +1,21 @@
|
||||
import { Injectable, ArgumentMetadata, BadRequestException, ValidationPipe, UnprocessableEntityException } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class IctValidateInputPipe extends ValidationPipe {
|
||||
public async transform(value, metadata: ArgumentMetadata) {
|
||||
try {
|
||||
return await super.transform(value, metadata);
|
||||
} catch (e) {
|
||||
if (e instanceof BadRequestException) {
|
||||
// throw new UnprocessableEntityException(this.handleError(e.message)); //commented after migration
|
||||
let err: Object = e.getResponse();
|
||||
console.log("====err1====",err["message"]);
|
||||
throw new UnprocessableEntityException(err["message"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleError(errors) {
|
||||
return errors.map(error => error.constraints);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import { Controller ,UseGuards} from '@nestjs/common';
|
||||
import { basicCategoryDto } from 'src/dto/basic-category.dto';
|
||||
import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller';
|
||||
import { basicCategoryService } from './category.service';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Controller('basic-category')
|
||||
export class basicCategoryController extends PcdFormGridController<basicCategoryDto> {
|
||||
|
||||
constructor(
|
||||
private productCategoryService: basicCategoryService
|
||||
) {
|
||||
super(productCategoryService);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom";
|
||||
import { TenderMaster } from "src/tables/tender-master/tender-master.entity";
|
||||
import { Column, Entity, OneToMany, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
|
||||
|
||||
@Entity("category")
|
||||
export class Category extends PcdBaseEntity{
|
||||
@PrimaryGeneratedColumn({
|
||||
name:"id"
|
||||
})
|
||||
id:number
|
||||
|
||||
@Column({
|
||||
name:"category",
|
||||
type:"varchar",
|
||||
nullable:true
|
||||
})
|
||||
productCategory:string
|
||||
|
||||
|
||||
|
||||
|
||||
@OneToMany(() => TenderMaster, (tenderMaster) => tenderMaster.tenderCategoryD )
|
||||
tenderMaster:TenderMaster[]
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { basicCategoryController } from './category.controller';
|
||||
import { basicCategoryService } from './category.service';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { basicCategoryRepository } from './category.repository';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { Category } from './category.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Category]),
|
||||
AuthModule
|
||||
],
|
||||
controllers: [basicCategoryController],
|
||||
providers: [basicCategoryService,basicCategoryRepository]
|
||||
})
|
||||
export class basicCategoryModule {}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
import { DataSource, EntityRepository, Repository } from "typeorm";
|
||||
import { Category } from "./category.entity";
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
@Injectable()
|
||||
export class basicCategoryRepository extends Repository<Category>{
|
||||
constructor(
|
||||
private datasource : DataSource
|
||||
){
|
||||
super(Category,datasource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { basicCategoryDto } from 'src/dto/basic-category.dto';
|
||||
import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service';
|
||||
import { basicCategoryRepository } from './category.repository';
|
||||
|
||||
@Injectable()
|
||||
export class basicCategoryService extends PcdFormGridService<basicCategoryDto>{
|
||||
|
||||
constructor(
|
||||
@InjectRepository(basicCategoryRepository)
|
||||
private basicCategoryRepository: basicCategoryRepository,
|
||||
) {
|
||||
super(basicCategoryRepository);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
|
||||
import { closedTenderUsersDto } from 'src/dto/closed-tender-users.dto';
|
||||
import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller';
|
||||
import { ClosedTenderUsersService } from './closed-tender-users.service';
|
||||
import { GetUser } from 'src/auth/dto/get-user.decorator';
|
||||
import { PcduserDto } from 'src/auth/dto/pcd-user.dto';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@UseGuards(AuthGuard())
|
||||
@Controller('closed-tender-users')
|
||||
export class ClosedTenderUsersController extends PcdFormGridController<closedTenderUsersDto> {
|
||||
|
||||
constructor(
|
||||
private ClosedTenderUsersService: ClosedTenderUsersService
|
||||
) {
|
||||
super(ClosedTenderUsersService);
|
||||
}
|
||||
|
||||
@Post('users')
|
||||
async closedTenderUsers(
|
||||
@GetUser() user:PcduserDto,
|
||||
@Body() body:any
|
||||
) {
|
||||
return await this.ClosedTenderUsersService.closedTenderUsers(user,body)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
import { Pcduser } from "src/auth/pcduser.entity";
|
||||
import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom";
|
||||
import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { TenderMaster } from "../tender-master/tender-master.entity";
|
||||
|
||||
@Entity('closed-tender-users')
|
||||
export class closedTenderUsers extends PcdBaseEntity{
|
||||
@PrimaryGeneratedColumn({
|
||||
name:"id"
|
||||
})
|
||||
id:number
|
||||
|
||||
@Column({
|
||||
name:"tenderId",
|
||||
type:"numeric",
|
||||
nullable:true
|
||||
})
|
||||
tenderId:number
|
||||
|
||||
|
||||
@Column({
|
||||
name:"userId",
|
||||
type:"numeric",
|
||||
nullable:true
|
||||
})
|
||||
userId:number
|
||||
|
||||
@ManyToOne(() => Pcduser, (Pcduser) => Pcduser.closedTenderUsers, { eager: true })
|
||||
@JoinColumn([{ name: "userId", referencedColumnName: "userId" }])
|
||||
userD: Pcduser
|
||||
|
||||
@ManyToOne(() => TenderMaster, (tenderMaster) => tenderMaster.closedTenderUsers, { eager: true })
|
||||
@JoinColumn([{ name: "tenderId", referencedColumnName: "id" }])
|
||||
tenderD: TenderMaster
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ClosedTenderUsersService } from './closed-tender-users.service';
|
||||
import { ClosedTenderUsersController } from './closed-tender-users.controller';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuthModule } from 'src/auth/auth.module';
|
||||
import { closedTenderUsers } from './closed-tender-users.entity';
|
||||
import { closedTenderUsersRepository } from './closed-tender-users.repository';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([closedTenderUsers]),
|
||||
AuthModule
|
||||
],
|
||||
providers: [ClosedTenderUsersService,closedTenderUsersRepository],
|
||||
controllers: [ClosedTenderUsersController]
|
||||
})
|
||||
export class ClosedTenderUsersModule {}
|
||||
@ -0,0 +1,12 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { DataSource, Repository } from "typeorm";
|
||||
import { closedTenderUsers } from "./closed-tender-users.entity";
|
||||
|
||||
@Injectable()
|
||||
export class closedTenderUsersRepository extends Repository<closedTenderUsers>{
|
||||
constructor(
|
||||
private datasource : DataSource
|
||||
){
|
||||
super(closedTenderUsers,datasource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { closedTenderUsersDto } from 'src/dto/closed-tender-users.dto';
|
||||
import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service';
|
||||
import { closedTenderUsersRepository } from './closed-tender-users.repository';
|
||||
|
||||
@Injectable()
|
||||
export class ClosedTenderUsersService extends PcdFormGridService<closedTenderUsersDto>{
|
||||
|
||||
constructor(
|
||||
@InjectRepository(closedTenderUsersRepository)
|
||||
private closedTenderUsersRepository: closedTenderUsersRepository,
|
||||
) {
|
||||
super(closedTenderUsersRepository);
|
||||
}
|
||||
|
||||
|
||||
async closedTenderUsers(user, body) {
|
||||
console.log("body", body[0].tenderId );
|
||||
|
||||
if (user.secuLevel == 'User') {
|
||||
throw new BadRequestException('Saving data is restricted due to the absence of the necessary authorization or privilege.')
|
||||
}
|
||||
try {
|
||||
await this.closedTenderUsersRepository.delete({ tenderId: body[0].tenderId });
|
||||
} catch (error) {
|
||||
console.error("Error deleting data:", error);
|
||||
}
|
||||
for (let i of body) {
|
||||
console.log(i);
|
||||
|
||||
let closedUser = new closedTenderUsersDto
|
||||
closedUser.userId = parseInt(i.userId)
|
||||
closedUser.tenderId = i.tenderId
|
||||
console.log("closedUser", closedUser);
|
||||
|
||||
await this.closedTenderUsersRepository.save(closedUser)
|
||||
}
|
||||
return { msg: "Data Saved successfully" }
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { CommonDto } from 'src/dto/common.dto';
|
||||
import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller';
|
||||
import { CommonService } from './common.service';
|
||||
|
||||
@Controller('common')
|
||||
export class CommonController extends PcdFormGridController<CommonDto>{
|
||||
|
||||
constructor(
|
||||
private commonService: CommonService
|
||||
) {
|
||||
super(commonService);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom";
|
||||
import { Column, Entity, EntityRepository, PrimaryGeneratedColumn } from "typeorm";
|
||||
|
||||
@Entity('common')
|
||||
export class Common extends PcdBaseEntity{
|
||||
|
||||
|
||||
@PrimaryGeneratedColumn({
|
||||
name:"id"
|
||||
})
|
||||
id:number
|
||||
|
||||
@Column({
|
||||
name:'marquee',
|
||||
type:"varchar",
|
||||
length:1000,
|
||||
nullable:true
|
||||
})
|
||||
marquee:string
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CommonController } from './common.controller';
|
||||
import { CommonService } from './common.service';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { commonRepository } from './common.repository';
|
||||
import { Common } from './common.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Common]),
|
||||
],
|
||||
controllers: [CommonController],
|
||||
providers: [CommonService,commonRepository]
|
||||
})
|
||||
export class CommonModule {}
|
||||
@ -0,0 +1,12 @@
|
||||
import { DataSource, Repository } from "typeorm";
|
||||
import { Common } from "./common.entity";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class commonRepository extends Repository<Common>{
|
||||
constructor(
|
||||
private datasource:DataSource
|
||||
){
|
||||
super(Common,datasource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PcdFormGridService } from 'src/framework/beans/pcd-form-grid.service';
|
||||
import { Common } from './common.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { commonRepository } from './common.repository';
|
||||
|
||||
@Injectable()
|
||||
export class CommonService extends PcdFormGridService<Common>{
|
||||
|
||||
constructor(
|
||||
@InjectRepository(commonRepository)
|
||||
private commonRepository: commonRepository,
|
||||
) {
|
||||
super(commonRepository);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { coverTypeDto } from 'src/dto/cover-type.dto';
|
||||
import { PcdFormGridController } from 'src/framework/beans/pcd-form-grid.controller';
|
||||
import { CoversLovService } from './covers-lov.service';
|
||||
|
||||
@Controller('covers-lov')
|
||||
export class CoversLovController extends PcdFormGridController<coverTypeDto>{
|
||||
|
||||
constructor(
|
||||
private coversLovService: CoversLovService
|
||||
) {
|
||||
super(coversLovService);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { PcdBaseDto } from "src/framework/custom/pcd-dto.custom";
|
||||
import { PcdBaseEntity } from "src/framework/custom/pcd-entity.custom";
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { CoverDoc } from "../covers-master/covers-master.entity";
|
||||
|
||||
@Entity('covers-lov')
|
||||
export class CoversLov extends PcdBaseEntity{
|
||||
|
||||
@PrimaryGeneratedColumn({
|
||||
name:"id"
|
||||
})
|
||||
id:number
|
||||
|
||||
@Column({
|
||||
name:"covertype",
|
||||
type:"varchar",
|
||||
length:500,
|
||||
nullable:true
|
||||
})
|
||||
coverType:string
|
||||
|
||||
@OneToMany(() => CoverDoc, (coverDoc) => coverDoc.coverTypeD )
|
||||
coverDoc:CoverDoc[]
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue