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

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

New Release 1.4.1

Change Project file format to VS 2010.

File size: 34.1 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"; // WHERE INTERNAL[INSTITUTION]=" + m_ConnectInfo.DUZ2;
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.