SupplierLoad
Read and write supplier records. A supplier has a tree of children: locations, each with addresses and bank accounts.
Supplier
└── locations[]
├── addresses[]
└── bank_accounts[]
Import
from lib.objects.supplier import SupplierLoad
Standard methods (from BaseLoad)
load.get_all(), load.search(...), load.new(), load.save_all(),
load.patch_all(...), load.delete_keys(...), load.index_by_source(...),
obj.save(), obj.deactivate(), obj.delete(). See
BaseLoad.
SupplierLoad(context, source_system='ZOHO_BOOKS') writes as that source
system instead of the connector's own.
Keys
A supplier is found by its Nuntiq id, by source_system +
source_record_id, or by supplier_number + organization_code.
Children are matched within their parent:
| Child | Keys |
|---|---|
| Location | id, source key, location_code |
| Address | id, source key, the address itself (street, city, postal code, country) |
| Bank account | id, source key, bank_account_number (spaces removed, upper case) |
Supplier fields
| Field | Type | Required | Notes |
|---|---|---|---|
supplier_id | str (UUID) | The Nuntiq id. Set on records you read (the API answers it as id) and after a save | |
supplier_number | str | yes | Natural key, with organization_code |
supplier_name | str | yes | |
alternative_supplier_name | str | ||
supplier_type | str | Default "1" | |
organization_code | str | References organization.code; save organizations first | |
is_active | bool | Default true | |
source_system | str | Leave out, or the connector's source system | |
source_record_id | str | The supplier's id in your system | |
source_updated_at | str (ISO-8601) | When your system last changed it; an older value than the stored one is not applied | |
custom_field_1..5 | str | Five user-defined slots |
SupplierLocation fields
| Field | Type | Required | Notes |
|---|---|---|---|
supplier_location_id | str (UUID) | The Nuntiq id. Set on records you read (the API answers it as id) | |
location_code | str | yes | Unique within the supplier |
location_name | str | ||
organization_code | str | ||
site_purpose | int | Default 1 | |
default_currency_code | str | Stored upper case | |
default_payment_term_code | str | ||
default_payment_method | str | ||
taxpayer_id | str | ||
duns_number | str | ||
is_default | bool | Default false. The supplier's default location | |
is_active | bool | Default true | |
source_system / source_record_id / source_updated_at | str | As on the supplier | |
custom_field_1..5 | str |
SupplierAddress fields
id (str, UUID), street, city, state, postal_code, country_code
(stored upper case), remit_to_address (bool, default false), status,
source_system, source_record_id, source_updated_at,
custom_field_1..3.
SupplierBankAccount fields
id (str, UUID), bank_account_number (required), bank_name,
bank_branch, bank_routing_number, swift_code, account_currency,
is_primary (bool, default false), status (default "Active"),
source_system, source_record_id, source_updated_at,
custom_field_1..3.
When an integration writes bank accounts, the portals show the tenant's bank details read-only: your system owns them. Every bank change is recorded in the supplier's change history.
Building a supplier graph
load = SupplierLoad(context)
s = load.new()
s.supplier_number = 'SUP-100'
s.supplier_name = 'Acme Co'
s.source_record_id = 'V-100'
loc = s.new_location()
loc.location_code = 'MAIN'
loc.default_currency_code = 'EUR'
addr = loc.new_address()
addr.street = '1 Main St'
addr.city = 'Amsterdam'
addr.country_code = 'NL'
bank = loc.new_bank_account()
bank.bank_account_number = 'NL91ABNA0417164300'
bank.swift_code = 'ABNANL2A'
bank.is_primary = True
results = load.save_all()
# [{'index': 0, 'status': 'created', 'id': '…', 'record': {...}}]
A POST is the full supplier. The locations you send replace your
connector's locations of that supplier, and the addresses and bank
accounts you send replace your own under each location. Children someone
added in the portal stay. A list you leave out keeps what is there (an
object without locations leaves the list out). To remove all your children
of a kind, assign an empty list (loc.bank_accounts = []); an assigned
list is sent also when it is empty. To remove one child, patch it with
'_delete': True.
Full load
If you've fetched the complete supplier list from the ERP:
for ext in fetch_all_suppliers_from_erp():
s = load.new()
s.supplier_number = ext['number']
s.supplier_name = ext['name']
s.source_record_id = ext['id']
# ... locations, addresses, banks ...
load.save_all(full_load=True)
This is a sync run: after the last batch, your connector's suppliers that
the run did not send are soft-deleted. When any supplier was rejected,
nothing is removed and RecordsRejected is raised. For an incremental
sync, leave full_load off.
Change a few fields
load.patch_all([
{'source_record_id': 'V-100', 'is_active': False},
{'supplier_number': 'SUP-200', 'organization_code': 'EMEA',
'locations': [{'location_code': 'OLD', '_delete': True}]},
])
Search
Exact-match filters: supplier_number, organization_code, is_active,
source_system, source_record_id, plus updated_since and
include_deleted.
matches = load.search(supplier_number='SUP-100')
for s in load.get_all(organization_code='EMEA', is_active=True):
process(s)
Delete
load.delete_keys([
{'source_record_id': 'V-100'},
{'supplier_number': 'SUP-200', 'organization_code': 'EMEA'},
])
Soft delete, your connector's own suppliers only. Sending a deleted
supplier again restores it. A supplier you read can also go one at a time
with s.delete().
Deactivate
for s in load.search(source_record_id='V-300'):
s.deactivate() # PATCH is_active = false; nothing else changes