branch dev

This commit is contained in:
JurTI-BR
2025-03-28 11:29:34 -03:00
parent 41e56dda12
commit 8af4b05f28
18 changed files with 4289 additions and 7731 deletions

View File

@@ -18,7 +18,7 @@ module.exports = {
rules: { rules: {
'@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
}, },
}; };

11011
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,11 @@
"scripts": { "scripts": {
"prebuild": "rimraf dist", "prebuild": "rimraf dist",
"build": "nest build", "build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "format": "prettier --write \"../../**/*.ts\" \"test/**/*.ts\"",
"start": "nest start", "start": "nest start",
"start:dev": "nest start --watch", "start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch", "start:debug": "nest start --debug --watch",
"start:prod": "node dist/main", "start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest", "test": "jest",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:cov": "jest --coverage", "test:cov": "jest --coverage",
@@ -28,6 +27,8 @@
"@nestjs/passport": "^10.0.3", "@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^7.5.1", "@nestjs/platform-express": "^7.5.1",
"@nestjs/typeorm": "^10.0.2", "@nestjs/typeorm": "^10.0.2",
"@types/eslint": "^9.6.1",
"@types/estree": "^1.0.7",
"aws-sdk": "^2.1692.0", "aws-sdk": "^2.1692.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"fs": "0.0.1-security", "fs": "0.0.1-security",
@@ -54,11 +55,8 @@
"@types/express": "^4.17.8", "@types/express": "^4.17.8",
"@types/jest": "^26.0.15", "@types/jest": "^26.0.15",
"@types/multer": "^1.4.12", "@types/multer": "^1.4.12",
"@types/node": "^14.14.6", "@types/node": "^22.13.14",
"@types/supertest": "^2.0.10", "@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.6.1",
"eslint": "^7.12.1",
"eslint-config-prettier": "^6.15.0", "eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4", "eslint-plugin-prettier": "^3.1.4",
"jest": "^26.6.3", "jest": "^26.6.3",
@@ -68,7 +66,7 @@
"ts-loader": "^8.0.8", "ts-loader": "^8.0.8",
"ts-node": "^9.0.0", "ts-node": "^9.0.0",
"tsconfig-paths": "^3.9.0", "tsconfig-paths": "^3.9.0",
"typescript": "^4.0.5" "typescript": "^5.8.2"
}, },
"jest": { "jest": {
"moduleFileExtensions": [ "moduleFileExtensions": [

View File

@@ -9,10 +9,10 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { UsersService } from '../users/users.service'; import { UsersService } from '../users/users.service';
import { UserModel } from 'src/core/models/user.model'; import { UserModel } from '../../core/models/user.model';
import { ResultModel } from 'src/core/models/result.model'; import { ResultModel } from '../../core/models/result.model';
import { ResetPasswordModel } from 'src/core/models/reset-password.model'; import { ResetPasswordModel } from '../../core/models/reset-password.model';
import { ChangePasswordModel } from 'src/core/models/change-password.model'; import { ChangePasswordModel } from '../../core/models/change-password.model';
@Controller('api/v1/auth') @Controller('api/v1/auth')
export class AuthController { export class AuthController {

View File

@@ -4,8 +4,8 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import md5 = require('md5'); import md5 = require('md5');
import { Guid } from "guid-typescript"; import { Guid } from "guid-typescript";
import { typeOrmConfig } from 'src/core/configs/typeorm.config'; import { typeOrmConfig } from '../../core/configs/typeorm.config';
import { UserModel } from 'src/core/models/user.model'; import { UserModel } from '../../core/models/user.model';
@Injectable() @Injectable()

View File

@@ -1,25 +1,24 @@
export class Invoice { export class Invoice {
customer: string; customer: string;
invoiceNumber: number; invoiceNumber: number;
loadingNumber: number; loadingNumber: number;
reasonId: number; reasonId: number;
reasonText: string; reasonText: string;
status: string; status: string;
} }
export class CarInDelivery { export class CarInDelivery {
finalKm: number; finalKm: number;
invoices: Invoice[]; invoices: Invoice[];
licensePlate: string; licensePlate: string;
loadingNumber: number; loadingNumber: number;
observation: string; observation: string;
images: string[]; images: string[];
userId: number; userId: number;
qtdPaletesPbr: number; qtdPaletesPbr: number;
qtdPaletesCim: number; qtdPaletesCim: number;
qtdPaletesDes: number; qtdPaletesDes: number;
remnant: string; remnant: string;
observationRemnant: string; observationRemnant: string;
imagesRemnant: string[]; imagesRemnant: string[];
}
}

View File

@@ -1,18 +1,16 @@
export class CarOutDelivery { export class CarOutDelivery {
helpers: Helper[]; // Array de objetos auxiliares helpers: Helper[]; // Array de objetos auxiliares
licensePlate: string; // Placa do veículo licensePlate: string; // Placa do veículo
numberLoading: number[]; // Número do carregamento numberLoading: number[]; // Número do carregamento
palletCount: number; // Quantidade de pallets palletCount: number; // Quantidade de pallets
photos: string[]; // Array de URLs das fotos photos: string[]; // Array de URLs das fotos
startKm: number; // Quilometragem de início (como string) startKm: number; // Quilometragem de início (como string)
userCode: number; // Código do usuário userCode: number; // Código do usuário
vehicleCode: number; // Código do veículo vehicleCode: number; // Código do veículo
} }
export class Helper {
export class Helper { id: number;
id: number; name: string;
name: string; phone: string;
phone: string; }
}

View File

@@ -1,94 +1,101 @@
import { DropAction } from './../../../node_modules/aws-sdk/clients/mailmanager.d'; import { DropAction } from './../../../node_modules/aws-sdk/clients/mailmanager.d';
/* /*
https://docs.nestjs.com/controllers#controllers https://docs.nestjs.com/controllers#controllers
*/ */
import { import {
Body, Controller, Get, HttpException, HttpStatus, Post, Query, Req, UseInterceptors, Body,
UploadedFile Controller,
} from '@nestjs/common'; Get,
import { BaseService } from './base.service'; HttpException,
import { FileInterceptor } from '@nestjs/platform-express'; HttpStatus,
import { diskStorage } from 'multer'; Post,
import { extname } from 'path'; Query,
import * as fs from "fs"; Req,
UseInterceptors,
@Controller('api/v1/base') UploadedFile,
export class BaseController { } from '@nestjs/common';
constructor(public readonly baseService: BaseService) { } import { BaseService } from './base.service';
// @UseGuards(JwtAuthGuard) import { FileInterceptor } from '@nestjs/platform-express';
@Get('execute-view') import { diskStorage } from 'multer';
/* @ApiOperation({ import { extname } from 'path';
summary: 'Executa uma view com ou sem parâmetros', import * as fs from 'fs';
})
@ApiResponse({ @Controller('api/v1/base')
status: 200, export class BaseController {
description: 'Dados retornados com sucesso.', constructor(public readonly baseService: BaseService) {}
}) // @UseGuards(JwtAuthGuard)
@ApiResponse({ @Get('execute-view')
status: 400, /* @ApiOperation({
description: 'O nome da view é obrigatório.', summary: 'Executa uma view com ou sem parâmetros',
}) })
@ApiResponse({ @ApiResponse({
status: 500, status: 200,
description: 'Erro ao executar a view.', description: 'Dados retornados com sucesso.',
})*/ })
async executeView( @ApiResponse({
@Query('viewName') viewName: string, status: 400,
@Query() params: Record<string, any>, description: 'O nome da view é obrigatório.',
) { })
if (!viewName) { @ApiResponse({
throw new HttpException( status: 500,
'O nome da view é obrigatório.', description: 'Erro ao executar a view.',
HttpStatus.BAD_REQUEST, })*/
); async executeView(
} @Query('viewName') viewName: string,
try { @Query() params: Record<string, any>,
return await this.baseService.executeView(viewName, params); ) {
} catch (error) { if (!viewName) {
throw new HttpException( throw new HttpException(
`Erro ao executar a view: ${error.message}`, 'O nome da view é obrigatório.',
HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.BAD_REQUEST,
); );
} }
} try {
return await this.baseService.executeView(viewName, params);
@Post('send-image') } catch (error) {
@UseInterceptors( throw new HttpException(
FileInterceptor('file', { `Erro ao executar a view: ${error.message}`,
storage: diskStorage({ HttpStatus.INTERNAL_SERVER_ERROR,
// 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); @Post('send-image')
const fileExtName = extname(file.originalname); @UseInterceptors(
callback(null, `${file.fieldname}-${uniqueSuffix}${fileExtName}`); FileInterceptor('file', {
}, storage: diskStorage({
}), // Pasta onde os arquivos serão salvos; certifique-se que essa pasta exista ou crie-a automaticamente
// Opcional: definir limites (ex.: tamanho máximo do arquivo) destination: './uploads',
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB filename: (req, file, callback) => {
}), // Gera um nome único para o arquivo
) const uniqueSuffix =
async sendImage( Date.now() + '-' + Math.round(Math.random() * 1e9);
@UploadedFile() file: Express.Multer.File, const fileExtName = extname(file.originalname);
@Body('licensePlate') licensePlate: string, callback(null, `${file.fieldname}-${uniqueSuffix}${fileExtName}`);
) { },
if (!file) { }),
throw new HttpException('Nenhum arquivo enviado', HttpStatus.BAD_REQUEST); // Opcional: definir limites (ex.: tamanho máximo do arquivo)
} limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
}),
// 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. async sendImage(
this.baseService.sendImages('./uploads/'+file.filename); @UploadedFile() file: Express.Multer.File,
fs.unlink('./uploads/'+file.filename, () => {}); @Body('licensePlate') licensePlate: string,
return { ) {
success: true, if (!file) {
message: 'Upload realizado com sucesso', throw new HttpException('Nenhum arquivo enviado', HttpStatus.BAD_REQUEST);
url: `https://jur-saidaretornoveiculo.s3.sa-east-1.amazonaws.com/${file.filename}`, }
licensePlate,
}; // 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,
};
}
}

View File

@@ -1,15 +1,14 @@
import { BaseController } from './base.controller'; import { BaseController } from './base.controller';
/* /*
https://docs.nestjs.com/modules https://docs.nestjs.com/modules
*/ */
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { BaseService } from './base.service'; import { BaseService } from './base.service';
@Module({ @Module({
imports: [], imports: [],
controllers: [ controllers: [BaseController],
BaseController,], providers: [BaseService],
providers: [BaseService,], })
}) export class BaseModule {}
export class BaseModule { }

View File

@@ -1,289 +1,331 @@
import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common'; import {
import { DataSource } from 'typeorm'; Inject,
import { typeOrmConfig } from '../configs/typeorm.config'; Injectable,
import { S3 } from 'aws-sdk'; InternalServerErrorException,
import * as fs from "fs"; } from '@nestjs/common';
import { DataSource } from 'typeorm';
@Injectable() import { typeOrmConfig } from '../configs/typeorm.config';
export class BaseService { import { S3 } from 'aws-sdk';
constructor() { } import * as fs from 'fs';
async findAll(table: string) { @Injectable()
const dataSource = new DataSource(typeOrmConfig); export class BaseService {
await dataSource.initialize(); constructor() {}
const queryRunner = dataSource.createQueryRunner();
await queryRunner.connect(); async findAll(table: string) {
await queryRunner.startTransaction(); const dataSource = new DataSource(typeOrmConfig);
try { await dataSource.initialize();
const [rows] = await queryRunner.query(`SELECT * FROM ${table}`); const queryRunner = dataSource.createQueryRunner();
return rows; await queryRunner.connect();
} catch (error) { await queryRunner.startTransaction();
this.handleDatabaseError(error, `Erro ao buscar todos os registros da tabela ${table}`); try {
} finally { const [rows] = await queryRunner.query(`SELECT * FROM ${table}`);
queryRunner.release(); return rows;
dataSource.destroy(); } catch (error) {
} this.handleDatabaseError(
} error,
`Erro ao buscar todos os registros da tabela ${table}`,
async findOne(table: string, id: any) { );
const dataSource = new DataSource(typeOrmConfig); } finally {
await dataSource.initialize(); queryRunner.release();
const queryRunner = dataSource.createQueryRunner(); dataSource.destroy();
await queryRunner.connect(); }
await queryRunner.startTransaction(); }
try {
const [rows] = await queryRunner.query(`SELECT * FROM ${table} WHERE id = '${id}'`); async findOne(table: string, id: any) {
return rows[0]; const dataSource = new DataSource(typeOrmConfig);
} catch (error) { await dataSource.initialize();
this.handleDatabaseError(error, `Erro ao buscar o registro com ID ${id} na tabela ${table}`); const queryRunner = dataSource.createQueryRunner();
} finally { await queryRunner.connect();
queryRunner.release(); await queryRunner.startTransaction();
dataSource.destroy(); try {
} const [rows] = await queryRunner.query(
} `SELECT * FROM ${table} WHERE id = '${id}'`,
);
async create(table: string, data: any) { return rows[0];
const dataSource = new DataSource(typeOrmConfig); } catch (error) {
await dataSource.initialize(); this.handleDatabaseError(
const queryRunner = dataSource.createQueryRunner(); error,
await queryRunner.connect(); `Erro ao buscar o registro com ID ${id} na tabela ${table}`,
await queryRunner.startTransaction(); );
try { } finally {
const columns = Object.keys(data).map((key) => `${key}`).join(', '); queryRunner.release();
const values = Object.values(data); dataSource.destroy();
const placeholders = values.map(() => '?').join(', '); }
}
const query = `INSERT INTO ${table} (${columns}) VALUES (${placeholders})`;
async create(table: string, data: any) {
const [result] = await queryRunner.query(query, values); const dataSource = new DataSource(typeOrmConfig);
return result; await dataSource.initialize();
} catch (error) { const queryRunner = dataSource.createQueryRunner();
this.handleDatabaseError(error, `Erro ao criar um registro na tabela ${table}`); await queryRunner.connect();
} finally { await queryRunner.startTransaction();
queryRunner.release(); try {
dataSource.destroy(); const columns = Object.keys(data)
} .map((key) => `${key}`)
} .join(', ');
const values = Object.values(data);
async update(table: string, where: any, data: any) { const placeholders = values.map(() => '?').join(', ');
const dataSource = new DataSource(typeOrmConfig);
await dataSource.initialize(); const query = `INSERT INTO ${table} (${columns}) VALUES (${placeholders})`;
const queryRunner = dataSource.createQueryRunner();
await queryRunner.connect(); const [result] = await queryRunner.query(query, values);
await queryRunner.startTransaction(); return result;
try { } catch (error) {
const [result] = await queryRunner.query(`UPDATE ${table} SET ${data} WHERE ${where}`); this.handleDatabaseError(
return result; error,
} catch (error) { `Erro ao criar um registro na tabela ${table}`,
this.handleDatabaseError(error, `Erro ao atualizar o registro com ${where} na tabela ${table}`); );
} finally { } finally {
queryRunner.release(); queryRunner.release();
dataSource.destroy(); dataSource.destroy();
} }
} }
async delete(table: string, where: any) { async update(table: string, where: any, data: any) {
const dataSource = new DataSource(typeOrmConfig); const dataSource = new DataSource(typeOrmConfig);
await dataSource.initialize(); await dataSource.initialize();
const queryRunner = dataSource.createQueryRunner(); const queryRunner = dataSource.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
await queryRunner.startTransaction(); await queryRunner.startTransaction();
try { try {
const [result] = await queryRunner.query(`DELETE FROM ${table} WHERE ${where}`); const [result] = await queryRunner.query(
return result; `UPDATE ${table} SET ${data} WHERE ${where}`,
} catch (error) { );
this.handleDatabaseError(error, `Erro ao deletar o registro com ID ${where} na tabela ${table}`); return result;
} finally { } catch (error) {
queryRunner.release(); this.handleDatabaseError(
dataSource.destroy(); error,
} `Erro ao atualizar o registro com ${where} na tabela ${table}`,
} );
} finally {
async query(queryString: string, params: any[]): Promise<any[]> { queryRunner.release();
const dataSource = new DataSource(typeOrmConfig); dataSource.destroy();
await dataSource.initialize(); }
const queryRunner = dataSource.createQueryRunner(); }
await queryRunner.connect();
await queryRunner.startTransaction(); async delete(table: string, where: any) {
try { const dataSource = new DataSource(typeOrmConfig);
const [rows] = await queryRunner.query(queryString, params); await dataSource.initialize();
return rows as any[]; const queryRunner = dataSource.createQueryRunner();
} catch (error) { await queryRunner.connect();
this.handleDatabaseError(error, `Erro ao executar a consulta SQL personalizada`); await queryRunner.startTransaction();
} finally { try {
queryRunner.release(); const [result] = await queryRunner.query(
dataSource.destroy(); `DELETE FROM ${table} WHERE ${where}`,
} );
} return result;
} catch (error) {
async executeView(viewName: string, params: Record<string, any>) { this.handleDatabaseError(
const dataSource = new DataSource(typeOrmConfig); error,
await dataSource.initialize(); `Erro ao deletar o registro com ID ${where} na tabela ${table}`,
const queryRunner = dataSource.createQueryRunner(); );
await queryRunner.connect(); } finally {
await queryRunner.startTransaction(); queryRunner.release();
try { dataSource.destroy();
// Valida se o nome da view foi fornecido }
if (!viewName) { }
throw new Error('O nome da view é obrigatório.');
} async query(queryString: string, params: any[]): Promise<any[]> {
const dataSource = new DataSource(typeOrmConfig);
console.log(`Iniciando execução da view: ${viewName}`); await dataSource.initialize();
console.log('Parâmetros recebidos:', params); const queryRunner = dataSource.createQueryRunner();
await queryRunner.connect();
const conditions: string[] = []; await queryRunner.startTransaction();
const values: any[] = []; try {
const [rows] = await queryRunner.query(queryString, params);
// Remove o parâmetro viewName dos parâmetros antes de processar return rows as any[];
const filteredParams = { ...params }; } catch (error) {
delete filteredParams.viewName; this.handleDatabaseError(
error,
// Adiciona as condições baseadas nos parâmetros fornecidos `Erro ao executar a consulta SQL personalizada`,
if (filteredParams && Object.keys(filteredParams).length > 0) { );
console.log('Adicionando condições para os parâmetros fornecidos...'); } finally {
for (const [key, value] of Object.entries(filteredParams)) { queryRunner.release();
// Verifica se a chave e o valor são válidos dataSource.destroy();
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); async executeView(viewName: string, params: Record<string, any>) {
} else { const dataSource = new DataSource(typeOrmConfig);
console.warn(`Parâmetro ignorado: ${key} = '${value}'`); await dataSource.initialize();
} const queryRunner = dataSource.createQueryRunner();
} await queryRunner.connect();
} else { await queryRunner.startTransaction();
console.log('Nenhum parâmetro válido foi fornecido.'); try {
} // Valida se o nome da view foi fornecido
if (!viewName) {
// Monta a cláusula WHERE somente se houver condições throw new Error('O nome da view é obrigatório.');
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; }
const query = `SELECT * FROM ${ viewName } ${whereClause}`;
console.log(`Iniciando execução da view: ${viewName}`);
console.log(`Consulta SQL montada: ${ query }`); console.log('Parâmetros recebidos:', params);
console.log(`{Valores para a consulta:, ${values}`);
const conditions: string[] = [];
// Executa a consulta const values: any[] = [];
const rows = await queryRunner.query(query);
// Remove o parâmetro viewName dos parâmetros antes de processar
console.log(`Consulta executada com sucesso.Linhas retornadas: ${ JSON.stringify(rows) }`); const filteredParams = { ...params };
return rows; delete filteredParams.viewName;
} catch (error) {
console.error(`Erro ao executar a view ${ viewName }: `, error.message); // Adiciona as condições baseadas nos parâmetros fornecidos
this.handleDatabaseError( if (filteredParams && Object.keys(filteredParams).length > 0) {
error, console.log('Adicionando condições para os parâmetros fornecidos...');
`Erro ao executar a view ${ viewName } com parâmetros.`, for (const [key, value] of Object.entries(filteredParams)) {
); // Verifica se a chave e o valor são válidos
} finally { if (value !== undefined && value !== null && value !== '') {
await queryRunner.release(); console.log(`Parâmetro válido: ${key} = '${value}'`);
await dataSource.destroy(); conditions.push(`${key} = '${value}'`); // Adiciona aspas para evitar problemas de SQL injection
} values.push(value);
} } else {
console.warn(`Parâmetro ignorado: ${key} = '${value}'`);
async executeProcedure(procedureName: string, params: Record<string, any>) { }
const dataSource = new DataSource(typeOrmConfig); }
await dataSource.initialize(); } else {
const queryRunner = dataSource.createQueryRunner(); console.log('Nenhum parâmetro válido foi fornecido.');
await queryRunner.connect(); }
await queryRunner.startTransaction();
try { // Monta a cláusula WHERE somente se houver condições
const placeholders = Object.keys(params) const whereClause =
.map(() => '?') conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
.join(', '); const query = `SELECT * FROM ${viewName} ${whereClause}`;
const values = Object.values(params);
console.log(`Consulta SQL montada: ${query}`);
const query = `EXECUTE IMMEDIATE ${ procedureName }(${ placeholders })`; console.log(`{Valores para a consulta:, ${values}`);
// Log da query e dos valores // Executa a consulta
console.log('Query executada:', query); const rows = await queryRunner.query(query);
console.log('Valores:', values);
console.log(
const [result] = await queryRunner.query(query, values); `Consulta executada com sucesso.Linhas retornadas: ${JSON.stringify(
rows,
// Verifica e converte campos que contenham JSON strings para objetos )}`,
const parsedResult = Array.isArray(result) );
? result.map((row) => { return rows;
const parsedRow = { ...row }; } catch (error) {
for (const [key, value] of Object.entries(parsedRow)) { console.error(`Erro ao executar a view ${viewName}: `, error.message);
try { this.handleDatabaseError(
// Tenta converter strings JSON para objetos error,
if (typeof value === 'string' && value.trim().startsWith('{') && value.trim().endsWith('}')) { `Erro ao executar a view ${viewName} com parâmetros.`,
parsedRow[key] = JSON.parse(value); );
} } finally {
} catch (error) { await queryRunner.release();
// Ignora se a conversão falhar await dataSource.destroy();
console.warn(`Campo ${ key } não é um JSON válido.Mantendo como string.`); }
} }
}
return parsedRow; async executeProcedure(procedureName: string, params: Record<string, any>) {
}) const dataSource = new DataSource(typeOrmConfig);
: result; await dataSource.initialize();
const queryRunner = dataSource.createQueryRunner();
// Retorna os valores e o resultado await queryRunner.connect();
return { await queryRunner.startTransaction();
message: 'Procedure executada com sucesso.', try {
executedQuery: query, const placeholders = Object.keys(params)
values: values, .map(() => '?')
result: parsedResult, .join(', ');
}; const values = Object.values(params);
} catch (error) {
this.handleDatabaseError( const query = `EXECUTE IMMEDIATE ${procedureName}(${placeholders})`;
error,
`Erro ao executar a procedure ${ procedureName } com parâmetros.`, // Log da query e dos valores
); console.log('Query executada:', query);
} console.log('Valores:', values);
}
const [result] = await queryRunner.query(query, values);
private handleDatabaseError(error: any, message: string): never {
console.error(message, error); // Log detalhado do erro // Verifica e converte campos que contenham JSON strings para objetos
throw new InternalServerErrorException({ const parsedResult = Array.isArray(result)
message, ? result.map((row) => {
sqlMessage: error.sqlMessage || error.message, const parsedRow = { ...row };
sqlState: error.sqlState, for (const [key, value] of Object.entries(parsedRow)) {
}); try {
} // Tenta converter strings JSON para objetos
if (
async sendImages(file: string) { typeof value === 'string' &&
// for (const file of files) { value.trim().startsWith('{') &&
// const file = 'C:\\Temp\\brasil_2.jpg' value.trim().endsWith('}')
if (file.endsWith(".jpg")) { ) {
const fileName = file; //directoryImages + '\\' + file; parsedRow[key] = JSON.parse(value);
fs.readFile(fileName, (err, data) => { }
if (err) throw err; } catch (error) {
if (err) { // Ignora se a conversão falhar
console.log(`WRITE ERROR: ${err}`); console.warn(
} else { `Campo ${key} não é um JSON válido.Mantendo como string.`,
this.uploadS3(data, 'jur-saidaretornoveiculo', file.replace('./uploads/', '')); );
} }
}); }
} return parsedRow;
//} })
} : result;
async uploadS3(file, bucket, name) { // Retorna os valores e o resultado
const s3 = this.getS3(); return {
const params = { message: 'Procedure executada com sucesso.',
Bucket: bucket, executedQuery: query,
Key: String(name), values: values,
Body: file, result: parsedResult,
};
}; } catch (error) {
return new Promise((resolve, reject) => { this.handleDatabaseError(
s3.upload(params, (err, data) => { error,
if (err) { `Erro ao executar a procedure ${procedureName} com parâmetros.`,
console.log(JSON.stringify(err)); );
reject(err.message); }
} }
resolve(data);
}); private handleDatabaseError(error: any, message: string): never {
}); console.error(message, error); // Log detalhado do erro
} throw new InternalServerErrorException({
message,
getS3() { sqlMessage: error.sqlMessage || error.message,
return new S3({ sqlState: error.sqlState,
accessKeyId: "AKIAVHJOO6W765ZT2PNI", //process.env.AWS_ACCESS_KEY_ID, });
secretAccessKey: "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", // process.env.AWS_SECRET_ACCESS_KEY, }
});
} 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: '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', // process.env.AWS_SECRET_ACCESS_KEY,
});
}
}

View File

@@ -6,7 +6,7 @@ https://docs.nestjs.com/providers#services
*/ */
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { typeOrmConfig } from 'src/core/configs/typeorm.config'; import { typeOrmConfig } from '../core/configs/typeorm.config';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@Injectable() @Injectable()

View File

@@ -6,8 +6,8 @@ https://docs.nestjs.com/controllers#controllers
import { Body, Controller, Get, Param, Post } from '@nestjs/common'; import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { LogisticService } from './logistic.service'; import { LogisticService } from './logistic.service';
import { CarOutDelivery } from 'src/core/models/car-out-delivery.model'; import { CarOutDelivery } from '../core/models/car-out-delivery.model';
import { CarInDelivery } from 'src/core/models/car-in-delivery.model'; import { CarInDelivery } from '../core/models/car-in-delivery.model';
@Controller('api/v1/logistic') @Controller('api/v1/logistic')
export class LogisticController { export class LogisticController {

View File

@@ -1,16 +1,8 @@
import { Length } from './../../node_modules/aws-sdk/clients/quicksight.d';
import { count } from './../../node_modules/aws-sdk/clients/health.d';
/* eslint-disable prettier/prettier */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Get, HttpException, HttpStatus, Injectable, Query, UseGuards } from '@nestjs/common'; import { Get, HttpException, HttpStatus, Injectable, Query, UseGuards } from '@nestjs/common';
import { stringify } from 'querystring'; import { typeOrmConfig, typeOrmPgConfig } from '../core/configs/typeorm.config';
import { typeOrmConfig, typeOrmPgConfig } from 'src/core/configs/typeorm.config'; import { CarOutDelivery } from '../core/models/car-out-delivery.model';
import { CarOutDelivery } from 'src/core/models/car-out-delivery.model';
import { BaseService } from 'src/core/services/base.service';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import { CarInDelivery } from 'src/core/models/car-in-delivery.model'; import { CarInDelivery } from '../core/models/car-in-delivery.model';
@Injectable() @Injectable()
export class LogisticService { export class LogisticService {
@@ -205,13 +197,13 @@ export class LogisticService {
const sqlSequence = `SELECT ESS_SAIDAVEICULO.NEXTVAL as "id" FROM DUAL`; const sqlSequence = `SELECT ESS_SAIDAVEICULO.NEXTVAL as "id" FROM DUAL`;
const dataSequence = await queryRunner.query(sqlSequence); const dataSequence = await queryRunner.query(sqlSequence);
let i = 0; let i = 0;
let helperId1: number = 0; let helperId1 = 0;
let helperId2: number = 0; let helperId2 = 0;
let helperId3: number = 0; let helperId3 = 0;
let image1: string = ''; const image1 = '';
let image2: string = ''; const image2 = '';
let image3: string = ''; const image3 = '';
let image4: string = ''; const image4 = '';
data.helpers.forEach(helper => { data.helpers.forEach(helper => {
switch (i) { switch (i) {
@@ -290,11 +282,11 @@ export class LogisticService {
throw new HttpException('Não foi localiza viagens em aberto para este veículo.', HttpStatus.BAD_REQUEST ); throw new HttpException('Não foi localiza viagens em aberto para este veículo.', HttpStatus.BAD_REQUEST );
} }
let i = 0; const i = 0;
let image1: string = ''; const image1 = '';
let image2: string = ''; const image2 = '';
let image3: string = ''; const image3 = '';
let image4: string = ''; const image4 = '';
for (let y = 0; y < data.invoices.length; y++) { for (let y = 0; y < data.invoices.length; y++) {
const invoice = data.invoices[y]; const invoice = data.invoices[y];

View File

@@ -6,7 +6,7 @@ https://docs.nestjs.com/providers#services
*/ */
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { typeOrmConfig } from 'src/core/configs/typeorm.config'; import { typeOrmConfig } from '../core/configs/typeorm.config';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@Injectable() @Injectable()

View File

@@ -5,7 +5,7 @@ https://docs.nestjs.com/providers#services
*/ */
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { typeOrmConfig } from 'src/core/configs/typeorm.config'; import { typeOrmConfig } from '../core/configs/typeorm.config';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@Injectable() @Injectable()

View File

@@ -7,7 +7,7 @@ https://docs.nestjs.com/controllers#controllers
import { Body, Controller, Get, Param, Post } from '@nestjs/common'; import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { ProductsService } from './products.service'; import { ProductsService } from './products.service';
import { ExposedProduct } from 'src/core/models/exposed-product.model'; import { ExposedProduct } from '../core/models/exposed-product.model';
@Controller('api/v1/products') @Controller('api/v1/products')
export class ProductsController { export class ProductsController {

View File

@@ -6,8 +6,8 @@ https://docs.nestjs.com/providers#services
*/ */
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { typeOrmConfig } from 'src/core/configs/typeorm.config'; import { typeOrmConfig } from '../core/configs/typeorm.config';
import { ExposedProduct } from 'src/core/models/exposed-product.model'; import { ExposedProduct } from '../core/models/exposed-product.model';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@Injectable() @Injectable()

View File

@@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common'; import { INestApplication } from '@nestjs/common';
import * as request from 'supertest'; import * as request from 'supertest';
import { AppModule } from './../src/app.module'; import { AppModule } from './../../../app.module';
describe('AppController (e2e)', () => { describe('AppController (e2e)', () => {
let app: INestApplication; let app: INestApplication;