Atualizações em data-consult e products
This commit is contained in:
@@ -83,6 +83,20 @@ export class DataConsultController {
|
|||||||
return this.dataConsultService.customers(filter);
|
return this.dataConsultService.customers(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@Get('products/codauxiliar/:codauxiliar')
|
||||||
|
@ApiOperation({ summary: 'Busca produtos por código auxiliar (EAN)' })
|
||||||
|
@ApiParam({ name: 'codauxiliar', description: 'Código auxiliar (EAN) do produto' })
|
||||||
|
@ApiResponse({
|
||||||
|
status: 200,
|
||||||
|
description: 'Lista de produtos encontrados por código auxiliar',
|
||||||
|
type: [ProductDto],
|
||||||
|
})
|
||||||
|
async productsByCodauxiliar(@Param('codauxiliar') codauxiliar: string): Promise<ProductDto[]> {
|
||||||
|
return this.dataConsultService.productsByCodauxiliar(codauxiliar);
|
||||||
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('products/:filter')
|
@Get('products/:filter')
|
||||||
|
|||||||
@@ -126,6 +126,17 @@ export class DataConsultRepository {
|
|||||||
return results.map((result) => new ProductDto(result));
|
return results.map((result) => new ProductDto(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findProductsByCodauxiliar(codauxiliar: string): Promise<ProductDto[]> {
|
||||||
|
const sql = `
|
||||||
|
SELECT PCPRODUT.CODPROD as "id",
|
||||||
|
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || ' ( ' || PCPRODUT.CODFAB || ' )' as "description"
|
||||||
|
FROM PCPRODUT
|
||||||
|
WHERE REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') = REGEXP_REPLACE(:codauxiliar, '[^0-9]', '')
|
||||||
|
`;
|
||||||
|
const results = await this.dataSource.query(sql, [codauxiliar]);
|
||||||
|
return results.map((result) => new ProductDto(result));
|
||||||
|
}
|
||||||
|
|
||||||
async findAllProducts(): Promise<ProductDto[]> {
|
async findAllProducts(): Promise<ProductDto[]> {
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT PCPRODUT.CODPROD as "id",
|
SELECT PCPRODUT.CODPROD as "id",
|
||||||
|
|||||||
@@ -227,6 +227,23 @@ export class DataConsultService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async productsByCodauxiliar(codauxiliar: string): Promise<ProductDto[]> {
|
||||||
|
this.logger.log(`Buscando produtos por codauxiliar: ${codauxiliar}`);
|
||||||
|
try {
|
||||||
|
if (!codauxiliar || typeof codauxiliar !== 'string') {
|
||||||
|
throw new HttpException('Código auxiliar inválido', HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
const products = await this.repository.findProductsByCodauxiliar(codauxiliar);
|
||||||
|
return products.map((product) => new ProductDto(product));
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('Erro ao buscar produtos por codauxiliar', error);
|
||||||
|
throw new HttpException(
|
||||||
|
'Erro ao buscar produtos por codauxiliar',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getAllProducts(): Promise<ProductDto[]> {
|
async getAllProducts(): Promise<ProductDto[]> {
|
||||||
this.logger.log('Buscando todos os produtos');
|
this.logger.log('Buscando todos os produtos');
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -14,13 +14,22 @@ export class ProductDetailQueryDto {
|
|||||||
numregiao: number;
|
numregiao: number;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Array de códigos de produtos',
|
description: 'Array de códigos de produtos (opcional se codauxiliar for informado)',
|
||||||
example: [1, 2, 3],
|
example: [1, 2, 3],
|
||||||
type: [Number],
|
type: [Number],
|
||||||
|
required: false,
|
||||||
})
|
})
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsNotEmpty()
|
codprod?: number[];
|
||||||
codprod: number[];
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Array de códigos auxiliares (opcional se codprod for informado)',
|
||||||
|
example: ['7891234567890', '7891234567891'],
|
||||||
|
type: [String],
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsArray()
|
||||||
|
codauxiliar?: string[];
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Código da filial',
|
description: 'Código da filial',
|
||||||
|
|||||||
@@ -14,12 +14,20 @@ export class RotinaA4QueryDto {
|
|||||||
numregiao: number;
|
numregiao: number;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Código do produto',
|
description: 'Código do produto (opcional se codauxiliar for informado)',
|
||||||
example: 12345,
|
example: 12345,
|
||||||
|
required: false,
|
||||||
})
|
})
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
@IsNotEmpty()
|
codprod?: number;
|
||||||
codprod: number;
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Código auxiliar do produto (opcional se codprod for informado)',
|
||||||
|
example: '7891234567890',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
codauxiliar?: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Código da filial',
|
description: 'Código da filial',
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ export class RotinaA4ResponseDto {
|
|||||||
})
|
})
|
||||||
CODPROD: number;
|
CODPROD: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Código auxiliar do produto',
|
||||||
|
example: '7891234567890',
|
||||||
|
})
|
||||||
|
CODAUXILIAR: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Preço normal do produto formatado como moeda brasileira (com decimais)',
|
description: 'Preço normal do produto formatado como moeda brasileira (com decimais)',
|
||||||
example: '1.109,90',
|
example: '1.109,90',
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable prettier/prettier */
|
/* eslint-disable prettier/prettier */
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
|
||||||
import { Body, Controller, Get, Param, Post,UseGuards } from '@nestjs/common';
|
import { Body, Controller, Get, Param, Post, Query, UseGuards } 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 'src/core/models/exposed-product.model';
|
||||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
||||||
import { ExposedProductDto } from './dto/exposed-product.dto';
|
import { ExposedProductDto } from './dto/exposed-product.dto';
|
||||||
import { ProductValidationDto } from './dto/ProductValidationDto';
|
import { ProductValidationDto } from './dto/ProductValidationDto';
|
||||||
import { ProductEcommerceDto } from './dto/product-ecommerce.dto';
|
import { ProductEcommerceDto } from './dto/product-ecommerce.dto';
|
||||||
import { ApiTags, ApiOperation, ApiParam, ApiBody, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiOperation, ApiParam, ApiQuery, ApiBody, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { ProductDetailQueryDto } from './dto/product-detail-query.dto';
|
import { ProductDetailQueryDto } from './dto/product-detail-query.dto';
|
||||||
import { ProductDetailResponseDto } from './dto/product-detail-response.dto';
|
import { ProductDetailResponseDto } from './dto/product-detail-response.dto';
|
||||||
import { RotinaA4QueryDto } from './dto/rotina-a4-query.dto';
|
import { RotinaA4QueryDto } from './dto/rotina-a4-query.dto';
|
||||||
@@ -37,6 +37,7 @@ export class ProductsController {
|
|||||||
@ApiOperation({ summary: 'Valida produto pelo filtro (código, EAN ou descrição)' })
|
@ApiOperation({ summary: 'Valida produto pelo filtro (código, EAN ou descrição)' })
|
||||||
@ApiParam({ name: 'storeId', type: String, description: 'ID da loja' })
|
@ApiParam({ name: 'storeId', type: String, description: 'ID da loja' })
|
||||||
@ApiParam({ name: 'filtro', type: String, description: 'Filtro de busca (código, EAN ou descrição)' })
|
@ApiParam({ name: 'filtro', type: String, description: 'Filtro de busca (código, EAN ou descrição)' })
|
||||||
|
@ApiQuery({ name: 'tipoBusca', required: false, enum: ['codauxiliar', 'codprod', 'descricao', 'todos'], description: 'Tipo de busca específica (opcional). Padrão: busca em todos os campos' })
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Produto encontrado com sucesso.',
|
description: 'Produto encontrado com sucesso.',
|
||||||
@@ -46,8 +47,9 @@ export class ProductsController {
|
|||||||
async productValidation(
|
async productValidation(
|
||||||
@Param('storeId') storeId: string,
|
@Param('storeId') storeId: string,
|
||||||
@Param('filtro') filtro: string,
|
@Param('filtro') filtro: string,
|
||||||
|
@Query('tipoBusca') tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||||
): Promise<ProductValidationDto> {
|
): Promise<ProductValidationDto> {
|
||||||
return this.productsService.productsValidation(storeId, filtro);
|
return this.productsService.productsValidation(storeId, filtro, tipoBusca);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,48 +15,83 @@ export class ProductsService {
|
|||||||
@InjectDataSource('oracle') private readonly dataSource: DataSource,
|
@InjectDataSource('oracle') private readonly dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
private buildProductsValidationWhereCondition(
|
||||||
* Valida e busca informações de um produto por código ou descrição
|
tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||||
* @param storeId - Código da filial
|
): { whereCondition: string; useSingleParam: boolean } {
|
||||||
* @param filtro - Filtro de busca (código auxiliar, código produto ou descrição)
|
if (tipoBusca === 'codauxiliar') {
|
||||||
* @returns Dados do produto encontrado com estoque e preço
|
return {
|
||||||
* @throws HttpException quando produto não é encontrado
|
whereCondition: 'PCPRODUT.CODAUXILIAR = REGEXP_REPLACE(:filtro, \'[^0-9]\', \'\')',
|
||||||
*/
|
useSingleParam: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tipoBusca === 'codprod') {
|
||||||
|
return {
|
||||||
|
whereCondition: 'PCPRODUT.CODPROD = REGEXP_REPLACE(:filtro, \'[^0-9]\', \'\')',
|
||||||
|
useSingleParam: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tipoBusca === 'descricao') {
|
||||||
|
return {
|
||||||
|
whereCondition: 'PCPRODUT.DESCRICAO LIKE \'%\' || :filtro || \'%\'',
|
||||||
|
useSingleParam: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
whereCondition: `(
|
||||||
|
PCPRODUT.CODAUXILIAR = REGEXP_REPLACE(:filtro1, '[^0-9]', '')
|
||||||
|
OR PCPRODUT.CODPROD = REGEXP_REPLACE(:filtro2, '[^0-9]', '')
|
||||||
|
OR PCPRODUT.DESCRICAO LIKE '%' || :filtro3 || '%'
|
||||||
|
)`,
|
||||||
|
useSingleParam: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async productsValidation(
|
async productsValidation(
|
||||||
storeId: string,
|
storeId: string,
|
||||||
filtro: string,
|
filtro: string,
|
||||||
|
tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||||
): Promise<ProductValidationDto> {
|
): Promise<ProductValidationDto> {
|
||||||
const sql = `SELECT PCPRODUT.DESCRICAO as "descricao"
|
const { whereCondition, useSingleParam } =
|
||||||
,PCPRODUT.CODPROD as "codigoProduto"
|
this.buildProductsValidationWhereCondition(tipoBusca);
|
||||||
,PCPRODUT.CODAUXILIAR as "codigoAuxiliar"
|
|
||||||
,PCMARCA.MARCA as "marca"
|
const sql = `
|
||||||
,REPLACE(NVL(URLIMAGEM, 'http://10.1.1.191/si.png'), 'http://167.249.211.178:8001/', 'http://10.1.1.191/') as "images"
|
SELECT
|
||||||
,CASE WHEN PCPRODUT.TIPOPRODUTO = 'A' THEN 'AUTOSSERVICO'
|
PCPRODUT.DESCRICAO as "descricao",
|
||||||
|
PCPRODUT.CODPROD as "codigoProduto",
|
||||||
|
PCPRODUT.CODAUXILIAR as "codigoAuxiliar",
|
||||||
|
PCMARCA.MARCA as "marca",
|
||||||
|
REPLACE(NVL(URLIMAGEM, 'http://10.1.1.191/si.png'), 'http://167.249.211.178:8001/', 'http://10.1.1.191/') as "images",
|
||||||
|
CASE
|
||||||
|
WHEN PCPRODUT.TIPOPRODUTO = 'A' THEN 'AUTOSSERVICO'
|
||||||
WHEN PCPRODUT.TIPOPRODUTO = 'S' THEN 'SHOWROOM'
|
WHEN PCPRODUT.TIPOPRODUTO = 'S' THEN 'SHOWROOM'
|
||||||
WHEN PCPRODUT.TIPOPRODUTO = 'E' THEN 'ELETROMOVEIS'
|
WHEN PCPRODUT.TIPOPRODUTO = 'E' THEN 'ELETROMOVEIS'
|
||||||
ELSE 'OUTROS' END as "tipoProduto"
|
ELSE 'OUTROS'
|
||||||
,PCTABPR.PVENDA1 as "precoVenda"
|
END as "tipoProduto",
|
||||||
,( PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA ) as "qtdeEstoqueLoja"
|
PCTABPR.PVENDA1 as "precoVenda",
|
||||||
,( SELECT ( ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA )
|
(PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA) as "qtdeEstoqueLoja",
|
||||||
|
(
|
||||||
|
SELECT (ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA)
|
||||||
FROM PCEST ESTOQUE_CD
|
FROM PCEST ESTOQUE_CD
|
||||||
WHERE ESTOQUE_CD.CODPROD = PCPRODUT.CODPROD
|
WHERE ESTOQUE_CD.CODPROD = PCPRODUT.CODPROD
|
||||||
AND ESTOQUE_CD.CODFILIAL = 6 ) as "qtdeEstoqueCD"
|
AND ESTOQUE_CD.CODFILIAL = 6
|
||||||
|
) as "qtdeEstoqueCD"
|
||||||
FROM PCPRODUT, PCEST, PCTABPR, PCMARCA
|
FROM PCPRODUT, PCEST, PCTABPR, PCMARCA
|
||||||
WHERE PCPRODUT.CODPROD = PCEST.CODPROD
|
WHERE PCPRODUT.CODPROD = PCEST.CODPROD
|
||||||
AND PCPRODUT.CODPROD = PCTABPR.CODPROD
|
AND PCPRODUT.CODPROD = PCTABPR.CODPROD
|
||||||
AND PCPRODUT.CODMARCA = PCMARCA.CODMARCA
|
AND PCPRODUT.CODMARCA = PCMARCA.CODMARCA
|
||||||
AND PCTABPR.NUMREGIAO = 1
|
AND PCTABPR.NUMREGIAO = 1
|
||||||
AND PCEST.CODFILIAL = :storeId
|
AND PCEST.CODFILIAL = :storeId
|
||||||
AND ( PCPRODUT.CODAUXILIAR = REGEXP_REPLACE(:filtro1, '[^0-9]', '') OR
|
AND ${whereCondition}
|
||||||
PCPRODUT.CODPROD = REGEXP_REPLACE(:filtro2, '[^0-9]', '') OR
|
`;
|
||||||
PCPRODUT.DESCRICAO LIKE '%'||:filtro3||'%' )`;
|
|
||||||
|
|
||||||
const products = await this.dataSource.query(sql, [
|
const params = useSingleParam
|
||||||
storeId,
|
? [storeId, filtro]
|
||||||
filtro,
|
: [storeId, filtro, filtro, filtro];
|
||||||
filtro,
|
|
||||||
filtro,
|
const products = await this.dataSource.query(sql, params);
|
||||||
]);
|
|
||||||
|
|
||||||
if (products.length === 0) {
|
if (products.length === 0) {
|
||||||
throw new HttpException('Produto não localizado!', HttpStatus.NOT_FOUND);
|
throw new HttpException('Produto não localizado!', HttpStatus.NOT_FOUND);
|
||||||
@@ -66,21 +101,16 @@ export class ProductsService {
|
|||||||
|
|
||||||
if (!product.images) {
|
if (!product.images) {
|
||||||
product.images = [];
|
product.images = [];
|
||||||
} else {
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
product.images = product.images.includes(';')
|
product.images = product.images.includes(';')
|
||||||
? product.images.split(';')
|
? product.images.split(';')
|
||||||
: [product.images];
|
: [product.images];
|
||||||
}
|
|
||||||
|
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Registra produto exposto em showroom
|
|
||||||
* @param product - Dados do produto exposto (storeId, ean, userId)
|
|
||||||
* @returns Mensagem de sucesso
|
|
||||||
* @throws Lança exceção em caso de erro na transação
|
|
||||||
*/
|
|
||||||
async exposedProduct(product: ExposedProduct) {
|
async exposedProduct(product: ExposedProduct) {
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
await queryRunner.connect();
|
await queryRunner.connect();
|
||||||
@@ -104,28 +134,22 @@ export class ProductsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Busca produtos disponíveis para e-commerce
|
|
||||||
* @returns Lista de produtos com preços para e-commerce
|
|
||||||
*/
|
|
||||||
async getProductsEcommerce(): Promise<ProductEcommerceDto[]> {
|
async getProductsEcommerce(): Promise<ProductEcommerceDto[]> {
|
||||||
const sql = `SELECT P.CODPROD as "productIdErp"
|
const sql = `
|
||||||
,P.VTEXSKUID as "productId"
|
SELECT
|
||||||
,ROUND(P.PVENDA,2) as "price"
|
P.CODPROD as "productIdErp",
|
||||||
,ROUND(P.PRECOKIT,2) as "priceKit"
|
P.VTEXSKUID as "productId",
|
||||||
|
ROUND(P.PVENDA, 2) as "price",
|
||||||
|
ROUND(P.PRECOKIT, 2) as "priceKit"
|
||||||
FROM ESVPRODUTOSECOMMERCE P
|
FROM ESVPRODUTOSECOMMERCE P
|
||||||
WHERE P.VTEXSKUID > 0
|
WHERE P.VTEXSKUID > 0
|
||||||
AND P.CODPROD IN (52057, 33702, 46410, 24518, 25816)`;
|
AND P.CODPROD IN (52057, 33702, 46410, 24518, 25816)
|
||||||
|
`;
|
||||||
|
|
||||||
const products = await this.dataSource.query(sql);
|
const products = await this.dataSource.query(sql);
|
||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formata um valor numérico para o padrão de moeda brasileira
|
|
||||||
* @param valor - Valor numérico a ser formatado
|
|
||||||
* @returns String formatada no padrão brasileiro (ex: 1.109,90)
|
|
||||||
*/
|
|
||||||
private formatarMoedaBrasileira(valor: number): string {
|
private formatarMoedaBrasileira(valor: number): string {
|
||||||
if (valor === null || valor === undefined) {
|
if (valor === null || valor === undefined) {
|
||||||
return '0,00';
|
return '0,00';
|
||||||
@@ -136,19 +160,115 @@ export class ProductsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private buildProductDetailsWhereCondition(
|
||||||
* Busca detalhes de produtos com preço integrado com região
|
codprod: number[] | undefined,
|
||||||
* @param query - Parâmetros de busca (codprod, numregiao, codfilial)
|
codauxiliar: string[] | undefined,
|
||||||
* @returns Lista de produtos com detalhes
|
startParamIndex: number,
|
||||||
*/
|
): { whereCondition: string; params: any[]; nextParamIndex: number } {
|
||||||
|
const hasCodprod = codprod?.length > 0;
|
||||||
|
const hasCodauxiliar = codauxiliar?.length > 0;
|
||||||
|
|
||||||
|
if (hasCodprod && hasCodauxiliar) {
|
||||||
|
return this.buildWhereConditionWithBoth(codprod, codauxiliar, startParamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCodprod) {
|
||||||
|
return this.buildWhereConditionWithCodprod(codprod, startParamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCodauxiliar) {
|
||||||
|
return this.buildWhereConditionWithCodauxiliar(codauxiliar, startParamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { whereCondition: '', params: [], nextParamIndex: startParamIndex };
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildWhereConditionWithBoth(
|
||||||
|
codprod: number[],
|
||||||
|
codauxiliar: string[],
|
||||||
|
startParamIndex: number,
|
||||||
|
): { whereCondition: string; params: any[]; nextParamIndex: number } {
|
||||||
|
let paramIndex = startParamIndex;
|
||||||
|
const codprodPlaceholders: string[] = [];
|
||||||
|
const codauxiliarPlaceholders: string[] = [];
|
||||||
|
const params: any[] = [];
|
||||||
|
|
||||||
|
codprod.forEach(() => {
|
||||||
|
codprodPlaceholders.push(`:${paramIndex}`);
|
||||||
|
paramIndex++;
|
||||||
|
});
|
||||||
|
|
||||||
|
codauxiliar.forEach(() => {
|
||||||
|
codauxiliarPlaceholders.push(`:${paramIndex}`);
|
||||||
|
paramIndex++;
|
||||||
|
});
|
||||||
|
|
||||||
|
const whereCondition = `(PCPRODUT.CODPROD IN (${codprodPlaceholders.join(',')}) OR REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') IN (${codauxiliarPlaceholders.join(',')}))`;
|
||||||
|
|
||||||
|
params.push(...codprod);
|
||||||
|
codauxiliar.forEach((aux) => {
|
||||||
|
params.push(aux.replace(/\D/g, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
return { whereCondition, params, nextParamIndex: paramIndex };
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildWhereConditionWithCodprod(
|
||||||
|
codprod: number[],
|
||||||
|
startParamIndex: number,
|
||||||
|
): { whereCondition: string; params: any[]; nextParamIndex: number } {
|
||||||
|
let paramIndex = startParamIndex;
|
||||||
|
const placeholders: string[] = [];
|
||||||
|
|
||||||
|
codprod.forEach(() => {
|
||||||
|
placeholders.push(`:${paramIndex}`);
|
||||||
|
paramIndex++;
|
||||||
|
});
|
||||||
|
|
||||||
|
const whereCondition = `PCPRODUT.CODPROD IN (${placeholders.join(',')})`;
|
||||||
|
const params = [...codprod];
|
||||||
|
|
||||||
|
return { whereCondition, params, nextParamIndex: paramIndex };
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildWhereConditionWithCodauxiliar(
|
||||||
|
codauxiliar: string[],
|
||||||
|
startParamIndex: number,
|
||||||
|
): { whereCondition: string; params: any[]; nextParamIndex: number } {
|
||||||
|
let paramIndex = startParamIndex;
|
||||||
|
const placeholders: string[] = [];
|
||||||
|
const params: any[] = [];
|
||||||
|
|
||||||
|
codauxiliar.forEach(() => {
|
||||||
|
placeholders.push(`:${paramIndex}`);
|
||||||
|
paramIndex++;
|
||||||
|
});
|
||||||
|
|
||||||
|
const whereCondition = `REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') IN (${placeholders.join(',')})`;
|
||||||
|
codauxiliar.forEach((aux) => {
|
||||||
|
params.push(aux.replace(/\D/g, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
return { whereCondition, params, nextParamIndex: paramIndex };
|
||||||
|
}
|
||||||
|
|
||||||
async getProductDetails(
|
async getProductDetails(
|
||||||
query: ProductDetailQueryDto,
|
query: ProductDetailQueryDto,
|
||||||
): Promise<ProductDetailResponseDto[]> {
|
): Promise<ProductDetailResponseDto[]> {
|
||||||
const { numregiao, codprod, codfilial } = query;
|
const { numregiao, codprod, codauxiliar, codfilial } = query;
|
||||||
|
|
||||||
const placeholders = codprod
|
if (!codprod?.length && !codauxiliar?.length) {
|
||||||
.map((_, index) => `:codprod${index}`)
|
throw new HttpException(
|
||||||
.join(',');
|
'É necessário informar codprod ou codauxiliar.',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseParams: any[] = [numregiao, codfilial, numregiao];
|
||||||
|
const { whereCondition, params: whereParams } =
|
||||||
|
this.buildProductDetailsWhereCondition(codprod, codauxiliar, 4);
|
||||||
|
|
||||||
|
const params = [...baseParams, ...whereParams];
|
||||||
|
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT
|
SELECT
|
||||||
@@ -157,22 +277,27 @@ export class ProductsService {
|
|||||||
PCPRODUT.EMBALAGEM AS "embalagem",
|
PCPRODUT.EMBALAGEM AS "embalagem",
|
||||||
PCPRODUT.CODAUXILIAR AS "codauxiliar",
|
PCPRODUT.CODAUXILIAR AS "codauxiliar",
|
||||||
PCMARCA.MARCA AS "marca",
|
PCMARCA.MARCA AS "marca",
|
||||||
(SELECT PCTABPR.PVENDA1
|
(
|
||||||
|
SELECT PCTABPR.PVENDA1
|
||||||
FROM PCTABPR
|
FROM PCTABPR
|
||||||
WHERE PCTABPR.CODPROD = PCPRODUT.CODPROD
|
WHERE PCTABPR.CODPROD = PCPRODUT.CODPROD
|
||||||
AND PCTABPR.NUMREGIAO = :numregiao1) AS "preco",
|
AND PCTABPR.NUMREGIAO = :1
|
||||||
(SELECT TRIM(REPLACE(RAZAOSOCIAL, 'LTDA', ''))
|
) AS "preco",
|
||||||
|
(
|
||||||
|
SELECT TRIM(REPLACE(RAZAOSOCIAL, 'LTDA', ''))
|
||||||
FROM PCFILIAL F
|
FROM PCFILIAL F
|
||||||
WHERE CODIGO = :codfilial) AS "filial",
|
WHERE CODIGO = :2
|
||||||
(SELECT REGIAO
|
) AS "filial",
|
||||||
|
(
|
||||||
|
SELECT REGIAO
|
||||||
FROM PCREGIAO
|
FROM PCREGIAO
|
||||||
WHERE NUMREGIAO = :numregiao2) AS "regiao"
|
WHERE NUMREGIAO = :3
|
||||||
|
) AS "regiao"
|
||||||
FROM PCPRODUT
|
FROM PCPRODUT
|
||||||
LEFT JOIN PCMARCA ON PCPRODUT.CODMARCA = PCMARCA.CODMARCA
|
LEFT JOIN PCMARCA ON PCPRODUT.CODMARCA = PCMARCA.CODMARCA
|
||||||
WHERE PCPRODUT.CODPROD IN (${placeholders})
|
WHERE ${whereCondition}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const params = [numregiao, codfilial, numregiao, ...codprod];
|
|
||||||
const products = await this.dataSource.query(sql, params);
|
const products = await this.dataSource.query(sql, params);
|
||||||
|
|
||||||
return products.map((product) => ({
|
return products.map((product) => ({
|
||||||
@@ -181,67 +306,129 @@ export class ProductsService {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private buildRotinaA4WhereCondition(
|
||||||
* Busca informações do produto conforme rotina A4
|
codprod: number | undefined,
|
||||||
* @param query - Parâmetros de busca (numregiao, codprod, codfilial)
|
codauxiliar: string | undefined,
|
||||||
* @returns Dados do produto conforme rotina A4
|
): { whereCondition: string; params: any[] } {
|
||||||
*/
|
const hasCodprod = !!codprod;
|
||||||
|
const hasCodauxiliar = !!codauxiliar;
|
||||||
|
|
||||||
|
if (hasCodprod && hasCodauxiliar) {
|
||||||
|
return {
|
||||||
|
whereCondition:
|
||||||
|
'and (pcprodut.codprod = :3 OR REGEXP_REPLACE(pcprodut.CODAUXILIAR, \'[^0-9]\', \'\') = REGEXP_REPLACE(:4, \'[^0-9]\', \'\'))',
|
||||||
|
params: [codprod, codauxiliar],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCodprod) {
|
||||||
|
return {
|
||||||
|
whereCondition: 'and pcprodut.codprod = :3',
|
||||||
|
params: [codprod],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCodauxiliar) {
|
||||||
|
return {
|
||||||
|
whereCondition:
|
||||||
|
'and REGEXP_REPLACE(pcprodut.CODAUXILIAR, \'[^0-9]\', \'\') = REGEXP_REPLACE(:3, \'[^0-9]\', \'\')',
|
||||||
|
params: [codauxiliar],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { whereCondition: '', params: [] };
|
||||||
|
}
|
||||||
|
|
||||||
async getRotinaA4(query: RotinaA4QueryDto): Promise<RotinaA4ResponseDto> {
|
async getRotinaA4(query: RotinaA4QueryDto): Promise<RotinaA4ResponseDto> {
|
||||||
const { numregiao, codprod, codfilial } = query;
|
const { numregiao, codprod, codauxiliar, codfilial } = query;
|
||||||
|
|
||||||
|
if (!codprod && !codauxiliar) {
|
||||||
|
throw new HttpException(
|
||||||
|
'É necessário informar codprod ou codauxiliar.',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseParams: any[] = [numregiao, codfilial];
|
||||||
|
const { whereCondition, params: whereParams } =
|
||||||
|
this.buildRotinaA4WhereCondition(codprod, codauxiliar);
|
||||||
|
|
||||||
|
const params = [...baseParams, ...whereParams];
|
||||||
|
|
||||||
const sql = `
|
const sql = `
|
||||||
SELECT
|
SELECT
|
||||||
DADOS.DESCRICAO,
|
DADOS.DESCRICAO,
|
||||||
DADOS.CODPROD,
|
DADOS.CODPROD,
|
||||||
|
DADOS.CODAUXILIAR,
|
||||||
DADOS.PRECO_NORMAL,
|
DADOS.PRECO_NORMAL,
|
||||||
DADOS.UNIDADE,
|
DADOS.UNIDADE,
|
||||||
TRUNC(DADOS.VALOR_VENDA, 0) VALOR_VENDA,
|
TRUNC(DADOS.VALOR_VENDA, 0) VALOR_VENDA,
|
||||||
REPLACE(REPLACE(TO_CHAR( (DADOS.VALOR_VENDA - TRUNC(DADOS.VALOR_VENDA,0)) ,'FM999G9D00'),',',''),'.','') DECIMAL_VENDA,
|
REPLACE(
|
||||||
|
REPLACE(
|
||||||
|
TO_CHAR((DADOS.VALOR_VENDA - TRUNC(DADOS.VALOR_VENDA, 0)), 'FM999G9D00'),
|
||||||
|
',',
|
||||||
|
''
|
||||||
|
),
|
||||||
|
'.',
|
||||||
|
''
|
||||||
|
) DECIMAL_VENDA,
|
||||||
DADOS.MARCA
|
DADOS.MARCA
|
||||||
FROM
|
FROM (
|
||||||
(SELECT
|
SELECT
|
||||||
pcprodut.DESCRICAO,
|
pcprodut.DESCRICAO,
|
||||||
pcprodut.embalagem as unidade,
|
pcprodut.embalagem as unidade,
|
||||||
pctabpr.PVENDA PRECO_NORMAL,
|
pctabpr.PVENDA PRECO_NORMAL,
|
||||||
pcprodut.CODPROD,
|
pcprodut.CODPROD,
|
||||||
|
pcprodut.CODAUXILIAR,
|
||||||
TRUNC(pctabpr.PVENDA1, 2) PVENDA1,
|
TRUNC(pctabpr.PVENDA1, 2) PVENDA1,
|
||||||
(CASE WHEN
|
(
|
||||||
NVL(TRUNC((SELECT P.PRECOFIXO
|
CASE
|
||||||
|
WHEN NVL(
|
||||||
|
TRUNC(
|
||||||
|
(
|
||||||
|
SELECT P.PRECOFIXO
|
||||||
FROM PCPRECOPROM P
|
FROM PCPRECOPROM P
|
||||||
WHERE P.CODPROD = PCTABPR.CODPROD
|
WHERE P.CODPROD = PCTABPR.CODPROD
|
||||||
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
||||||
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
||||||
AND ROWNUM = 1
|
AND ROWNUM = 1
|
||||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO),1) ,0) = 0
|
AND P.NUMREGIAO = PCTABPR.NUMREGIAO
|
||||||
THEN PCTABPR.PVENDA1
|
),
|
||||||
ELSE
|
1
|
||||||
TRUNC((SELECT P.PRECOFIXO
|
),
|
||||||
|
0
|
||||||
|
) = 0 THEN PCTABPR.PVENDA1
|
||||||
|
ELSE TRUNC(
|
||||||
|
(
|
||||||
|
SELECT P.PRECOFIXO
|
||||||
FROM PCPRECOPROM P
|
FROM PCPRECOPROM P
|
||||||
WHERE P.CODPROD = PCTABPR.CODPROD
|
WHERE P.CODPROD = PCTABPR.CODPROD
|
||||||
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
||||||
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
||||||
AND ROWNUM = 1
|
AND ROWNUM = 1
|
||||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO),2) END ) VALOR_VENDA,
|
AND P.NUMREGIAO = PCTABPR.NUMREGIAO
|
||||||
(select marca from pcmarca where pcmarca.codmarca = pcprodut.codmarca)marca
|
),
|
||||||
FROM
|
2
|
||||||
pctabpr,
|
)
|
||||||
pcprodut,
|
END
|
||||||
pcest
|
) VALOR_VENDA,
|
||||||
WHERE
|
(
|
||||||
pctabpr.CODPROD = pcprodut.CODPROD
|
SELECT marca
|
||||||
and pcest.codprod = pctabpr.CODPROD
|
FROM pcmarca
|
||||||
AND pctabpr.NUMREGIAO = :numregiao
|
WHERE pcmarca.codmarca = pcprodut.codmarca
|
||||||
and pcprodut.DTEXCLUSAO is null
|
) marca
|
||||||
and pcprodut.codprod = :codprod
|
FROM pctabpr, pcprodut, pcest
|
||||||
AND pcest.codfilial = :codfilial
|
WHERE pctabpr.CODPROD = pcprodut.CODPROD
|
||||||
and pctabpr.PVENDA is not null ) DADOS
|
AND pcest.codprod = pctabpr.CODPROD
|
||||||
|
AND pctabpr.NUMREGIAO = :1
|
||||||
|
AND pcprodut.DTEXCLUSAO is null
|
||||||
|
AND pcest.codfilial = :2
|
||||||
|
AND pctabpr.PVENDA is not null
|
||||||
|
${whereCondition}
|
||||||
|
) DADOS
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = await this.dataSource.query(sql, [
|
const result = await this.dataSource.query(sql, params);
|
||||||
numregiao,
|
|
||||||
codprod,
|
|
||||||
codfilial,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (result.length === 0) {
|
if (result.length === 0) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@@ -252,10 +439,6 @@ export class ProductsService {
|
|||||||
|
|
||||||
const produto = result[0];
|
const produto = result[0];
|
||||||
|
|
||||||
/**
|
|
||||||
* Formata o preço normal como moeda brasileira com decimais
|
|
||||||
* Exemplo: 1109.9 -> "1.109,90"
|
|
||||||
*/
|
|
||||||
if (produto.PRECO_NORMAL !== null && produto.PRECO_NORMAL !== undefined) {
|
if (produto.PRECO_NORMAL !== null && produto.PRECO_NORMAL !== undefined) {
|
||||||
produto.PRECO_NORMAL = produto.PRECO_NORMAL.toLocaleString('pt-BR', {
|
produto.PRECO_NORMAL = produto.PRECO_NORMAL.toLocaleString('pt-BR', {
|
||||||
minimumFractionDigits: 2,
|
minimumFractionDigits: 2,
|
||||||
@@ -263,10 +446,6 @@ export class ProductsService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formata o valor de venda como moeda brasileira sem decimais
|
|
||||||
* Exemplo: 2499 -> "R$ 2.499"
|
|
||||||
*/
|
|
||||||
if (produto.VALOR_VENDA !== null && produto.VALOR_VENDA !== undefined) {
|
if (produto.VALOR_VENDA !== null && produto.VALOR_VENDA !== undefined) {
|
||||||
produto.VALOR_VENDA = `R$ ${produto.VALOR_VENDA.toLocaleString('pt-BR', {
|
produto.VALOR_VENDA = `R$ ${produto.VALOR_VENDA.toLocaleString('pt-BR', {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user