StandardBooksi andmete lugemine ja kirjutamine Rest APIga

Allikas: Excellent || Opendoc
Redaktsioon seisuga 29. märts 2019, kell 08:04 kasutajalt Kaupo (arutelu | kaastöö)
Mine navigeerimisribale Mine otsikasti

Seadistamine

Alates versioonist 8.0 saab HansaWorldi toodetes kasutada Web API päringuid andmete väljastamiseks.

Eeltingimused

·        Kliendil peab olemas olema moodul

-         Standard ERP puhul - "Veebipood"

-         Standard Books puhul - "Veebipood ja CMS"

Veebipordid

Seadistatud peab olema veebi port. Veebiport on võimalik seadistada - moodul Tehnika > Programmiseadistus > Veebiport

Joonis 1 - Veebipordid programmis

Veebipordid on vajalikud, et oleks võimalik suhtlus üle HTTP või HTTPS protokolli. Neid mitte sassi ajada Hansa pordiga, millega käib suhtlus klientprogrammi ja serveri vahel.

Veebiporti saab muuta ilma programmi muud tööd segamata.

Tuleb veenduda ka selles, et kasutatav port on serveris avatud - tulemüürid lubavad suhtlust vaid teatud portidel, kõik ei ole enamasti maailmale lahti. Excellenti majutuse puhul on OK kasutada porte vahemikus 1200 kuni 9000.

Tuleb veenduda, et samas serveris ei ole kasutusele võetav port juba kasutusel.

Ligipääs funktsioonidele veebist

Programmis sees. Moodul "Veebipood ja CMS"/“Veebipood“ seadistus Ligipääs funktsioonidele Veebist tuleb lisada rida (või read) käsitsi selliselt:

Funktsioon: API

Avalik: Avalik

SSL: Jah,

Sessioon: Ei

Näide, kus esimesel real on API ilma SSLita ja kolmandal API SSLiga:

Joonis 3 - Ligipääs funktsioonidele veebist

Väli Lubatud IP-d tuleb täita vastaval juhul, kui on soov lubada ainult konkreetsetel süsteemidel teha Rest-API päringuid. Kui väljale on vaja lisada mitu aadressi, siis tuleb need eraldada komaga. Näide:

-         „90.191.43.252,213.35.184.82

Kasutajagrupid

Moodul Üldine > Seadistused > Kasutajagrupid

Kasutajagrupile tuleb lisada õigusi lubav rida toimingule Rest API

Moodul Üldine > Isikud - Kasutajal peab olema peal kasutajagrupp, millel on antud õigus - Toiming Rest API Täis

Sisenemise paroolid tulevad Isiku kaardi õigustest.

Joonis 4 - Kasutajagrupid

Valikulised võimalused

Moodul Üldine > Seadistused > Valikulised võimalused.

Märgitud peavad olema järgnevad valikud:

·        Web Rest API

·        Allow Basic HTTP Authentication

Joonis 5 - Valikulised võimalused

Kasutamine

·        Lugeda saab kõiki hansa registreid ja andme-blokke, sealhulgas HALiga tehtud asju.

·        Päringuga on kasutatav otsimine ja filtreerimine (käitub nagu aruanne)

·        Jätame meelde eelmise päringu ja saame väljastada vahepeal muutunud andmeid

·        Kasutajanimi, parool töötavad. Samuti kontrollitakse andmete lugemise õigust kasutajagruppidest

·        Saab määrata väljade nimekirja kaardil, mida väljastada. Näide: varem oli üks üherealine müügiarve ca 350 XML rida pikk, siis nüüd saan lasta endale saata vaid näiteks 5 rida per arve.

URL’I kasutamine

Andmed päritakse URLiga ehk inimkeeli - klient ütleb Hansa serverile aadressi, mille põhjal Hansa server väljastab vastava info.

Element Kirjeldus Näide
Protokoll kasutatakse kas HTTP või HTTPS protokolli. HTTPS on turvaline, HTTP on peaagu avalik https
IP Serveri IP aadress mars.excellent.ee
Port Serveri veebi port 4455
Ettevõte Ettevõtte kood andmebaasis 1
Register Registri nimi, mida pärime ivvc
Filter Väli, mille alusel päringut filtreerida filter.Custcode=
Väljad Väljad, mis tagastatakse päringuga. (Ilma antud elemendita tagastatakse kõik väljad) fields=SerNr,OKFlag,

 

