Articles sur : Ressources

Mapping d'intégration Netsuite

Attention : Le connecteur s'appuie sur plusieurs champs et enregistrements personnalisés (custcol_iw_, CUSTOMLIST_IW_, CUSTOMRECORD_CSEG_IW_*). Ces éléments dépendent de la configuration du compte NetSuite. Une nouvelle instance doit exposer des champs équivalents (ou être mappée spécifiquement) avant l'onboarding.


Connexion & authentification


  • API utilisée : SuiteQL (langage de requête SQL de NetSuite), exposé via un unique endpoint REST :

POST https://{account_id}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql

  • Authentification : OAuth 2.0 Machine-to-Machine (M2M), via une assertion JWT signée en ES256 (grant_type=client_credentials). Il n'y a pas de flux OAuth interactif côté utilisateur.
  • Endpoint de jeton : https://{account_id}.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token
  • En-têtes des requêtes : Authorization: Bearer <token> et Prefer: transient.
  • Sur une réponse 401, le jeton est régénéré automatiquement et la requête est rejouée une fois ; en cas d'échec, une erreur InvalidCredentials est levée.
  • Prérequis côté NetSuite :
  1. Activer les fonctionnalités REST Web Services et OAuth 2.0.
  2. Un rôle disposant des droits de lecture sur customer, item, transaction, transactionLine, currency, classification et les enregistrements personnalisés éventuels, ainsi que l'accès aux REST Web Services / SuiteQL.


Mise en place de la connexion


La connexion est machine-to-machine : vous enregistrez Fincome comme application de confiance dans votre compte NetSuite, puis vous reportez trois identifiants dans Fincome. La clé privée de signature ne quitte jamais Fincome — vous n'importez que le certificat public Fincome.


  1. Créer l'enregistrement d'intégration.

Setup ▸ Integration ▸ Manage Integrations ▸ New. Cochez toutes les cases Token-Based Authentication, OAuth 2.0 et Client Credentials (Machine to Machine) Grant, enregistrez, puis notez le Client ID (Consumer Key).

  1. Téléverser le certificat Fincome.

Téléchargez le certificat public Fincome : <https://fincome-public-assets.s3.eu-west-3.amazonaws.com/netsuite/fincome-netsuite.pem>

Puis allez dans Setup ▸ Integration ▸ OAuth 2.0 Client Credentials (M2M) Setup ▸ New : sélectionnez l'intégration de l'étape 1, importez le certificat et rattachez-le à une entité et un rôle disposant des droits REST Web Services / SuiteQL (cf. prérequis). Notez le Certificate ID renvoyé.

  1. Renseigner Fincome.

Dans Fincome, ouvrez le connecteur NetSuite et saisissez votre Account ID (Setup ▸ Company ▸ Company Information), votre Client ID (étape 1) et votre Certificate ID (étape 2). Optionnellement, indiquez les IDs de vos champs personnalisés de reconnaissance du revenu et votre/vos catégorie(s) de revenu récurrent.


Objets synchronisés


Le connecteur traite cinq flux, dans cet ordre :


Flux

Source NetSuite

Objets Fincome créés

Condition de filtrage

customer

table customer

Customer

aucune (sync complète)

product

table item

Product + Price

aucune

subscription

transactions salesorder

Subscription

taxline = 'F' ET tranDate > TRUNC(CURRENT_DATE)

invoice

transactions salesorder

Invoice + InvoiceLineItem

taxline = 'F' ET tranDate <= TRUNC(CURRENT_DATE)

credit_note

transactions creditmemo

Invoice + InvoiceLineItem

taxline = 'F'



Point clé — factures vs abonnements. Les factures et les abonnements proviennent du même type d'enregistrement (salesorder). Ils sont séparés uniquement par la date de transaction : -tranDate dans le futur → abonnement (Subscription), -tranDate aujourd'hui ou dans le passé → facture (Invoice).



Seules les lignes dont taxline = 'F' sont importées (liste blanche) : toute autre valeur — notamment les lignes de taxe — est exclue. La taxe n'est donc jamais importée et tax_amount vaut toujours 0.

Mapping des champs


Clients (customer)


Champ NetSuite

Champ Fincome

Remarque

id

original_id

entitytitle

name

email

email

toplevelparent

root_parent_id

Renseigné uniquement si toplevelparent ≠ id (hiérarchie parent/enfant), résolu via une clé étrangère Customer


Produits & tarifs (product)


À partir de la table item, le connecteur crée un Product et un Price :


Champ NetSuite

Champ Fincome (Product)

id

original_id

itemid

name


Champ NetSuite

Champ Fincome (Price)

id

original_id

id

product_id (clé étrangère vers Product)

itemid

name

itemrevenuecategory

type → subscription si = "1", sinon one_off


Factures (invoice)


En-tête (Invoice) :


Champ NetSuite

Champ Fincome

Remarque

id

original_id

tranId

invoice_number

entity

customer_id

clé étrangère vers Customer

tranDate

date

format JJ/MM/AAAA ; si absente, la facture est ignorée

status

status

mappé via la table salesorder (voir § Mapping des statuts)


Lignes (InvoiceLineItem) :


