# API SOAP — Servidor Castrolanda (`servidor.php`)

Documentação derivada do código em `legado/server/servidor.php` (versão comentada **2.0**, agosto/2025). Descreve contrato WSDL dinâmico, parâmetros, retornos e regras de negócio **implementadas no ficheiro**, não necessariamente o desejado em produção.

---

## 1. Visão geral


| Item            | Valor                                                    |
| --------------- | -------------------------------------------------------- |
| Protocolo       | SOAP 1.1 sobre HTTP                                      |
| Estilo WSDL     | **RPC** / **encoded** (`encodingStyle` SOAP 1.1)         |
| Namespace SOAP  | `urn:ServidorCastrolanda`                                |
| Serviço WSDL    | `ServidorCastrolandaService`                             |
| Porta / binding | `ServidorCastrolandaPort` / `ServidorCastrolandaBinding` |
| Classe PHP      | `ServicoCastrolanda`                                     |
| Motor           | `SoapServer` nativo do PHP (WSDL obtido por URL)         |


### URLs


| Uso                      | URL (padrão)                                                                                               |
| ------------------------ | ---------------------------------------------------------------------------------------------------------- |
| **Endpoint SOAP** (POST) | `http://{HTTP_HOST}{caminho}/servidor.php` — o mesmo script que serve o WSDL, **sem** query string `wsdl`. |
| **WSDL**                 | `http://{HTTP_HOST}{caminho}/servidor.php?wsdl`                                                            |


O `HTTP_HOST` e o caminho vêm de `$_SERVER`; em documentação legada apareceu por exemplo `http://10.2.1.60/ws_castrolanda/ws/server/servidor.php?wsdl`.

### soapAction (por operação)

Formato: `urn:ServidorCastrolanda#{nomeOperacao}`

Exemplo: `urn:ServidorCastrolanda#precad`

---

## 2. Base de dados (Oracle)

O serviço usa **PDO OCI**; no código legado constam host `192.168.104.101`, porta `1521`, SID `xe` (valores devem migrar para configuração segura).

**Tabelas / vistas referenciadas:**


| Objeto                     | Uso                                                        |
| -------------------------- | ---------------------------------------------------------- |
| `integr_erp_conceitto`     | Pré-cadastro, troca de status, consulta de pesagem por tag |
| `integr_erp_conceitto_log` | Leitura para classificação (última operação por ordem)     |
| `supervisao`               | `id` = balança → `tag_atu`, `peso`                         |
| `TICKETGER`                | Ticket / impressão; `PEDIDO` = número da ordem             |
| `CLASSIFICA`               | Linhas de classificação (desconto) por ordem               |
| `tagbal` / `TAGBAL`        | Tag ↔ placa (`TAGNUM`, `PLACA`)                            |
| `BALCOMANDO`               | Comandos por balança (`BALANCA`, `COMANDO`)                |
| `HIST_VEICULOS_ACESSO`     | Histórico de acesso de veículos                            |


**Sequência:** `integr_erp_conceitto_seq.nextval` no insert de `integr_erp_conceitto`.

---

## 3. Resumo das operações


| Operação                    | Entrada (WSDL)                       | Saída (tipo WSDL)                       | Função resumida                        |
| --------------------------- | ------------------------------------ | --------------------------------------- | -------------------------------------- |
| `exemplo`                   | nome, idade                          | string                                  | Teste                                  |
| `gera_ticket`               | nr_ordem, status                     | string                                  | Marca ticket para impressão            |
| `classifica`                | 16 parâmetros                        | string                                  | Classificação + TICKETGER + CLASSIFICA |
| `consulta_automatiza`       | bal (int)                            | string                                  | Alias de `pesagem`                     |
| `pesagem`                   | bal (int)                            | string                                  | Estado da balança / integração         |
| `trocastatus`               | tag, status, msg1–3, peso_ordem, obs | int                                     | Atualiza `integr_erp_conceitto`        |
| `trocastatus_automatiza`    | idem                                 | string                                  | `trocastatus` + sufixo `tag,status`    |
| `precad`                    | 15 parâmetros                        | string (código retorno int como string) | Insert pré-cadastro                    |
| `precad_automatiza`         | idem                                 | string                                  | `{placa_cavalo},{status}`              |
| `registrar_comando_tag`     | dispositivo, comando, tag            | string                                  | Comando + histórico                    |
| `consulta_historico_acesso` | 8 filtros opcionais                  | array de `HistoricoItem`                | Lista histórico                        |


