Motor de recomendação
O coração do módulo. Decide o que transferir, de onde e quanto.
Algoritmo
- Gatilho de necessidade — por (loja, produto, cor, tamanho):
dias até ruptura ≈ estoque_destino / venda_média_diária(janela =períododas regras). Candidato se em ruptura (estoque 0) ou risco dentro do horizonte. - Seleção de origem
- CD-first (se
priorizar CD): se o CD tem o item, ele é a origem. - Fallback loja→loja (só se o CD esgotou): escolhe a loja por score ponderado.
- CD-first (se
- Score ponderado (0–100)
score = w_dist · proximidade + w_giro · baixo_giro + w_estoque · folga- proximidade — distância haversine (lat/lng das lojas); mais perto, melhor.
- baixo_giro — origem com venda baixa do item é boa doadora.
- folga — origem mantém pelo menos
qtd mínimaapós ceder. - pesos
w_*=peso_distancia / peso_giro / peso_estoque(devem somar 100). - CD recebe bônus quando
priorizar CDestá ligado.
- Bloqueios — exclui loja bloqueada, lojas/marcas bloqueadas, produto
em campanha(sebloqueio_campanha), origem == destino, e destino nunca é o CD. - Quantidade — cobre ~7 dias de venda do destino, respeitando
qtd mínimana origem eqtd máximapor transferência. - Prioridade —
dias até ruptura0–2 → Alta · 3–4 → Média · 5+ → Baixa. - Justificativa — texto explicando origem, distância, unidades e motivo.
Onde está no código
app/services/engine.py (back). Saída materializada como Recomendacao com snapshot de estoque/venda/distância/score no momento da geração.