Files
update_xlsx/README.md
T
2026-06-04 14:45:08 -03:00

127 lines
4.3 KiB
Markdown

# Portal de importação Excel → Clarizen WorkItem
Portal web MVP para enviar um arquivo `.xlsx` e criar ou atualizar **WorkItems** no Planview Adaptive Work (Clarizen), usando [@arco/clarizen-lib](https://gitea.rivuslab.com/leonardotoniolo/clarizen-lib).
## Pré-requisitos
- [Node.js](https://nodejs.org/) 18 ou superior
- Acesso ao Gitea da Rivus Lab (para instalar `clarizen-lib` via Git)
- Chave de API do Adaptive Work
## Instalação
```bash
cd update_xlsx
npm install
```
Se o repositório `clarizen-lib` for privado, configure autenticação Git (SSH ou token HTTPS) antes do `npm install`.
## Configuração
```bash
cp .env.example .env
```
Edite `.env` na raiz do projeto:
```env
CLARIZEN_BASE_URL=https://api.clarizen.com
CLARIZEN_API_KEY=sua_chave_aqui
PORT=3000
```
Alternativa aceita: `API_KEY_AW` em vez de `CLARIZEN_API_KEY`.
O carregador também tenta `../clarizen-lib/.env` se existir (desenvolvimento local no monorepo ARCO).
## Executar
```bash
npm start
```
Abra [http://localhost:3000](http://localhost:3000).
| Comando | Descrição |
| -------- | --------- |
| `npm start` | Sobe o portal (Express + UI estática) |
| `npm run check:clarizen` | Verifica se a lib foi instalada e compilada (`OK Clarizen`) |
## Formato do Excel
- **Linha 1:** cabeçalhos — pode usar o **nome do campo** na API ou o **label** exibido no Adaptive Work (ex.: `ExternalID` ou `External ID`, `CreatedOn` ou `Created On`).
- **Linhas 2+:** um WorkItem por linha.
- Colunas vazias são ignoradas.
Na importação, o portal consulta o metadata de `WorkItem` no Clarizen e resolve cada cabeçalho para o nome técnico do campo. Colunas não reconhecidas retornam erro 400 antes de criar/atualizar registros.
### Cabeçalhos: nome vs label
| Cabeçalho no Excel | Campo enviado à API |
|--------------------|---------------------|
| `Name` | `Name` |
| `Name` (label) | `Name` |
| `ExternalID` | `ExternalID` |
| `External ID` | `ExternalID` |
| `Created On` | `CreatedOn` |
Após a importação, a UI mostra o mapeamento **Excel → API** (`headerMapping`).
### Create vs update
| Situação | Ação |
| -------- | ---- |
| Linha **sem** valor em `ExternalID` (ou coluna mapeada para ele) | **Criar** novo WorkItem |
| Linha **com** `ExternalID` preenchido | **Atualizar** WorkItem existente com esse ID externo |
Aliases de cabeçalho aceitos: `ExternalId`, `External ID`, `externalId``ExternalID`.
### Exemplo (labels)
| Name | External ID | Description | Start Date |
|------|-------------|-------------|------------|
| Tarefa nova | | Descrição da tarefa | 2026-06-01 |
| Tarefa existente | EXT-001 | Descrição atualizada | 2026-06-15 |
### Exemplo (nomes API)
| Name | ExternalID | Description | StartDate |
|------|------------|-------------|-----------|
| Tarefa nova | | Descrição da tarefa | 2026-06-01 |
| Tarefa existente | EXT-001 | Descrição atualizada | 2026-06-15 |
A lógica de create/update está em `src/import/config.ts` e `src/import/processor.ts` para facilitar alterações futuras.
## Estrutura
```text
update_xlsx/
├── .env.example
├── public/ # UI (HTML, CSS, JS)
├── src/
│ ├── server.ts
│ ├── clarizen/ # cliente e auth
│ ├── excel/ # leitura xlsx
│ ├── import/ # create/update, field-headers (name/label)
│ └── routes/ # POST /api/import
└── README.md
```
## Limitações (MVP)
- Apenas entidade **WorkItem** (sem seleção na UI).
- Campos de referência (`Manager`, `Parent`, etc.) podem exigir formato específico da API; o MVP envia valores escalares simples do Excel.
- Processamento sequencial linha a linha (sem bulk API).
## Problemas comuns
| Sintoma | O que fazer |
| -------- | ------------ |
| Erro ao clonar `clarizen-lib` no `npm install` | Verificar login SSH/HTTPS no Gitea |
| Banner amarelo na página | Conferir `.env` e `npm run check:clarizen` |
| `WorkItem não encontrado para ExternalID=...` | O ID externo não existe no tenant; use create (linha sem ExternalID) ou corrija o valor |
| Erro 400 no upload | Arquivo deve ser `.xlsx` / `.xls` com cabeçalho e ao menos uma linha de dados |
| `Colunas não reconhecidas: ...` | Cabeçalho não bate com nome nem label de campo WorkItem no seu tenant |
| `Label ambíguo` | Dois campos distintos compartilham o mesmo label — use o nome técnico do campo |