---

## 4. Operações — detalhe

### 4.1 `exemplo`


|                |                                   |
| -------------- | --------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#exemplo` |


**Entrada**


| Parâmetro | Tipo (WSDL) | Descrição   |
| --------- | ----------- | ----------- |
| `nome`    | string      | Texto livre |
| `idade`   | int         | Número      |


**Saída**


| Tipo   | Conteúdo                                   |
| ------ | ------------------------------------------ |
| string | `{nome} -> {idade}` (concatenação literal) |


**Regras**

- Sem acesso a base de dados.

---

### 4.2 `gera_ticket`


|                |                                       |
| -------------- | ------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#gera_ticket` |


**Entrada**


| Parâmetro  | Tipo (WSDL) | Uso no código                                               |
| ---------- | ----------- | ----------------------------------------------------------- |
| `nr_ordem` | int         | `TICKETGER.PEDIDO` no `WHERE` (concatenado na SQL)          |
| `status`   | int         | **Presente na assinatura mas não utilizado** no corpo atual |


**Saída**


| Sucesso                           | Erro                                     |
| --------------------------------- | ---------------------------------------- |
| `"Ticket enviado para impressao"` | `Exception` (conexão ou falha no update) |


**Regras**

- `UPDATE TICKETGER SET STATUS = 0 WHERE TICKETGER.PEDIDO = {nr_ordem}`.
- `nr_ordem` entra na query por concatenação (risco de injeção SQL se o valor não for controlado).

---

### 4.3 `classifica`


|                |                                      |
| -------------- | ------------------------------------ |
| **soapAction** | `urn:ServidorCastrolanda#classifica` |


**Entrada**


| Parâmetro             | Tipo (WSDL) | Descrição                                 |
| --------------------- | ----------- | ----------------------------------------- |
| `nr_ordem`            | int         | Ordem de pesagem (`ORDEM_PESAGEM` no log) |
| `num_moega`           | int         | Número da moega                           |
| `num_nota`            | string      | Número da nota                            |
| `num_ticket`          | int         | Número do ticket                          |
| `peso_seco`           | int         | Peso seco (update TICKETGER)              |
| `peso_liquido`        | int         | Peso líquido (`PLIQUIDO`)                 |
| `desconto`            | string      | Ver formato abaixo                        |
| `origem`              | string      | Origem                                    |
| `destino`             | string      | Destino                                   |
| `produto`             | string      | Produto                                   |
| `usuario_pesagem`     | string      | Utilizador pesagem                        |
| `usuario_pesagem2`    | string      | Segundo utilizador                        |
| `transportador`       | string      | Transportador                             |
| `motorista`           | string      | Motorista                                 |
| `cidade`              | string      | Município                                 |
| `uf`                  | string      | UF                                        |
| `tp_acondicionamento` | string      | Tipo de acondicionamento                  |
| `ds_observacao`       | string      | Observação (campo `OBS` no ticket)        |


**Formato de `desconto`**

- Vários itens separados por `**;**`
- Cada item: `**descrição,valor**` (vírgula separa descrição e valor)
- Exemplo: `Desc A,10;Desc B,5`
- Para cada item com `descricao` não vazia: novo registo em `CLASSIFICA` com `NUMORDEM` = `nr_ordem`, `CLASSIFICA_DESC`, `CLASSIFICA_VAL`. IDs gerados por `MAX(ID)+1`.

**Saída**