Eraldajad:

·         ? - Sisestatakse peale Registri defineerimist, et kirjeldada filtreid.

·        & - Sisestatakse erineva tüübiga filtreeringute vahele.

Näidis URL:

https://mars.excellent.ee:4455/api/1/ivvc?filter.CustCode=105&fields=SerNr,OKFlag,Addr0,ArtCode,CustCode,InvDate,TransDate,Objects

See väljastab arved kliendilt 105. Arve pole täielik, vaid on ainult väljad number, Kinnita linnuke, aadressi esimene rida, artiklikood, kliendikood, arve kuupäev, kande kuupäev, objektid.

Päringu vormistamine

http://username:@hostname:port/api/1/IVVc

See on kõige lihtsam näidis päring kindlast ettevõttest ja kindlast registrist, kus

- "username" on kasutajanimi Isikute registrist;

- "api" on kohustuslik päringu osa stringina;

- "1" on ettevõtte kood ettevõtete registrist;

- "IVVc" on registri nimi.

See päring tõmbab kõik müügiarved ettevõttest 1. Kui soovid sarnaselt saada infot näiteks baasvaluutade kohta, siis pead kasutama päringut:

http://username:@hostname:port/api/1/BaseCurBlock

ANDMETE FORMAAT

Päringute andmeformaadid ja kättesaadud andmete formaadid on samad ning kindlalt fikseeritud:

- komakoha eraldajaks tuleb kasuyada "." (punkt);

- tuhandete eraldajat ei tohi olla;

- kuupäevad on ISO formaadis YYYY-MM-DD (ehk aasta-kuu-päev)

PARAMEETRID

Reaalsed parameetri väärtused, mida päringutes kasutatakse (näiteks kasutatud võti/ID ja vahemik, serveri versioon jm.), esitatakse tulemustes andmeväljade atribuutidena("data tag"). Järgnevalt näited parameetritest.

sort - sorteerimise parameeter sorteerib saadud kaardid määratud andmevälja järgi. Indeksi nimi, mida kasutati, väljastatakse samuti päringu tulemuses. Sorteerida saab ainult kaardi päise väljade järgi. Võimalik on sorteerida ainult ühe välja järgi korraga, ja eeldusel, et selle jaoks on olemas sobiv indeks. Kui sobiv indeks puudub, siis päring tulemust ei väljasta. Välja nime puhul on olulised suured ja väikesed tähed. Näide (päring müügiarvete registrist, sorteerituna kliendikoodi järgi):

http://username:@hostname/api/1/IVVc?sort=CustCode

range - vahemiku parameetri kasutamiseks tuleb kasutada ka sorteerimise parameetrit. Vahemik pärib ainult need kaardid, kus sorteeritava välja väärtus langeb määratud vahemikku. Väärtused, mis võrduvad vahemiku alguse ja lõpuga, kaastakse tulemusse. Vahemiku alguse ja lõpu väärtused eraldatakse ":" (kooloniga). On lubatud ka päringud, kus määratud on ainult vahemiku alguse või ainult lõpu väärtus. Kui päringus kasutatakse ainult ühte kindlat väärtust (ilma koolonita), siis väljastatakse ainult kaardid, mis vastavad sellele konkreetsele väärtusele.

Näide 1 (väljastab müügiarved, kus kliendikoodid on vahemikus 10101 kuni 10104):

http://username:@hostname/api/1/IVVc?sort=CustCode&range=10101:10104

Näide 2 (väljastab müügiarved, kus kliendikoodid on 10104 kuni viimase kliendini):

http://username:@hostname/api/1/IVVc?sort=CustCode&range=10104:

Näide 3 (väljastab müügiarved, kus on ainult klient koodiga 10104):

http://username:@hostname/api/1/IVVc?sort=CustCode&range=10104

Vahemiku parameeter on kiire, sest kasutab indeksit.

fields - Väljade parameeter määrab, mis väljad tulemusse kaasatakse. Väljad eraldatakse komadega. Kui parameetrit ei ole määratud, siis võetakse tulemusse info kõikidest väljadest. Kui kaardi/dokumendi päises ja ridadel on sama nimega väli, kaasatakse tulemusse mõlemate info. Kui ridadelt ei pärita ühtegi välja, siis mingisugust ridade infot (ridade numbrid vms) ei väljastata tulemustes.

