Integração de Machine Curve (Curva ABC) no Pricing Agent
Data: 2025-01-03
Objetivo: Documentar como a machine_curve é obtida e usada no sistema de precificação
📋 Onde a Tabela product_classification é Usada
A tabela csuite_pricing.product_classification armazena a classificação ABC (machine_curve) de cada produto e é usada em três pontos principais:
1. Stored Procedure sp_price_compute_v8
A stored procedure recebe machine_curve como parâmetro de entrada (p_machine_curve) e usa para calcular o curve_factor:
-- Dentro da stored procedure
SELECT COALESCE((
SELECT factor
FROM csuite_pricing.pricing_curve_factors
WHERE machine_curve = p_machine_curve
AND is_active = 1
LIMIT 1
), 1.000000)
INTO v_curve_factor;
-- O curve_factor é então usado para ajustar o desconto final
SET v_discount_final = v_discount_allowed * v_curve_factor;
Arquivo: csuite-pricing/sql/sp_price_compute_v8_corrigida.sql
2. Engine Python (agents/pricing/engine.py)
O engine recebe machine_curve como parâmetro e passa para a stored procedure:
def compute_price_v8(
org_id: int,
brand_id: int,
customer_id: Optional[int],
sku_id: int,
sku_qty: int,
order_value: float,
payment_term: str,
stock_level: str,
machine_curve: str, # A | B | C | D | E
db: Optional[Session] = None
) -> Dict[str, Any]:
Arquivo: agents/pricing/engine.py
3. Context Builder (agents/pricing/context.py)
O context builder busca machine_curve da tabela product_classification quando não vem no payload:
# Consultar Machine Curve (curva ABC) da tabela product_classification
if org_id and sku_id:
machine_curve_from_table = get_machine_curve(org_id, sku_id)
if machine_curve_from_table:
context["machine_curve"] = machine_curve_from_table
context["machine_curve_source"] = "product_classification"
Arquivo: agents/pricing/context.py
4. Repository (agents/pricing/repository.py)
Nova função criada para buscar machine_curve:
def get_machine_curve(org_id: int, sku_id: int) -> Optional[str]:
"""
Consulta machine_curve (curva ABC) para SKU
Returns:
machine_curve (A, B, C, D, E) ou None se não encontrado
"""
Arquivo: agents/pricing/repository.py
🔄 Como Adicionar machine_curve na View vw_pricing_catalog_active
Script SQL Criado
Foi criado o script csuite-pricing/sql/update_vw_pricing_catalog_active_with_curve.sql que:
- Dropa a view existente (se houver)
- Cria a view atualizada com
machine_curveincluído - Faz LEFT JOIN com
product_classificationpara obter a curva - Usa fallback
'B'se não houver classificação - Prioriza classificação mais recente quando há múltiplas org_ids
Estrutura da View Atualizada
CREATE VIEW vw_pricing_catalog_active AS
SELECT
ps.brand_id,
ps.sku_id,
ps.pt AS PT,
pf.piso AS PISO,
COALESCE(pc.machine_curve, 'B') AS machine_curve, -- ✅ NOVO CAMPO
pc.is_active AS classification_active,
ps.is_active AS screen_active,
pf.is_active AS floor_active,
GREATEST(...) AS last_updated
FROM
csuite_pricing.price_screen ps
INNER JOIN csuite_pricing.price_floor pf
ON ps.sku_id = pf.sku_id
LEFT JOIN (
-- Subquery para pegar apenas a classificação mais recente e ativa por sku_id
SELECT
sku_id,
machine_curve,
is_active,
updated_at,
ROW_NUMBER() OVER (PARTITION BY sku_id ORDER BY updated_at DESC, org_id DESC) AS rn
FROM csuite_pricing.product_classification
WHERE is_active = 1
) pc ON ps.sku_id = pc.sku_id AND pc.rn = 1
WHERE
ps.is_active = 1
AND pf.is_active = 1
ORDER BY
ps.brand_id, ps.sku_id;
Como Executar
# Conectar ao banco e executar o script
mysql -h <host> -u <user> -p csuite_pricing < csuite-pricing/sql/update_vw_pricing_catalog_active_with_curve.sql
Ou via Python:
from agents.pricing.database import get_pricing_db_session
db = get_pricing_db_session()
with open('csuite-pricing/sql/update_vw_pricing_catalog_active_with_curve.sql', 'r') as f:
sql = f.read()
db.execute(text(sql))
db.commit()
📊 Fluxo de Dados
1. product_classification (tabela)
└─> machine_curve: A, B, C, D, E
│
├─> vw_pricing_catalog_active (view) ✅ NOVO
│ └─> Exibe machine_curve junto com PT e PISO
│
├─> get_machine_curve() (repository)
│ └─> context.py
│ └─> build_context()
│ └─> engine.compute_price_v8()
│ └─> sp_price_compute_v8()
│ └─> pricing_curve_factors
│ └─> curve_factor
│ └─> v_discount_final
✅ Resumo das Mudanças
- ✅ Função
get_machine_curve()criada emrepository.py - ✅ Context builder atualizado para buscar
machine_curveda tabela quando não vem no payload - ✅ Script SQL criado para atualizar
vw_pricing_catalog_activecommachine_curve - ✅ View atualizada para incluir
machine_curvecom fallback para'B'
🔍 Verificação
Após executar o script SQL, verifique a view:
-- Verificar se machine_curve está presente
SELECT
brand_id,
sku_id,
PT,
PISO,
machine_curve, -- ✅ Deve aparecer aqui
classification_active
FROM vw_pricing_catalog_active
LIMIT 10;
-- Estatísticas por curva
SELECT
machine_curve,
COUNT(*) AS total
FROM vw_pricing_catalog_active
GROUP BY machine_curve;