| Sucesso                                          |
| ------------------------------------------------ |
| `"Dados de classificacao recebidos com sucesso"` |


**Regras**

1. Seleciona **um** registo em `integr_erp_conceitto_log` com `ORDEM_PESAGEM = nr_ordem`, ordenado por `DT_HR_OPERACAO DESC`. Se não existir → `Exception`.
2. Dados do log alimentam placas, pesos, razão social, CNPJ, tipo pesagem, etc.
3. Se **não** existir linha em `TICKETGER` para `PEDIDO = nr_ordem`: **INSERT** com `BALANCA=1`, `STATUS=1`, `IDINT` = `ID` do log, `OBS` = `ds_observacao` (não o `OBSERVACAO` do log neste insert).
4. Se **existir** ticket: **UPDATE** completo, incluindo `PESOSECO`, `PESO2`, `DTHRP2`, `PLIQUIDO`, `OPERACAO` = tipo pesagem do log.
5. `nr_ordem` é concatenado em várias queries (risco SQL injection).
6. **Nota de implementação:** no `INSERT` em `CLASSIFICA`, o bind do ID usa a chave `'ID'` em vez de `':ID'` — pode falhar ou comportar-se de forma inesperada conforme o driver; vale revisão ao portar.

---

### 4.4 `pesagem`


|                |                                   |
| -------------- | --------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#pesagem` |


**Entrada**


| Parâmetro | Tipo | Descrição                                  |
| --------- | ---- | ------------------------------------------ |
| `bal`     | int  | Identificador da balança = `supervisao.id` |


**Saída**


| Situação                | Valor                                                       |
| ----------------------- | ----------------------------------------------------------- |
| Sem dados úteis / tag 0 | `"SEM INFORMACAO"`                                          |
| Com dados               | String CSV: `**bal,tag,placa,peso1,peso2,status,nr_ordem`** |


Onde (quando há integração):

- `tag`, `placa`, `peso1`, `peso2`, `status`, `nr_ordem` vêm de `integr_erp_conceitto` (`qt_peso1`, `qt_peso2`, `fg_status`, `ORDEM_PESAGEM`).
- O **tag** inicial obtém-se de `supervisao`: `SELECT tag_atu, peso FROM supervisao WHERE id = {bal}`; o código assume a **primeira coluna** do resultado como tag (iteração por índice).

**Regras**

1. `bal` concatenado na SQL (risco injeção).
2. A leitura das colunas no PHP é **posicional** (`$i == 0,1,2…`), não por nome de coluna — a ordem das colunas no resultado Oracle deve ser estável.

---

### 4.5 `consulta_automatiza`


|                |                                               |
| -------------- | --------------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#consulta_automatiza` |


**Entrada / saída / regras**

- Idêntico a `**pesagem($bal)`** — apenas delega para `pesagem`.

---

### 4.6 `trocastatus`


|                |                                       |
| -------------- | ------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#trocastatus` |


**Entrada**


| Parâmetro              | Tipo (WSDL) | Descrição                                                                                      |
| ---------------------- | ----------- | ---------------------------------------------------------------------------------------------- |
| `tag`                  | int         | Tag do veículo em `integr_erp_conceitto`                                                       |
| `status`               | int         | `fg_status` quando ≠ 0; ver ramo `status == 0`                                                 |
| `msg1`, `msg2`, `msg3` | string      | `mensagem_1` … `mensagem_3`                                                                    |
| `peso_ordem`           | int (WSDL)  | Em PHP usa-se `trim((string)$peso_ordem) === ''` para decidir se atualiza `peso_ordem_pesagem` |
| `obs`                  | string      | `observacao`                                                                                   |


**Saída**


| Tipo | Conteúdo                                                                |
| ---- | ----------------------------------------------------------------------- |
| int  | Valor de `status` recebido em caso de sucesso (`$status_ret = $status`) |


**Regras**

