You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
15 KiB
TypeScript
357 lines
15 KiB
TypeScript
import { PcdtTransactionInterface } from "../interface/pcd-transaction.interface";
|
|
import { FindManyOptions, Repository, QueryRunner, DataSource } from "typeorm";
|
|
import { BadRequestException, NotAcceptableException, 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`);
|
|
console.log(filter , this.TXN_TYPE);
|
|
|
|
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: FindManyOptions, 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,user): Promise<boolean> {
|
|
return true;
|
|
}
|
|
|
|
async deleteOne(filter: any, id: string | number,user): 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,user))
|
|
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(user,body: T,): 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(user,body))
|
|
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(user , 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(user , 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;
|
|
}
|
|
|
|
|
|
} |