Project

General

Profile

Partnerių API (#19245)

Softera API galinių taškų, įdiegtų/išplėstų per užduotį #19245, dokumentacija: partnerių organizacijos kūrimas, organizacijų paieška, LOCCAT katalogo vietų CRUD, organizacijos GLN keitimas.

Bendra informacija

  1. Bazinė URL: https://api-test.docura.net/ap1/partner/api/
  2. Autentifikavimas: antraštė X-Authorization: <api_key> (vartotojo prieigos raktas, laukas api_key lentelėje users).
  3. Antraštės X-App-Key klientai nenaudoja — šiuo metu užpakalinėje sistemoje šis patikrinimas neprijungtas prie jokios filtrų grandinės (mirusi kodas nuo 2023 m.), todėl jį galima praleisti.
  4. Formatas – JSON (išskyrus atvejus, kai aiškiai nurodyta kitaip).
  5. Rolės (teisės): SYSTEM_ADMIN, SYSTEM_SUPPORT, CLIENT_ADMIN, CLIENT_EDITOR, PROVIDER_ADMIN – konkrečias leistinas roles žr. kiekvieno galinio taško aprašyme.

1. Partnerių organizacijos sukūrimas

POST /user/organization

Sukuria naują organizaciją ir prideda skambinantį vartotoją prie jos kaip CLIENT_ADMIN (per atskirą, ankstesnį žingsnį kūrimo procese).

Teisės: jokių vaidmenų apribojimų – prieinama bet kuriam autentifikuotam vartotojui. Teisės išreiškiamos ne per skambinančiojo vaidmenį, o per tai, kuriai organizacijai priklauso pats skambinantysis (žr. operatorId logiką žemiau).

Užklausos kūnas:

Laukas Tipas Būtinas Apribojimai
taxId string taip 2–20 simbolių
registrationNumber string taip 2–50 simbolių
name string taip 2–50 simbolių
countryCode string taip 2 simboliai
locale string taip 2 simboliai, turi būti lokalės nuorodų sąraše
errorEmail string ne iki 250 simbolių, el. pašto formatas
notes string ne iki 255 simbolių
phones string ne iki 50 simbolių
email string ne iki 150 simbolių, el. pašto formatas

Laukas integrationProfileType, kuris atsirado ankstesnėse šios funkcijos iteracijose tame pačiame biliete, buvo pašalintas iš galutinės versijos – klientas negali pasirinkti profilio/connectionType aiškiai (žr. žemiau).

Atsakymas (200): tas pats laukų rinkinys + id (Long), iln (generuotas organizacijos GLN).

Klaidos:

  1. 409 Conflict (organization.create.conflict.tax_id) – organizacija su šiuo taxId jau egzistuoja.
  2. 400 – neteisingi užklausos kūno laukai (bean validavimas), arba lokalė nerasta (not.exists.specified.organization.locale).

Logika, pagal kurią nustatomas naujos organizacijos operatorius (operatorId)

Jis apskaičiuojamas iš KVIEČIANČIOJO vartotojo (callerIln – esamos sesijos organizacijos ILN) organizacijos, be jokių aiškių parametrų užklausoje:

  1. Jei kviečiančiojo organizacija yra pati softera (profile.softeraOrganizationIln) → naujos organizacijos operatorius = pati softera. Be to, šiuo atveju numatytasis softera vartotojas (profile.softeraDefaultUserId, jei nustatyta) pridedamas prie naujos organizacijos kaip CLIENT_ADMIN.
  2. Jei kviečiančiojo organizacija yra tiekėjas (role='P', bet ne softera) → operatorius = paties kviečiančiojo organizacija.
  3. Kitais atvejais (nei softera, nei tiekėjas) → operatorius = organizacija iš profile.defaultOperatorOrganizationIln (grįžtama prie „numatytojo operatoriaus“).
  4. Jei nei kviečiančiojo organizacija, nei atsarginė organizacija nerandama pagal ILN – 500 (IllegalStateException, paprastai neturėtų nutikti).

connectionType logika naujai organizacijai

  1. Skambintojas yra softera → visada Payment (fiksuota, nepriklausomai nuo nieko).
  2. Priešingu atveju → connectionType = paties operatoriaus organizacijos connectionType (apskaičiuota aukščiau – tiekėjo arba atsarginės organizacijos). Klientas negali aiškiai nurodyti connectionType/integracijos profilio.

2. Organizacijų paieška

GET /organizations/search?query=<string>

Teisės: SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN. Nėra apribojimų pagal operatorId – teikėjas mato rezultatus visoje organizacijų duomenų bazėje, o ne tik savo klientų (apgalvotas sprendimas, priimtas šiame biliete).

Parametrai:

Parametras Tipas Būtinas Aprašymas
query string taip Paieškos eilutė. Tuščia/trūkstama eilutė → tuščias sąrašas be klaidos.

Paieškos logika DB — vienas OR per organizaciją:

  1. tikslus atitikimas id (kaip tekstas);
  2. tikslus atitikimas iln (GLN);
  3. tikslus atitikimas regNr (nepaisant didžiųjų/mažųjų raidžių);
  4. tikslus atitikimas vatNr (nepaisant didžiųjų/mažųjų raidžių);
  5. subeilutė (ILIKE) organizacijos name;
  6. subeilutė (ILIKE) bet kurios jos LOCCAT vietos name.

Atsakymas (200): masyvas, kiekvienas elementas apvyniotas organization objekte:

[
  {
    "organization": {
      "id": 100099815,
      "name": "New brand sof",
      "iln": "2000005810008",
      "taxId": "...",
      "registrationNumber": "...",
      "countryCode": "EE",
      "locations": [ { "id": ..., "iln": "...", "name": "...", "formattedAddress": "...", ... } ]
    }
  }
]

Svarbus niuansas: locations[] yra tik tos vietos, kurių pavadinimas atitiko paieškos eilutę – ne visos rastos organizacijos vietos. Jei organizacija buvo rasta pagal id/iln/regNr/vatNr/pavadinimą, o ne pagal vietovės pavadinimą, locations bus tuščias masyvas. Tai yra apgalvotas elgesys, o ne klaida.


3. Organizacijos LOCCAT katalogo vietos

Pagrindinis kelias: /organization/{gln}/locations, kur {gln} yra organizacijos GLN (ne skaitmeninis ID).

Teisės (bendros visiems trims žemiau nurodytiems metodams):

  1. SYSTEM_ADMIN / SYSTEM_SUPPORT — jokių apribojimų.
  2. PROVIDER_ADMIN — tik tuo atveju, jei skambinančiojo organizacija = tikslinės organizacijos operatorId (teikėjas valdo tų organizacijų vietas, kurias pats administruoja).
  3. Kiti vaidmenys — 403 (not.have.access).
  4. Organizacija nerasta pagal GLN → 400 (organization.not.exists).

3.1 POST /organization/{gln}/locations – sukurti / atnaujinti vietovę

Įterpimo/atnaujinimo logika:

  1. Jei id perduodamas užklausos turinyje – aiškus esamos vietovės atnaujinimas pagal jos vidinį ID (ji turi priklausyti nurodytai organizacijai, kitaip grąžinamas 404).
  2. Jei id neperduodamas, bet perduodamas iln – ieškoma esamos organizacijos vietovės su tokiu iln; jei randama, ji atnaujinama, jei ne – sukuriama nauja.
  3. Jei iln taip pat neperduodamas (arba yra „tuščias“ pagal IlnHelper.isEmpty) – vietovės GLN sugeneruojamas automatiškai (žr. toliau).

Užklausos turinys (LoccatLocationWithIdData – LoccatLocationData + pasirenkamas id):

Laukas Tipas Būtina Apribojimai
id Long ne aiškiam atnaujinimui
iln string ne iki 13 simbolių; kai nėra – sugeneruojama automatiškai
codeBySender string taip iki 70 simbolių
codeByReceiver string ne iki 70 simbolių
name string taip iki 175 simbolių
legal boolean ne „teisės adreso“ vėliavėlė
formattedAddress string ne iki 300 simbolių
streetAndNumber string ne iki 140 simbolių
streetAndNumber2 string ne iki 140 simbolių
city string ne iki 175 simbolių
state string ne iki 175 simbolių
postalCode string ne iki 9 simbolių
countryCode string ne iki 2 simbolių
latitude / longitude double ne
remarks string ne iki 350 simbolių
phoneNumber string ne iki 175 simbolių
email string ne iki 350 simbolių, el. pašto formatas
web string ne iki 175 simbolių

Atsakymas (200): tas pats turinys + sukurtos / atnaujintos vietovės id.

Vietovės GLN automatinis generavimas (kai iln neperduodamas)

Pakartotinai naudojamas senas algoritmas UserWebController.getNextLocalizationCatalogGln (šerdis):

  1. Jei organizacija jau turi vietovių (maxIln rasta) → kitas GLN = paskutinio sugeneruoto GLN pagrindas + 1.
  2. Jei nėra vietovių ir organizacija yra bandomoji (isTest) → GLN sudaromas iš organizacijos glnPrefix, papildyto nuliais.
  3. Jei nėra vietovių, organizacija nėra bandomoji ir nėra „teisėtos“ vietovės → grąžinamas pačios organizacijos GLN.
  4. Jei yra teisėta vietovė, bet nėra kitų (kraštutinis atvejis) → GLN sudaromas iš glnPrefix.

Be to (šio bilieto pakeitimas): jei tokiu būdu sugeneruotas GLN sutampa su pačios organizacijos GLN (2 ir 3 punktai aukščiau) – jis padidinamas 1, kad niekada nedubliuotų organizacijos GLN.

Žinomos ribos (priimtos tokios, kokios yra, be papildomos apsaugos):

  1. Nėra transakcinio užrakto tarp „gauti kitą GLN“ ir „sukurti vietovę su juo“ – esant lygiagrečioms užklausoms be iln įmanomas konfliktas ir 400 duplicate.line.iln.
  2. Viršijimo atveju padidinimas (GLN pagrindas = 999999999999) teoriškai gali sukurti GLN, kuris yra vienu simboliu ilgesnis nei įprastai – itin mažai tikėtinas kraštutinis atvejis, pataisymo neprašyta.
  3. legal vėliavėlė NĖRA automatiškai nustatoma pirmai vietovei, sukurtai be iln – jei organizacija neturi teisinės vietovės, pakartotinis POST be iln bandys vėl sugeneruoti tą patį organizacijos GLN ir nepavyks su 400 duplicate.line.iln. Klientas turi arba aiškiai perduoti iln antroje ir vėlesnėse užklausose, arba pats tvarkyti legal.

3.2 GET /organization/{gln}/locations – gauti vietas

Ypatumai: filtras perduodamas GET užklausos turinyje (JSON); tai nėra užklausos parametrai. Jei turinys tuščias (Content-Length <= 0) – grąžinamos visos organizacijos vietos.

Užklausos turinys (pasirinktinai):

Laukas Tipas Aprašymas
id Long tikslus paieška pagal vietos ID (plius papildomas patikrinimas pagal iln, jei perduota)
iln string filtravimas pagal GLN
name string filtravimas pagal pavadinimą (poeilis)
address string filtravimas pagal adresą (poeilis)

Prioritetas: jei perduodamas id – grąžinama (daugiausiai) viena vieta pagal ID; priešingu atveju, jei nustatytas bent vienas iš iln/name/address – filtruota paieška; priešingu atveju – visos organizacijos vietos.

Atsakymas (200): vietų masyvas (tas pats formatas kaip POST atsakyme).

3.3 DELETE /organization/{gln}/locations

Užklausos turinys (privalomas):

Laukas Tipas Privalomas
id Long taip

Ištrynimas galimas tik pagal vidinį vietos ID; ištrynimas pagal iln nėra įdiegtas (tai buvo apsvarstyta ir atšaukta šiame tikete).

Atsakymas: 200 sėkmės atveju, 404 jei vieta su tokiu ID nerasta organizacijoje, 400 location.id.should.be.specified jei id nenurodytas.


4. Organizacijos GLN keitimas

PATCH /organization/{organizationId}/gln?gln=<naujas GLN>

Pastaba: čia {organizationId} yra skaitmeninis vidinis organizacijos ID (kitaip nei aukščiau esantys lokacijos galiniai taškai, kurie kelyje naudoja GLN).

Teisės:

  1. SYSTEM_ADMIN / SYSTEM_SUPPORT — jokių apribojimų.
  2. PROVIDER_ADMIN — tik tuo atveju, jei skambinančiojo organizacija = tikslinės organizacijos operatorId.
  3. Kiti — 403 neturi.prieigos.
  4. Organizacija nerasta pagal ID → 404 (tuščias atsakymas).

Parametrai:

Parametras Tipas Būtinas
gln eilutė taip, užklausos parametras

Kas vyksta viduje (pakartotinai naudojamas standartinis organizacijos atnaujinimo konvejeris, OrganizationUpdateEvent → OrganizationCommonUpdateHandler):

  1. GLN formato ir kontrolinio skaitmens patvirtinimas → 400 klaidos atveju.
  2. Dublikatų patikra – GLN neturi priklausyti kitai organizacijai → 400 Dubliuotas ILN.
  3. Senoji reikšmė išsaugoma previousIln.
  4. Jei organizacija turi „teisinę“ LOCCAT lokaciją – jos iln automatiškai sinchronizuojamas su nauju organizacijos GLN (loccatReconciliation). Jei teisinės lokacijos nėra – žingsnis praleidžiamas tyliai.
  5. Standartiniai organizacijos atnaujinimo suderinimo veiksmai (partneris/sąlyga/pranešimai ir t. t., nespecifiniai šiai funkcijai).

Atsakymas (200): organizacijos turinys (OrganizationWithIdData) su jau pritaikytu nauju GLN.


5. Santraukos lentelė apie prieigos taškus

Metodas Kelias Kelio identifikatorius Rolės
POST /user/organization — bet kuris autentifikuotas
GET /organizations/search — SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN
POST /organization/{gln}/locations GLN SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN (operatorId atitikimas)
GET /organization/{gln}/locations GLN SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN (operatorId atitikimas)
DELETE /organization/{gln}/locations GLN SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN (operatorId atitikimas)
PATCH /organization/{organizationId}/gln skaitmeninis ID SYSTEM_ADMIN, SYSTEM_SUPPORT, PROVIDER_ADMIN (operatorId atitikimas)

6. Pavyzdžiai

# Create an organisation
curl --location --request POST 'https://api-test.docura.net/ap1/partner/api/user/organization' \
--header 'X-Authorization: <token>' \
--header 'Content-Type: application/json' \
--data '{
  "taxId": "EE100000001",
  "registrationNumber": "12345678",
  "name": "Example OU",
  "countryCode": "EE",
  "locale": "en" 
}'

# Search organisations
curl --location 'https://api-test.docura.net/ap1/partner/api/organizations/search?query=Example' \
--header 'X-Authorization: <token>'

# Create a location without an explicit GLN (auto-generation)
curl --location --request POST 'https://api-test.docura.net/ap1/partner/api/organization/<org_gln>/locations' \
--header 'X-Authorization: <token>' \
--header 'Content-Type: application/json' \
--data '{
  "name": "Warehouse 1",
  "codeBySender": "WH1",
  "countryCode": "EE" 
}'

# Get all locations of an organisation
curl --location 'https://api-test.docura.net/ap1/partner/api/organization/<org_gln>/locations' \
--header 'X-Authorization: <token>'

# Delete a location by id
curl --location --request DELETE 'https://api-test.docura.net/ap1/partner/api/organization/<org_gln>/locations' \
--header 'X-Authorization: <token>' \
--header 'Content-Type: application/json' \
--data '{"id": 682021}'

# Change an organisation's GLN
curl --location --request PATCH 'https://api-test.docura.net/ap1/partner/api/organization/<numeric_id>/gln?gln=2000005819995' \
--header 'X-Authorization: <token>'

Source version: 3 · Status: fresh · Roman Startsev