PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/LISAssayImporter/LISAssayImporter.cs

https://bitbucket.org/endevea/listools
C# | 1455 lines | 1209 code | 192 blank | 54 comment | 292 complexity | fe242ca7b68c3dbcf131bca7dd2796ba MD5 | raw file
Possible License(s): LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data.Odbc;
  5. using System.Xml;
  6. using System.Xml.Serialization;
  7. using System.IO;
  8. using System.Net;
  9. using System.Diagnostics;
  10. using ADX4;
  11. using ADX4.Tools.Validation;
  12. using ADX4.Tools;
  13. namespace LISAssayImporter
  14. {
  15. public partial class AssayImporter
  16. {
  17. #region Enumerations
  18. private enum Mappings
  19. {
  20. Analytes,
  21. Analyte,
  22. MapsTo,
  23. };
  24. #endregion
  25. #region Internal Classes
  26. public class LabProperty
  27. {
  28. public String m_assayType;
  29. public String m_lowerDetection;
  30. public String m_upperDetection;
  31. public String m_analyticalWeight;
  32. public String m_analysisMethod;
  33. public String m_units;
  34. }
  35. #endregion
  36. #region Constants
  37. private const string c_basicHttpBinding = "BasicHttpBinding_ILabIntegrationServices";
  38. private const string c_wsHttpBinding = "WSHttpBinding_ILabIntegrationServices";
  39. private const string c_useHttpsSwitch = "/UseHttps";
  40. private const string c_importIntoStd = "/Standard";
  41. private const string c_saveAdxToFile = "/Save";
  42. private const string c_applyAliasesSwitch = "/ApplyAliases";
  43. private const string c_strictLabPropertiesSwitch = "/StrictLabProperties";
  44. private const string c_importLabStdsSwitch = "/ImportLabStds";
  45. private const string c_importDupsSwitch = "/ImportDups";
  46. private const string c_triggerProxySwitch = "/TriggerProxy";
  47. private const string c_queryDatesSwitch = "/QueryDates";
  48. private const string c_queryDespatchSwitch = "/QueryDespatch";
  49. private const string c_queryLabjobSwitch = "/QueryLabjob";
  50. private const string c_userNameSwitch = "/UserName";
  51. private const string c_passwordSwitch = "/Password";
  52. private const string c_ignoreOrphanSamples = "/IgnoreOrphanSamples";
  53. private const string c_defaultLabJobField = "SubmissionLabJob";
  54. private const string c_defaultResultField = "SubmissionError";
  55. private const string c_electronicAssayRetrieval = "Electronic Assay Retrieval";
  56. private const string c_electronicAssayTypes = "Assay Types";
  57. private const string c_electronicLabJobs = "Labjobs";
  58. private const string c_electronicUnits = "Units";
  59. private const string c_electronicAnalysisMethods = "Analysis Methods";
  60. private const string c_electronicDsc = "DSC";
  61. private const string c_electronicProcessingPath = "Processing Paths";
  62. private const string c_electronicDownloadError = "Download Error";
  63. private const string c_electronicDefaults = "Defaults";
  64. private const string c_electronicDefaultsUserName = "LaboratoryUserName";
  65. private const string c_electronicDefaultsPassword = "LaboratoryPassword";
  66. private const string c_electronicNewLabReferenceMaterialId = "NewLabReferenceMaterialId";
  67. private const string c_electronicNewDuplicateMaterialId = "NewDuplicateMaterialId";
  68. private const string c_electronicConvertLabStandardId = "ConvertLabStandardId";
  69. private const string c_electronicNewLabStandardId = "NewLabStandardId";
  70. private enum specialProcedures {ReceivedSampleWeight,AnalyticalWeight,AnalyticalOrder };
  71. private List<String> c_electronicSpecialProcedures = new List<String>() { "Received Sample Weight", "Analytical Weight", "Analytical Order" };
  72. //private const string c_electronicReceivedSampleWeight = "Received Sample Weight";
  73. //private const string c_electronicAnalyticalWeight = "Analytical Weight";
  74. //private const string c_electronicAnalyticalOrder = "Analytical Order";
  75. private string c_labBlankType = "LAB_BLANK";
  76. private string c_labStandardType = "LAB_STD";
  77. private string c_labStdDescription = "Created during assay download from laboratory";
  78. private char[] c_processingPathSeparator = new char[1] { ',' };
  79. #endregion
  80. #region Variables
  81. private int m_errorCount = 0;
  82. private string m_odbcDsn;
  83. private string m_odbcUserName;
  84. private string m_odbcPassword;
  85. private string m_adxFileName;
  86. private string m_retrievalContext;
  87. private string m_labJobNo;
  88. private string m_labUserName;
  89. private string m_labPassword;
  90. private string m_labServer;
  91. private Boolean m_ignoreOrphanSamples = false;
  92. private Boolean m_importDupsSwitch = false;
  93. private Boolean m_importIntoCorp = true;
  94. private OdbcConnection m_odbc;
  95. private List<String> m_errorLabMessages = new List<string>();
  96. private Dictionary<String, String> m_unitsMapping;
  97. private Dictionary<String, String> m_analysisMethodsMapping;
  98. private Dictionary<String,String> m_assayTypesMapping;
  99. private Dictionary<String, String> m_dscMapping;
  100. private Dictionary<String, String> m_processingPathMapping;
  101. private List<String> m_acQuireDsc;
  102. private List<String> m_acQuireUnits;
  103. private List<String> m_acQuireAssayTypes;
  104. private List<String> m_acQuireAnalysisMethods;
  105. private List<String> m_acQuireCheckStages;
  106. private String m_newLabReferenceMaterialId;
  107. private String m_newDuplicateMaterialId;
  108. private String m_convertLabStandardId;
  109. private String m_newLabStandardId;
  110. private Boolean m_importAllowed = true;
  111. private Boolean m_useHttps = false;
  112. private Boolean m_applyAliases = false;
  113. private Boolean m_importLabStdsSwitch = false;
  114. private String m_labStdsPrefix = "LABSTD";
  115. private Int32 m_labStdsCount = 1;
  116. private Boolean m_strictLabPropertiesSwitch = false;
  117. private Boolean m_queryDatesSwitch = false;
  118. private DateTime m_queryDatesStart;
  119. private DateTime m_queryDatesFinish;
  120. private Boolean m_queryDespatchSwitch = false;
  121. private String m_queryDespatchName;
  122. private Boolean m_queryLabjobSwitch = false;
  123. private String m_queryLabJobNo;
  124. #endregion
  125. #region Properties
  126. public string LabJobNo
  127. {
  128. get
  129. {
  130. return m_labJobNo;
  131. }
  132. set
  133. {
  134. m_labJobNo = value;
  135. }
  136. }
  137. public string ODBCdsn
  138. {
  139. get
  140. {
  141. return m_odbcDsn;
  142. }
  143. set
  144. {
  145. m_odbcDsn = value;
  146. }
  147. }
  148. public String LabUserName
  149. {
  150. get
  151. {
  152. return m_labUserName;
  153. }
  154. set
  155. {
  156. m_labUserName = value;
  157. }
  158. }
  159. public String LabPassword
  160. {
  161. get
  162. {
  163. return m_labPassword;
  164. }
  165. set
  166. {
  167. m_labPassword = value;
  168. }
  169. }
  170. public String LabServer
  171. {
  172. get
  173. {
  174. return m_labServer;
  175. }
  176. set
  177. {
  178. m_labServer = value;
  179. }
  180. }
  181. public Boolean ImportIntoCorpModel
  182. {
  183. get
  184. {
  185. return m_importIntoCorp;
  186. }
  187. set
  188. {
  189. m_importIntoCorp = value;
  190. }
  191. }
  192. public Boolean ApplyAliases
  193. {
  194. get
  195. {
  196. return m_applyAliases;
  197. }
  198. set
  199. {
  200. m_applyAliases = value;
  201. }
  202. }
  203. public Boolean UseHttps
  204. {
  205. get
  206. {
  207. return m_useHttps;
  208. }
  209. set
  210. {
  211. m_useHttps = value;
  212. }
  213. }
  214. public String RetrievalContext
  215. {
  216. get
  217. {
  218. return m_retrievalContext;
  219. }
  220. set
  221. {
  222. m_retrievalContext = value;
  223. }
  224. }
  225. public Boolean StrictLabProperties
  226. {
  227. get
  228. {
  229. return m_strictLabPropertiesSwitch;
  230. }
  231. set
  232. {
  233. m_strictLabPropertiesSwitch = value;
  234. }
  235. }
  236. public Boolean ImportLabStdsSwitch
  237. {
  238. get
  239. {
  240. return m_importLabStdsSwitch;
  241. }
  242. set
  243. {
  244. m_importLabStdsSwitch = value;
  245. }
  246. }
  247. public String NewDuplicateMaterialId
  248. {
  249. get
  250. {
  251. return m_newDuplicateMaterialId;
  252. }
  253. set
  254. {
  255. m_newDuplicateMaterialId = value;
  256. }
  257. }
  258. public String NewLabReferenceMaterialId
  259. {
  260. get
  261. {
  262. return m_newLabReferenceMaterialId;
  263. }
  264. set
  265. {
  266. m_newLabReferenceMaterialId = value;
  267. }
  268. }
  269. public String NewLabStandardId
  270. {
  271. get
  272. {
  273. return m_newLabStandardId;
  274. }
  275. set
  276. {
  277. m_newLabStandardId = value;
  278. }
  279. }
  280. public String ConvertLabStandardId
  281. {
  282. get
  283. {
  284. return m_convertLabStandardId;
  285. }
  286. set
  287. {
  288. m_convertLabStandardId = value;
  289. }
  290. }
  291. public Boolean QueryRequired
  292. {
  293. get
  294. {
  295. return m_queryDatesSwitch || m_queryDespatchSwitch || m_queryLabjobSwitch;
  296. }
  297. }
  298. #endregion
  299. public Boolean Parse(string[] args)
  300. {
  301. // Parse the switches
  302. int curArg = 0;
  303. m_importIntoCorp = true;
  304. m_adxFileName = null;
  305. m_useHttps = false;
  306. m_applyAliases = false;
  307. m_importLabStdsSwitch = false;
  308. m_strictLabPropertiesSwitch = false;
  309. for (int i = 0; i < args.Length && curArg < args.Length; i++)
  310. {
  311. // ImportIntoStd switch
  312. if (String.Compare(c_importIntoStd, args[curArg], true) == 0)
  313. {
  314. curArg++;
  315. if (curArg >= args.Length)
  316. return false;
  317. m_importIntoCorp = false;
  318. }
  319. // ODBC user name switch
  320. else if (String.Compare(c_userNameSwitch, args[curArg], true) == 0)
  321. {
  322. curArg++;
  323. if (curArg >= args.Length)
  324. return false;
  325. m_odbcUserName = args[curArg++];
  326. }
  327. // ODBC password switch
  328. else if (String.Compare(c_passwordSwitch, args[curArg], true) == 0)
  329. {
  330. curArg++;
  331. if (curArg >= args.Length)
  332. return false;
  333. m_odbcPassword = args[curArg++];
  334. }
  335. // StrictLabProperties switch
  336. else if (String.Compare(c_strictLabPropertiesSwitch, args[curArg], true) == 0)
  337. {
  338. curArg++;
  339. if (curArg >= args.Length)
  340. return false;
  341. m_strictLabPropertiesSwitch = true;
  342. }
  343. // StrictLabProperties switch
  344. else if (String.Compare(c_ignoreOrphanSamples, args[curArg], true) == 0)
  345. {
  346. curArg++;
  347. if (curArg >= args.Length)
  348. return false;
  349. m_ignoreOrphanSamples = true;
  350. }
  351. // ImportLabStdsSwitch switch
  352. else if (String.Compare(c_importLabStdsSwitch, args[curArg], true) == 0)
  353. {
  354. curArg++;
  355. if (curArg >= args.Length)
  356. return false;
  357. m_labStdsPrefix = args[curArg++];
  358. m_importLabStdsSwitch = true;
  359. }
  360. // ImportDups switch
  361. else if (String.Compare(c_importDupsSwitch, args[curArg], true) == 0)
  362. {
  363. curArg++;
  364. if (curArg >= args.Length)
  365. return false;
  366. m_importDupsSwitch = true;
  367. }
  368. // Apply aliases
  369. else if (String.Compare(c_applyAliasesSwitch, args[curArg], true) == 0)
  370. {
  371. curArg++;
  372. if (curArg >= args.Length)
  373. return false;
  374. m_applyAliases = true;
  375. }
  376. // Use https
  377. else if (String.Compare(c_useHttpsSwitch, args[curArg], true) == 0)
  378. {
  379. curArg++;
  380. if (curArg >= args.Length)
  381. return false;
  382. m_useHttps = true;
  383. }
  384. // Query labjob
  385. else if (String.Compare(c_queryLabjobSwitch, args[curArg], true) == 0)
  386. {
  387. curArg++;
  388. if (curArg >= args.Length)
  389. return false;
  390. m_queryLabJobNo = args[curArg++];
  391. m_queryLabjobSwitch = true;
  392. }
  393. // Query despatch
  394. else if (String.Compare(c_queryDespatchSwitch, args[curArg], true) == 0)
  395. {
  396. curArg++;
  397. if (curArg >= args.Length)
  398. return false;
  399. m_queryDespatchName = args[curArg++];
  400. m_queryDespatchSwitch = true;
  401. }
  402. // Query dates
  403. else if (String.Compare(c_queryDatesSwitch, args[curArg], true) == 0)
  404. {
  405. curArg++;
  406. if (curArg >= args.Length)
  407. return false;
  408. try
  409. {
  410. m_queryDatesStart = DateTime.Parse(args[curArg++]);
  411. }
  412. catch (System.Exception exc)
  413. {
  414. return false;
  415. }
  416. if (curArg >= args.Length)
  417. return false;
  418. try
  419. {
  420. m_queryDatesFinish = DateTime.Parse(args[curArg++]);
  421. }
  422. catch (System.Exception exc)
  423. {
  424. return false;
  425. }
  426. m_queryDatesSwitch = true;
  427. }
  428. // Save ADX to file switch
  429. else if (String.Compare(c_saveAdxToFile, args[curArg], true) == 0)
  430. {
  431. curArg++;
  432. if (curArg >= args.Length)
  433. return false;
  434. m_adxFileName = args[curArg++];
  435. }
  436. // Add the trigger proxy field
  437. else if (String.Compare(c_triggerProxySwitch, args[curArg], true) == 0)
  438. {
  439. curArg++;
  440. if (curArg >= args.Length)
  441. return false;
  442. try
  443. {
  444. HttpWebRequest triggerProxy = (HttpWebRequest)HttpWebRequest.Create("http://www.google.com");
  445. triggerProxy.UseDefaultCredentials = true;
  446. triggerProxy.GetResponse();
  447. }
  448. catch (System.Exception exc)
  449. {
  450. Console.WriteLine(exc.Message);
  451. }
  452. }
  453. }
  454. // Get ODBC name
  455. if (curArg >= args.Length)
  456. return false;
  457. this.ODBCdsn = args[curArg++];
  458. // Get lab job context
  459. if (curArg >= args.Length)
  460. return false;
  461. this.RetrievalContext = args[curArg++];
  462. // Get lab job name
  463. if (curArg >= args.Length)
  464. return false;
  465. this.LabJobNo = args[curArg++];
  466. // Get laboratory server
  467. if (curArg >= args.Length)
  468. return false;
  469. this.LabServer = args[curArg++];
  470. // Get laboratory user name
  471. if (curArg < args.Length)
  472. this.LabUserName = args[curArg++];
  473. // Get laboratory password
  474. if (curArg < args.Length)
  475. this.LabPassword = args[curArg++];
  476. return true;
  477. }
  478. public void Connect()
  479. {
  480. // Open the connection
  481. try
  482. {
  483. m_odbc = new OdbcConnection();
  484. m_odbc.ConnectionString = String.Concat("DSN=",this.ODBCdsn,";");
  485. if (!String.IsNullOrEmpty(this.m_odbcUserName) && !String.IsNullOrEmpty(this.m_odbcPassword))
  486. {
  487. m_odbc.ConnectionString = String.Concat(m_odbc.ConnectionString, "Uid=", this.m_odbcUserName, ";");
  488. m_odbc.ConnectionString = String.Concat(m_odbc.ConnectionString, "Pwd=", this.m_odbcPassword, ";");
  489. }
  490. m_odbc.Open();
  491. if (String.IsNullOrEmpty(this.LabUserName))
  492. this.LabUserName = this.GetLaboratoryUserName();
  493. if (String.IsNullOrEmpty(this.LabPassword))
  494. this.LabPassword = this.GetLaboratoryPassword();
  495. }
  496. // Trap and throw exceptions higher up
  497. catch(SystemException exc)
  498. {
  499. m_odbc = null;
  500. throw exc;
  501. }
  502. }
  503. public void Close()
  504. {
  505. if (m_odbc == null)
  506. return;
  507. // Close the connection
  508. try
  509. {
  510. m_odbc.Close();
  511. }
  512. // Trap and throw exceptions higher up
  513. catch (SystemException exc)
  514. {
  515. throw exc;
  516. }
  517. }
  518. public ADX GetLabJob()
  519. {
  520. Laboratory.LabIntegrationServicesClient laboratory;
  521. if (m_useHttps)
  522. laboratory = new Laboratory.LabIntegrationServicesClient("WSHttpBinding_ILabIntegrationServices", this.LabServer);
  523. else
  524. laboratory = new Laboratory.LabIntegrationServicesClient("BasicHttpBinding_ILabIntegrationServices", this.LabServer);
  525. laboratory.ClientCredentials.UserName.UserName = this.LabUserName;
  526. laboratory.ClientCredentials.UserName.Password = this.LabPassword;
  527. Laboratory.LabIntegrationContext context = new LISAssayImporter.Laboratory.LabIntegrationContext();
  528. context.Name = this.RetrievalContext;
  529. ADX[] results = laboratory.GetLabJobResults(context,this.m_labJobNo);
  530. if (results == null || results.Length != 1)
  531. return null;
  532. DocumentValidation validator = new DocumentValidation();
  533. validator.Check(results[0], ValidationLevel.LaboratoryExport, this.CleanSampleId);
  534. if (validator.Count > 0)
  535. {
  536. foreach (ValidationResult result in validator)
  537. if (result.level == ErrorLevel.Error)
  538. this.LogLaboratoryError(String.Format(Language.errValidationError, result.message));
  539. }
  540. return results[0];
  541. }
  542. public void ReportLabErrors(ADX results)
  543. {
  544. Laboratory.LabIntegrationServicesClient laboratory;
  545. if (m_useHttps)
  546. laboratory = new Laboratory.LabIntegrationServicesClient("WSHttpBinding_ILabIntegrationServices", this.LabServer);
  547. else
  548. laboratory = new Laboratory.LabIntegrationServicesClient("BasicHttpBinding_ILabIntegrationServices", this.LabServer);
  549. laboratory.ClientCredentials.UserName.UserName = this.LabUserName;
  550. laboratory.ClientCredentials.UserName.Password = this.LabPassword;
  551. Laboratory.ActionResult error = new LISAssayImporter.Laboratory.ActionResult();
  552. error.ErrorCode = -1;
  553. error.Status = LISAssayImporter.Laboratory.ActionResult.ResultStatus.Rejected;
  554. error.Message = String.Format("Labjob: {0}|",this.LabJobNo);
  555. foreach(String message in m_errorLabMessages)
  556. error.Message = String.Concat(error.Message,message,"|");
  557. Laboratory.LabIntegrationContext context = new LISAssayImporter.Laboratory.LabIntegrationContext();
  558. context.Name = this.RetrievalContext;
  559. laboratory.ReportInformationError(context, error, results);
  560. }
  561. public void Import(ADX document)
  562. {
  563. m_importAllowed = true;
  564. ReadSettings();
  565. // Import the ADX document into acQuire
  566. SendToCorpModel(document);
  567. }
  568. private void ReadSettings()
  569. {
  570. try
  571. {
  572. OdbcCommand odbcCmd = new OdbcCommand(String.Format("delete from METAIMPORTALIASES where CATEGORY = '{0}' and SUBCATEGORY = '{1}'", c_electronicAssayRetrieval, c_electronicDownloadError), this.m_odbc);
  573. odbcCmd.ExecuteNonQuery();
  574. }
  575. catch (System.Exception exc)
  576. {
  577. }
  578. try
  579. {
  580. OdbcCommand odbcCmd = new OdbcCommand(String.Format("select MAX(CAST(SUBSTRING(CHECKID,LEN('{0}')+1,100) as int))+1 from CHECKSAMPLE where CHECKID like '{1}%'", m_labStdsPrefix,m_labStdsPrefix), this.m_odbc);
  581. Object result = odbcCmd.ExecuteScalar();
  582. m_labStdsCount = (result == null || result == DBNull.Value ? 1 : (int)result);
  583. }
  584. catch (System.Exception exc)
  585. {
  586. }
  587. m_analysisMethodsMapping = GetAnalysisMethods();
  588. m_assayTypesMapping = GetAssayTypeMapping();
  589. m_unitsMapping = GetUnitsMapping();
  590. m_dscMapping = GetDscMapping();
  591. m_processingPathMapping = GetProcessingPathMapping();
  592. m_acQuireAnalysisMethods = GetacQuireAnalysisMethods();
  593. m_acQuireDsc = GetacQuireDSC();
  594. m_acQuireAssayTypes = GetacQuireAssayTypes();
  595. m_acQuireUnits = GetacQuireUnits();
  596. m_acQuireCheckStages = GetacQuireCheckStages();
  597. m_newDuplicateMaterialId = GetSetting(c_electronicNewDuplicateMaterialId);
  598. m_newLabReferenceMaterialId = GetSetting(c_electronicNewLabReferenceMaterialId);
  599. m_convertLabStandardId = GetSetting(c_electronicConvertLabStandardId);
  600. m_newLabStandardId = GetSetting(c_electronicNewLabStandardId);
  601. }
  602. private void SendToCorpModel(ADX document)
  603. {
  604. CheckLabJob(document);
  605. List<LabProperty> labProperties = CheckLabCorpProperties(document);
  606. CheckAssays(document);
  607. if (this.m_importAllowed)
  608. {
  609. AddLabJob(document);
  610. AddLabCorpProperties(document, labProperties);
  611. AddAssays(document, labProperties);
  612. }
  613. else if (m_errorLabMessages.Count > 0)
  614. ReportLabErrors(document);
  615. }
  616. /// <summary>
  617. /// Checks the lab job information for errors.
  618. /// </summary>
  619. /// <param name="document">The ADX document.</param>
  620. private void CheckLabJob(ADX document)
  621. {
  622. OdbcCommand odbcCmd;
  623. // Is there an ADX lab job ?
  624. if (document.Header == null || document.Header.AnalyticalReport == null || document.Header.AnalyticalReport.LabJob == null)
  625. {
  626. LogLaboratoryError(Language.errNoLabjobSpecified);
  627. }
  628. else
  629. {
  630. // Is the ADX LAB JOB in the acQuire database ?
  631. odbcCmd = new OdbcCommand(String.Concat("select 1 from DESPATCHRETURN where LABJOBNO = '", document.Header.AnalyticalReport.LabJob, "'"), this.m_odbc);
  632. if (odbcCmd.ExecuteScalar() != null)
  633. LogLocalError(String.Format(Language.errLabjobIsAlreadyLoaded, document.Header.AnalyticalReport.LabJob));
  634. }
  635. // Is there a DespatchNo in the ADX document ?
  636. if (document.Header == null || document.Header.Despatch == null || String.IsNullOrEmpty(document.Header.Despatch.DespatchNo) || true)
  637. {
  638. String despatchNo = SearchForDespatch(document);
  639. if (String.IsNullOrEmpty(despatchNo))
  640. {
  641. LogLocalError(Language.errNoDespatchSpecified);
  642. return;
  643. }
  644. else
  645. {
  646. if (document.Header == null)
  647. document.Header = new Header();
  648. if (document.Header.Despatch == null)
  649. document.Header.Despatch = new DespatchDetails();
  650. document.Header.Despatch.DespatchNo = despatchNo;
  651. }
  652. }
  653. if (String.IsNullOrEmpty(document.Header.Despatch.DespatchNo))
  654. {
  655. LogLocalError(Language.errNoDespatchSpecified);
  656. return;
  657. }
  658. // Is the ADX DespatchNo in the acQuire database ?
  659. odbcCmd = new OdbcCommand(String.Concat("select 1 from DESPATCHSEND where DESPATCHNO = '", document.Header.Despatch.DespatchNo, "'"), this.m_odbc);
  660. if (odbcCmd.ExecuteScalar() == null)
  661. {
  662. LogLaboratoryError(String.Format(Language.errDespatchNotListedInDatabase, document.Header.Despatch.DespatchNo));
  663. return;
  664. }
  665. }
  666. /// <summary>
  667. /// Searches for the despatch matching this labjob using the SubmissionLabJob field.
  668. /// <remarks>This search only works if the despatch was submitted electronically.</remarks>
  669. /// </summary>
  670. /// <param name="document">The ADX document.</param>
  671. /// <returns>The matching despatch</returns>
  672. private String SearchForDespatch(ADX document)
  673. {
  674. OdbcCommand odbcCmd = new OdbcCommand(String.Concat("select DESPATCHNO from DESPATCHDETAILS where NAME = '", c_defaultLabJobField, "' and VALUE = '", document.Header.AnalyticalReport.LabJob, "'"), this.m_odbc);
  675. Object despatchNo = odbcCmd.ExecuteScalar();
  676. if (despatchNo != null)
  677. return despatchNo.ToString();
  678. return null;
  679. }
  680. private List<LabProperty> CheckLabCorpProperties(ADX document)
  681. {
  682. // Get the analysis suite definition for this despatch
  683. OdbcCommand odbcCmd = new OdbcCommand(String.Concat("select ANALYSISSUITE from DESPATCHSEND where DESPATCHNO = '", document.Header.Despatch.DespatchNo, "'"), this.m_odbc);
  684. Object result = odbcCmd.ExecuteScalar();
  685. String analysisSuite = (result == null ? null : result.ToString());
  686. List<String> analysisSuiteDef = new List<string>();
  687. if (!String.IsNullOrEmpty(analysisSuite))
  688. analysisSuiteDef = GetacQuireAnalysisSuite(analysisSuite);
  689. ProcessingTrees processingTrees = new ProcessingTrees(document, this.ValidationEventCallback,this.CleanSampleId);
  690. processingTrees.Build(document.Results.ProcessingGroup);
  691. List<LabProperty> labProperties = new List<LabProperty>();
  692. foreach (ProcessingTree processingTree in processingTrees)
  693. {
  694. foreach (AssayRecord assayRecord in processingTree)
  695. {
  696. Procedure sampleWeightProcedure = assayRecord.ProcessingHistory.FindProcedure(c_electronicSpecialProcedures[(int)specialProcedures.ReceivedSampleWeight]);
  697. if (sampleWeightProcedure is WeighingProcedure)
  698. {
  699. // Is this property in the analysis suite definition ?
  700. String assayType = c_electronicSpecialProcedures[(int)specialProcedures.ReceivedSampleWeight];
  701. if (this.ApplyAliases)
  702. if (m_assayTypesMapping.ContainsKey(assayType))
  703. assayType = m_assayTypesMapping[assayType];
  704. if (analysisSuiteDef.Count == 0 || analysisSuiteDef.Contains(assayType))
  705. {
  706. Measurement sampleWeight = new Measurement();
  707. sampleWeight.ProcedureRef = c_electronicSpecialProcedures[(int)specialProcedures.ReceivedSampleWeight];
  708. sampleWeight.Status = MeasurementStatus.Detected;
  709. sampleWeight.StatusSpecified = true;
  710. sampleWeight.Property = c_electronicSpecialProcedures[(int)specialProcedures.ReceivedSampleWeight];
  711. sampleWeight.Value = (sampleWeightProcedure as WeighingProcedure).Mass;
  712. ExtractLabCorpProperty(labProperties, new AssayMeasurement(sampleWeight,sampleWeightProcedure));
  713. }
  714. }
  715. foreach (AssayMeasurement measurement in assayRecord)
  716. {
  717. if (measurement.Procedure == null || String.IsNullOrEmpty(measurement.Procedure.Id))
  718. continue;
  719. ExtractLabCorpProperty(labProperties, measurement);
  720. }
  721. }
  722. }
  723. // Map the lab properties to acquire codes
  724. foreach (LabProperty labProperty in labProperties)
  725. {
  726. // Is this property in the analysis suite definition ?
  727. if (analysisSuiteDef.Count > 0)
  728. if (!analysisSuiteDef.Contains(labProperty.m_assayType) && !c_electronicSpecialProcedures.Contains(labProperty.m_assayType))
  729. LogLaboratoryError(String.Format(Language.errAssayTypeNotInDespatchAnalysisSuite, labProperty.m_assayType, document.Header.Despatch.DespatchNo, analysisSuite));
  730. // Check the units
  731. if (String.IsNullOrEmpty(labProperty.m_units))
  732. LogLaboratoryError(String.Format(Language.errNoUnitsSpecified, labProperty.m_assayType));
  733. else if (this.ApplyAliases)
  734. {
  735. if (m_unitsMapping.ContainsKey(labProperty.m_units))
  736. labProperty.m_units = m_unitsMapping[labProperty.m_units];
  737. if (!m_acQuireUnits.Contains(labProperty.m_units))
  738. LogLaboratoryError(String.Format(Language.errUnitsNotRecognised, labProperty.m_units,labProperty.m_assayType));
  739. }
  740. else if (!m_acQuireUnits.Contains(labProperty.m_units))
  741. LogLaboratoryError(String.Format(Language.errUnitsNotRecognised, labProperty.m_units, labProperty.m_assayType));
  742. // Check the analysis method
  743. if (String.IsNullOrEmpty(labProperty.m_analysisMethod) && this.StrictLabProperties)
  744. LogLaboratoryError(String.Format(Language.errNoAnalysisMethodSpecified, labProperty.m_assayType));
  745. else if (!String.IsNullOrEmpty(labProperty.m_analysisMethod))
  746. {
  747. if (this.ApplyAliases)
  748. {
  749. if (m_analysisMethodsMapping.ContainsKey(labProperty.m_analysisMethod))
  750. labProperty.m_analysisMethod = m_analysisMethodsMapping[labProperty.m_analysisMethod];
  751. if (!m_acQuireAnalysisMethods.Contains(labProperty.m_analysisMethod))
  752. {
  753. if (this.StrictLabProperties)
  754. LogLaboratoryError(String.Format(Language.errAnalysisMethodNotRecognised, labProperty.m_analysisMethod, labProperty.m_assayType));
  755. else
  756. labProperty.m_analysisMethod = "";
  757. }
  758. }
  759. else if (!m_acQuireAnalysisMethods.Contains(labProperty.m_analysisMethod))
  760. {
  761. if (this.StrictLabProperties)
  762. LogLaboratoryError(String.Format(Language.errAnalysisMethodNotRecognised, labProperty.m_analysisMethod, labProperty.m_assayType));
  763. else
  764. labProperty.m_analysisMethod = "";
  765. }
  766. }
  767. // Check the lower detection limit
  768. if (String.IsNullOrEmpty(labProperty.m_lowerDetection) && this.StrictLabProperties)
  769. {
  770. LogLaboratoryError(String.Format(Language.errNoLowerDetectionLimitSpecified, labProperty.m_assayType));
  771. }
  772. else if (!String.IsNullOrEmpty(labProperty.m_lowerDetection))
  773. {
  774. try
  775. {
  776. Double.Parse(labProperty.m_lowerDetection);
  777. }
  778. catch (System.Exception exc)
  779. {
  780. LogLaboratoryError(String.Format(Language.errLowerDetectionNotRecognised, labProperty.m_lowerDetection, labProperty.m_assayType));
  781. }
  782. }
  783. // Check the upper detection limit
  784. if (String.IsNullOrEmpty(labProperty.m_upperDetection) && this.StrictLabProperties)
  785. {
  786. LogLaboratoryError(String.Format(Language.errNoUpperDetectionLimitSpecified, labProperty.m_assayType));
  787. }
  788. else if (!String.IsNullOrEmpty(labProperty.m_upperDetection))
  789. {
  790. try
  791. {
  792. Double.Parse(labProperty.m_upperDetection);
  793. }
  794. catch (System.Exception exc)
  795. {
  796. LogLaboratoryError(String.Format(Language.errUpperDetectionNotRecognised, labProperty.m_upperDetection, labProperty.m_assayType));
  797. }
  798. }
  799. // Check if the lab properties are already loaded
  800. odbcCmd = new OdbcCommand(String.Concat("select 1 from CORPLABPROPERTIES where LABJOBNO = '", document.Header.AnalyticalReport.LabJob, "' and NAME = '", labProperty.m_assayType, "'"), this.m_odbc);
  801. if (odbcCmd.ExecuteScalar() != null)
  802. LogLocalError(String.Format(Language.errLabPropertyAlreadyLoaded, labProperty.m_assayType,document.Header.AnalyticalReport.LabJob));
  803. }
  804. return labProperties;
  805. }
  806. private void ExtractLabCorpProperty(List<LabProperty> labProperties, AssayMeasurement measurement)
  807. {
  808. String assayType = measurement.Procedure.Id;
  809. if (String.IsNullOrEmpty(assayType))
  810. LogLaboratoryError(String.Format(Language.errNoProcedureRefSpecified, assayType));
  811. else if (this.ApplyAliases)
  812. {
  813. if (m_assayTypesMapping.ContainsKey(assayType))
  814. assayType = m_assayTypesMapping[assayType];
  815. if (!m_acQuireAssayTypes.Contains(assayType) && !c_electronicSpecialProcedures.Contains(assayType))
  816. LogLaboratoryError(String.Format(Language.errProcedureRefNotRecognised, assayType));
  817. }
  818. else if (!m_acQuireAssayTypes.Contains(assayType) && !c_electronicSpecialProcedures.Contains(assayType))
  819. LogLaboratoryError(String.Format(Language.errProcedureRefNotRecognised, assayType));
  820. Boolean found = false;
  821. foreach (LabProperty labProperty in labProperties)
  822. {
  823. if (String.Equals(labProperty.m_assayType, assayType))
  824. {
  825. found = true;
  826. break;
  827. }
  828. }
  829. if (!found)
  830. {
  831. LabProperty labProperty = new LabProperty();
  832. labProperty.m_assayType = assayType;
  833. if (measurement.Procedure is AnalysisProcedure)
  834. {
  835. AnalysisProcedure analysisProcedure = measurement.Procedure as AnalysisProcedure;
  836. labProperty.m_analysisMethod = analysisProcedure.Code;
  837. labProperty.m_units = analysisProcedure.UOM;
  838. if (analysisProcedure.BelowDetectionLimit != null && analysisProcedure.BelowDetectionLimit.Value != null)
  839. labProperty.m_lowerDetection = analysisProcedure.BelowDetectionLimit.Value;
  840. if (analysisProcedure.OverRangeLimit != null && analysisProcedure.OverRangeLimit.Value != null)
  841. labProperty.m_upperDetection = analysisProcedure.OverRangeLimit.Value;
  842. }
  843. if (measurement.Procedure is WeighingProcedure)
  844. {
  845. WeighingProcedure weighProcedure = measurement.Procedure as WeighingProcedure;
  846. if (weighProcedure.Mass != null)
  847. labProperty.m_units = weighProcedure.Mass.UOM;
  848. }
  849. labProperties.Add(labProperty);
  850. }
  851. }
  852. private void CheckAssays(ADX document)
  853. {
  854. if (document.Samples == null || document.Samples.Sample == null)
  855. LogLaboratoryError(String.Format(Language.errNoSamplesListIsSpecified));
  856. ProcessingTrees processingTrees = new ProcessingTrees(document, this.ValidationEventCallback, this.CleanSampleId);
  857. processingTrees.Build(document.Results.ProcessingGroup);
  858. foreach (ProcessingTree processingTree in processingTrees)
  859. {
  860. Boolean isLabStandard = false;
  861. if (document.Samples != null && document.Samples.Sample != null)
  862. {
  863. foreach (SampleReference sampleRef in processingTree.SampleRefs)
  864. {
  865. Sample selectedSample = null;
  866. foreach (Sample sample in document.Samples.Sample)
  867. if (sample != null)
  868. if (String.Equals(this.CleanSampleId(sample.Id), sampleRef.IdRef))
  869. selectedSample = sample;
  870. if (selectedSample == null)
  871. LogLaboratoryError(String.Format(Language.errBrokenSampleReference, sampleRef.IdRef));
  872. else
  873. {
  874. OdbcCommand odbcCmd = new OdbcCommand(String.Concat("select 1 from SAMPLEDESPATCH where DESPATCHNO = '", document.Header.Despatch.DespatchNo, "' and SAMPLEID = '", CleanSampleId(sampleRef.IdRef), "'"), this.m_odbc);
  875. if (odbcCmd.ExecuteScalar() == null)
  876. {
  877. odbcCmd = new OdbcCommand(String.Concat("select 1 from CHECKDESPATCH where DESPATCHNO = '", document.Header.Despatch.DespatchNo, "' and CHECKID = '", CleanSampleId(sampleRef.IdRef), "'"), this.m_odbc);
  878. if (odbcCmd.ExecuteScalar() == null)
  879. {
  880. if (!(selectedSample is ReferenceMaterial))
  881. {
  882. if (!m_ignoreOrphanSamples || processingTree.Count > 0)
  883. LogLaboratoryError(String.Format(Language.errSampleNotMemberOfDespatch, sampleRef.IdRef, document.Header.Despatch.DespatchNo));
  884. }
  885. else
  886. isLabStandard = true;
  887. }
  888. }
  889. }
  890. }
  891. }
  892. foreach (AssayRecord assayRecord in processingTree)
  893. {
  894. if (assayRecord == null)
  895. continue;
  896. String checkStage = assayRecord.ProcessingPath.ToString();
  897. if (this.ApplyAliases)
  898. checkStage = MapProcessingPath(assayRecord);
  899. if (!String.IsNullOrEmpty(checkStage))
  900. if (!m_acQuireCheckStages.Contains(checkStage))
  901. if (!isLabStandard)
  902. LogLaboratoryError(String.Format(Language.errUnknownProcessingPath, (String.IsNullOrEmpty(assayRecord.InternalAnalysisId) ? "" : assayRecord.InternalAnalysisId), assayRecord.ProcessingPath.ToString()));
  903. foreach (AssayMeasurement measurement in assayRecord)
  904. {
  905. if (measurement == null || measurement.Procedure == null)
  906. continue;
  907. String assayType = measurement.Procedure.Id;
  908. if (String.IsNullOrEmpty(assayType))
  909. LogLaboratoryError(String.Format(Language.errNoProcedureRefSpecified, assayType));
  910. else
  911. {
  912. if (this.ApplyAliases)
  913. {
  914. if (m_assayTypesMapping.ContainsKey(measurement.Procedure.Id))
  915. {
  916. assayType = m_assayTypesMapping[measurement.Procedure.Id];
  917. if (!m_acQuireAssayTypes.Contains(assayType))
  918. LogLocalError(String.Format(Language.errProcedureRefNotRecognised, measurement.Procedure.Id));
  919. }
  920. }
  921. else if (!m_acQuireAssayTypes.Contains(assayType))
  922. LogLaboratoryError(String.Format(Language.errProcedureRefNotRecognised, measurement.Procedure.Id));
  923. }
  924. String status = "";
  925. if (measurement.Measurement.StatusSpecified)
  926. status = measurement.Measurement.Status.ToString();
  927. if (this.ApplyAliases)
  928. if (m_dscMapping.ContainsKey(status))
  929. status = m_dscMapping[status];
  930. if (!m_acQuireDsc.Contains(status) && !String.IsNullOrEmpty(status))
  931. LogLocalError(String.Format(Language.errDSCNotRecognised, status));
  932. if (!String.IsNullOrEmpty(document.Header.AnalyticalReport.LabJob) && processingTree.SampleRefs.Count > 0 && !String.IsNullOrEmpty(processingTree.SampleRefs[0].IdRef))
  933. {
  934. OdbcCommand odbcCmd = new OdbcCommand(String.Concat("select 1 from CORPSAMPLEASSAY where LABJOBNO = '", document.Header.AnalyticalReport.LabJob, "' and SAMPLEID = '", CleanSampleId(processingTree.SampleRefs[0].IdRef), "' and NAME = '",assayType,"'"), this.m_odbc);
  935. if (odbcCmd.ExecuteScalar() != null)
  936. LogLocalError(String.Format(Language.errSampleAssayAlreadyLoaded, processingTree.SampleRefs[0].IdRef, assayType));
  937. odbcCmd = new OdbcCommand(String.Concat("select 1 from CORPCHECKASSAY where LABJOBNO = '", document.Header.AnalyticalReport.LabJob, "' and CHECKID = '", CleanSampleId(processingTree.SampleRefs[0].IdRef), "' and NAME = '", assayType, "'"), this.m_odbc);
  938. if (odbcCmd.ExecuteScalar() != null)
  939. LogLocalError(String.Format(Language.errCheckAssayAlreadyLoaded, processingTree.SampleRefs[0].IdRef, assayType));
  940. }
  941. }
  942. }
  943. }
  944. }
  945. private void AddLabJob(ADX document)
  946. {
  947. OdbcCommand odbcCmd;
  948. // Add the lab job to acQuire
  949. odbcCmd = new OdbcCommand(String.Concat(new String[] { "insert into DESPATCHRETURN (LABJOBNO,RETURNDATE,DESPATCHNO) values(?,?,?)", }), this.m_odbc);
  950. odbcCmd.Parameters.Add(new OdbcParameter("@LABJOBNO",document.Header.AnalyticalReport.LabJob));
  951. odbcCmd.Parameters.Add(new OdbcParameter("@RETURNDATE", ConvertToacQuireDate(DateTime.Now)));
  952. odbcCmd.Parameters.Add(new OdbcParameter("@DESPATCHNO", document.Header.Despatch.DespatchNo));
  953. if (odbcCmd.ExecuteNonQuery() != 1)
  954. {
  955. LogLocalError(String.Format(Language.errLabJobDetailsCannotBeLoaded));
  956. return;
  957. }
  958. }
  959. private string ConvertToacQuireDate(DateTime dateTime)
  960. {
  961. string[] acQuireMonth = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  962. return String.Format("{0}-{1}-{2}", dateTime.Day, acQuireMonth[dateTime.Month-1], dateTime.Year);
  963. }
  964. private void AddLabCorpProperties(ADX document,List<LabProperty> labProperties)
  965. {
  966. OdbcCommand odbcCmd;
  967. // Add the lab job property to acQuire
  968. foreach (LabProperty labProperty in labProperties)
  969. {
  970. odbcCmd = new OdbcCommand(String.Concat(new String[] { "insert into CORPLABPROPERTIES (LABJOBNO,DESPATCHNO,NAME,UOM,LABANALYSISMETHOD,LOWERDETECTION,UPPERDETECTION) values(?,?,?,?,?,?,?)", }), this.m_odbc);
  971. odbcCmd.Parameters.Add(new OdbcParameter("@LABJOBNO", document.Header.AnalyticalReport.LabJob));
  972. odbcCmd.Parameters.Add(new OdbcParameter("@DESPATCHNO", document.Header.Despatch.DespatchNo));
  973. odbcCmd.Parameters.Add(new OdbcParameter("@NAME", labProperty.m_assayType));
  974. odbcCmd.Parameters.Add(new OdbcParameter("@UOM", labProperty.m_units));
  975. if (String.IsNullOrEmpty(labProperty.m_analysisMethod))
  976. odbcCmd.Parameters.Add(new OdbcParameter("@LABANALYSISMETHOD", DBNull.Value));
  977. else
  978. odbcCmd.Parameters.Add(new OdbcParameter("@LABANALYSISMETHOD", labProperty.m_analysisMethod));
  979. if (String.IsNullOrEmpty(labProperty.m_lowerDetection))
  980. odbcCmd.Parameters.Add(new OdbcParameter("@LOWERDETECTION", DBNull.Value));
  981. else
  982. odbcCmd.Parameters.Add(new OdbcParameter("@LOWERDETECTION", labProperty.m_lowerDetection));
  983. if (String.IsNullOrEmpty(labProperty.m_upperDetection))
  984. odbcCmd.Parameters.Add(new OdbcParameter("@UPPERDETECTION", DBNull.Value));
  985. else
  986. odbcCmd.Parameters.Add(new OdbcParameter("@UPPERDETECTION", labProperty.m_upperDetection));
  987. if (odbcCmd.ExecuteNonQuery() != 1)
  988. LogLocalError(String.Format(Language.errLabPropertyDetailsCannotBeLoaded, labProperty.m_assayType));
  989. }
  990. }
  991. private void AddAssays(ADX document, List<LabProperty> labProperties)
  992. {
  993. ProcessingTrees processingTrees = new ProcessingTrees(document,null,this.CleanSampleId);
  994. processingTrees.Build(document.Results.ProcessingGroup);
  995. foreach (ProcessingTree processingTree in processingTrees)
  996. {
  997. String sampleId = CleanSampleId(processingTree.SampleRefs[0].IdRef);
  998. Boolean isCheckSample = true;
  999. Boolean sampleExists = true;
  1000. String checkDuplicateNo = null;
  1001. Boolean isLabStandard = false;
  1002. OdbcCommand odbcCmd = new OdbcCommand(String.Concat("select 1 from SAMPLEDESPATCH where DESPATCHNO = '", document.Header.Despatch.DespatchNo, "' and SAMPLEID = '", sampleId, "'"), this.m_odbc);
  1003. if (odbcCmd.ExecuteScalar() != null)
  1004. isCheckSample = false;
  1005. else
  1006. {
  1007. odbcCmd = new OdbcCommand(String.Concat("select DUPLICATENO from CHECKDESPATCH where DESPATCHNO = '", document.Header.Despatch.DespatchNo

Large files files are truncated, but you can click here to view the full file