1. `**status == 0`:** não altera `fg_status`; atualiza apenas mensagens, opcionalmente `peso_ordem_pesagem` e `observacao`.
2. `**status != 0`:** atualiza `fg_status`, mensagens, opcionalmente peso e observação.
3. `msg1`, `msg2`, `msg3`, `obs` são **concatenados diretamente** na SQL (aspas simples) → **alto risco de SQL injection** e quebra com caracteres especiais.
4. `tag` e `peso_ordem` entram concatenados no `WHERE` / `SET`.

---

### 4.7 `trocastatus_automatiza`


|                |                                                  |
| -------------- | ------------------------------------------------ |
| **soapAction** | `urn:ServidorCastrolanda#trocastatus_automatiza` |


**Entrada**

- Igual a `trocastatus`.

**Saída**


| Tipo   | Formato                                                             |
| ------ | ------------------------------------------------------------------- |
| string | `{tag},{status_ret}` onde `status_ret` é o retorno de `trocastatus` |


---

### 4.8 `precad`


|                |                                  |
| -------------- | -------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#precad` |


**Entrada**


| Parâmetro       | Tipo   | Descrição                                    |
| --------------- | ------ | -------------------------------------------- |
| `tag`           | int    | Tag RFID / identificador                     |
| `placa_cavalo`  | string | Placa cavalo                                 |
| `placa_carreta` | string | Placa carreta                                |
| `transportador` | string | Transportador                                |
| `motorista`     | string | Motorista                                    |
| `razaosocial`   | string | Razão social                                 |
| `cnpj`          | string | CPF/CNPJ                                     |
| `ie`            | string | Inscrição estadual                           |
| `endereco`      | string | Endereço                                     |
| `municipio`     | string | Município                                    |
| `uf`            | string | UF                                           |
| `produto`       | string | Produto                                      |
| `data_ordem`    | string | Data/hora ordem — múltiplos formatos aceites |
| `nr_ordem`      | string | Número da ordem de pesagem                   |
| `tp_pesagem`    | string | Tipo de pesagem                              |


**Normalização de `data_ordem`**

Aceites, entre outros:

- `DDMMYYYYHHMMSS` (14 dígitos)
- `DDMMYYYY` (8 dígitos)
- `DDMMMYYYY` com mês abreviado PT/EN (ex.: `26AUG2025`, opcional hora)
- `d/m/Y`, `Y-m-d`, `d-m-Y`, `d.M.Y`, `d-M-Y` com ou sem hora
- `strtotime` como último recurso

Saída interna normalizada: `Y-m-d H:i:s` para `TO_DATE(..., 'YYYY-MM-DD HH24:MI:SS')`.

**Saída**


| Tipo                                                   | Valor              |
| ------------------------------------------------------ | ------------------ |
| int (serializado como string em SOAP conforme binding) | `**1`** em sucesso |


**Regras**

1. `INSERT` em `integr_erp_conceitto` com `integr_erp_conceitto_seq.nextval`, `fg_status = 1`, `ctrlcnc = 0`.
2. Se `data_ordem` não for reconhecida: `Exception` com mensagem explicativa; escrita em `C:\TMP\insert_log.txt` (caminho fixo Windows).
3. Após insert: `UPDATE tagbal SET PLACA = :placa_cavalo WHERE TAGNUM = :tag`.
4. Log de debug adicional em `C:\TMP\insert_log.txt` com query e JSON de parâmetros.
5. O `SELECT MAX(id)` antes do insert é calculado mas o insert usa **sequence** — o `MAX` pode ser legado redundante.

---

### 4.9 `precad_automatiza`


|                |                                             |
| -------------- | ------------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#precad_automatiza` |


**Entrada**

- Mesmos 15 parâmetros que `precad` (mesma ordem que no WSDL).

**Saída**


| Formato                                                                                  |
| ---------------------------------------------------------------------------------------- |
| `{placa_cavalo},{status}` — com `status` = retorno inteiro de `precad` (tipicamente `1`) |


---

### 4.10 `registrar_comando_tag`


|                |                                                 |
| -------------- | ----------------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#registrar_comando_tag` |


