Atualização repositorio
This commit is contained in:
22
src/core/configs/typeorm.config.ts
Normal file
22
src/core/configs/typeorm.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
import { DataSourceOptions } from 'typeorm/data-source';
|
||||
|
||||
export const typeOrmConfig: DataSourceOptions = {
|
||||
type: 'oracle',
|
||||
connectString: '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.1.1.241)(PORT = 1521)))(CONNECT_DATA = (SERVICE_NAME = WINT)))',
|
||||
username: 'SEVEN',
|
||||
password: 'USR54SEV',
|
||||
synchronize: false,
|
||||
logging: false,
|
||||
entities: [__dirname + '/../**/*.entity.{js,ts}'],
|
||||
};
|
||||
|
||||
export const typeOrmPgConfig: DataSourceOptions = {
|
||||
type: 'postgres',
|
||||
host: '10.1.1.222',
|
||||
port: 5432,
|
||||
username: 'ti',
|
||||
password: 'ti',
|
||||
database: 'ksdb',
|
||||
synchronize: true,
|
||||
}
|
||||
25
src/core/models/car-in-delivery.model.ts
Normal file
25
src/core/models/car-in-delivery.model.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export class Invoice {
|
||||
customer: string;
|
||||
invoiceNumber: number;
|
||||
loadingNumber: number;
|
||||
reasonId: number;
|
||||
reasonText: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export class CarInDelivery {
|
||||
finalKm: number;
|
||||
invoices: Invoice[];
|
||||
licensePlate: string;
|
||||
loadingNumber: number;
|
||||
observation: string;
|
||||
images: string[];
|
||||
userId: number;
|
||||
qtdPaletesPbr: number;
|
||||
qtdPaletesCim: number;
|
||||
qtdPaletesDes: number;
|
||||
remnant: string;
|
||||
observationRemnant: string;
|
||||
imagesRemnant: string[];
|
||||
|
||||
}
|
||||
18
src/core/models/car-out-delivery.model.ts
Normal file
18
src/core/models/car-out-delivery.model.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export class CarOutDelivery {
|
||||
helpers: Helper[]; // Array de objetos auxiliares
|
||||
licensePlate: string; // Placa do veículo
|
||||
numberLoading: number[]; // Número do carregamento
|
||||
palletCount: number; // Quantidade de pallets
|
||||
photos: string[]; // Array de URLs das fotos
|
||||
startKm: number; // Quilometragem de início (como string)
|
||||
userCode: number; // Código do usuário
|
||||
vehicleCode: number; // Código do veículo
|
||||
}
|
||||
|
||||
|
||||
export class Helper {
|
||||
id: number;
|
||||
name: string;
|
||||
phone: string;
|
||||
}
|
||||
|
||||
6
src/core/models/change-password.model.ts
Normal file
6
src/core/models/change-password.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
export class ChangePasswordModel {
|
||||
id: number;
|
||||
password: string;
|
||||
newPassword: string;
|
||||
}
|
||||
6
src/core/models/exposed-product.model.ts
Normal file
6
src/core/models/exposed-product.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
export class ExposedProduct {
|
||||
ean: string;
|
||||
storeId: string;
|
||||
userId: number;
|
||||
}
|
||||
5
src/core/models/reset-password.model.ts
Normal file
5
src/core/models/reset-password.model.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
export class ResetPasswordModel {
|
||||
document: string;
|
||||
email: string;
|
||||
}
|
||||
9
src/core/models/result.model.ts
Normal file
9
src/core/models/result.model.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
export class ResultModel {
|
||||
|
||||
constructor(
|
||||
public success: boolean,
|
||||
public message: string,
|
||||
public data: any,
|
||||
public errors: any) {};
|
||||
}
|
||||
8
src/core/models/user.model.ts
Normal file
8
src/core/models/user.model.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export class UserModel {
|
||||
id: number;
|
||||
password: string;
|
||||
application: string;
|
||||
storeId: string;
|
||||
sellerId: number;
|
||||
email: string;
|
||||
}
|
||||
94
src/core/services/base.controller.ts
Normal file
94
src/core/services/base.controller.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { DropAction } from './../../../node_modules/aws-sdk/clients/mailmanager.d';
|
||||
/*
|
||||
https://docs.nestjs.com/controllers#controllers
|
||||
*/
|
||||
|
||||
import {
|
||||
Body, Controller, Get, HttpException, HttpStatus, Post, Query, Req, UseInterceptors,
|
||||
UploadedFile
|
||||
} from '@nestjs/common';
|
||||
import { BaseService } from './base.service';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { diskStorage } from 'multer';
|
||||
import { extname } from 'path';
|
||||
import * as fs from "fs";
|
||||
|
||||
@Controller('api/v1/base')
|
||||
export class BaseController {
|
||||
constructor(public readonly baseService: BaseService) { }
|
||||
// @UseGuards(JwtAuthGuard)
|
||||
@Get('execute-view')
|
||||
/* @ApiOperation({
|
||||
summary: 'Executa uma view com ou sem parâmetros',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Dados retornados com sucesso.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 400,
|
||||
description: 'O nome da view é obrigatório.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 500,
|
||||
description: 'Erro ao executar a view.',
|
||||
})*/
|
||||
async executeView(
|
||||
@Query('viewName') viewName: string,
|
||||
@Query() params: Record<string, any>,
|
||||
) {
|
||||
if (!viewName) {
|
||||
throw new HttpException(
|
||||
'O nome da view é obrigatório.',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
try {
|
||||
return await this.baseService.executeView(viewName, params);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
`Erro ao executar a view: ${error.message}`,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Post('send-image')
|
||||
@UseInterceptors(
|
||||
FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
// Pasta onde os arquivos serão salvos; certifique-se que essa pasta exista ou crie-a automaticamente
|
||||
destination: './uploads',
|
||||
filename: (req, file, callback) => {
|
||||
// Gera um nome único para o arquivo
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
|
||||
const fileExtName = extname(file.originalname);
|
||||
callback(null, `${file.fieldname}-${uniqueSuffix}${fileExtName}`);
|
||||
},
|
||||
}),
|
||||
// Opcional: definir limites (ex.: tamanho máximo do arquivo)
|
||||
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
|
||||
}),
|
||||
)
|
||||
async sendImage(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body('licensePlate') licensePlate: string,
|
||||
) {
|
||||
if (!file) {
|
||||
throw new HttpException('Nenhum arquivo enviado', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// Aqui você pode processar o arquivo (ex.: enviar para o S3) ou armazená-lo no disco mesmo.
|
||||
// Neste exemplo, retornamos a URL do arquivo salvo localmente.
|
||||
this.baseService.sendImages('./uploads/'+file.filename);
|
||||
fs.unlink('./uploads/'+file.filename, () => {});
|
||||
return {
|
||||
success: true,
|
||||
message: 'Upload realizado com sucesso',
|
||||
url: `https://jur-saidaretornoveiculo.s3.sa-east-1.amazonaws.com/${file.filename}`,
|
||||
licensePlate,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
15
src/core/services/base.module.ts
Normal file
15
src/core/services/base.module.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { BaseController } from './base.controller';
|
||||
/*
|
||||
https://docs.nestjs.com/modules
|
||||
*/
|
||||
|
||||
import { Module } from '@nestjs/common';
|
||||
import { BaseService } from './base.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [
|
||||
BaseController,],
|
||||
providers: [BaseService,],
|
||||
})
|
||||
export class BaseModule { }
|
||||
289
src/core/services/base.service.ts
Normal file
289
src/core/services/base.service.ts
Normal file
@@ -0,0 +1,289 @@
|
||||
import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { typeOrmConfig } from '../configs/typeorm.config';
|
||||
import { S3 } from 'aws-sdk';
|
||||
import * as fs from "fs";
|
||||
|
||||
@Injectable()
|
||||
export class BaseService {
|
||||
constructor() { }
|
||||
|
||||
async findAll(table: string) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const [rows] = await queryRunner.query(`SELECT * FROM ${table}`);
|
||||
return rows;
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao buscar todos os registros da tabela ${table}`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(table: string, id: any) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const [rows] = await queryRunner.query(`SELECT * FROM ${table} WHERE id = '${id}'`);
|
||||
return rows[0];
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao buscar o registro com ID ${id} na tabela ${table}`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async create(table: string, data: any) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const columns = Object.keys(data).map((key) => `${key}`).join(', ');
|
||||
const values = Object.values(data);
|
||||
const placeholders = values.map(() => '?').join(', ');
|
||||
|
||||
const query = `INSERT INTO ${table} (${columns}) VALUES (${placeholders})`;
|
||||
|
||||
const [result] = await queryRunner.query(query, values);
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao criar um registro na tabela ${table}`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async update(table: string, where: any, data: any) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const [result] = await queryRunner.query(`UPDATE ${table} SET ${data} WHERE ${where}`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao atualizar o registro com ${where} na tabela ${table}`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async delete(table: string, where: any) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const [result] = await queryRunner.query(`DELETE FROM ${table} WHERE ${where}`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao deletar o registro com ID ${where} na tabela ${table}`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async query(queryString: string, params: any[]): Promise<any[]> {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const [rows] = await queryRunner.query(queryString, params);
|
||||
return rows as any[];
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(error, `Erro ao executar a consulta SQL personalizada`);
|
||||
} finally {
|
||||
queryRunner.release();
|
||||
dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async executeView(viewName: string, params: Record<string, any>) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
// Valida se o nome da view foi fornecido
|
||||
if (!viewName) {
|
||||
throw new Error('O nome da view é obrigatório.');
|
||||
}
|
||||
|
||||
console.log(`Iniciando execução da view: ${viewName}`);
|
||||
console.log('Parâmetros recebidos:', params);
|
||||
|
||||
const conditions: string[] = [];
|
||||
const values: any[] = [];
|
||||
|
||||
// Remove o parâmetro viewName dos parâmetros antes de processar
|
||||
const filteredParams = { ...params };
|
||||
delete filteredParams.viewName;
|
||||
|
||||
// Adiciona as condições baseadas nos parâmetros fornecidos
|
||||
if (filteredParams && Object.keys(filteredParams).length > 0) {
|
||||
console.log('Adicionando condições para os parâmetros fornecidos...');
|
||||
for (const [key, value] of Object.entries(filteredParams)) {
|
||||
// Verifica se a chave e o valor são válidos
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
console.log(`Parâmetro válido: ${key} = '${value}'`);
|
||||
conditions.push(`${key} = '${value}'`); // Adiciona aspas para evitar problemas de SQL injection
|
||||
values.push(value);
|
||||
} else {
|
||||
console.warn(`Parâmetro ignorado: ${key} = '${value}'`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('Nenhum parâmetro válido foi fornecido.');
|
||||
}
|
||||
|
||||
// Monta a cláusula WHERE somente se houver condições
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
||||
const query = `SELECT * FROM ${ viewName } ${whereClause}`;
|
||||
|
||||
console.log(`Consulta SQL montada: ${ query }`);
|
||||
console.log(`{Valores para a consulta:, ${values}`);
|
||||
|
||||
// Executa a consulta
|
||||
const rows = await queryRunner.query(query);
|
||||
|
||||
console.log(`Consulta executada com sucesso.Linhas retornadas: ${ JSON.stringify(rows) }`);
|
||||
return rows;
|
||||
} catch (error) {
|
||||
console.error(`Erro ao executar a view ${ viewName }: `, error.message);
|
||||
this.handleDatabaseError(
|
||||
error,
|
||||
`Erro ao executar a view ${ viewName } com parâmetros.`,
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
await dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
async executeProcedure(procedureName: string, params: Record<string, any>) {
|
||||
const dataSource = new DataSource(typeOrmConfig);
|
||||
await dataSource.initialize();
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
try {
|
||||
const placeholders = Object.keys(params)
|
||||
.map(() => '?')
|
||||
.join(', ');
|
||||
const values = Object.values(params);
|
||||
|
||||
const query = `EXECUTE IMMEDIATE ${ procedureName }(${ placeholders })`;
|
||||
|
||||
// Log da query e dos valores
|
||||
console.log('Query executada:', query);
|
||||
console.log('Valores:', values);
|
||||
|
||||
const [result] = await queryRunner.query(query, values);
|
||||
|
||||
// Verifica e converte campos que contenham JSON strings para objetos
|
||||
const parsedResult = Array.isArray(result)
|
||||
? result.map((row) => {
|
||||
const parsedRow = { ...row };
|
||||
for (const [key, value] of Object.entries(parsedRow)) {
|
||||
try {
|
||||
// Tenta converter strings JSON para objetos
|
||||
if (typeof value === 'string' && value.trim().startsWith('{') && value.trim().endsWith('}')) {
|
||||
parsedRow[key] = JSON.parse(value);
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignora se a conversão falhar
|
||||
console.warn(`Campo ${ key } não é um JSON válido.Mantendo como string.`);
|
||||
}
|
||||
}
|
||||
return parsedRow;
|
||||
})
|
||||
: result;
|
||||
|
||||
// Retorna os valores e o resultado
|
||||
return {
|
||||
message: 'Procedure executada com sucesso.',
|
||||
executedQuery: query,
|
||||
values: values,
|
||||
result: parsedResult,
|
||||
};
|
||||
} catch (error) {
|
||||
this.handleDatabaseError(
|
||||
error,
|
||||
`Erro ao executar a procedure ${ procedureName } com parâmetros.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private handleDatabaseError(error: any, message: string): never {
|
||||
console.error(message, error); // Log detalhado do erro
|
||||
throw new InternalServerErrorException({
|
||||
message,
|
||||
sqlMessage: error.sqlMessage || error.message,
|
||||
sqlState: error.sqlState,
|
||||
});
|
||||
}
|
||||
|
||||
async sendImages(file: string) {
|
||||
// for (const file of files) {
|
||||
// const file = 'C:\\Temp\\brasil_2.jpg'
|
||||
if (file.endsWith(".jpg")) {
|
||||
const fileName = file; //directoryImages + '\\' + file;
|
||||
fs.readFile(fileName, (err, data) => {
|
||||
if (err) throw err;
|
||||
if (err) {
|
||||
console.log(`WRITE ERROR: ${err}`);
|
||||
} else {
|
||||
this.uploadS3(data, 'jur-saidaretornoveiculo', file.replace('./uploads/', ''));
|
||||
}
|
||||
});
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
async uploadS3(file, bucket, name) {
|
||||
const s3 = this.getS3();
|
||||
const params = {
|
||||
Bucket: bucket,
|
||||
Key: String(name),
|
||||
Body: file,
|
||||
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.upload(params, (err, data) => {
|
||||
if (err) {
|
||||
console.log(JSON.stringify(err));
|
||||
reject(err.message);
|
||||
}
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getS3() {
|
||||
return new S3({
|
||||
accessKeyId: "AKIAVHJOO6W765ZT2PNI", //process.env.AWS_ACCESS_KEY_ID,
|
||||
secretAccessKey: "IFtP6Foc7JlE6TfR3psBAERUCMlH+4cRMx0GVIx2", // process.env.AWS_SECRET_ACCESS_KEY,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user