Pular para o conteúdo principal

Price Service

Gerencia operações relacionadas aos preços de produtos, permitindo buscar tabelas de preços e consultar valores conforme diferentes políticas comerciais.

Visão Geral

O PriceService é responsável por:

  • Buscar preços de produtos da API remota
  • Consultar valores por tabela de preços
  • Filtrar preços por produto específico
  • Gerenciar preços flexíveis e fixos
  • Suportar múltiplas políticas de precificação

Os preços são fundamentais para operações comerciais, permitindo que o sistema trabalhe com diferentes tabelas de preços para diferentes clientes, canais de venda ou condições comerciais.

Localização: services/price/price.service.ts

Endpoints Utilizados

Base URL

Todos os endpoints são relativos à base URL configurada em services/api.service.ts

Métodos

fetchRemote(params)

Busca preços remotamente com paginação e filtros.

Endpoint: GET /precoProduto

Parâmetros:

type FetchPricesParams = {
page?: number; // Número da página (padrão: 0)
size?: number; // Quantidade de itens por página (padrão: 2000)
dataHora?: string;
idTab?: string; // Filtrar por ID da tabela de preços
idProd?: string; // Filtrar por ID do produto
};

Query Params enviados:

  • page: número da página
  • size: tamanho da página
  • dataHora: timestamp (opcional)
  • idTab: ID da tabela de preços (opcional)
  • idProd: ID do produto (opcional)

Retorno:

Promise<Price[]>;

Exemplo de uso:

import { priceService } from "@/services/price/price.service.instance";

// Buscar todos os preços
const allPrices = await priceService.fetchRemote();

// Buscar preços de uma tabela específica
const tablePrices = await priceService.fetchRemote({
idTab: "tabela-123",
});

// Buscar preços de um produto específico
const productPrices = await priceService.fetchRemote({
idProd: "produto-456",
});

// Buscar preço específico (tabela + produto)
const specificPrice = await priceService.fetchRemote({
idTab: "tabela-123",
idProd: "produto-456",
});

// Buscar com paginação
const pricesPage = await priceService.fetchRemote({
page: 0,
size: 100,
});

// Buscar para sincronização
const prices = await priceService.fetchRemote({
dataHora: "2026-02-25T10:00:00Z",
});

Tratamento de erros:

  • Lança Error se o status da resposta não for 2xx
  • Mensagem: PriceService.fetchRemote failed: {status}

Estruturas de Dados

Interface Price

interface Price {
preco: number; // Preço do produto
precoFlex: number; // Preço flexível (negociável)
idTabelaPreco: string; // ID da tabela de preços
produtoId: string; // ID do produto
}

Campos Importantes

preco

  • Preço fixo do produto
  • Base para cálculos comerciais
  • Não pode ser alterado pelo vendedor no momento da venda

precoFlex

  • Preço flexível/negociável
  • Pode ser ajustado pelo vendedor dentro de regras
  • Geralmente tem limites de desconto configurados

idTabelaPreco

  • Identifica qual política de preços está sendo usada
  • Exemplos: "Varejo", "Atacado", "Distribuidor", "VIP"
  • Cliente pode ter tabela específica

produtoId

  • Relaciona o preço ao produto
  • Mesmo produto pode ter preços diferentes em tabelas diferentes

Componentes Relacionados

buildQueryParams Helper

Função utilitária que converte objeto de parâmetros em URLSearchParams.

Localização: helpers/buildQueryParams.ts

PageResponse Interface

Interface compartilhada para respostas paginadas.

Localização: services/client/client.service.ts

interface PageResponse<T> {
content: T[]; // Array de itens da página
page?: number; // Número da página atual
size?: number; // Tamanho da página
totalPages?: number; // Total de páginas
totalElements?: number; // Total de elementos
}

Fluxo de Integração

Fluxo de Consulta de Preço

1. App precisa exibir preço de produto
2. Determina tabela de preços do cliente
3. App chama priceService.fetchRemote({ idTab: '...', idProd: '...' })
4. GET /precoProduto é enviado com filtros
5. API retorna preço específico
6. App exibe preço ou precoFlex conforme política

