Release v4928.1.4.2 stable
This commit is contained in:
135
docs/JASMIN_CLIENTFLOW.md
Normal file
135
docs/JASMIN_CLIENTFLOW.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Integração Jasmin no ClientFlow
|
||||
|
||||
Esta versão adiciona a primeira integração Jasmin validada com testes reais em Jasmin 3.02.
|
||||
|
||||
## O que foi validado
|
||||
|
||||
- OAuth Client Credentials:
|
||||
- `https://identity.primaverabss.com/connect/token`
|
||||
- `grant_type=client_credentials`
|
||||
- `scope=application`
|
||||
- `GET /businessCore/productInfos/getVersions`
|
||||
- Clientes:
|
||||
- `GET /salesCore/customerParties/getCustomerByCompanyTaxId/{nif}`
|
||||
- `POST /salesCore/customerParties`
|
||||
- Produtos:
|
||||
- `GET /salesCore/salesItems/extension/odata?$top=50`
|
||||
- Orçamentos:
|
||||
- `POST /sales/quotations`
|
||||
- `documentType=ORC`
|
||||
- `serie=ORC2026`
|
||||
- Faturas:
|
||||
- `POST /billing/invoices/fromQuotation/{quotationId}` com body `{}`
|
||||
|
||||
## Regras importantes descobertas
|
||||
|
||||
1. O NIF deve ser pesquisado no Jasmin sem prefixo `PT`.
|
||||
2. O Jasmin rejeita `electronicMail` e `telephone` vazios; campos opcionais vazios são omitidos.
|
||||
3. OData tem limite de `$top=100`.
|
||||
4. Cliente novo pode usar `partyKey=CF{NIF}`.
|
||||
5. Converter orçamento em fatura exige `json={}`; sem body pode devolver `411 Length Required`.
|
||||
|
||||
## Novas tabelas
|
||||
|
||||
- `customers`
|
||||
- `commercial_documents`
|
||||
- `commercial_document_lines`
|
||||
- `shipments`
|
||||
|
||||
Estas tabelas permitem o pressuposto correto:
|
||||
|
||||
```text
|
||||
Cliente
|
||||
→ várias oportunidades
|
||||
→ vários orçamentos
|
||||
→ várias faturas
|
||||
```
|
||||
|
||||
## Fluxo na oportunidade
|
||||
|
||||
A página da oportunidade tem dois botões simples:
|
||||
|
||||
```text
|
||||
[Criar orçamento]
|
||||
[Converter em fatura]
|
||||
```
|
||||
|
||||
`Criar orçamento` faz internamente:
|
||||
|
||||
```text
|
||||
find_or_create_customer
|
||||
create_quotation
|
||||
```
|
||||
|
||||
`Converter em fatura` faz internamente:
|
||||
|
||||
```text
|
||||
pegar no orçamento ativo/mais recente
|
||||
POST /billing/invoices/fromQuotation/{quotationId} com {}
|
||||
grava a fatura ligada ao orçamento local
|
||||
```
|
||||
|
||||
## Variáveis `.env`
|
||||
|
||||
```env
|
||||
JASMIN_ENABLED=true
|
||||
JASMIN_OUTBOX_ENABLED=true
|
||||
JASMIN_BASE_URL=https://my.jasminsoftware.com
|
||||
JASMIN_PUBLIC_URL=https://my.jasminsoftware.com
|
||||
JASMIN_TOKEN_URL=https://identity.primaverabss.com/connect/token
|
||||
JASMIN_SCOPE=application
|
||||
JASMIN_ACCOUNT=...
|
||||
JASMIN_SUBSCRIPTION=...
|
||||
JASMIN_CLIENT_ID=...
|
||||
JASMIN_CLIENT_SECRET=...
|
||||
|
||||
JASMIN_COMPANY_KEY=CTULDA
|
||||
JASMIN_QUOTATION_TYPE=ORC
|
||||
JASMIN_QUOTATION_SERIE=ORC2026
|
||||
JASMIN_DEFAULT_PRICE_LIST=03
|
||||
JASMIN_DEFAULT_PAYMENT_METHOD=TRA
|
||||
JASMIN_DEFAULT_PAYMENT_TERM=00
|
||||
JASMIN_DEFAULT_DELIVERY_TERM=TRANSP
|
||||
JASMIN_DEFAULT_CURRENCY=EUR
|
||||
JASMIN_DEFAULT_COUNTRY=PT
|
||||
JASMIN_DEFAULT_CUSTOMER_GROUP=02
|
||||
JASMIN_DEFAULT_PARTY_TAX_SCHEMA=CONTINENTE
|
||||
JASMIN_DEFAULT_UNIT=UN
|
||||
JASMIN_DEFAULT_ITEM_TAX_SCHEMA=NORMAL
|
||||
JASMIN_DEFAULT_SALES_ITEM=CARREGADOR_MONO_7KW
|
||||
```
|
||||
|
||||
## Teste não destrutivo
|
||||
|
||||
```bash
|
||||
python scripts/test_jasmin_connection.py
|
||||
```
|
||||
|
||||
## Processar outbox Jasmin
|
||||
|
||||
Modo seguro:
|
||||
|
||||
```bash
|
||||
OUTBOX_TARGET_SYSTEM=jasmin JASMIN_OUTBOX_ENABLED=true OUTBOX_DRY_RUN=true python scripts/process_outbox.py
|
||||
```
|
||||
|
||||
Modo real:
|
||||
|
||||
```bash
|
||||
OUTBOX_TARGET_SYSTEM=jasmin JASMIN_OUTBOX_ENABLED=true OUTBOX_DRY_RUN=false python scripts/process_outbox.py
|
||||
```
|
||||
|
||||
## Dados necessários na oportunidade
|
||||
|
||||
Para criar cliente Jasmin novo, a oportunidade precisa de:
|
||||
|
||||
- nome do cliente
|
||||
- NIF em `metadata.customer_tax_id`, `metadata.nif` ou `metadata.customer.tax_id`
|
||||
- morada/código postal/cidade se disponível
|
||||
|
||||
Para criar orçamento, as linhas da oportunidade precisam de mapear para artigos Jasmin. O serviço usa por ordem:
|
||||
|
||||
1. `opportunity_items.metadata.jasmin_sales_item`
|
||||
2. `opportunity_items.metadata.jasmin_item_key`
|
||||
3. `opportunity_items.sku`
|
||||
4. `JASMIN_DEFAULT_SALES_ITEM`
|
||||
Reference in New Issue
Block a user