Champ NetSuite

Champ Fincome

Remarque

transactionLine.id

original_id (combiné à l'id facture)

invoice_id

clé étrangère vers Invoice (ligne ignorée si la facture est absente)

itemrevenuecategory + dates de période

type

subscription si période valide (period_start < period_end) et itemrevenuecategory = "1", sinon one_off

creditforeignamount / debitforeignamount

amount_excluding_tax_after_discount

voir § Montants

tax_amount

toujours 0 (lignes de taxe exclues)

quantity

quantity

transformé en -1 × arrondi_supérieur(quantity)

currency.symbol

currency_code

transactionLine.memo

description

custcol_iw_rr_start_date

period_start

date de début de reconnaissance du revenu

custcol_iw_rr_end_date

period_end

1 jour (NetSuite borne la fin de façon inclusive)

item

price_id

clé étrangère vers Price


Axes personnalisés (custom_axis_field) :


Enregistrement NetSuite

Champ Fincome

CUSTOMLIST_IW_CONTRACT_TYPE.name

contract_type

CUSTOMRECORD_CSEG_IW_CA_COUNTRY.name

country_name

classification.name

class


Abonnements (subscription)


Champ NetSuite

Champ Fincome

Remarque

id (+ id de ligne)

original_id

identifiant combiné

id (transaction)

subscription_set_id

regroupe les lignes d'un même salesorder

entity

customer_id

clé étrangère vers Customer

custcol_iw_rr_start_date

subscription_start_date

montant de la ligne ÷ nombre de mois de la période

monthly_value

les mois partiels sont calculés au prorata

monthly_value_main

monthly_value converti dans la devise de base (voir § Montants)


Avoirs (credit_note)


Structure identique aux factures, à trois différences près :


  • source = transactions creditmemo (et non salesorder) ;
  • status mappé via la table creditmemo (voir § Mapping des statuts) ;
  • original_id = l'id de l'avoir lui-même (ce n'est pas un lien vers une facture d'origine).

Mapping des statuts


Les statuts dépendent du type d'enregistrement source.


Bons de commande (salesorder) → utilisés pour les factures


Code NetSuite

Libellé NetSuite

Statut Fincome

A

Pending Approval

pending

B

Pending Fulfillment

open

C

Cancelled

ignoré

D

Partially Fulfilled

open

E

Pending Billing/Part. Fulf.

open

F

Pending Billing

open

G

Billed

open

H

Closed

ignoré

Y

Undefined

ignoré


Avoirs (creditmemo)


Code NetSuite

Libellé NetSuite

Statut Fincome

A

Open

open

B

Fully Applied

paid

C

Undefined

ignoré

D

Voided

ignoré


Un enregistrement passé à un statut ignoré (commande annulée/clôturée, avoir annulé…) est marqué comme supprimé côté Fincome lors du sync suivant.

Montants, quantités, dates & devises


  • Montants. NetSuite scinde chaque ligne en deux pieds comptables. Le connecteur lit les montants en devise étrangère :
  • creditforeignamount → montant positif ;
  • sinon debitforeignamount → montant négatif (-1 ×).
  • Le champ netamount n'est pas utilisé.
  • Quantités. Inversées et arrondies au supérieur : -1 × ceil(quantity).
  • Dates. Format attendu JJ/MM/AAAA. Les dates de fin de période (period_end) sont décalées de +1 jour.
  • Devises. Les montants sont exprimés dans la devise de la transaction (*foreignamount). Ils sont convertis dans la devise de base de l'entreprise au taux de la date de la transaction (champs *_main). À noter : pour les abonnements, cette date est dans le futur (tranDate > aujourd'hui), la conversion utilise donc le taux de change associé à cette date future.


Synchronisation incrémentale & pagination


  • Pagination : par limit (1000) et offset sur SuiteQL.
  • Curseur : { offset, last_modified_date }. Une fois un flux épuisé (hasMore = false), offset repasse à 0 et last_modified_date avance à la date de début du dernier sync.
  • Champ de dernière modification :
  • customer → lastmodifieddate ;
  • subscription / invoice / credit_note → t.lastmodifieddate.
  • Suppressions. Les suppressions définitives côté NetSuite ne sont pas propagées : un enregistrement supprimé cesse simplement d'apparaître, sans être retiré de Fincome. En revanche, un enregistrement passé à un statut ignoré (voir § Mapping des statuts) est marqué comme supprimé.

Champs & enregistrements personnalisés requis


Ces éléments doivent exister dans l'instance NetSuite pour un mapping complet :


Élément

Usage Fincome

custcol_iw_rr_start_date

début de période (period_start, subscription_start_date)

custcol_iw_rr_end_date

fin de période (period_end)

CUSTOMLIST_IW_CONTRACT_TYPE

axe personnalisé contract_type

CUSTOMRECORD_CSEG_IW_CA_COUNTRY

axe personnalisé country_name


À noter : itemrevenuecategory (qui distingue abonnement / one-off) est un champ standard de l'objet item, pas un champ personnalisé.

Mis à jour le : 23/06/2026

Cet article a-t-il répondu à vos questions ?

Partagez vos commentaires

Annuler

Merci !