Atualizações em data-consult e products
This commit is contained in:
@@ -83,6 +83,20 @@ export class DataConsultController {
|
||||
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)
|
||||
@ApiBearerAuth()
|
||||
@Get('products/:filter')
|
||||
|
||||
@@ -126,6 +126,17 @@ export class DataConsultRepository {
|
||||
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[]> {
|
||||
const sql = `
|
||||
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[]> {
|
||||
this.logger.log('Buscando todos os produtos');
|
||||
try {
|
||||
|
||||
@@ -14,13 +14,22 @@ export class ProductDetailQueryDto {
|
||||
numregiao: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Array de códigos de produtos',
|
||||
description: 'Array de códigos de produtos (opcional se codauxiliar for informado)',
|
||||
example: [1, 2, 3],
|
||||
type: [Number],
|
||||
required: false,
|
||||
})
|
||||
@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({
|
||||
description: 'Código da filial',
|
||||
|
||||
@@ -14,12 +14,20 @@ export class RotinaA4QueryDto {
|
||||
numregiao: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Código do produto',
|
||||
description: 'Código do produto (opcional se codauxiliar for informado)',
|
||||
example: 12345,
|
||||
required: false,
|
||||
})
|
||||
@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({
|
||||
description: 'Código da filial',
|
||||
|
||||
@@ -16,6 +16,12 @@ export class RotinaA4ResponseDto {
|
||||
})
|
||||
CODPROD: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Código auxiliar do produto',
|
||||
example: '7891234567890',
|
||||
})
|
||||
CODAUXILIAR: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Preço normal do produto formatado como moeda brasileira (com decimais)',
|
||||
example: '1.109,90',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
/* 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 { ExposedProduct } from 'src/core/models/exposed-product.model';
|
||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
||||
import { ExposedProductDto } from './dto/exposed-product.dto';
|
||||
import { ProductValidationDto } from './dto/ProductValidationDto';
|
||||
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 { ProductDetailResponseDto } from './dto/product-detail-response.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)' })
|
||||
@ApiParam({ name: 'storeId', type: String, description: 'ID da loja' })
|
||||
@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({
|
||||
status: 200,
|
||||
description: 'Produto encontrado com sucesso.',
|
||||
@@ -46,8 +47,9 @@ export class ProductsController {
|
||||
async productValidation(
|
||||
@Param('storeId') storeId: string,
|
||||
@Param('filtro') filtro: string,
|
||||
@Query('tipoBusca') tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||
): 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,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Valida e busca informações de um produto por código ou descrição
|
||||
* @param storeId - Código da filial
|
||||
* @param filtro - Filtro de busca (código auxiliar, código produto ou descrição)
|
||||
* @returns Dados do produto encontrado com estoque e preço
|
||||
* @throws HttpException quando produto não é encontrado
|
||||
*/
|
||||
private buildProductsValidationWhereCondition(
|
||||
tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||
): { whereCondition: string; useSingleParam: boolean } {
|
||||
if (tipoBusca === 'codauxiliar') {
|
||||
return {
|
||||
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(
|
||||
storeId: string,
|
||||
filtro: string,
|
||||
tipoBusca?: 'codauxiliar' | 'codprod' | 'descricao' | 'todos',
|
||||
): Promise<ProductValidationDto> {
|
||||
const sql = `SELECT 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'
|
||||
const { whereCondition, useSingleParam } =
|
||||
this.buildProductsValidationWhereCondition(tipoBusca);
|
||||
|
||||
const sql = `
|
||||
SELECT
|
||||
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 = 'E' THEN 'ELETROMOVEIS'
|
||||
ELSE 'OUTROS' END as "tipoProduto"
|
||||
,PCTABPR.PVENDA1 as "precoVenda"
|
||||
,( PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA ) as "qtdeEstoqueLoja"
|
||||
,( SELECT ( ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA )
|
||||
ELSE 'OUTROS'
|
||||
END as "tipoProduto",
|
||||
PCTABPR.PVENDA1 as "precoVenda",
|
||||
(PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA) as "qtdeEstoqueLoja",
|
||||
(
|
||||
SELECT (ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA)
|
||||
FROM PCEST ESTOQUE_CD
|
||||
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
|
||||
WHERE PCPRODUT.CODPROD = PCEST.CODPROD
|
||||
AND PCPRODUT.CODPROD = PCTABPR.CODPROD
|
||||
AND PCPRODUT.CODMARCA = PCMARCA.CODMARCA
|
||||
AND PCTABPR.NUMREGIAO = 1
|
||||
AND PCEST.CODFILIAL = :storeId
|
||||
AND ( PCPRODUT.CODAUXILIAR = REGEXP_REPLACE(:filtro1, '[^0-9]', '') OR
|
||||
PCPRODUT.CODPROD = REGEXP_REPLACE(:filtro2, '[^0-9]', '') OR
|
||||
PCPRODUT.DESCRICAO LIKE '%'||:filtro3||'%' )`;
|
||||
AND ${whereCondition}
|
||||
`;
|
||||
|
||||
const products = await this.dataSource.query(sql, [
|
||||
storeId,
|
||||
filtro,
|
||||
filtro,
|
||||
filtro,
|
||||
]);
|
||||
const params = useSingleParam
|
||||
? [storeId, filtro]
|
||||
: [storeId, filtro, filtro, filtro];
|
||||
|
||||
const products = await this.dataSource.query(sql, params);
|
||||
|
||||
if (products.length === 0) {
|
||||
throw new HttpException('Produto não localizado!', HttpStatus.NOT_FOUND);
|
||||
@@ -66,21 +101,16 @@ export class ProductsService {
|
||||
|
||||
if (!product.images) {
|
||||
product.images = [];
|
||||
} else {
|
||||
return product;
|
||||
}
|
||||
|
||||
product.images = product.images.includes(';')
|
||||
? product.images.split(';')
|
||||
: [product.images];
|
||||
}
|
||||
|
||||
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) {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
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[]> {
|
||||
const sql = `SELECT P.CODPROD as "productIdErp"
|
||||
,P.VTEXSKUID as "productId"
|
||||
,ROUND(P.PVENDA,2) as "price"
|
||||
,ROUND(P.PRECOKIT,2) as "priceKit"
|
||||
const sql = `
|
||||
SELECT
|
||||
P.CODPROD as "productIdErp",
|
||||
P.VTEXSKUID as "productId",
|
||||
ROUND(P.PVENDA, 2) as "price",
|
||||
ROUND(P.PRECOKIT, 2) as "priceKit"
|
||||
FROM ESVPRODUTOSECOMMERCE P
|
||||
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);
|
||||
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 {
|
||||
if (valor === null || valor === undefined) {
|
||||
return '0,00';
|
||||
@@ -136,19 +160,115 @@ export class ProductsService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca detalhes de produtos com preço integrado com região
|
||||
* @param query - Parâmetros de busca (codprod, numregiao, codfilial)
|
||||
* @returns Lista de produtos com detalhes
|
||||
*/
|
||||
private buildProductDetailsWhereCondition(
|
||||
codprod: number[] | undefined,
|
||||
codauxiliar: string[] | undefined,
|
||||
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(
|
||||
query: ProductDetailQueryDto,
|
||||
): Promise<ProductDetailResponseDto[]> {
|
||||
const { numregiao, codprod, codfilial } = query;
|
||||
const { numregiao, codprod, codauxiliar, codfilial } = query;
|
||||
|
||||
const placeholders = codprod
|
||||
.map((_, index) => `:codprod${index}`)
|
||||
.join(',');
|
||||
if (!codprod?.length && !codauxiliar?.length) {
|
||||
throw new HttpException(
|
||||
'É 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 = `
|
||||
SELECT
|
||||
@@ -157,22 +277,27 @@ export class ProductsService {
|
||||
PCPRODUT.EMBALAGEM AS "embalagem",
|
||||
PCPRODUT.CODAUXILIAR AS "codauxiliar",
|
||||
PCMARCA.MARCA AS "marca",
|
||||
(SELECT PCTABPR.PVENDA1
|
||||
(
|
||||
SELECT PCTABPR.PVENDA1
|
||||
FROM PCTABPR
|
||||
WHERE PCTABPR.CODPROD = PCPRODUT.CODPROD
|
||||
AND PCTABPR.NUMREGIAO = :numregiao1) AS "preco",
|
||||
(SELECT TRIM(REPLACE(RAZAOSOCIAL, 'LTDA', ''))
|
||||
AND PCTABPR.NUMREGIAO = :1
|
||||
) AS "preco",
|
||||
(
|
||||
SELECT TRIM(REPLACE(RAZAOSOCIAL, 'LTDA', ''))
|
||||
FROM PCFILIAL F
|
||||
WHERE CODIGO = :codfilial) AS "filial",
|
||||
(SELECT REGIAO
|
||||
WHERE CODIGO = :2
|
||||
) AS "filial",
|
||||
(
|
||||
SELECT REGIAO
|
||||
FROM PCREGIAO
|
||||
WHERE NUMREGIAO = :numregiao2) AS "regiao"
|
||||
WHERE NUMREGIAO = :3
|
||||
) AS "regiao"
|
||||
FROM PCPRODUT
|
||||
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);
|
||||
|
||||
return products.map((product) => ({
|
||||
@@ -181,67 +306,129 @@ export class ProductsService {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca informações do produto conforme rotina A4
|
||||
* @param query - Parâmetros de busca (numregiao, codprod, codfilial)
|
||||
* @returns Dados do produto conforme rotina A4
|
||||
*/
|
||||
private buildRotinaA4WhereCondition(
|
||||
codprod: number | undefined,
|
||||
codauxiliar: string | undefined,
|
||||
): { 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> {
|
||||
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 = `
|
||||
SELECT
|
||||
DADOS.DESCRICAO,
|
||||
DADOS.CODPROD,
|
||||
DADOS.CODAUXILIAR,
|
||||
DADOS.PRECO_NORMAL,
|
||||
DADOS.UNIDADE,
|
||||
TRUNC(DADOS.VALOR_VENDA,0) VALOR_VENDA,
|
||||
REPLACE(REPLACE(TO_CHAR( (DADOS.VALOR_VENDA - TRUNC(DADOS.VALOR_VENDA,0)) ,'FM999G9D00'),',',''),'.','') DECIMAL_VENDA,
|
||||
TRUNC(DADOS.VALOR_VENDA, 0) VALOR_VENDA,
|
||||
REPLACE(
|
||||
REPLACE(
|
||||
TO_CHAR((DADOS.VALOR_VENDA - TRUNC(DADOS.VALOR_VENDA, 0)), 'FM999G9D00'),
|
||||
',',
|
||||
''
|
||||
),
|
||||
'.',
|
||||
''
|
||||
) DECIMAL_VENDA,
|
||||
DADOS.MARCA
|
||||
FROM
|
||||
(SELECT
|
||||
FROM (
|
||||
SELECT
|
||||
pcprodut.DESCRICAO,
|
||||
pcprodut.embalagem as unidade,
|
||||
pctabpr.PVENDA PRECO_NORMAL,
|
||||
pcprodut.CODPROD,
|
||||
TRUNC(pctabpr.PVENDA1,2) PVENDA1,
|
||||
(CASE WHEN
|
||||
NVL(TRUNC((SELECT P.PRECOFIXO
|
||||
pcprodut.CODAUXILIAR,
|
||||
TRUNC(pctabpr.PVENDA1, 2) PVENDA1,
|
||||
(
|
||||
CASE
|
||||
WHEN NVL(
|
||||
TRUNC(
|
||||
(
|
||||
SELECT P.PRECOFIXO
|
||||
FROM PCPRECOPROM P
|
||||
WHERE P.CODPROD = PCTABPR.CODPROD
|
||||
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
||||
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
||||
AND ROWNUM = 1
|
||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO),1) ,0) = 0
|
||||
THEN PCTABPR.PVENDA1
|
||||
ELSE
|
||||
TRUNC((SELECT P.PRECOFIXO
|
||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO
|
||||
),
|
||||
1
|
||||
),
|
||||
0
|
||||
) = 0 THEN PCTABPR.PVENDA1
|
||||
ELSE TRUNC(
|
||||
(
|
||||
SELECT P.PRECOFIXO
|
||||
FROM PCPRECOPROM P
|
||||
WHERE P.CODPROD = PCTABPR.CODPROD
|
||||
AND TRUNC(SYSDATE) BETWEEN P.DTINICIOVIGENCIA AND P.DTFIMVIGENCIA
|
||||
AND (P.CODPLPAGMAX = 10 OR P.CODPLPAGMAX = 1)
|
||||
AND ROWNUM = 1
|
||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO),2) END ) VALOR_VENDA,
|
||||
(select marca from pcmarca where pcmarca.codmarca = pcprodut.codmarca)marca
|
||||
FROM
|
||||
pctabpr,
|
||||
pcprodut,
|
||||
pcest
|
||||
WHERE
|
||||
pctabpr.CODPROD = pcprodut.CODPROD
|
||||
and pcest.codprod = pctabpr.CODPROD
|
||||
AND pctabpr.NUMREGIAO = :numregiao
|
||||
and pcprodut.DTEXCLUSAO is null
|
||||
and pcprodut.codprod = :codprod
|
||||
AND pcest.codfilial = :codfilial
|
||||
and pctabpr.PVENDA is not null ) DADOS
|
||||
AND P.NUMREGIAO = PCTABPR.NUMREGIAO
|
||||
),
|
||||
2
|
||||
)
|
||||
END
|
||||
) VALOR_VENDA,
|
||||
(
|
||||
SELECT marca
|
||||
FROM pcmarca
|
||||
WHERE pcmarca.codmarca = pcprodut.codmarca
|
||||
) marca
|
||||
FROM pctabpr, pcprodut, pcest
|
||||
WHERE pctabpr.CODPROD = pcprodut.CODPROD
|
||||
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, [
|
||||
numregiao,
|
||||
codprod,
|
||||
codfilial,
|
||||
]);
|
||||
const result = await this.dataSource.query(sql, params);
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new HttpException(
|
||||
@@ -252,10 +439,6 @@ export class ProductsService {
|
||||
|
||||
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) {
|
||||
produto.PRECO_NORMAL = produto.PRECO_NORMAL.toLocaleString('pt-BR', {
|
||||
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) {
|
||||
produto.VALOR_VENDA = `R$ ${produto.VALOR_VENDA.toLocaleString('pt-BR', {
|
||||
minimumFractionDigits: 0,
|
||||
|
||||
Reference in New Issue
Block a user