Last modified by Nico Lemaire on 2025/05/06 15:49

From version 18.4
edited by Luca de Laat
on 2024/04/10 11:29
Change comment: There is no comment for this version
To version 26.5
edited by Nico Lemaire
on 2025/05/06 15:49
Change comment: There is no comment for this version

Summary

Details

Page properties
Title
... ... @@ -1,1 +1,1 @@
1 -Setting up Lab communication by REST services with TerraIndex
1 +Setting up API communication by REST services with TerraIndex for laboratories
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.LucadeLaat
1 +XWiki.NicoLemaire
Content
... ... @@ -3,8 +3,8 @@
3 3  
4 4  = Digital Lab Exchange process =
5 5  
6 -The flow diagram gives a small overview of what the data flow of a lab assignment is. Every green block shows a step of the lab assignment process. From top to bottom these steps are:
7 -~==> nle what green blocks?
6 +The flow diagram gives a small overview of what the data flow of a lab assignment is.
7 +Every block shows a step of the lab assignment process. From top to bottom these steps are:
8 8  
9 9  1. Showing the laboratory and all the analyses that can be requested as an option to the user.
10 10  1. The user creating a lab assignment and sending it to the lab trough TerraIndex.
... ... @@ -14,14 +14,16 @@
14 14  
15 15  [[image:1712326465681-980.png||height="315" width="630"]]
16 16  
17 +
17 17  [[image:1712326492306-381.png||height="781" width="635"]]
18 18  
19 -[[image:1712326520488-924.png||height="312" width="632"]]
20 +~==> TODO; add option to confirm order based on the Order price PDF
20 20  
21 21  
22 -(% class="wikigeneratedid" element-id="1884" %)
23 -~==> nle Perhaps add option download labcertificate
23 +[[image:1712326520488-924.png||height="312" width="632"]]
24 24  
25 +~==> TODO; add option download labcertificate
26 +
25 25  (% element-id="1884" %)
26 26  = =
27 27  
... ... @@ -32,29 +32,41 @@
32 32  Our IP-addresses:
33 33  
34 34  (% element-id="1881" %)
35 -inbound [[Web.terraindex.com>>url:http://Web.terraindex.com||element-id="1880"]]
37 +__**inbound [[Web.terraindex.com>>url:http://Web.terraindex.com||element-id="1880"]]**__
36 36  137.116.199.164
37 37  
38 38  (% element-id="1878" %)
39 -outbound [[Test.terraindex.com>>url:http://Test.terraindex.com||element-id="1877"]]
41 +__**outbound [[Test.terraindex.com>>url:http://Test.terraindex.com||element-id="1877"]]**__
40 40  104.45.9.128
41 41  
42 42  (% element-id="1875" %)
43 -Production outbound
45 +__**Production outbound (http)**__
44 44  40.115.34.64
45 45  
48 +__**Production outbound (ftp):**__
49 +
50 +13.93.123.234
51 +
46 46  (% element-id="1873" %)
47 -Test outbound
53 +__**Test outbound (http, ftp)**__
48 48  13.73.138.173
49 49  
56 +__**Test outbound (ftp: eurofins, eurofins spain):**__
57 +
58 +51.145.244.12
59 +
50 50  (% element-id="1871" %)
51 -CD/CI outbound
61 +__**CD/CI outbound**__
52 52  40.114.238.16
53 53  
54 54  (% element-id="1869" %)
55 -Office outbound
65 +__**Office outbound**__
56 56  213.124.115.132
57 57  
68 +(% element-id="1869" %)
69 +__**Deliveryservice**__
70 +Production: 13.93.123.234
71 +Test: 51.145.244.12
58 58  
59 59  (% element-id="1864" %)
60 60  = (% element-id="1863" %)Labdelivery (menu-card) files Exchange(%%) =
... ... @@ -1247,7 +1247,7 @@
1247 1247  )))
1248 1248  
1249 1249  (% element-id="654" %)
1250 -= (% element-id="653" %)Get Order status and Results(%%) =
1264 += (% element-id="653" %)Get Order status and Results XML and with PDF(%%) =
1251 1251  
1252 1252  (% element-id="652" %)
1253 1253  == (% element-id="651" %)Solution/Design(%%) ==
... ... @@ -1255,6 +1255,15 @@
1255 1255  (% element-id="650" %)
1256 1256  TerraIndex will request per license/customer which results are ready. These are queried if the latest changes are newer than the last check. This way we never download too much unnecessarily and it can always be requested again.
1257 1257  
1272 +
1273 +(% class="box infomessage" element-id="650" %)
1274 +(((
1275 +**Order status** we support as minimal:
1276 +3 = Reportnumber is known, no results yet, but it's the official report certificate number. This is optional to send.
1277 +4 = Conceptual, temporary results avaiable, but not final yet. This is optional to send.
1278 +5 = Final results are available. This is required to send.
1279 +)))
1280 +
1258 1258  (% class="table-hover" element-id="647" %)
1259 1259  (% element-id="645" %)|(% element-id="644" %)Action|(% element-id="643" %)TerraIndex|(% element-id="642" %) |(% element-id="640" %)Laboratorium|(% element-id="639" %)Parameters/Message|(% element-id="638" %)Remarks|(% element-id="637" %)ResultCodes
1260 1260  (% element-id="636" %)|(% element-id="635" %)1|(% element-id="634" %)Sends a request to the function: GetCustomers().|=(% element-id="633" %)>|(% element-id="632" %) |(% element-id="630" %)WebserviceUsername (string), 
... ... @@ -1261,7 +1261,7 @@
1261 1261  WebservicePassword (string),
1262 1262  CustomerUsername (string)|(% element-id="627" %)We want to skip the Password of the customer, and we introduce the WebserviceUsername + WebservicePassword.|(% element-id="626" %)
1263 1263  (% element-id="624" %)|(% element-id="623" %)2|(% element-id="622" %) |(% element-id="620" %) |(% element-id="618" %)Receives the request and check the customers this username and searches the dateLastChanged for this Customer.|(% element-id="617" %) |(% element-id="615" %) |(% element-id="613" %)
1264 -(% element-id="611" %)|(% element-id="610" %)3|(% element-id="609" %) |(% element-id="607" %)<=|(% element-id="606" %)Sends back the list of customers with the lastChangedTimestamp|(% element-id="605" %)ResultCode (),
1287 +(% element-id="611" %)|(% element-id="610" %)3|(% element-id="609" %) |(% element-id="607" %)<=|(% element-id="606" %)Sends back the list of customers to check for orderStatuses|(% element-id="605" %)ResultCode (),
1265 1265  ErrorMessage (string),
1266 1266  List<customer> , Customer:
1267 1267  CustomerCode (string),
... ... @@ -1378,6 +1378,240 @@
1378 1378  (% element-id="370" %)|(% element-id="369" %)12|(% element-id="368" %)Receives the PDF and stores it for reporting and downloading.|(% element-id="367" %) |(% element-id="365" %) |(% element-id="363" %) |(% element-id="361" %) |(% element-id="359" %)
1379 1379  
1380 1380  (% element-id="357" %)
1404 +== Request example Order Status ==
1405 +
1406 +public GetOrderStatusesCall.Response OrderStatuses(string WebserviceUsername, string WebservicePassword, string CustomerUsername, string customerid, DateTime? timestampSince)
1407 + {
1408 + GetOrderStatusesCall.Response set = new GetOrderStatusesCall.Response();
1409 + string responseMessage = null;
1410 +
1411 + if (timestampSince == null) timestampSince = DateTime.Now.AddHours(-3); ~/~/Now, minus 3 hours
1412 + var formattedTimestamp = System.Xml.XmlConvert.ToString((DateTime)timestampSince, System.Xml.XmlDateTimeSerializationMode.RoundtripKind);
1413 +
1414 + try
1415 + {
1416 + var content = new FormUrlEncodedContent(new[]
1417 + {
1418 + new KeyValuePair<string, string>("userName", WebserviceUsername),
1419 + new KeyValuePair<string, string>("password", WebservicePassword),
1420 + new KeyValuePair<string, string>("customerUsername", CustomerUsername),
1421 + new KeyValuePair<string, string>("clientId", customerid),
1422 + new KeyValuePair<string, string>("lastModified", formattedTimestamp),
1423 + });
1424 +
1425 + HttpResponseMessage response = _HttpClient.PostAsync(_HttpClient.BaseAddress + "/GetOrderStatuses", content).GetAwaiter().GetResult();
1426 + responseMessage = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
1427 + response.EnsureSuccessStatusCode();
1428 +
1429 + if (string.IsNullOrEmpty(responseMessage))
1430 + {
1431 + throw new Exception("Empty response from: [" + _HttpClient.BaseAddress + " /GetOrderStatuses" + "]");
1432 + }
1433 + using (var ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(responseMessage~)~)~)
1434 + {
1435 + XmlSerializer serializer = new XmlSerializer(typeof(GetOrderStatusesCall.Response));
1436 + set = (GetOrderStatusesCall.Response)serializer.Deserialize(ms);
1437 + }               
1438 +
1439 + }
1440 + catch (Exception ex)
1441 + {
1442 + #region handle exception
1443 +
1444 + set.Status = new BusinessEntities.LabRestService.GetOrderStatusesCall.ResponseStatus();
1445 + set.Status.StatusCode = ((int)ResultCodes.GeneralError).ToString();
1446 + set.Status.ErrorMessage = "Exception occurred in GetOrderStatuses (username: " + WebserviceUsername + ", password: " + WebservicePassword + ") with message: " + ex.ToString();
1447 +
1448 + ex.Data.Add("Response", responseMessage);
1449 + ex.Data.Add("WebserviceUsername", WebserviceUsername);
1450 + ex.Data.Add("WebservicePassword", WebservicePassword);
1451 + ex.Data.Add("CustomerUsername", CustomerUsername);
1452 + ex.Data.Add("customerid", customerid);
1453 + ex.Data.Add("lastModified", formattedTimestamp);
1454 + ex.Data.Add("Result", set);
1455 +
1456 + throw;
1457 + #endregion
1458 + }
1459 +
1460 + return set;
1461 + }       
1462 +
1463 +== Response Status XML Example ==
1464 +
1465 + <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1466 + <Response>
1467 + <Orders>
1468 + <Order>
1469 + <OrderStatus>Reported</OrderStatus>
1470 + <SIKBOrderId></SIKBOrderId>
1471 + <SIKBOrderStatus>5</SIKBOrderStatus>
1472 + <OrderId>4855422</OrderId>
1473 + <RapportNummer>12193838</RapportNummer>
1474 + <IsDelayed>False</IsDelayed>
1475 + <ExpectedOn>09/10/2015 17:15:00</ExpectedOn>
1476 + </Order>
1477 + <Order>
1478 + <OrderStatus>New</OrderStatus>
1479 + <SIKBOrderId></SIKBOrderId>
1480 + <SIKBOrderStatus>3</SIKBOrderStatus>
1481 + <OrderId>7106525</OrderId>
1482 + <RapportNummer>02808304-0749-41ae-96eb-d62b0365ebe4</RapportNummer>
1483 + <IsDelayed>False</IsDelayed>
1484 + <ExpectedOn></ExpectedOn>
1485 + </Order>
1486 + <Order>
1487 + <OrderStatus>New</OrderStatus>
1488 + <SIKBOrderId></SIKBOrderId>
1489 + <SIKBOrderStatus>3</SIKBOrderStatus>
1490 + <OrderId>7108954</OrderId>
1491 + <RapportNummer>10776137-ef99-4947-9a6a-9a3b32cd2dec</RapportNummer>
1492 + <IsDelayed>False</IsDelayed>
1493 + <ExpectedOn></ExpectedOn>
1494 + </Order>
1495 + <Order>
1496 + <OrderStatus>New</OrderStatus>
1497 + <SIKBOrderId></SIKBOrderId>
1498 + <SIKBOrderStatus>3</SIKBOrderStatus>
1499 + <OrderId>7110401</OrderId>
1500 + <RapportNummer>7881575c-bee2-409f-b304-9e472e7ac702</RapportNummer>
1501 + <IsDelayed>False</IsDelayed>
1502 + <ExpectedOn>11/10/2018 00:00:00</ExpectedOn>
1503 + </Order>
1504 + </Orders>
1505 + <Status>
1506 + <StatusCode>1</StatusCode>
1507 + <StatusCodeDescription>OK</StatusCodeDescription>
1508 + <AtmisErrorCode>0</AtmisErrorCode>
1509 + <ErrorMessage></ErrorMessage>
1510 + </Status>
1511 + </Response>
1512 +
1513 +
1514 +== Request example Order XML ==
1515 +
1516 +
1517 +public GetOrderResultsCall.Response GetOrderResults(string WebserviceUsername, string WebservicePassword, string CustomerUsername, string customerid, string orderid, string sikbVersion)
1518 + {
1519 + GetOrderResultsCall.Response set = new GetOrderResultsCall.Response();
1520 + string responseMessage = null;
1521 + try
1522 + {
1523 + bool useZipstream = true;
1524 + var content = new FormUrlEncodedContent(new[]
1525 + {
1526 + new KeyValuePair<string, string>("userName", WebserviceUsername),
1527 + new KeyValuePair<string, string>("password", WebservicePassword),
1528 + new KeyValuePair<string, string>("customerUsername", CustomerUsername),
1529 + new KeyValuePair<string, string>("clientId", customerid),
1530 + new KeyValuePair<string, string>("orderId", orderid),
1531 + new KeyValuePair<string, string>("sikbVersion", sikbVersion),
1532 + new KeyValuePair<string, string>("useZip", useZipstream.ToString() ),
1533 + });
1534 +
1535 + HttpResponseMessage response = _HttpClient.PostAsync(_HttpClient.BaseAddress + "/GetOrderResults", content).GetAwaiter().GetResult();
1536 + responseMessage = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
1537 + response.EnsureSuccessStatusCode();
1538 +
1539 + if (string.IsNullOrEmpty(responseMessage))
1540 + {
1541 + throw new Exception("Empty response from: [" + _HttpClient.BaseAddress + " /GetOrderResults" + "]");
1542 + }
1543 + using (var ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(responseMessage~)~)~)
1544 + {
1545 + XmlSerializer serializer = new XmlSerializer(typeof(GetOrderResultsCall.Response));
1546 + set = (GetOrderResultsCall.Response)serializer.Deserialize(ms);
1547 + }
1548 +
1549 + if (useZipstream && !string.IsNullOrEmpty(set.FileContent))
1550 + {
1551 + ~/~/convert from base64 string back to normal
1552 + ~/~/first check for real Base64, by checking there is no 'xml' in it
1553 + ~/~/If encoded, it wont contain either of the root XML tags of SIKB
1554 + if (!set.FileContent.Contains("FeatureCollectionIMSIKB0101") && !set.FileContent.Contains("labresultaat"))
1555 + {
1556 + set.FileContent = ZipStreamHelper.DecompressBase64StringToString(set.FileContent);
1557 + }
1558 + }
1559 +
1560 + }
1561 + catch (Exception ex)
1562 + {
1563 + #region handle exception
1564 +
1565 + set.Status = new BusinessEntities.LabRestService.GetOrderResultsCall.ResponseStatus();
1566 + set.Status.StatusCode = ((int)ResultCodes.GeneralError).ToString();
1567 + set.Status.ErrorMessage = "Exception occurred in GetOrderResults (username: " + WebserviceUsername + ", password: " + WebservicePassword + ") with message: " + ex.ToString();
1568 +
1569 + ex.Data.Add("Response", responseMessage);
1570 + ex.Data.Add("WebserviceUsername", WebserviceUsername);
1571 + ex.Data.Add("WebservicePassword", WebservicePassword);
1572 + ex.Data.Add("CustomerUsername", CustomerUsername);
1573 + ex.Data.Add("sikbVersion", sikbVersion);
1574 + ex.Data.Add("customerid", customerid);
1575 + ex.Data.Add("orderId", orderid);
1576 + ex.Data.Add("Result", set);
1577 +
1578 + throw;
1579 + #endregion
1580 + }
1581 +
1582 + return set;
1583 +
1584 +
1585 +== Response Order XML Example ==
1586 +
1587 +
1588 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
1589 + <Response>
1590 + <FileContent>DhVn3Q1AA==</FileContent>  ~/~/BASE64 Zip Stream, SIKB0101 labresults xml file
1591 + <Status>
1592 + <StatusCode>1</StatusCode>
1593 + <StatusCodeDescription>OK</StatusCodeDescription>
1594 + <AtmisErrorCode>0</AtmisErrorCode>  
1595 + <ErrorMessage></ErrorMessage>
1596 + </Status>
1597 + </Response>
1598 +
1599 +
1600 +== Request example Order PDF File ==
1601 +
1602 +
1603 +
1604 + bool useZipstream = true; ~/~/ Always Supported, Keep it true!!
1605 + var content = new FormUrlEncodedContent(new[]
1606 + {
1607 + new KeyValuePair<string, string>("userName", WebserviceUsername),
1608 + new KeyValuePair<string, string>("password", WebservicePassword),
1609 + new KeyValuePair<string, string>("customerUsername", CustomerUsername),
1610 + new KeyValuePair<string, string>("clientId", customerid),
1611 + new KeyValuePair<string, string>("orderId", orderid),
1612 + new KeyValuePair<string, string>("useZip", useZipstream.ToString()), ~/~/ Always Supported, Keep it true!!.
1613 + new KeyValuePair<string, string>("languageCode", languageCode)
1614 + });
1615 +
1616 + HttpResponseMessage response = _HttpClient.PostAsync("GetOrderPdf", content).GetAwaiter().GetResult();
1617 + responseMessage = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
1618 + response.EnsureSuccessStatusCode();
1619 +
1620 +
1621 +== Response Order PDF Example ==
1622 +
1623 + <Response>
1624 + <OrderId>7113737</OrderId>
1625 + <FileContent>
1626 + BASE64 encoded file
1627 + </FileContent>
1628 + <Status>
1629 + <StatusCode>1</StatusCode>
1630 + <StatusCodeDescription>OK</StatusCodeDescription>
1631 + <ErrorMessage></ErrorMessage>
1632 + </Status>
1633 + </Response>
1634 +
1635 +
1636 +
1637 +(% element-id="357" %)
1381 1381  = (% element-id="356" %)Customer wants to see real time information about the status in the interface(%%) =
1382 1382  
1383 1383  (% element-id="354" %)