**Entrada**


| Parâmetro     | Tipo (WSDL) | Descrição                                                                 |
| ------------- | ----------- | ------------------------------------------------------------------------- |
| `dispositivo` | string      | Gravado em `BALCOMANDO.BALANCA` e `HIST_VEICULOS_ACESSO.HIST_DISPOSITIVO` |
| `comando`     | string      | `BALCOMANDO.COMANDO`                                                      |
| `tag`         | string      | `TAGBAL.TAGNUM`                                                           |


**Saída**


| Sucesso                                          | Erro                                              |
| ------------------------------------------------ | ------------------------------------------------- |
| `"Comando e histórico registrados com sucesso."` | `Exception` (TAG inexistente, falha insert, etc.) |


**Regras**

1. `INSERT INTO BALCOMANDO (BALANCA, COMANDO)`.
2. `SELECT PLACA FROM TAGBAL WHERE TAGNUM = :tag` — obrigatório existir.
3. Novo `HIST_ID` = `NVL(MAX(HIST_ID),0)+1` em `HIST_VEICULOS_ACESSO`.
4. Insert histórico: `HIST_LIBERADO = 0`, `HIST_STATUS = 0`, data `SYSDATE`.

---

### 4.11 `consulta_historico_acesso`


|                |                                                     |
| -------------- | --------------------------------------------------- |
| **soapAction** | `urn:ServidorCastrolanda#consulta_historico_acesso` |


**Entrada (todos opcionais; string vazia = filtro desligado)**


| Parâmetro          | Descrição                                                       |
| ------------------ | --------------------------------------------------------------- |
| `hist_id`          | Igualdade em `HIST_ID`                                          |
| `hist_placa`       | Igualdade em `HIST_PLACA` (**uppercase** aplicado ao parâmetro) |
| `data_inicio`      | Início de intervalo em `HIST_DTH_ACESSO`                        |
| `data_fim`         | Fim de intervalo                                                |
| `hist_dispositivo` | `HIST_DISPOSITIVO`                                              |
| `hist_status`      | `HIST_STATUS`                                                   |
| `hist_tag`         | `HIST_TAG`                                                      |
| `hist_liberado`    | `HIST_LIBERADO`                                                 |


**Datas**

- Aceita `dd/mm/yyyy`, `yyyy-mm-dd`, com ou sem hora; `T` substituído por espaço.
- Só data → início `00:00:00`, fim `23:59:59`.
- Horários curtos (`HH:mm`, `HHmm`, `HHmmss`) são normalizados.

**Saída**


| Caso          | Retorno                                                                                                                                                            |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Nenhuma linha | **Array vazio** `[]`                                                                                                                                               |
| Com linhas    | Array de objetos `**HistoricoItem`** com campos string: `HIST_ID`, `HIST_PLACA`, `HIST_TAG`, `HIST_DISPOSITIVO`, `HIST_DTH_ACESSO`, `HIST_LIBERADO`, `HIST_STATUS` |


Ordenação: `HIST_DTH_ACESSO DESC`.

---

## 5. Segurança e qualidade (legado)

- **Credenciais** Oracle em texto no código — devem ser variáveis de ambiente numa reimplementação.
- **SQL injection:** concatenação de `nr_ordem`, `tag`, `bal`, mensagens em vários métodos.
- **Credenciais / PII em log:** `precad` grava parâmetros em ficheiro local `C:\TMP\insert_log.txt`.
- **Portabilidade:** caminhos `C:\TMP\...` são específicos de Windows.

---

## 6. Referência cruzada código ↔ WSDL

O WSDL é emitido quando `$_GET['wsdl']` está definido; caso contrário o script atua como servidor SOAP usando o próprio URL com `?wsdl` como definição (`SoapServer`).

Ficheiro fonte: `legado/server/servidor.php`.

---

*Documento gerado para apoio à migração ou substituição desta API. Ajustar URLs e credenciais conforme ambiente real.*