تخطَّ إلى المحتوى

Build a Dynamics 365 F&O connector

هذا المحتوى غير متوفر بلغتك بعد.

If your company runs Dynamics 365 Finance and Operations, the connector is an extension in your model: a few tables, a client class, and batch jobs. Most partners already have this skeleton from another integration — a parameters form, an HTTP client with retry rules, staging tables, an execution log. Pointing it at Slflo changes the mappings and contracts, not the skeleton. This page lists each piece and what it does against Slflo.

Read the pull connector and master data guides first: they show the same flow with code that runs.

Piece in your extension Against Slflo
Parameters table and form Base URL https://api.slflo.com/api/integration/v1; the token, stored encrypted; page size (100); your throttle; the last version staged per stream and the last seq per document stream; an on/off switch per flow.
API client class (a .NET HttpClient wrapper called from X++) Stop on 401 and alert (Slflo never blocks an IP for 401s); wait Retry-After on 429; back off on 500, 502, 503, 504 and timeouts; send an Idempotency-Key on every POST/PUT/DELETE, retries included. See retries.
Throttle Just under rate_limit_per_minute from GET /me (120 by default).
Data contracts Generated or hand-written from openapi-v1.json: OrderDto, OrderLineDto, RefDto, TotalsDto, InvoiceDto, PaymentDto, ReturnDto. Ignore fields you don’t know — new ones may be added to v1.
Staging tables Header and lines, with a unique index on (Slflo id, version, line number) and a status field.
Batch jobs (SysOperation) One per flow — orders, invoices, payments, returns, master data — on a recurrence, each writing to your execution log with Slflo’s request_id for every failed call.
  1. Pull GET /orders?filter[status]=ERP_PENDING&filter[version_after]=<last staged version>&per_page=100, following meta.next_version_after until has_more is false. Customer, branch, rep, product and unit come inline with both keys — no second call to look them up.
  2. Stage every line under the unique index. A duplicate insert is not an error; skip it.
  3. Create one sales order per Slflo order. Put the Slflo order id in the sales order’s customer reference (CustomersOrderReference on the sales order header entity), and search for it before creating. A job that died after creating finds its own sales order.
    • Customer account: customer.external_ref. Delivery address: branch.external_ref, which reads ACCOUNT/BRANCH.
    • Lines: product.external_ref is your item number, unit.external_ref your unit symbol, quantity, unit_price, discount; is_free_goods lines at zero price.
    • Prices and VAT: the rep quoted the customer unit_price and the VAT in tax[]. Fix the line price to it rather than letting trade agreements re-price, and map the tax code (VAT) to your sales tax groups.
  4. Ack POST /orders/{id}/ack, ACCEPTED with the sales order number as external_ref, or REJECTED with a reason_code and the infolog text as message (the office reads it). Many at once: POST /acks with "entity": "order".

A refused order the office fixes comes back at a higher version through the same pull; see the refusal path.

  • Read GET /payments?filter[seq_after]=<last receipt seq> — each receipt once, in issue order — or by version.
  • One journal line per payment: account type Customer, account customer.external_ref, credit amount, date collection_date. Map method (CASH, CHEQUE, TRANSFER, INSTAPAY, WALLET, from GET /reference/payment-methods) to your methods of payment; a cheque carries bank, number and due date for post-dated cheques.
  • Settle against the invoices in allocations — each names the invoice with both keys; what’s left is on_account.
  • Ack with the journal number. A payment reversed or a cheque bounced later is pending again (filter[ack]=pending) with a reversal: reverse the journal and ack again. See invoices by seq.
  • Read GET /returns?filter[seq_after]=<last credit note seq>; a return gets its seq when it is credited (credit_note_number).
  • Each line points at the original invoice line (invoice with both keys, invoice_line_number); map reason (from GET /reference/return-reasons) to your return reason codes, and create a return order (RMA) or a credit note as your process books returns.
  • Ack with its number.

Slflo issues an invoice for what it delivers: every van sale, at the shop, and any order the office delivers in Slflo. If you don’t invoice those sales in Dynamics yourself, read GET /invoices?filter[seq_after]=… and book them — as your accountant decides, for example as free text invoices — then ack with your voucher. The counter has no gaps, so you can prove you hold every invoice.

Slflo From Dynamics 365 Call
Customer Customer account (AccountNum), name, credit limit, blocked, customer price group PUT /customers/{AccountNum}
Branch The customer’s delivery addresses PUT /customers/{AccountNum}/branches/{ref}
Unit Unit symbol PUT /units/{Symbol} or POST /batch/units
Product Item number, name, inventory unit, active PUT /products/{ItemId} or POST /batch/products
Sellable units Unit conversions to the inventory unit PUT /products/{ItemId}/units
Price list Customer price group PUT /price-lists/{PriceGroup}
Prices Sales trade agreements for the group, resolved to one price per item, unit and from-date PUT /price-lists/{PriceGroup}/prices (≤ 500 rows, several merge calls when more)
Balance The customer’s open balance, and when it was taken PUT /customers/{AccountNum}/balance or POST /batch/balances

There is no id to store: you push by your own keys. Keep a hash of each payload you sent (MD5 or SHA-256 of the JSON) in a small table and skip the call when it hasn’t changed; Slflo answers unchanged anyway, but skipping saves the request. Send the record’s modified time as source_version so two jobs racing can’t roll a record back.

Fetch Slflo’s code lists once and map them in small tables of your own: GET /reference/payment-methods, return-reasons, units, warehouses, tax-codes. Each item has code, a name in English and Arabic, and — for the company’s own lists — your key beside ours.

  1. Parameters: the base URL and a sandbox token (sfi_live_…); check it with GET /me.
  2. Map the code lists.
  3. Master data out: units, price groups, items, prices, customers, balances — by your keys, with the payload-hash skip.
  4. Documents in: orders, then payments, returns and invoices — pull, stage, create with find-before-create, ack.
  5. Run the go-live checklist against the sandbox, then switch the parameters to a live token.