Skip to main content

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:

ChildKeys
Locationid, source key, location_code
Addressid, source key, the address itself (street, city, postal code, country)
Bank accountid, source key, bank_account_number (spaces removed, upper case)

Supplier fields​

FieldTypeRequiredNotes
supplier_idstr (UUID)The Nuntiq id. Set on records you read (the API answers it as id) and after a save
supplier_numberstryesNatural key, with organization_code
supplier_namestryes
alternative_supplier_namestr
supplier_typestrDefault "1"
organization_codestrReferences organization.code; save organizations first
is_activeboolDefault true
source_systemstrLeave out, or the connector's source system
source_record_idstrThe supplier's id in your system
source_updated_atstr (ISO-8601)When your system last changed it; an older value than the stored one is not applied
custom_field_1..5strFive user-defined slots

SupplierLocation fields​

FieldTypeRequiredNotes
supplier_location_idstr (UUID)The Nuntiq id. Set on records you read (the API answers it as id)
location_codestryesUnique within the supplier
location_namestr
organization_codestr
site_purposeintDefault 1
default_currency_codestrStored upper case
default_payment_term_codestr
default_payment_methodstr
taxpayer_idstr
duns_numberstr
is_defaultboolDefault false. The supplier's default location
is_activeboolDefault true
source_system / source_record_id / source_updated_atstrAs on the supplier
custom_field_1..5str

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}]},
])

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