Fluxo de Sincronização de Preços

1. App inicia sincronização de catálogo
2. Busca todas as tabelas de preços ativas
3. Para cada tabela, busca preços:
- priceService.fetchRemote({ idTab: tabela.id })
4. Armazena preços localmente (database/cache)
5. App pode consultar offline

Fluxo de Negociação

1. Vendedor seleciona produto
2. App busca preço do produto na tabela do cliente
3. Verifica se pode usar precoFlex
4. Vendedor aplica desconto (se permitido)
5. Valida se desconto está dentro do limite
6. Adiciona item ao pedido com preço negociado

Casos de Uso

Buscar Preço de um Produto

// Obter preço específico
async function getProductPrice(
productId: string,
tableId: string,
): Promise<number | null> {
const prices = await priceService.fetchRemote({
idProd: productId,
idTab: tableId,
});

return prices.length > 0 ? prices[0].preco : null;
}

const price = await getProductPrice("prod-123", "tab-varejo");
console.log(`Preço: R$ ${price?.toFixed(2)}`);

Listar Todos os Preços de uma Tabela

// Obter catálogo de preços completo
async function getPriceList(tableId: string) {
const prices = await priceService.fetchRemote({
idTab: tableId,
});

console.log(`Total de preços na tabela: ${prices.length}`);

// Agrupar por faixa de preço
const ranges = {
ate50: prices.filter((p) => p.preco <= 50).length,
ate100: prices.filter((p) => p.preco > 50 && p.preco <= 100).length,
acima100: prices.filter((p) => p.preco > 100).length,
};

console.log("Distribuição:");
console.log(`Até R$ 50: ${ranges.ate50} produtos`);
console.log(`R$ 50 - R$ 100: ${ranges.ate100} produtos`);
console.log(`Acima de R$ 100: ${ranges.acima100} produtos`);
}

await getPriceList("tab-varejo");

Sincronizar Preços Localmente

import { database } from "@/database";

// Sincronizar preços para uso offline
async function syncPrices(tableId: string) {
console.log("Sincronizando preços...");

let page = 0;
let hasMore = true;
let totalSynced = 0;

while (hasMore) {
const prices = await priceService.fetchRemote({
idTab: tableId,
page,
size: 500,
});

if (prices.length === 0) {
hasMore = false;
break;
}

// Salvar no banco local
await database.write(async () => {
for (const price of prices) {
// Lógica de insert/update no WatermelonDB
// ... código de persistência
}
});

totalSynced += prices.length;
console.log(`Sincronizados: ${totalSynced} preços`);

page++;
}

console.log(`Sincronização concluída: ${totalSynced} preços`);
}

await syncPrices("tab-varejo");

Testes

Localização

services/price/price.service.test.ts

Executar Testes

# Teste específico do serviço
npx jest services/price/price.service.test.ts

# Modo watch
npx jest services/price/price.service.test.ts --watch

# Com coverage
npx jest services/price/price.service.test.ts --coverage

Casos de Teste

  • fetchRemote: busca de preços com paginação
  • fetchRemote: filtro por tabela de preços
  • fetchRemote: filtro por produto
  • fetchRemote: filtro combinado (tabela + produto)
  • ✅ Tratamento de erros para status não-2xx

Mocks

Localização

__mocks__/price.mock.ts

Dados Disponíveis

Mock com preços de exemplo:

  • Diferentes tabelas de preços
  • Produtos com preços variados
  • Diferentes margens entre preco e precoFlex

Exemplo de uso em testes:

import { priceResponseMock } from "@/__mocks__/price.mock";

// Mock da API
const apiMock = {
get: jest.fn(async () => ({
status: 200,
data: priceResponseMock,
})),
};

const service = new PriceService({ apiWithoutAccessToken: apiMock });
const result = await service.fetchRemote();

expect(result).toEqual(priceResponseMock.content);