vCloudScanData.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. using System;
  2. using System.IO;
  3. using System.Threading;
  4. using Vinno.IUS.Common.Log;
  5. using Vinno.IUS.Common.Network.Leaf;
  6. using Vinno.IUS.Common.Network.Transfer;
  7. using Vinno.vCloud.Common.Storage;
  8. using Vinno.vCloud.Common.Storage.Upload;
  9. using Vinno.vCloud.FIS.CrossPlatform.Common.Helper;
  10. using Vinno.vCloud.Protocol.Infrastructures;
  11. using Vinno.vCloud.Protocol.Messages.Report;
  12. using Vinno.vCloud.Protocol.Messages.Terminal.Remedical.TerminalDatas;
  13. namespace Vinno.vCloud.Common.FIS.Remedicals
  14. {
  15. internal class vCloudScanData : IvCloudScanData, IDisposable
  16. {
  17. private UploadStatus _status;
  18. private bool _disposed;
  19. public readonly ClientLeaf Leaf;
  20. /// <inheritdoc />
  21. /// <summary>
  22. /// Gets the id of this scan data.
  23. /// </summary>
  24. public string Id { get; }
  25. /// <inheritdoc />
  26. /// <summary>
  27. /// Gets the examId of this scan data.
  28. /// </summary>
  29. public string ExamId { get; }
  30. /// <inheritdoc />
  31. /// <summary>
  32. /// Gets or sets the ExamRecordId for this scan data.
  33. /// </summary>
  34. public string ExamRecordId { get; set; }
  35. /// <inheritdoc />
  36. /// <summary>
  37. /// Gets the workorder Id.
  38. /// </summary>
  39. public string WorkOrderId { get; }
  40. /// <summary>
  41. /// Raised when the status changed.
  42. /// </summary>
  43. public event EventHandler StatusChanged;
  44. /// <inheritdoc />
  45. /// <summary>
  46. /// Gets the status of this Scan data.
  47. /// </summary>
  48. public UploadStatus Status
  49. {
  50. get => _status;
  51. internal set
  52. {
  53. if (_status != value)
  54. {
  55. var old = _status;
  56. _status = value;
  57. if (_status == UploadStatus.Uploaded || _status == UploadStatus.Deleted)
  58. {
  59. Delete(old);
  60. }
  61. else
  62. {
  63. Move(old, _status);
  64. }
  65. OnStatusChanged();
  66. }
  67. }
  68. }
  69. /// <inheritdoc />
  70. /// <summary>
  71. /// Gets the vid file path.
  72. /// </summary>
  73. public string VidFilePath { get; private set; }
  74. /// <summary>
  75. /// Gets the sd file path.
  76. /// </summary>
  77. public string ScanDataFilePath { get; private set; }
  78. /// <inheritdoc />
  79. /// <summary>
  80. /// Gets the description of this scan data.
  81. /// </summary>
  82. public string Description { get; }
  83. /// <inheritdoc />
  84. /// <summary>
  85. /// Gets the data type of this scan data.
  86. /// </summary>
  87. public VidType DataType { get; }
  88. /// <inheritdoc />
  89. /// <summary>
  90. /// Gets the patient info for this scan data.
  91. /// </summary>
  92. public PatientScanInfo PatientInfo { get; }
  93. public vCloudScanData(ClientLeaf leaf, IvCloudExamRecord record, string id, string vidFilePath,
  94. VidType dataType, string description, PatientScanInfo patientInfo, UploadStatus status)
  95. {
  96. _status = status;
  97. Leaf = leaf;
  98. ExamRecordId = record.Id;
  99. ExamId = record.ExamId;
  100. WorkOrderId = record.WorkOrderId;
  101. Id = id;
  102. DataType = dataType;
  103. if (description == "FromSonopost")
  104. {
  105. Description = "From agent";
  106. }
  107. else
  108. {
  109. Description = description;
  110. }
  111. PatientInfo = patientInfo;
  112. //Generate files.
  113. VidFilePath = GetVidFilePath(_status);
  114. if (string.Compare(VidFilePath, vidFilePath, StringComparison.OrdinalIgnoreCase) != 0)
  115. {
  116. File.Move(vidFilePath, VidFilePath);
  117. }
  118. //Save self.
  119. Save();
  120. }
  121. ~vCloudScanData()
  122. {
  123. DoDispose();
  124. }
  125. private void OnStatusChanged()
  126. {
  127. StatusChanged?.Invoke(this, EventArgs.Empty);
  128. }
  129. private ReportPatientInfoMessage1 CreateReportPatientInfoMessage()
  130. {
  131. ReportPatientInfoMessage1 patientInfoMessage = null;
  132. if (PatientInfo != null)
  133. {
  134. ReportPatientURInfoMessage patientUrInfo;
  135. if (PatientInfo.PatientUrInfo != null)
  136. {
  137. patientUrInfo = MessagePool.GetMessage<ReportPatientURInfoMessage>();
  138. patientUrInfo.PPSACoefficient = PatientInfo.PatientUrInfo.PPSACoefficient;
  139. patientUrInfo.PSA = PatientInfo.PatientUrInfo.PSA;
  140. }
  141. else
  142. {
  143. patientUrInfo = null;
  144. }
  145. ReportPatientGYNInfoMessage patientGynInfo;
  146. if (PatientInfo.PatientGynInfo != null)
  147. {
  148. patientGynInfo = MessagePool.GetMessage<ReportPatientGYNInfoMessage>();
  149. patientGynInfo.AB = PatientInfo.PatientGynInfo.AB;
  150. patientGynInfo.Ectopic = PatientInfo.PatientGynInfo.Ectopic;
  151. patientGynInfo.Gravida = PatientInfo.PatientGynInfo.Gravida;
  152. patientGynInfo.LMP = PatientInfo.PatientGynInfo.LMP;
  153. patientGynInfo.Para = PatientInfo.PatientGynInfo.Para;
  154. }
  155. else
  156. {
  157. patientGynInfo = null;
  158. }
  159. ReportPatientOBInfoMessage patientObInfo;
  160. if (PatientInfo.PatientObInfo != null)
  161. {
  162. patientObInfo = MessagePool.GetMessage<ReportPatientOBInfoMessage>();
  163. patientObInfo.AB = PatientInfo.PatientObInfo.AB;
  164. patientObInfo.Ectopic = PatientInfo.PatientObInfo.Ectopic;
  165. patientObInfo.Gravida = PatientInfo.PatientObInfo.Gravida;
  166. patientObInfo.LMP = PatientInfo.PatientObInfo.LMP;
  167. patientObInfo.Para = PatientInfo.PatientObInfo.Para;
  168. patientObInfo.FetusNumber = PatientInfo.PatientObInfo.FetusNumber;
  169. patientObInfo.BBT = PatientInfo.PatientObInfo.BBT;
  170. patientObInfo.EstimateDueDate = PatientInfo.PatientObInfo.EstimateDueDate;
  171. patientObInfo.GestationalAge = PatientInfo.PatientObInfo.GestationalAge;
  172. patientObInfo.GestationalAgeOrigin = PatientInfo.PatientObInfo.GestationalAgeOrigin;
  173. }
  174. else
  175. {
  176. patientObInfo = null;
  177. }
  178. PatientAnimalDetailMessage patientAnimalDetailMessage = null;
  179. if (PatientInfo.AnimalDetail != null)
  180. {
  181. patientAnimalDetailMessage = MessagePool.GetMessage<PatientAnimalDetailMessage>();
  182. patientAnimalDetailMessage.Species = PatientInfo.AnimalDetail.Species;
  183. patientAnimalDetailMessage.Owner = PatientInfo.AnimalDetail.Owner;
  184. patientAnimalDetailMessage.Breed = PatientInfo.AnimalDetail.Breed;
  185. }
  186. var patientId = PatientInfo.PatientId;
  187. var firstName = PatientInfo.FirstName;
  188. var lastNamae = PatientInfo.LastName;
  189. patientInfoMessage = MessagePool.GetMessage<ReportPatientInfoMessage1>();
  190. patientInfoMessage.Id = string.Empty;
  191. patientInfoMessage.PatientId = patientId;
  192. patientInfoMessage.FirstName = firstName;
  193. patientInfoMessage.LastName = lastNamae;
  194. patientInfoMessage.Birthday = PatientInfo.Birthday;
  195. patientInfoMessage.IsMale = PatientInfo.IsMale;
  196. patientInfoMessage.Height = PatientInfo.Height;
  197. patientInfoMessage.Weight = PatientInfo.Weight;
  198. patientInfoMessage.PatientGynInfo = patientGynInfo;
  199. patientInfoMessage.PatientObInfo = patientObInfo;
  200. patientInfoMessage.PatientUrInfo = patientUrInfo;
  201. patientInfoMessage.AnimalDetail = patientAnimalDetailMessage;
  202. patientInfoMessage.Age = PatientInfo.Age;
  203. }
  204. return patientInfoMessage;
  205. }
  206. /// <summary>
  207. /// Delete this scanData and its files.
  208. /// </summary>
  209. public void Delete()
  210. {
  211. Status = UploadStatus.Deleted;
  212. }
  213. /// <summary>
  214. /// Force update the scan data's status.
  215. /// </summary>
  216. /// <param name="status">The new status</param>
  217. public void ForceUpdateStaus(UploadStatus status)
  218. {
  219. Status = status;
  220. }
  221. /// <summary>
  222. /// Force update and save the scan data.
  223. /// </summary>
  224. public void Update()
  225. {
  226. Save();
  227. }
  228. /// <summary>
  229. /// Get saved scan data file path
  230. /// </summary>
  231. /// <param name="status"></param>
  232. /// <returns></returns>
  233. private string GetScanDataFilePath(UploadStatus status)
  234. {
  235. if (status == UploadStatus.Deleted)
  236. {
  237. throw new InvalidOperationException("File already deleted.");
  238. }
  239. var subFolder = string.Empty;
  240. if (status == UploadStatus.Idle || status == UploadStatus.Waiting || status == UploadStatus.Uploading)
  241. {
  242. subFolder = "Upload";
  243. }
  244. if (status == UploadStatus.Fail)
  245. {
  246. subFolder = "Failed";
  247. }
  248. var folder = GetWorkingFolder(subFolder);
  249. var fileName = $"{Id}.sd";
  250. return Path.Combine(folder, fileName);
  251. }
  252. private string GetWorkingFolder(string subFolder)
  253. {
  254. var folder = Path.Combine(vCloudTerminal.WorkingFolder, "Remedical", subFolder);
  255. DirectoryHelper.CreateDirectory(folder);
  256. return folder;
  257. }
  258. /// <summary>
  259. /// Get the vid file path.
  260. /// </summary>
  261. /// <param name="status"></param>
  262. /// <returns></returns>
  263. private string GetVidFilePath(UploadStatus status)
  264. {
  265. if (status == UploadStatus.Deleted)
  266. {
  267. throw new InvalidOperationException("File already deleted.");
  268. }
  269. var subFolder = string.Empty;
  270. if (status == UploadStatus.Idle || status == UploadStatus.Waiting || status == UploadStatus.Uploading)
  271. {
  272. subFolder = "Upload";
  273. }
  274. if (status == UploadStatus.Fail)
  275. {
  276. subFolder = "Failed";
  277. }
  278. var folder = GetWorkingFolder(subFolder);
  279. var fileName = $"{Id}.vid";
  280. return Path.Combine(folder, fileName);
  281. }
  282. /// <summary>
  283. /// Delete the files
  284. /// </summary>
  285. /// <param name="status"></param>
  286. private void Delete(UploadStatus status)
  287. {
  288. var scanDataFilePath = GetScanDataFilePath(status);
  289. var vidFilePath = GetVidFilePath(status);
  290. FileHelper.DeleteFile(scanDataFilePath);
  291. FileHelper.DeleteFile(vidFilePath);
  292. }
  293. /// <summary>
  294. /// Save scan data and vid file to the disk by current status.
  295. /// </summary>
  296. private void Save()
  297. {
  298. ScanDataFilePath = GetScanDataFilePath(Status);
  299. this.Serialize(ScanDataFilePath);
  300. }
  301. /// <summary>
  302. /// Move scan data from one to another
  303. /// </summary>
  304. /// <param name="source"></param>
  305. /// <param name="dest"></param>
  306. private void Move(UploadStatus source, UploadStatus dest)
  307. {
  308. var sourceScanDataFilePath = GetScanDataFilePath(source);
  309. var sourceVidFilePath = GetVidFilePath(source);
  310. var destScanDataFilePath = GetScanDataFilePath(dest);
  311. var destVidFilePath = GetVidFilePath(dest);
  312. if (File.Exists(sourceScanDataFilePath) && !File.Exists(destScanDataFilePath))
  313. {
  314. File.Move(sourceScanDataFilePath, destScanDataFilePath);
  315. ScanDataFilePath = destScanDataFilePath;
  316. }
  317. if (File.Exists(sourceVidFilePath) && !File.Exists(destVidFilePath))
  318. {
  319. File.Move(sourceVidFilePath, destVidFilePath);
  320. VidFilePath = destVidFilePath;
  321. }
  322. }
  323. /// <summary>
  324. /// Upload the data to the vCloud server.
  325. /// </summary>
  326. public void Upload(StorageInfo storageInfo, CancellationTokenSource cancellationTokenSource)
  327. {
  328. if (cancellationTokenSource.IsCancellationRequested)
  329. {
  330. throw new OperationCanceledException("Cancelled");
  331. }
  332. var fileToken = UploadHelper.UploadFile(storageInfo, VidFilePath, string.Empty, null, cancellationTokenSource);
  333. if (cancellationTokenSource.IsCancellationRequested)
  334. {
  335. throw new OperationCanceledException("Cancelled");
  336. }
  337. if (string.IsNullOrWhiteSpace(fileToken))
  338. {
  339. throw new InvalidOperationException("Get token failed when Uploading file");
  340. }
  341. var patientInfoMessage = CreateReportPatientInfoMessage();
  342. var fileType = VidType.VinnoVidSingle;
  343. if (DataType == VidType.VinnoVidMovie)
  344. {
  345. fileType = VidType.VinnoVidMovie;
  346. }
  347. if (DataType == VidType.ThirdVidSingle)
  348. {
  349. fileType = VidType.ThirdVidSingle;
  350. }
  351. if (DataType == VidType.ThirdVidMovie)
  352. {
  353. fileType = VidType.ThirdVidMovie;
  354. }
  355. if (cancellationTokenSource.IsCancellationRequested)
  356. {
  357. throw new OperationCanceledException("Cancelled");
  358. }
  359. using (var request = MessagePool.GetMessage<AddRecordDataRequest1>())
  360. {
  361. request.TerminalRecordId = ExamRecordId;
  362. request.DataType = fileType;
  363. request.Application = Description;
  364. request.ImageFileToken = fileToken;
  365. request.PatientInfo = patientInfoMessage;
  366. var result = Leaf.Send(request);
  367. var success = AddRecordDataSuccess.Convert(result);
  368. if (success == null)
  369. {
  370. throw new InvalidOperationException("AddRecordDataRequest fail.");
  371. }
  372. }
  373. Status = UploadStatus.Uploaded;
  374. }
  375. private void DoDispose()
  376. {
  377. try
  378. {
  379. if (!_disposed)
  380. {
  381. //if not uploaded just save it to disk.
  382. if (Status != UploadStatus.Uploaded && Status != UploadStatus.Deleted)
  383. {
  384. Save();
  385. }
  386. }
  387. }
  388. catch (Exception ex)
  389. {
  390. Logger.WriteLineError($"vCloudScanData: dispose upload data error:{ex}");
  391. }
  392. finally
  393. {
  394. _disposed = true;
  395. }
  396. }
  397. public void Dispose()
  398. {
  399. DoDispose();
  400. GC.SuppressFinalize(this);
  401. }
  402. }
  403. }