> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alana.shopping/llms.txt
> Use this file to discover all available pages before exploring further.

# Ações em Lote

> Execute Normalizar (Silver) ou Analisar (Gold) em múltiplos produtos de uma vez — com seletor de escopo, acompanhamento de progresso e revisão de resultados.

## Visão geral

**Ações em Lote** permitem executar estágios do pipeline — normalização Silver ou pontuação Gold — em múltiplos produtos simultaneamente. Em vez de processar produtos um a um, você seleciona um escopo (produtos individuais, uma seleção ou o catálogo inteiro) e aciona a operação uma vez.

***

## Selecionando produtos

### Produto único

Na página de detalhe do produto, use o botão **Normalizar** ou **Analisar** no painel do pipeline na barra lateral direita. Isso executa a operação somente naquele produto.

### Seleção

1. Na lista de produtos do catálogo, marque as caixas ao lado dos produtos que deseja processar
2. Uma barra de ação flutuante aparece na parte inferior: **X produtos selecionados**
3. Clique em **Normalizar** ou **Analisar** na barra de ação

### Catálogo completo

1. Na lista de produtos do catálogo, clique em **Selecionar Todos** (seleciona todos os produtos do catálogo, não apenas a página atual)
2. Clique em **Normalizar** ou **Analisar** na barra de ação
3. Alternativamente, use o dropdown **Ações em Lote** → **Normalizar Todos** ou **Analisar Todos**

***

## Seletor de escopo

O seletor de escopo define o alvo do lote em chamadas de API:

| Escopo        | Comportamento                                  |
| ------------- | ---------------------------------------------- |
| `"selection"` | Processa somente os `productIds` especificados |
| `"all"`       | Processa todos os produtos no catálogo         |

Quando `scope: "all"`, o campo `productIds` é ignorado.

***

## Executar Silver (Normalizar)

O Silver normaliza campos: padroniza capitalização, valida URLs, detecta duplicatas, mapeia categorias e marcas.

### Via UI

1. Selecione produtos (ou use Selecionar Todos)
2. Clique em **Normalizar**
3. Uma barra de progresso exibe: `Normalizado X / Y produtos`
4. Quando concluído, um painel de resultados exibe:
   * Contagem de campos normalizados
   * Duplicatas detectadas
   * URLs de imagens quebradas encontradas

### Via API

