source: Scheduling/trunk/cs/bsdx0200GUISourceCode/CGDocumentManager.cs@ 935

Last change on this file since 935 was 935, checked in by Sam Habiel, 14 years ago

Finally. v. 1.4.
Support for checking encoding on the server (if supports UTF-8 and encoding not specified, uses UTF-8; otherwise uses what locale says).

File size: 34.0 KB
Line 
1using System;
2using System.Windows.Forms;
3using System.Collections;
4using System.Data;
5using System.Diagnostics;
6using IndianHealthService.BMXNet;
7using Mono.Options;
8using System.Runtime.InteropServices;
9
10namespace IndianHealthService.ClinicalScheduling
11{
12 /// <summary>
13 /// Summary description for DocumentManager.
14 /// </summary>
15 public class CGDocumentManager : System.Windows.Forms.Form
16 {
17 #region Member Variables
18
19 private static CGDocumentManager _current;
20 private Hashtable _views = new Hashtable();
21 private Hashtable m_AVViews = new Hashtable();
22 private string m_sWindowText = "Clinical Scheduling"; //Default Window Text
23 private bool m_bSchedManager;
24 private bool m_bExitOK = true;
25 public string m_sHandle = "0";
26
27 //Connection variables
28 private string m_AccessCode="";
29 private string m_VerifyCode="";
30 private string m_Server="";
31 private int m_Port=0;
32
33 //Encoding string (empty by default)
34 private string m_Encoding="";
35
36 //Data Access Layer
37 private DAL _dal = null;
38
39 //M Connection member variables
40 private DataSet m_dsGlobal = null;
41 private System.ComponentModel.IContainer components = null;
42 private BMXNetConnectInfo m_ConnectInfo = null;
43 private BMXNetConnectInfo.BMXNetEventDelegate CDocMgrEventDelegate;
44
45 #endregion
46
47 /// <summary>
48 /// Constructor. Sets up connector, and ties BMXNet Events to function here.
49 /// </summary>
50 public CGDocumentManager()
51 {
52 InitializeComponent();
53 m_bSchedManager = false;
54 }
55
56 #region BMXNet Event Handler
57 private void CDocMgrEventHandler(Object obj, BMXNet.BMXNetEventArgs e)
58 {
59 if (e.BMXEvent == "BSDX CALL WORKSTATIONS")
60 {
61 string sParam = "";
62 string sDelim="~";
63 sParam += this.m_ConnectInfo.UserName + sDelim;
64 sParam += this.m_sHandle + sDelim;
65 sParam += Application.ProductVersion + sDelim;
66 sParam += this._views.Count.ToString();
67 _current.m_ConnectInfo.RaiseEvent("BSDX WORKSTATION REPORT", sParam, true);
68 }
69 if (e.BMXEvent == "BSDX ADMIN MESSAGE")
70 {
71 string sMsg = e.BMXParam;
72 ShowAdminMsgDelegate samd = new ShowAdminMsgDelegate(ShowAdminMsg);
73 this.Invoke(samd, new object [] {sMsg});
74 }
75 if (e.BMXEvent == "BSDX ADMIN SHUTDOWN")
76 {
77 string sMsg = e.BMXParam;
78 CloseAllDelegate cad = new CloseAllDelegate(CloseAll);
79 this.Invoke(cad, new object [] {sMsg});
80 }
81 }
82
83 delegate void ShowAdminMsgDelegate(string sMsg);
84
85 private void ShowAdminMsg(string sMsg)
86 {
87 MessageBox.Show(sMsg, "Message from Scheduling Administrator", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
88 }
89
90 #endregion BMXNet Event Handler
91
92 #region Properties
93
94 /// <summary>
95 /// Returns the document manager's BMXNetConnectInfo member
96 /// </summary>
97 public BMXNetConnectInfo ConnectInfo
98 {
99 get
100 {
101 return m_ConnectInfo;
102 }
103 }
104
105 /// <summary>
106 /// True if the current user holds the BSDXZMGR or XUPROGMODE keys in RPMS
107 /// </summary>
108 public bool ScheduleManager
109 {
110 get
111 {
112 return m_bSchedManager;
113 }
114 }
115
116 /// <summary>
117 /// Holds the user and division
118 /// </summary>
119 public string WindowText
120 {
121 get
122 {
123 return m_sWindowText;
124 }
125 }
126
127 /// <summary>
128 /// This dataset contains tables used by the entire application
129 /// </summary>
130 public DataSet GlobalDataSet
131 {
132 get
133 {
134 return m_dsGlobal;
135 }
136 set
137 {
138 m_dsGlobal = value;
139 }
140 }
141 //public BMXNetConnection ADOConnection
142 //{
143 // get
144 // {
145 // return m_ADOConnection;
146 // }
147 //}
148
149 /// <summary>
150 /// Returns the single CGDocumentManager object
151 /// </summary>
152 public static CGDocumentManager Current
153 {
154 get
155 {
156 return _current;
157 }
158 }
159
160 /// <summary>
161 /// Returns the list of currently opened documents
162 /// </summary>
163 public Hashtable Views
164 {
165 get
166 {
167 return _views;
168 }
169 }
170
171 /// <summary>
172 /// Returns the list of currently opened CGAVViews
173 /// </summary>
174 public Hashtable AvailabilityViews
175 {
176 get
177 {
178 return this.m_AVViews;
179 }
180 }
181
182 public DAL DAL
183 {
184 get { return this._dal; }
185 }
186
187
188 #endregion
189
190 #region Methods & Events
191 /// <summary>
192 /// Clean up any resources being used.
193 /// </summary>
194 protected override void Dispose( bool disposing )
195 {
196 if( disposing )
197 {
198 if (m_ConnectInfo != null)
199 {
200 m_ConnectInfo.EventPollingEnabled = false;
201 m_ConnectInfo.UnSubscribeEvent("BSDX SCHEDULE");
202 m_ConnectInfo.UnSubscribeEvent("BSDX CALL WORKSTATIONS");
203 m_ConnectInfo.CloseConnection();
204 }
205 if (components != null)
206 {
207 components.Dispose();
208 }
209 }
210 base.Dispose( disposing );
211 }
212
213
214 private void InitializeComponent()
215 {
216 }
217
218
219 private DSplash m_ds;
220 public void StartSplash()
221 {
222 m_ds = new DSplash();
223 m_ds.ShowDialog();
224 }
225
226 private void InitializeApp()
227 {
228 InitializeApp(false);
229 }
230
231 private void InitializeApp(bool bReLogin)
232 {
233 m_ConnectInfo = new BMXNetConnectInfo(m_Encoding); // Encoding is "" unless passed in command line
234 _dal = new DAL(m_ConnectInfo); // Data access layer
235 //m_ConnectInfo.bmxNetLib.StartLog(); //This line turns on logging of messages
236 CDocMgrEventDelegate = new BMXNetConnectInfo.BMXNetEventDelegate(CDocMgrEventHandler);
237 m_ConnectInfo.BMXNetEvent += CDocMgrEventDelegate;
238 m_ConnectInfo.EventPollingEnabled = false;
239
240 try
241 {
242 //Set M connection info
243 //Show a splash screen while initializing
244 m_ds = new DSplash();
245 m_ds.Show(this);
246 m_ds.SetStatus("Loading Configuration Settings...");
247 m_ds.Refresh();
248 this.Activate();
249 // smh--not used System.Configuration.ConfigurationManager.GetSection("appSettings");
250 m_ds.SetStatus("Connecting to VistA Server...");
251 m_ds.Refresh();
252 bool bRetry = true;
253
254 //Try to connect using supplied values for Server and Port
255 //Why am I doing this? The library BMX net uses prompts for access and verify code
256 //whether you can connect or not. Not good. So I test first whether
257 //we can connect at all by doing a simple connection and disconnect.
258 //TODO: Make this more robust by sending a TCPConnect message and seeing if you get a response.
259
260 if (m_Server != "" && m_Port != 0)
261 {
262 System.Net.Sockets.TcpClient tcpClient = new System.Net.Sockets.TcpClient();
263 try
264 {
265 tcpClient.Connect(m_Server, m_Port); // open it
266 tcpClient.Close(); // then close it
267 }
268 catch (System.Net.Sockets.SocketException ex)
269 {
270 throw ex;
271 }
272 }
273 do
274 {
275 // login crap
276 try
277 {
278 // Not my code
279 if (bReLogin == true)
280 {
281 //Prompt for Access and Verify codes
282 _current.m_ConnectInfo.LoadConnectInfo("", "");
283 }
284 // My code -- buts looks so ugly!
285 else
286 {
287 if (m_Server != String.Empty && m_Port != 0 && m_AccessCode != String.Empty
288 && m_VerifyCode != String.Empty)
289 {
290 m_ConnectInfo.LoadConnectInfo(m_Server, m_Port, m_AccessCode, m_VerifyCode);
291 }
292 else if (m_Server != String.Empty && m_Port != 0)
293 m_ConnectInfo.LoadConnectInfo(m_Server, m_Port, "", "");
294 else
295 m_ConnectInfo.LoadConnectInfo();
296 }
297 bRetry = false;
298 }
299 catch (System.Net.Sockets.SocketException)
300 {
301 MessageBox.Show("Cannot connect to VistA. ");
302 }
303 catch (Exception ex)
304 {
305 m_ds.Close();
306 if (MessageBox.Show("Unable to connect to VistA. " + ex.Message, "Clinical Scheduling", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
307 {
308 bRetry = true;
309 _current.m_ConnectInfo.ChangeServerInfo();
310 }
311 else
312 {
313 bRetry = false;
314 throw ex;
315 }
316 }
317 }while (bRetry == true);
318
319 //Create global dataset
320 _current.m_dsGlobal = new DataSet("GlobalDataSet");
321
322 //Version info
323 m_ds.SetStatus("Getting Version Info...");
324 m_ds.Refresh();
325
326 DataTable ver = _dal.GetVersion("BSDX"); //sCmd, "VersionInfo", m_dsGlobal);
327 ver.TableName = "VersionInfo";
328 m_dsGlobal.Tables.Add(ver);
329
330 //Keep the following commented code for future use:
331 //How to extract the version numbers:
332 //DataTable dtVersion = m_dsGlobal.Tables["VersionInfo"];
333 //Debug.Assert(dtVersion.Rows.Count == 1);
334 //DataRow rVersion = dtVersion.Rows[0];
335 //string sMajor = rVersion["MAJOR_VERSION"].ToString();
336 //string sMinor = rVersion["MINOR_VERSION"].ToString();
337 //string sBuild = rVersion["BUILD"].ToString();
338 //decimal fBuild = Convert.ToDecimal(sBuild);
339
340 //Change encoding
341 if (m_Encoding == String.Empty)
342 {
343 string utf8_server_support = m_ConnectInfo.bmxNetLib.TransmitRPC("BMX UTF-8", "");
344 if (utf8_server_support == "1")
345 m_ConnectInfo.bmxNetLib.Encoder = System.Text.UTF8Encoding.UTF8;
346 }
347 //Set application context
348 m_ds.SetStatus("Setting Application Context to BSDXRPC...");
349 m_ds.Refresh();
350 m_ConnectInfo.AppContext = "BSDXRPC";
351
352 //Load global recordsets
353 m_ds.SetStatus("Loading VistA data tables...");
354 m_ds.Refresh();
355 if (_current.LoadGlobalRecordsets() == false)
356 {
357 MessageBox.Show("Unable to create VistA recordsets"); //TODO Improve this message
358 m_ds.Close();
359 return;
360 }
361
362 //smh -- why get handles?
363 System.IntPtr pHandle = this.Handle;
364 System.IntPtr pConnHandle = this.ConnectInfo.Handle;
365 this.m_sHandle = pHandle.ToString();
366
367 _current.m_ConnectInfo.ReceiveTimeout = 30000; //30-second timeout
368
369#if DEBUG
370 _current.m_ConnectInfo.ReceiveTimeout = 600000; //longer timeout for debugging
371#endif
372 _current.m_ConnectInfo.SubscribeEvent("BSDX SCHEDULE");
373 _current.m_ConnectInfo.SubscribeEvent("BSDX CALL WORKSTATIONS");
374 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN MESSAGE");
375 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN SHUTDOWN");
376
377 _current.m_ConnectInfo.EventPollingInterval = 5000; //in milliseconds
378 _current.m_ConnectInfo.EventPollingEnabled = true;
379 _current.m_ConnectInfo.AutoFire = 12; //AutoFire every 12*5 seconds
380
381 m_ds.Close();
382 }
383 catch (Exception ex)
384 {
385 m_ds.Close();
386 Debug.Write(ex.Message);
387 MessageBox.Show(ex.Message + ex.StackTrace, "Clinical Scheduling Error -- Closing Application");
388 throw ex;
389 }
390 }
391
392 //To write to the console
393 [DllImport("kernel32.dll")]
394 static extern bool AttachConsole(int dwProcessId);
395 private const int ATTACH_PARENT_PROCESS = -1;
396
397 [STAThread()]
398 static void Main(string[] args)
399 {
400#if DEBUG
401 // Print console messages to console if launched from console
402 // Note: Imported From kernel32.dll
403 AttachConsole(ATTACH_PARENT_PROCESS);
404#endif
405 try
406 {
407 //Store the current manager
408 _current = new CGDocumentManager();
409
410 //Get command line options; store in private variables
411 var opset = new OptionSet () {
412 { "s=", s => _current.m_Server = s },
413 { "p=", p => _current.m_Port = int.Parse(p) },
414 { "a=", a => _current.m_AccessCode = a },
415 { "v=", v => _current.m_VerifyCode = v },
416 { "e=", e => _current.m_Encoding = e}
417 };
418
419 opset.Parse(args);
420
421 try
422 {
423 _current.InitializeApp();
424 }
425 catch (Exception ex)
426 {
427 Debug.Write(ex.Message);
428 return;
429 }
430
431 //Create the first empty document
432 CGDocument doc = new CGDocument();
433 doc.DocManager = _current;
434 doc.OnNewDocument();
435 Application.DoEvents();
436
437 //Run the application
438 Application.Run();
439 }
440 catch (Exception ex)
441 {
442 Debug.Write(ex.Message);
443 MessageBox.Show(ex.Message + ex.StackTrace, "CGDocumentManager.Main(): Clinical Scheduling Error -- Closing Application");
444 return;
445 }
446 }
447
448
449 public void LoadAccessGroupsTable()
450 {
451 string sCommandText = "SELECT * FROM BSDX_ACCESS_GROUP";
452 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroup", m_dsGlobal);
453 Debug.Write("LoadGlobalRecordsets -- AccessGroups loaded\n");
454 }
455
456 public void LoadAccessGroupTypesTable()
457 {
458 string sCommandText = "BSDX GET ACCESS GROUP TYPES";
459 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroupType", m_dsGlobal);
460 Debug.Write("LoadGlobalRecordsets -- AccessGroupTypes loaded\n");
461 }
462
463 public void LoadBSDXResourcesTable()
464 {
465 string sCommandText = "BSDX RESOURCES^" + m_ConnectInfo.DUZ;
466 ConnectInfo.RPMSDataTable(sCommandText, "Resources", m_dsGlobal);
467 Debug.Write("LoadGlobalRecordsets -- Resources loaded\n");
468 }
469
470 public void LoadResourceGroupTable()
471 {
472 //ResourceGroup Table (Resource Groups by User)
473 //Table "ResourceGroup" contains all resource group names
474 //to which user has access
475 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP
476 string sCommandText = "BSDX RESOURCE GROUPS BY USER^" + m_ConnectInfo.DUZ;
477 ConnectInfo.RPMSDataTable(sCommandText, "ResourceGroup", m_dsGlobal);
478 Debug.Write("LoadGlobalRecordsets -- ResourceGroup loaded\n");
479 }
480
481 public void LoadGroupResourcesTable()
482 {
483 //Table "GroupResources" contains all active GROUP/RESOURCE combinations
484 //to which user has access based on entries in BSDX RESOURCE USER file
485 //If user has BSDXZMGR or XUPROGMODE keys, then ALL Group/Resource combinstions
486 //are returned.
487 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP, RESOURCE_GROUP_ITEMID, RESOURCE_NAME, RESOURCE_ID
488 string sCommandText = "BSDX GROUP RESOURCE^" + m_ConnectInfo.DUZ;
489 ConnectInfo.RPMSDataTable(sCommandText, "GroupResources", m_dsGlobal);
490 Debug.Write("LoadGlobalRecordsets -- GroupResources loaded\n");
491 }
492
493 public void LoadScheduleUserTable()
494 {
495 //Table "ScheduleUser" contains an entry for each user in File 200 (NEW PERSON)
496 //who possesses the BSDXZMENU security key.
497 string sCommandText = "BSDX SCHEDULE USER";
498 ConnectInfo.RPMSDataTable(sCommandText, "ScheduleUser", m_dsGlobal);
499 Debug.Write("LoadGlobalRecordsets -- ScheduleUser loaded\n");
500 }
501
502 public void LoadResourceUserTable()
503 {
504 //Table "ResourceUser" duplicates the BSDX RESOURCE USER File.
505 //NOTE: Column names are RESOURCEUSER_ID, RESOURCEID,
506 // OVERBOOK, MODIFY_SCHEDULE, USERID, USERID1
507 //string sCommandText = "SELECT BMXIEN RESOURCEUSER_ID, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, USERNAME USERID, INTERNAL[USERNAME] FROM BSDX_RESOURCE_USER";
508 LoadResourceUserTable(false);
509 }
510
511 public void LoadResourceUserTable(bool bAllUsers)
512 {
513 string sCommandText = "SELECT BMXIEN RESOURCEUSER_ID, RESOURCENAME, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, MODIFY_APPOINTMENTS, USERNAME, INTERNAL[USERNAME] USERID FROM BSDX_RESOURCE_USER";
514 ConnectInfo.RPMSDataTable(sCommandText, "ResourceUser", m_dsGlobal);
515 Debug.Write("LoadGlobalRecordsets -- ResourceUser loaded\n");
516 }
517
518 private bool LoadGlobalRecordsets()
519 {
520
521 string sCommandText;
522
523 //Schedule User Info
524 DataTable dtUser = _dal.GetUserInfo(m_ConnectInfo.DUZ);
525 dtUser.TableName = "SchedulingUser";
526 m_dsGlobal.Tables.Add(dtUser);
527 Debug.Assert(dtUser.Rows.Count == 1);
528
529 // Only one row and one column named "MANAGER". Set local var m_bSchedManager to true if Manager.
530 DataRow rUser = dtUser.Rows[0];
531 Object oUser = rUser["MANAGER"];
532 string sUser = oUser.ToString();
533 m_bSchedManager = (sUser == "YES")?true:false;
534
535 //Get Access Types
536 DataTable dtAccessTypes = _dal.GetAccessTypes();
537 dtAccessTypes.TableName = "AccessTypes";
538 m_dsGlobal.Tables.Add(dtAccessTypes);
539
540 //AccessGroups
541 LoadAccessGroupsTable();
542
543 //Build Primary Key for AccessGroup table
544 DataTable dtGroups = m_dsGlobal.Tables["AccessGroup"];
545 DataColumn dcKey = dtGroups.Columns["ACCESS_GROUP"];
546 DataColumn[] dcKeys = new DataColumn[1];
547 dcKeys[0] = dcKey;
548 dtGroups.PrimaryKey = dcKeys;
549
550 //AccessGroupType
551 LoadAccessGroupTypesTable();
552
553 //Build Primary Key for AccessGroupType table
554 DataTable dtAGTypes = m_dsGlobal.Tables["AccessGroupType"];
555 DataColumn dcGTKey = dtAGTypes.Columns["ACCESS_GROUP_TYPEID"];
556 DataColumn[] dcGTKeys = new DataColumn[1];
557 dcGTKeys[0] = dcGTKey;
558 dtAGTypes.PrimaryKey = dcGTKeys;
559
560 //Build Data Relationship between AccessGroupType and AccessTypes tables
561 DataRelation dr = new DataRelation("AccessGroupType", //Relation Name
562 m_dsGlobal.Tables["AccessGroup"].Columns["BMXIEN"], //Parent
563 m_dsGlobal.Tables["AccessGroupType"].Columns["ACCESS_GROUP_ID"]); //Child
564 m_dsGlobal.Relations.Add(dr);
565
566 //ResourceGroup Table (Resource Groups by User)
567 LoadResourceGroupTable();
568
569 //Resources by user
570 LoadBSDXResourcesTable();
571
572 //Build Primary Key for Resources table
573 DataColumn[] dc = new DataColumn[1];
574 dc[0] = m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"];
575 m_dsGlobal.Tables["Resources"].PrimaryKey = dc;
576
577 //GroupResources table
578 LoadGroupResourcesTable();
579
580 //Build Primary Key for ResourceGroup table
581 dc = new DataColumn[1];
582 dc[0] = m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"];
583 m_dsGlobal.Tables["ResourceGroup"].PrimaryKey = dc;
584
585 //Build Data Relationships between ResourceGroup and GroupResources tables
586 dr = new DataRelation("GroupResource", //Relation Name
587 m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"], //Parent
588 m_dsGlobal.Tables["GroupResources"].Columns["RESOURCE_GROUP"]); //Child
589 CGSchedLib.OutputArray(m_dsGlobal.Tables["GroupResources"], "GroupResources");
590 m_dsGlobal.Relations.Add(dr);
591
592 //HospitalLocation table
593 //cmd.CommandText = "SELECT BMXIEN 'HOSPITAL_LOCATION_ID', NAME 'HOSPITAL_LOCATION', DEFAULT_PROVIDER, STOP_CODE_NUMBER, INACTIVATE_DATE, REACTIVATE_DATE FROM HOSPITAL_LOCATION";
594 sCommandText = "BSDX HOSPITAL LOCATION";
595 ConnectInfo.RPMSDataTable(sCommandText, "HospitalLocation", m_dsGlobal);
596 Debug.Write("LoadGlobalRecordsets -- HospitalLocation loaded\n");
597
598 //Build Primary Key for HospitalLocation table
599 dc = new DataColumn[1];
600 DataTable dtTemp = m_dsGlobal.Tables["HospitalLocation"];
601 dc[0] = dtTemp.Columns["HOSPITAL_LOCATION_ID"];
602 m_dsGlobal.Tables["HospitalLocation"].PrimaryKey = dc;
603
604 //smh
605 //LoadClinicSetupTable();
606
607 //smh
608 //Build Primary Key for ClinicSetupParameters table
609 /*dc = new DataColumn[1];
610 dtTemp = m_dsGlobal.Tables["ClinicSetupParameters"];
611 dc[0] = dtTemp.Columns["HOSPITAL_LOCATION_ID"];
612 m_dsGlobal.Tables["ClinicSetupParameters"].PrimaryKey = dc;
613
614 //Build Data Relationships between ClinicSetupParameters and HospitalLocation tables
615 dr = new DataRelation("HospitalLocationClinic", //Relation Name
616 m_dsGlobal.Tables["HospitalLocation"].Columns["HOSPITAL_LOCATION_ID"], //Parent
617 m_dsGlobal.Tables["ClinicSetupParameters"].Columns["HOSPITAL_LOCATION_ID"], false); //Child
618 m_dsGlobal.Relations.Add(dr);*/
619 /*SMH
620 dtTemp.Columns.Add("PROVIDER", System.Type.GetType("System.String"), "Parent.DEFAULT_PROVIDER");
621 dtTemp.Columns.Add("CLINIC_STOP", System.Type.GetType("System.String"), "Parent.STOP_CODE_NUMBER");
622 dtTemp.Columns.Add("INACTIVATE_DATE", System.Type.GetType("System.String"), "Parent.INACTIVATE_DATE");
623 dtTemp.Columns.Add("REACTIVATE_DATE", System.Type.GetType("System.String"), "Parent.REACTIVATE_DATE");
624 */
625
626 //Build Data Relationships between Resources and HospitalLocation tables
627 dr = new DataRelation("HospitalLocationResource", //Relation Name
628 m_dsGlobal.Tables["HospitalLocation"].Columns["HOSPITAL_LOCATION_ID"], //Parent
629 m_dsGlobal.Tables["Resources"].Columns["HOSPITAL_LOCATION_ID"], false); //Child
630 m_dsGlobal.Relations.Add(dr);
631
632 //Build ScheduleUser table
633 this.LoadScheduleUserTable();
634
635 //Build Primary Key for ScheduleUser table
636 dc = new DataColumn[1];
637 dtTemp = m_dsGlobal.Tables["ScheduleUser"];
638 dc[0] = dtTemp.Columns["USERID"];
639 m_dsGlobal.Tables["ScheduleUser"].PrimaryKey = dc;
640
641 //Build ResourceUser table
642 this.LoadResourceUserTable();
643
644 //Build Primary Key for ResourceUser table
645 dc = new DataColumn[1];
646 dtTemp = m_dsGlobal.Tables["ResourceUser"];
647 dc[0] = dtTemp.Columns["RESOURCEUSER_ID"];
648 m_dsGlobal.Tables["ResourceUser"].PrimaryKey = dc;
649
650 //Create relation between BSDX Resource and BSDX Resource User tables
651 dr = new DataRelation("ResourceUser", //Relation Name
652 m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"], //Parent
653 m_dsGlobal.Tables["ResourceUser"].Columns["RESOURCEID"]); //Child
654 m_dsGlobal.Relations.Add(dr);
655
656 //Build active provider table
657 sCommandText = "SELECT BMXIEN, NAME FROM NEW_PERSON WHERE INACTIVE_DATE = '' AND BMXIEN > 1";
658 ConnectInfo.RPMSDataTable(sCommandText, "Provider", m_dsGlobal);
659 Debug.Write("LoadGlobalRecordsets -- Provider loaded\n");
660
661 //Build the CLINIC_STOP table
662 // sCommandText = "SELECT BMXIEN, CODE, NAME FROM CLINIC_STOP"; //SMH
663 sCommandText = "SELECT BMXIEN, AMIS_REPORTING_STOP_CODE, NAME FROM CLINIC_STOP";
664 ConnectInfo.RPMSDataTable(sCommandText, "ClinicStop", m_dsGlobal);
665 Debug.Write("LoadGlobalRecordsets -- ClinicStop loaded\n");
666
667 //Build the HOLIDAY table
668 sCommandText = "SELECT NAME, DATE FROM HOLIDAY WHERE DATE > '" + DateTime.Today.ToShortDateString() + "'";
669 ConnectInfo.RPMSDataTable(sCommandText, "HOLIDAY", m_dsGlobal);
670 Debug.Write("LoadingGlobalRecordsets -- Holidays loaded\n");
671
672
673 //Save the xml schema
674 //m_dsGlobal.WriteXmlSchema(@"..\..\csSchema20060526.xsd");
675
676 return true;
677 }
678
679 public void RegisterDocumentView(CGDocument doc, CGView view)
680 {
681 //Store the view in the list of views
682 this.Views.Add(view, doc);
683
684 //Hook into the view's 'closed' event
685 view.Closed += new EventHandler(ViewClosed);
686
687 //Hook into the view's mnuRPMSServer.Click event
688 view.mnuRPMSServer.Click += new EventHandler(mnuRPMSServer_Click);
689
690 //Hook into the view's mnuRPMSLogin.Click event
691 view.mnuRPMSLogin.Click += new EventHandler(mnuRPMSLogin_Click);
692
693 }
694
695 public void RegisterAVDocumentView(CGAVDocument doc, CGAVView view)
696 {
697 //Store the view in the list of views
698 this.AvailabilityViews.Add(view, doc);
699
700 //Hook into the view's 'closed' event
701 view.Closed += new EventHandler(AVViewClosed);
702 }
703
704 public CGAVView GetAVViewByResource(ArrayList sResourceArray)
705 {
706 if (sResourceArray == null)
707 return null;
708
709 bool bEqual = true;
710 foreach (CGAVView v in m_AVViews.Keys)
711 {
712 CGAVDocument d = v.Document;
713
714 bEqual = false;
715 if (d.Resources.Count == sResourceArray.Count)
716 {
717 bEqual = true;
718 for (int j = 0; j < sResourceArray.Count; j++)
719 {
720 if (sResourceArray.Contains(d.Resources[j]) == false)
721 {
722 bEqual = false;
723 break;
724 }
725 if (d.Resources.Contains(sResourceArray[j]) == false)
726 {
727 bEqual = false;
728 break;
729 }
730 }
731 if (bEqual == true)
732 return v;
733 }
734 }
735 return null;
736 }
737 /// <summary>
738 /// Return the first view having a resource array matching sResourceArray
739 /// </summary>
740 /// <param name="sResourceArray"></param>
741 /// <returns></returns>
742 public CGView GetViewByResource(ArrayList sResourceArray)
743 {
744 if (sResourceArray == null)
745 return null;
746
747 bool bEqual = true;
748 foreach (CGView v in _views.Keys)
749 {
750 CGDocument d = v.Document;
751
752 bEqual = false;
753 if (d.Resources.Count == sResourceArray.Count)
754 {
755 bEqual = true;
756 for (int j = 0; j < sResourceArray.Count; j++)
757 {
758 if (sResourceArray.Contains(d.Resources[j]) == false)
759 {
760 bEqual = false;
761 break;
762 }
763 if (d.Resources.Contains(sResourceArray[j]) == false)
764 {
765 bEqual = false;
766 break;
767 }
768 }
769 if (bEqual == true)
770 return v;
771 }
772 }
773 return null;
774 }
775
776 private void ViewClosed(object sender, EventArgs e)
777 {
778 //Remove the sender from our document list
779 Views.Remove(sender);
780
781 //If no documents left, then close RPMS connection & exit the application
782 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
783 {
784 m_ConnectInfo.EventPollingEnabled = false;
785 m_ConnectInfo.UnSubscribeEvent("BSDX SCHEDULE");
786 m_ConnectInfo.CloseConnection();
787 Application.Exit();
788 }
789 }
790
791 private void AVViewClosed(object sender, EventArgs e)
792 {
793 //Remove the sender from our document list
794 this.AvailabilityViews.Remove(sender);
795
796 //If no documents left, then close RPMS connection & exit the application
797 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
798 {
799 m_ConnectInfo.bmxNetLib.CloseConnection();
800 Application.Exit();
801 }
802 }
803
804 private void KeepAlive()
805 {
806 foreach (CGView v in _views.Keys)
807 {
808 CGDocument d = v.Document;
809 DateTime dNow = DateTime.Now;
810 DateTime dLast = d.LastRefreshed;
811 TimeSpan tsDiff = dNow - dLast;
812 if (tsDiff.Seconds > 180)
813 {
814 for (int j = 0; j < d.Resources.Count; j++)
815 {
816 v.RaiseRPMSEvent("SCHEDULE-" + d.Resources[j].ToString(), "");
817 }
818
819 break;
820 }
821 }
822 }
823
824 /// <summary>
825 /// Propogate availability updates to all sRresource's doc/views
826 /// </summary>
827 public void UpdateViews(string sResource, string sOldResource)
828 {
829 if (sResource == null)
830 return;
831 foreach (CGView v in _views.Keys)
832 {
833 CGDocument d = v.Document;
834 for (int j = 0; j < d.Resources.Count; j++)
835 {
836 if ((sResource == "") || (sResource == ((string) d.Resources[j])) || (sOldResource == ((string) d.Resources[j])))
837 {
838 d.RefreshDocument();
839 break;
840 }
841 }
842 v.UpdateTree();
843 }
844 }
845
846 /// <summary>
847 /// Propogate availability updates to all doc/views
848 /// </summary>
849 public void UpdateViews()
850 {
851 UpdateViews("","");
852 foreach (CGView v in _views.Keys)
853 {
854 v.UpdateTree();
855 }
856 }
857
858 /// <summary>
859 /// Calls each view associated with document Doc and closes it.
860 /// </summary>
861 public void CloseAllViews(CGDocument doc)
862 {
863 //iterate through all views and call update.
864 Hashtable h = CGDocumentManager.Current.Views;
865
866 CGDocument d;
867 int nTempCount = h.Count;
868 do
869 {
870 nTempCount = h.Count;
871 foreach (CGView v in h.Keys)
872 {
873 d = (CGDocument) h[v];
874 if (d == doc)
875 {
876 v.Close();
877 break;
878 }
879 }
880 } while ((h.Count > 0) && (nTempCount != h.Count));
881 }
882
883 /// <summary>
884 /// Calls each view associated with Availability Doc and closes it.
885 /// </summary>
886 public void CloseAllViews(CGAVDocument doc)
887 {
888 //iterate through all views and call update.
889 Hashtable h = CGDocumentManager.Current.AvailabilityViews;
890
891 CGAVDocument d;
892 int nTempCount = h.Count;
893 do
894 {
895 nTempCount = h.Count;
896 foreach (CGAVView v in h.Keys)
897 {
898 d = (CGAVDocument) h[v];
899 if (d == doc)
900 {
901 v.Close();
902 break;
903 }
904 }
905 } while ((h.Count > 0) && (nTempCount != h.Count));
906
907
908 }
909
910 private void mnuRPMSServer_Click(object sender, EventArgs e)
911 {
912 //Warn that changing servers will close all schedules
913 if (MessageBox.Show("Are you sure you want to close all schedules and connect to a different VistA server?", "Clinical Scheduling", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
914 return;
915
916 //Reconnect to RPMS and recreate all global recordsets
917 try
918 {
919 m_bExitOK = false;
920 bool bRetry = true;
921 BMXNetConnectInfo tmpInfo;
922 do
923 {
924 tmpInfo = m_ConnectInfo;
925 try
926 {
927 tmpInfo.ChangeServerInfo();
928 bRetry = false;
929 }
930 catch (Exception ex)
931 {
932 if (ex.Message == "User cancelled.")
933 {
934 bRetry = false;
935 return;
936 }
937 if (MessageBox.Show("Unable to connect to VistA. " + ex.Message , "Clinical Scheduling", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
938 {
939 bRetry = true;
940 }
941 else
942 {
943 bRetry = false;
944 return;
945 }
946 }
947 } while (bRetry == true);
948
949 CloseAll();
950 m_bExitOK = true;
951 m_ConnectInfo = tmpInfo;
952
953 this.InitializeApp();
954
955 //Create a new document
956 CGDocument doc = new CGDocument();
957 doc.DocManager = _current;
958 doc.OnNewDocument();
959
960 }
961 catch (Exception ex)
962 {
963 throw ex;
964 }
965
966 }
967
968 private void mnuRPMSLogin_Click(object sender, EventArgs e)
969 {
970 //Warn that changing login will close all schedules
971 if (MessageBox.Show("Are you sure you want to close all schedules and login to VistA?", "Clinical Scheduling", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
972 return;
973
974 //Reconnect to RPMS and recreate all global recordsets
975 try
976 {
977 m_bExitOK = false;
978 CloseAll();
979 m_bExitOK = true;
980 _current.m_ConnectInfo = new BMXNet.BMXNetConnectInfo();
981 this.InitializeApp(true);
982 //Create a new document
983 CGDocument doc = new CGDocument();
984 doc.DocManager = _current;
985 doc.OnNewDocument();
986 }
987 catch (Exception ex)
988 {
989 throw ex;
990 }
991
992 }
993
994 delegate void CloseAllDelegate(string sMsg);
995
996 private void CloseAll(string sMsg)
997 {
998 if (sMsg == "")
999 {
1000 sMsg = "Scheduling System Shutting Down Immediately for Maintenance.";
1001 }
1002
1003 MessageBox.Show(sMsg, "Clinical Scheduling Administrator -- System Shutdown Notification", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1004
1005 CloseAll();
1006 }
1007
1008 private void CloseAll()
1009 {
1010 //Close all documents, views and connections
1011 Hashtable h = CGDocumentManager.Current.Views;
1012 int nTempCount = h.Count;
1013 do
1014 {
1015 nTempCount = h.Count;
1016 foreach (CGView v in h.Keys)
1017 {
1018 v.Close();
1019 break;
1020 }
1021 } while ((h.Count > 0) && (nTempCount != h.Count));
1022
1023 h = CGDocumentManager.Current.AvailabilityViews;
1024 nTempCount = h.Count;
1025 do
1026 {
1027 nTempCount = h.Count;
1028 foreach (CGAVView v in h.Keys)
1029 {
1030 v.Close();
1031 break;
1032 }
1033 } while ((h.Count > 0) && (nTempCount != h.Count));
1034
1035 }
1036
1037 delegate DataTable RPMSDataTableDelegate(string CommandString, string TableName);
1038
1039 public DataTable RPMSDataTable(string sSQL, string sTableName)
1040 {
1041 //Retrieves a recordset from RPMS
1042 string sErrorMessage = "";
1043 DataTable dtOut;
1044
1045#if TRACE
1046 DateTime sendTime = DateTime.Now;
1047#endif
1048 try
1049 {
1050 System.IntPtr pHandle = this.Handle;
1051 RPMSDataTableDelegate rdtd = new RPMSDataTableDelegate(ConnectInfo.RPMSDataTable);
1052 dtOut = (DataTable) this.Invoke(rdtd, new object[] {sSQL, sTableName});
1053 }
1054
1055 catch (Exception ex)
1056 {
1057 sErrorMessage = "CGDocumentManager.RPMSDataTable error: " + ex.Message;
1058 throw ex;
1059 }
1060
1061#if TRACE
1062 DateTime receiveTime = DateTime.Now;
1063 TimeSpan executionTime = receiveTime - sendTime;
1064 Debug.Write("CGDocumentManager::RPMSDataTable Execution Time: " + executionTime.Milliseconds + " ms.\n");
1065#endif
1066
1067 return dtOut;
1068
1069 }
1070
1071 public void ChangeDivision(System.Windows.Forms.Form frmCaller)
1072 {
1073 this.ConnectInfo.ChangeDivision(frmCaller);
1074 foreach (CGView v in _views.Keys)
1075 {
1076 v.InitializeDocView(v.Document.DocName);
1077 v.Document.RefreshDocument();
1078 }
1079 }
1080
1081 public void ViewRefresh()
1082 {
1083 foreach (CGView v in _views.Keys)
1084 {
1085 try
1086 {
1087 v.Document.RefreshDocument();
1088 }
1089 catch (Exception ex)
1090 {
1091 Debug.Write("CGDocumentManager.ViewRefresh Exception: " + ex.Message + "\n");
1092 }
1093 finally
1094 {
1095 }
1096 }
1097 Debug.Write("DocManager refreshed all views.\n");
1098 }
1099
1100 #endregion Methods & Events
1101
1102 }
1103}
Note: See TracBrowser for help on using the repository browser.