# Atualização em massa de campo — Clarizen

App terminal em Node.js para escolher um tipo de entidade e um campo via metadata do Adaptive Work, e atualizar esse campo em massa nos objetos do tipo selecionado (com filtros opcionais).

## Pré-requisitos

- Node.js 18+
- API key do Adaptive Work (`CLARIZEN_API_KEY`)
- Biblioteca `@arco/clarizen-lib` compilada no diretório irmão (`../clarizen-lib`)

## Instalação

```bash
cd ../clarizen-lib && npm install && npm run build
cd ../update_field_API
cp .env.example .env
# Edite .env com CLARIZEN_BASE_URL e CLARIZEN_API_KEY
npm install
```

## Uso

```bash
npm start
```

Fluxo interativo:

1. Autenticação com API key
2. Escolha do tipo de entidade (nível) — lista completa ou filtro por texto
3. **Filtro de objetos** — todos, por State (se o tipo tiver lifecycle), ou cláusula WHERE em CZQL
4. Escolha do campo — cada opção mostra **label**, **nome** e **tipo**
5. Exibição de exemplo de preenchimento conforme o tipo
6. Informe o novo valor (ou limpe o campo, se nullable)
7. Busca dos objetos conforme o filtro
8. Confirmação com resumo (tipo, filtro, campo, valor, quantidade)
9. Atualização em massa com barra de progresso, porcentagem e ETA

## Filtros de objetos

Após escolher o tipo de entidade, você pode limitar quais registros serão atualizados:

| Opção | Descrição |
|-------|-----------|
| Todos os objetos | Sem filtro (comportamento original) |
| Filtrar por State | Disponível quando a metadata expõe `validStates` (ex.: Active, Completed) |
| CZQL WHERE | Informe só a cláusula `WHERE`; o app valida contra a API antes de continuar |

### Exemplos de cláusula WHERE (CZQL)

```
State = 'Active'
Name LIKE 'Projeto%'
State = 'Active' AND Name LIKE 'Test%'
```

A cláusula é aplicada via `entityQuery` com filtro CZQL. Comandos de modificação (`DELETE`, `UPDATE`, etc.) são rejeitados.

## Exemplos de valor por tipo de campo

| Tipo | Como preencher no terminal |
|------|---------------------------|
| Boolean | `true`, `false`, `sim`, `não` |
| String | texto livre, ex: `Meu valor` |
| Integer / Long | `42` |
| Double | `3.14` |
| DateTime | `2026-06-09` ou `2026-06-09T14:30:00Z` |
| Date | `2026-06-09` |
| Entity | `/User/abc-123` ou `{"id":"/User/abc-123"}` |
| Duration | `{"value":5,"unit":"Days"}` |
| Money | `{"value":100,"currency":"BRL"}` |

Campos **nullable** permitem limpar o valor escolhendo "Limpar campo (null)" ou digitando `null`.

## Campos PickList

Campos com `presentationType: PickList` (listas de opções customizadas ou do sistema) exibem uma **lista carregada da API** com nomes legíveis (ex: `Conteúdo`). O app envia automaticamente o ID correto (`/C_GenericTaskSetor/<guid>`), evitando erros ao digitar o nome manualmente.

Campos de **referência** (`ReferenceToObject`, ex: User, Project) continuam exigindo o ID manual ou JSON `{"id":"/Tipo/guid"}`.

## Variáveis de ambiente

| Variável | Descrição |
|----------|-----------|
| `CLARIZEN_BASE_URL` | URL base da API (padrão: `https://api.clarizen.com`) |
| `CLARIZEN_API_KEY` | API key (alternativa: `API_KEY_AW`) |

O app também tenta carregar `../clarizen-lib/.env` se não houver `.env` local.

## Log de execução

Após cada atualização concluída, o app gera `run-log-<timestamp>.json` na pasta do projeto com o registro completo da execução:

- data/hora e duração
- usuário autenticado
- tipo de entidade, filtro, campo e valor aplicado
- resumo (total, atualizados, erros)
- lista de cada objeto com `status: "updated"` ou `status: "error"`

Exemplo resumido:

```json
{
  "executedAt": "2026-06-09T15:30:00.000Z",
  "durationMs": 45230,
  "userId": "/User/abc123",
  "operation": {
    "typeName": "Task",
    "filter": "Todos",
    "fieldName": "C_MeuCampo",
    "value": { "id": "/C_GenericTaskSetor/abc123" },
    "valueLabel": "Conteúdo (/C_GenericTaskSetor/abc123)"
  },
  "summary": { "total": 10, "updated": 9, "errors": 1 },
  "results": [
    { "id": "/Task/...", "displayName": "Tarefa 1", "status": "updated" },
    { "id": "/Task/...", "displayName": "Tarefa 2", "status": "error", "message": "..." }
  ]
}
```

O caminho do arquivo é exibido no terminal ao final: `Log da execução: ...`

## Erros

Objetos que falharem na atualização também aparecem no `run-log-*.json`. Além disso, um arquivo `errors-<timestamp>.json` é gerado quando há falhas, contendo só os erros para reprocessamento.

## Observações

- Apenas campos **atualizáveis** são listados (exclui calculados, create-only e internos).
- A atualização usa `bulk.execute` em lotes de 20, com fallback individual em caso de falha no lote.
- Rate limit da API: ~25 requisições/segundo por organização.