<CodeGroup>
  ```bash curl theme={null}
  # Normalizar uma seleção
  curl -X POST "https://app.alana.shopping/api/workspace/WORKSPACE_ID/catalogs/CATALOG_ID/batch/silver" \
    -H "Authorization: Bearer SUA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "productIds": ["prod_abc", "prod_def", "prod_ghi"],
      "scope": "selection"
    }'

  # Normalizar o catálogo inteiro
  curl -X POST "https://app.alana.shopping/api/workspace/WORKSPACE_ID/catalogs/CATALOG_ID/batch/silver" \
    -H "Authorization: Bearer SUA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"scope": "all"}'
  ```

  ```javascript JavaScript theme={null}
  // Normalizar uma seleção
  const response = await fetch(
    `https://app.alana.shopping/api/workspace/${workspaceId}/catalogs/${catalogId}/batch/silver`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        productIds: ['prod_abc', 'prod_def', 'prod_ghi'],
        scope: 'selection',
      }),
    }
  );
  const { results, processed, duration_ms } = await response.json();
  console.log(`Processados ${processed} produtos em ${duration_ms}ms`);
  ```

  ```python Python theme={null}
  import requests

  # Normalizar catálogo inteiro
  response = requests.post(
      f"https://app.alana.shopping/api/workspace/{workspace_id}/catalogs/{catalog_id}/batch/silver",
      headers={"Authorization": f"Bearer {api_key}"},
      json={"scope": "all"}
  )
  data = response.json()
  print(f"Processados {data['processed']} produtos em {data['duration_ms']}ms")
  ```
</CodeGroup>

### Estrutura do resultado Silver

```json theme={null}
{
  "results": [
    {
      "productId": "prod_abc",
      "status": "success",
      "fieldsNormalized": 4,
      "duplicateOf": null,
      "urlsValidated": 3
    },
    {
      "productId": "prod_def",
      "status": "success",
      "fieldsNormalized": 2,
      "duplicateOf": "prod_xyz",
      "urlsValidated": 1
    },
    {
      "productId": "prod_ghi",
      "status": "error",
      "error": "Marca não encontrada: 'MarcaDesconhecida'"
    }
  ],
  "processed": 3,
  "duration_ms": 1240
}
```

| Campo              | Descrição                                                           |
| ------------------ | ------------------------------------------------------------------- |
| `status`           | `"success"` ou `"error"`                                            |
| `fieldsNormalized` | Número de campos que foram transformados                            |
| `duplicateOf`      | Se uma duplicata foi detectada, o ID do produto original            |
| `urlsValidated`    | Número de URLs de imagens/mídia verificadas quanto à acessibilidade |

***

## Executar Gold (Analisar)

O Gold pontua produtos em uma escala de 0–100 em 7 estágios e produz uma lista de lacunas dos campos que mais melhorariam a pontuação.

### Via UI

1. Selecione produtos (ou use Selecionar Todos)
2. Clique em **Analisar**
3. Uma barra de progresso exibe: `Analisado X / Y produtos`
4. Quando concluído, cada card de produto exibe um badge de pontuação (0–100)
5. Clique em qualquer produto para ver o detalhamento completo de lacunas

### Via API

<CodeGroup>
  ```bash curl theme={null}
  # Analisar uma seleção
  curl -X POST "https://app.alana.shopping/api/workspace/WORKSPACE_ID/catalogs/CATALOG_ID/batch/gold" \
    -H "Authorization: Bearer SUA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "productIds": ["prod_abc", "prod_def"],
      "scope": "selection"
    }'

  # Analisar catálogo inteiro
  curl -X POST "https://app.alana.shopping/api/workspace/WORKSPACE_ID/catalogs/CATALOG_ID/batch/gold" \
    -H "Authorization: Bearer SUA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"scope": "all"}'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://app.alana.shopping/api/workspace/${workspaceId}/catalogs/${catalogId}/batch/gold`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ scope: 'all' }),
    }
  );
  const { results, catalogSummary } = await response.json();
  console.log(`Pontuação média: ${catalogSummary.avgScore}`);
  console.log(`Principais lacunas: ${catalogSummary.topGaps.join(', ')}`);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      f"https://app.alana.shopping/api/workspace/{workspace_id}/catalogs/{catalog_id}/batch/gold",
      headers={"Authorization": f"Bearer {api_key}"},
      json={"scope": "all"}
  )
  data = response.json()
  summary = data["catalogSummary"]
  print(f"Pontuação média: {summary['avgScore']}")
  print(f"Distribuição de pontuações: {summary['scoreDistribution']}")
  ```
</CodeGroup>

### Estrutura do resultado Gold

```json theme={null}
{
  "results": [
    {
      "productId": "prod_abc",
      "status": "success",
      "score": 82,
      "gaps": ["secondaryImages", "gtin"],
      "missingFields": ["gtin"]
    },
    {
      "productId": "prod_def",
      "status": "success",
      "score": 41,
      "gaps": ["description", "gtin", "brand", "images"],
      "missingFields": ["description", "gtin"]
    }
  ],
  "catalogSummary": {
    "avgScore": 61.5,
    "scoreDistribution": {
      "excellent": 12,
      "good": 34,
      "warning": 28,
      "poor": 8
    },
    "topGaps": ["gtin", "description", "secondaryImages"]
  }
}
```

| Campo                              | Descrição                                                          |
| ---------------------------------- | ------------------------------------------------------------------ |
| `score`                            | Pontuação de otimização 0–100                                      |
| `gaps`                             | Campos ordenados por impacto na pontuação (maior impacto primeiro) |
| `missingFields`                    | Campos completamente ausentes do produto                           |
| `catalogSummary.topGaps`           | Lacunas mais comuns em todos os produtos                           |
| `catalogSummary.scoreDistribution` | Contagem por faixa de limite                                       |

***

## Acompanhamento de progresso

Para catálogos grandes, as operações em lote rodam de forma assíncrona. Acompanhe o progresso via:

* **UI** — barra de progresso ao vivo atualizada a cada 2 segundos
* **API** — consulte o endpoint de status do job:

<CodeGroup>
  ```bash curl theme={null}
  curl "https://app.alana.shopping/api/workspace/WORKSPACE_ID/catalogs/CATALOG_ID/batch/JOB_ID/status" \
    -H "Authorization: Bearer SUA_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const poll = async (jobId) => {
    const response = await fetch(
      `https://app.alana.shopping/api/workspace/${workspaceId}/catalogs/${catalogId}/batch/${jobId}/status`,
      { headers: { 'Authorization': `Bearer ${apiKey}` } }
    );
    const { status, progress, total } = await response.json();
    console.log(`${status}: ${progress}/${total}`);
    if (status === 'running') setTimeout(() => poll(jobId), 2000);
  };
  ```

  ```python Python theme={null}
  import requests, time

  def poll_job(job_id):
      response = requests.get(
          f"https://app.alana.shopping/api/workspace/{workspace_id}/catalogs/{catalog_id}/batch/{job_id}/status",
          headers={"Authorization": f"Bearer {api_key}"}
      )
      job = response.json()
      print(f"{job['status']}: {job['progress']}/{job['total']}")
      if job['status'] == 'running':
          time.sleep(2)
          poll_job(job_id)
  ```
</CodeGroup>

***

## Boas práticas

<AccordionGroup>
  <Accordion title="Execute o Silver antes do Gold">
    As pontuações Gold dependem de dados normalizados. Sempre execute o Silver primeiro para garantir que marcas e categorias estejam vinculadas antes de pontuar.
  </Accordion>

  <Accordion title="Use o resumo do catálogo para priorizar o trabalho">
    O campo `catalogSummary.topGaps` informa as lacunas mais comuns em todo o catálogo. Enderece-as sistematicamente em vez de produto por produto.
  </Accordion>

  <Accordion title="Agende lotes grandes para horários de baixo tráfego">
    Processar mais de 10.000 produtos pode levar vários minutos. Use a API para acionar jobs em lote a partir de uma tarefa agendada em horários de baixo tráfego.
  </Accordion>

  <Accordion title="Execute o Gold seletivamente após edições">
    Após preencher lacunas, execute o Gold apenas nos produtos editados (use `scope: "selection"` com `productIds`) em vez do catálogo inteiro.
  </Accordion>
</AccordionGroup>