Näide (väljastab müügiarved, ainult arve numbriga: 

http://username:@hostname/api/1/IVVc? fields=SerNr

filter - Andmeid saab filtreerida selle parameetri abil. Filter on oluliselt aeglasem kui vahemik, kuna ei kasuta indekseid ja otsib läbi kõik kaardid. Kui kasutad vahemiku parameetrit, siis filter köib läbi ainult need kaardid, mis jäävad vahemikku. Sellepärast on soovitav kasutada võimalikult täpset vahemiku määrangut ja teisi filtreid.

Näide:

http://username:@hostname/api/1/IVVc?filter.CustCode=10104

• Ühe välja kohta tohib kasutada ainult ühte filtrit

• Erinevate väljade kasutamisel, saab kasutada mitut filtrit

• Filtrid saavad kasutada sarnaselt väärtuste vahemike, k.a. ainult vahemiku alguse või ainult lõpuga määratud.

• Filtrid toimivad ainult kaartide/dokumentide päise andmeväljadega

• Nimekirja väljades filtreerimine (näiteks Objektid) toimub kogu stringi ulatuses.

Näiteks:  filter.Objects=AB ei kaasa tulemust "AB,D10101"

Näide (väljastab müügiarved, mille lõppsumma on vahemikus 100 kuni 1000 ja kus kliendikoodid on vahemikus 10100 kuni 10200):

http://username:@hostname/api/1/IVVc?filter.CustCode=10100:10200&Sum4=100:1000

offset and limit - Kui päringu tulemus on suurem, kui api kasutaja suudab töödelda ühe päringuga, siis saab tulemusi jagada väiksemateks osadeks. "offset" jätab vahele määratud arvu kaarte/dokumente päringu tulemuses. "limit" piirab kaartide koguarvu päringu tulemuses.

Näide (väljastab 15 esimest müügiarvet 3 erineva päringuga):

http://username:@hostname/api/1/IVVc?offset=0&limit=5 

http://username:@hostname/api/1/IVVc?offset=5&limit=5 

http://username:@hostname/api/1/IVVc?offset=10&limit=5

"offset" ja "limit" saab kasutada koos kõikide teiste parameetritega.

updates_after - väljastab kõik kaardid/dokumendid, mida on uuendatud peale määratud järjekorra numbrit. Järjekorra number väljastatakse igas päringus (sequence="x") ning seda saab kasutada hiljem koos parameetriga "updates_after"

Näide:

http://username:@hostname/api/1/IVVc?updates_after=5000

deletes_after - väljastab kõik kaardid/dokumendid, mis on kustutatud peale määratud järjekorra numbrit. Järjekorra number väljastatakse igas päringus ning seda saab kasutada hiljem koos parametriga "deletes_after"

Näide:

http://username:@hostname/api/1/IVVc?deletes_after=5000

Andmete kirjutamine StandardBooksi, > 8.5

Andmete kirjutamisel StandardBooksi kasutatakse funktsiooni "RecordNew" ehk dokumendile kehtivad täpselt samad loomise reeglid, nagu klientprogrammi kasutades (näiteks mis andmed asetatakse dokumendile peale Kontakti koodi valimist; mis on kohustuslikud väljad, mis on Kontakti-põhised andmed dokumendil jms).

Andmete mahu piirangut andmete kirjutamisel ei ole. On võimalik päringu sisu saata kas URLis või POST päringu Body osas (raw text).

POST päringu järgselt saadetakse alati tagasi vastus, StandardBooksi XML formaadis. Selleks saab olla kas loodud dokument/kaart või veateade. Loodud dokumendi/kaardiga võib aga ei pruugi vastuses olla ka informatiivseid teateid, hoiatusi. Vastuses on XMLis ainult andmeid sisaldavad read.

Vastuses on alati ka link loodud dokumendile, url parameetris. Näiteks kirjutasime baasi artikli koodiga 2005, siis on url osas sisu: "url="/api/1/INVc/1005"". Kui kirjutatakse korraga mitu dokumenti, on urlis koodid eraldatud "/" märgiga. Kui koodis on täpitähti või muid erilisi tähemärke, on nad url-kodeeritud.

Kõik teated, mis kasutajale tagastatakse, asuvad vastuses message osas, teated luuakse täoselt samadel alustel, nagu klientprogrammi kasutades: <message description='message_text'></message>

In case of error while inserting/updating a record, following will be returned: <error code='error_code' description='error description' row='row_no' field='field_name'></error>

POST

To create new records you POST to the registers. The 'set' commands have the same syntax and functionality as with POST.

Example

curl -X POST 'http://SJ:@127.0.0.1:8080/api/1/IVVc?set_field.CustCode=001&set_row_field.0.ArtCode=10101&set_row_field.0.Quant=3';

The reply will be in this format:

<data register="IVVc" sequence="9693" url="/api/1/IVVc/10000014" systemversion="8.5.15.5" <IVVc>
			<SerNr>10000010</SerNr>
			<InvDate>2018-05-30</InvDate>
			<CustCode>001</CustCode>
			<Math/>
			<PayDate>2018-06-29</PayDate>
			<Addr0>Against All Odds Trading Co</Addr0> ... <rows>
				<row rownumber="0">
					<stp>1</stp>
					<ArtCode>10101</ArtCode>
					<Quant>3</Quant>
					<Price>25.00</Price>
					<Sum>71.25</Sum>

This will create a new invoice for 001 customer, adding 3 10101 items.

PATCH

To change an existing record you PATCH the url given in the POST command.

Example

curl -X PATCH 'http://SJ:@127.0.0.1:8080/api/1/IVVc/10000014?set_row_field.0.Quant=100'

The reply will be in the same format:

<data register="IVVc" sequence="9729" url="/api/1/IVVc/10000014" systemversion="8.5.15.6" <IVVc>
			<SerNr>10000014</SerNr> ... <rows>
				<row rownumber="0">
					<stp>1</stp>
					<ArtCode>10101</ArtCode>
					<Quant>100</Quant>
					<Price>25.00</Price>
					<Sum>2375.00</Sum>

This will change the quantity to 100.

Lihtsad POSTi näited

POST meetodiga saab tekitada uusi dokumente

PATCH meetodiga saab muuta olemasolevaid kaarte (ei pea kaasa saatma kogu kaardi sisu, muudetava dokumendi nr sisaldub URLis)

Koostame kliendi

Request: https://mars.excellent.ee:4455/api/1/CUVc/
Method: Post
Headers: Authorization: Basic [user:pass in base64] example: dXNlcjpwYXNz
Body:
set_field.Code=&
set_field.Name=Kohvimasina POST OÜ&
set_field.InvAddr0=Saue&
set_field.InvAddr1=Kodu 13/3&
set_field.InvAddr2=Maja&
set_field.Phone=55887744&
set_field.CountryCode=EE&
set_field.ExportFlag=0&
set_field.CustCat=EES&
set_field.PayDeal=7&
set_field.VATNr=EE792919432&
set_field.LangCode=EST
set_field.VATCode=20&
set_field.Fax=6672823&
set_field.Classification=62031,73121,74901,82991&
set_field.ExportFlag=0&
set_field.Person=Mariliis Männik&

Posteri ekraanipilt:

Poster Contact.png

Saame vastuse:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<data  register="CUVc" sequence="252020" url="/api/1/CUVc/1985" systemversion="8.5.28.512">
 <CUVc>
  <UUID>BC96B2EF-6DDFCA41-D7333126-26FAE7C4-7BCE7A18</UUID>
  <SyncFlags>1</SyncFlags>
  <Code>1985</Code>
  <Name>Kohvimasina POST O&#220;</Name>
  <Person>Mariliis M&#228;nnik</Person>
  <InvAddr0>Saue</InvAddr0>
  <InvAddr1>Kodu 13/3</InvAddr1>
  <InvAddr2>Maja</InvAddr2>
  <Phone>55887744</Phone>
  <Fax>6672823</Fax>
  <CustCat>EES</CustCat>
  <PayDeal>7</PayDeal>
  <InterestFlag>1</InterestFlag>
  <VATNr>EE792919432</VATNr>
  <CountryCode>EE</CountryCode>
  <RemndrFlag>1</RemndrFlag>
  <LangCode>EST</LangCode>
  <OnAccount>1</OnAccount>
  <SalesMan>AA</SalesMan>
  <CreditLimit>0.00</CreditLimit>
  <VATCode>20</VATCode>
  <Classification>62031,73121,74901,82991</Classification>
  <DateChanged>2019-02-14</DateChanged>
  <Password>0</Password>
  <DateCreated>2019-02-14</DateCreated>
  <CUType>1</CUType>
  <CreditLimitDays>0</CreditLimitDays>
  <InvCountryName>Eesti</InvCountryName>
  <TaxCondition>2</TaxCondition>
  <Sign>AA</Sign>
  <eInvPostage>2</eInvPostage>
 </CUVc>
</data>
  • astuses vaid need read kontaktikaardilt, mis on täidetud.
  • täidetud on ka väljad, mis GUIga kontakti luues automaatselt täidetakse

Koostame artikli

Request: https://mars.excellent.ee:4455/api/1/INVc/
Method: Post
Headers: Authorization: Basic [user:pass in base64] example: dXNlcjpwYXNz
Body:
set_field.Code=&
set_field.Name=Trenažöör põlvedele&
set_field.MinLevel=100&
set_field.Objects=NO_PREEMIA&
set_field.UPrice1=1700.00&
set_field.Group=KOHV&
set_field.BarCode=1022154455&

Posteri ekraanipilt:

Item post.png

Vastuse saame sellise:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<data  register="INVc" sequence="252082" url="/api/1/INVc/19.321-127" systemversion="8.5.28.512">
 <INVc>
  <UUID>215B7710-46C044D2-D464046D-5806B64D-BAC293D8</UUID>
  <SyncFlags>1</SyncFlags>
  <Code>19.321-127</Code>
  <Name>Trenaz&#246;&#246;r p&#245;lvedele</Name>
  <MinLevel>100</MinLevel>
  <Objects>NO_PREEMIA</Objects>
  <UPrice1>1700.00</UPrice1>
  <ItemType>1</ItemType>
  <Group>KOHV</Group>
  <BarCode>1022154455</BarCode>
  <UpdateCost>1</UpdateCost>
  <LastPriceChange>2019-02-14</LastPriceChange>
  <LastBasePriceChange>2019-02-14</LastBasePriceChange>
  <colnr>Grey</colnr>
  <SRUpdateCost>1</SRUpdateCost>
  <rows></rows>
 </INVc>
</data>

Meil on nüüd olemas Klient koodiga "1985" (Kohvimasina Post OÜ) ja artikkel "19.321-127"

Müüme postitatud artikli postitatud kliendile maha.

Koostame arve, kasutame loodud artiklit ja klienti

Request: https://mars.excellent.ee:4455/api/1/IVVc/
Method: Post
Headers: Authorization: Basic [user:pass in base64] example: dXNlcjpwYXNz
Body:
set_field.InvDate=2019-02-10&
set_field.CustCode=1985&
set_field.NotUpdStockFlag=1&
set_row_field.0.ArtCode=19.321-127&
set_row_field.0.Quant=1&
Post invoice.png

Vastuseks saime üherealise arve:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<data  register="IVVc" sequence="252169" url="/api/1/IVVc/2180325" systemversion="8.5.28.512">
 <IVVc>
  <SerNr>2180325</SerNr>
  <InvDate>2019-02-10</InvDate>
  <CustCode>1985</CustCode>
  <Math></Math>
  <PayDate>2019-02-17</PayDate>
  <Addr0>Kohvimasina POST O&#220;</Addr0>
  <Addr1>Saue</Addr1>
  <Addr2>Kodu 13/3</Addr2>
  <Addr3>Maja</Addr3>
  <ClientContact>Mariliis M&#228;nnik</ClientContact>
  <PayDeal>7</PayDeal>
  <Prntdf>1</Prntdf>
  <pdays>7</pdays>
  <pdvrebt>0</pdvrebt>
  <pdrdays>0</pdrdays>
  <CustCat>EES</CustCat>
  <InvType>1</InvType>
  <ARAcc>1210</ARAcc>
  <SalesMan>AA</SalesMan>
  <TransDate>2019-02-10</TransDate>
  <CurncyCode>EUR</CurncyCode>
  <LangCode>EST</LangCode>
  <Sign>AA</Sign>
  <FrGP>0.00</FrGP>
  <Sum0>0.00</Sum0>
  <Sum1>1700.00</Sum1>
  <Sum3>340.00</Sum3>
  <Sum4>2040.00</Sum4>
  <VATNr>EE792919432</VATNr>
  <TAX1Sum>340.00</TAX1Sum>
  <CustVATCode>20</CustVATCode>
  <Phone>55887744</Phone>
  <Fax>6672823</Fax>
  <IntCode>25.55</IntCode>
  <ARonTR>1</ARonTR>
  <BaseSum4>2040.00</BaseSum4>
  <TotGP>1700.00</TotGP>
  <RetValue>-2040.00</RetValue>
  <TotQty>1</TotQty>
  <SumIncCom>2040.00</SumIncCom>
  <RetnValue>-2040.00</RetnValue>
  <TransTime>15:47:16</TransTime>
  <ServiceDelDate>2019-02-10</ServiceDelDate>
  <NoTAXonVAT>1</NoTAXonVAT>
  <TotalwoTAX>1</TotalwoTAX>
  <RegDate>2019-02-14</RegDate>
  <RegTime>15:47:16</RegTime>
  <InvCountry>EE</InvCountry>
  <InvCountryName>Eesti</InvCountryName>
  <GPProc>100.0</GPProc>
  <rows>
   <row rownumber="0">
    <stp>1</stp>
    <ArtCode>19.321-127</ArtCode>
    <Quant>1</Quant>
    <Price>1700.00</Price>
    <Sum>1700.00</Sum>
    <SalesAcc>3100</SalesAcc>
    <Objects>NO_PREEMIA</Objects>
    <rowGP>1700.00</rowGP>
    <Spec>Trenaz&#246;&#246;r p&#245;lvedele</Spec>
    <VATCode>20</VATCode>
    <TaxMatrix></TaxMatrix>
   </row>
  </rows>
 </IVVc>
</data>

Nagu näha, on arvele kandunud korrektselt objektid, kliendi kontaktisikud jms, mida me postitasime algsetele kaartidele.

NB: On oluline ka lisatava info järjekord. Näiteks, kui lisate tasumistingimuse koodi, seejärel kontakti koodi ning sellel kontaktil ei ole Müügi Tasumistingimus täidetud, siis saate veateate, et tasumistingimus on tühi. Õige järjekord antud juhul oleks Kontaktikood, peale seda tasumistingimus. Sama reegel on objektidega - need lisada peale kontakti, ridadel peale Kontot või Artiklit.

Muudame koostatud arvel kogust

Request: https://mars.excellent.ee:4455/api/1/IVVc/2180325
Method: Patch
Headers: Authorization: Basic [user:pass in base64] example: dXNlcjpwYXNz
Body:
set_row_field.0.Quant=3'&

Vastuseks on samasugune arve XML, nagu arve postitamisel, vaid kogus on muutunud 3-ks.

Kogus 3.png

Muudame Arvel artiklit, kogust, kirjeldust ja hinda

Oletame, et sooime arvel vahetada artiklit, kogust ja hinda ning lisada kaks uut rida kirjeldusega (nö täiendavad kirjeldavad read)

set_row_field.0.ArtCode=0032251100060&
set_row_field.0.Quant=1&
set_row_field.0.Price=4000&
set_row_field.0.Spec=M20 EX stainless steel 316 Maxed Out&
set_row_field.1.Spec=Description here: neti.ee&
set_row_field.2.Spec=Refund, when broken or pieces missing&

Tulemus on selline:

Lisatud read.png

Kinnitame arve

Request: https://mars.excellent.ee:4455/api/1/IVVc/2180325
Method: Patch
Headers: Authorization: Basic [user:pass in base64] example: dXNlcjpwYXNz
Body:
set_field.OKFlag=1&

tekkis viga, puudu on konto käibemaksukoodi pealt. Kuidas seda tean? Sest sain vastu veateate:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<message  description="TAX Account not found, check VAT Codes"></message>
<error  code="20078" description="TAX Account not found, check VAT Codes" row="-1" field="-1"></error>

Parandasin vea, seejärel sain tulemuseks OK ning tulemus:

OK tulemus.png