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

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

Some refactoring of code into DAL.cs for Data Access.
Addition of Fileman date code (not used yet).
Removal of .config and .xml file from bin/Release/
Removal of BMXNet20.dll to replace with BMXNet21.dll

File size: 33.6 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 //Set application context
341 m_ds.SetStatus("Setting Application Context to BSDXRPC...");
342 m_ds.Refresh();
343 m_ConnectInfo.AppContext = "BSDXRPC";
344
345 //Load global recordsets
346 m_ds.SetStatus("Loading VistA data tables...");
347 m_ds.Refresh();
348 if (_current.LoadGlobalRecordsets() == false)
349 {
350 MessageBox.Show("Unable to create VistA recordsets"); //TODO Improve this message
351 m_ds.Close();
352 return;
353 }
354
355 //smh -- why get handles?
356 System.IntPtr pHandle = this.Handle;
357 System.IntPtr pConnHandle = this.ConnectInfo.Handle;
358 this.m_sHandle = pHandle.ToString();
359
360 _current.m_ConnectInfo.ReceiveTimeout = 30000; //30-second timeout
361
362#if DEBUG
363 _current.m_ConnectInfo.ReceiveTimeout = 600000; //longer timeout for debugging
364#endif
365 _current.m_ConnectInfo.SubscribeEvent("BSDX SCHEDULE");
366 _current.m_ConnectInfo.SubscribeEvent("BSDX CALL WORKSTATIONS");
367 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN MESSAGE");
368 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN SHUTDOWN");
369
370 _current.m_ConnectInfo.EventPollingInterval = 5000; //in milliseconds
371 _current.m_ConnectInfo.EventPollingEnabled = true;
372 _current.m_ConnectInfo.AutoFire = 12; //AutoFire every 12*5 seconds
373
374 m_ds.Close();
375 }
376 catch (Exception ex)
377 {
378 m_ds.Close();
379 Debug.Write(ex.Message);
380 MessageBox.Show(ex.Message + ex.StackTrace, "Clinical Scheduling Error -- Closing Application");
381 throw ex;
382 }
383 }
384
385 //To write to the console
386 [DllImport("kernel32.dll")]
387 static extern bool AttachConsole(int dwProcessId);
388 private const int ATTACH_PARENT_PROCESS = -1;
389
390 [STAThread()]
391 static void Main(string[] args)
392 {
393#if DEBUG
394 // Print console messages to console if launched from console
395 // Note: Imported From kernel32.dll
396 AttachConsole(ATTACH_PARENT_PROCESS);
397#endif
398 try
399 {
400 //Store the current manager
401 _current = new CGDocumentManager();
402
403 //Get command line options; store in private variables
404 var opset = new OptionSet () {
405 { "s=", s => _current.m_Server = s },
406 { "p=", p => _current.m_Port = int.Parse(p) },
407 { "a=", a => _current.m_AccessCode = a },
408 { "v=", v => _current.m_VerifyCode = v },
409 { "e=", e => _current.m_Encoding = e}
410 };
411
412 opset.Parse(args);
413
414 try
415 {
416 _current.InitializeApp();
417 }
418 catch (Exception ex)
419 {
420 Debug.Write(ex.Message);
421 return;
422 }
423
424 //Create the first empty document
425 CGDocument doc = new CGDocument();
426 doc.DocManager = _current;
427 doc.OnNewDocument();
428 Application.DoEvents();
429
430 //Run the application
431 Application.Run();
432 }
433 catch (Exception ex)
434 {
435 Debug.Write(ex.Message);
436 MessageBox.Show(ex.Message + ex.StackTrace, "CGDocumentManager.Main(): Clinical Scheduling Error -- Closing Application");
437 return;
438 }
439 }
440
441
442 public void LoadAccessGroupsTable()
443 {
444 string sCommandText = "SELECT * FROM BSDX_ACCESS_GROUP";
445 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroup", m_dsGlobal);
446 Debug.Write("LoadGlobalRecordsets -- AccessGroups loaded\n");
447 }
448
449 public void LoadAccessGroupTypesTable()
450 {
451 string sCommandText = "BSDX GET ACCESS GROUP TYPES";
452 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroupType", m_dsGlobal);
453 Debug.Write("LoadGlobalRecordsets -- AccessGroupTypes loaded\n");
454 }
455
456 public void LoadBSDXResourcesTable()
457 {
458 string sCommandText = "BSDX RESOURCES^" + m_ConnectInfo.DUZ;
459 ConnectInfo.RPMSDataTable(sCommandText, "Resources", m_dsGlobal);
460 Debug.Write("LoadGlobalRecordsets -- Resources loaded\n");
461 }
462
463 public void LoadResourceGroupTable()
464 {
465 //ResourceGroup Table (Resource Groups by User)
466 //Table "ResourceGroup" contains all resource group names
467 //to which user has access
468 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP
469 string sCommandText = "BSDX RESOURCE GROUPS BY USER^" + m_ConnectInfo.DUZ;
470 ConnectInfo.RPMSDataTable(sCommandText, "ResourceGroup", m_dsGlobal);
471 Debug.Write("LoadGlobalRecordsets -- ResourceGroup loaded\n");
472 }
473
474 public void LoadGroupResourcesTable()
475 {
476 //Table "GroupResources" contains all active GROUP/RESOURCE combinations
477 //to which user has access based on entries in BSDX RESOURCE USER file
478 //If user has BSDXZMGR or XUPROGMODE keys, then ALL Group/Resource combinstions
479 //are returned.
480 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP, RESOURCE_GROUP_ITEMID, RESOURCE_NAME, RESOURCE_ID
481 string sCommandText = "BSDX GROUP RESOURCE^" + m_ConnectInfo.DUZ;
482 ConnectInfo.RPMSDataTable(sCommandText, "GroupResources", m_dsGlobal);
483 Debug.Write("LoadGlobalRecordsets -- GroupResources loaded\n");
484 }
485
486 public void LoadScheduleUserTable()
487 {
488 //Table "ScheduleUser" contains an entry for each user in File 200 (NEW PERSON)
489 //who possesses the BSDXZMENU security key.
490 string sCommandText = "BSDX SCHEDULE USER";
491 ConnectInfo.RPMSDataTable(sCommandText, "ScheduleUser", m_dsGlobal);
492 Debug.Write("LoadGlobalRecordsets -- ScheduleUser loaded\n");
493 }
494
495 public void LoadResourceUserTable()
496 {
497 //Table "ResourceUser" duplicates the BSDX RESOURCE USER File.
498 //NOTE: Column names are RESOURCEUSER_ID, RESOURCEID,
499 // OVERBOOK, MODIFY_SCHEDULE, USERID, USERID1
500 //string sCommandText = "SELECT BMXIEN RESOURCEUSER_ID, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, USERNAME USERID, INTERNAL[USERNAME] FROM BSDX_RESOURCE_USER";
501 LoadResourceUserTable(false);
502 }
503
504 public void LoadResourceUserTable(bool bAllUsers)
505 {
506 string sCommandText = "SELECT BMXIEN RESOURCEUSER_ID, RESOURCENAME, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, MODIFY_APPOINTMENTS, USERNAME, INTERNAL[USERNAME] USERID FROM BSDX_RESOURCE_USER";
507 ConnectInfo.RPMSDataTable(sCommandText, "ResourceUser", m_dsGlobal);
508 Debug.Write("LoadGlobalRecordsets -- ResourceUser loaded\n");
509 }
510
511 private bool LoadGlobalRecordsets()
512 {
513
514 string sCommandText;
515
516 //Schedule User Info
517 DataTable dtUser = _dal.GetUserInfo(m_ConnectInfo.DUZ);
518 dtUser.TableName = "SchedulingUser";
519 m_dsGlobal.Tables.Add(dtUser);
520 Debug.Assert(dtUser.Rows.Count == 1);
521
522 // Only one row and one column named "MANAGER". Set local var m_bSchedManager to true if Manager.
523 DataRow rUser = dtUser.Rows[0];
524 Object oUser = rUser["MANAGER"];
525 string sUser = oUser.ToString();
526 m_bSchedManager = (sUser == "YES")?true:false;
527
528 //Get Access Types
529 DataTable dtAccessTypes = _dal.GetAccessTypes();
530 dtAccessTypes.TableName = "AccessTypes";
531 m_dsGlobal.Tables.Add(dtAccessTypes);
532
533 //AccessGroups
534 LoadAccessGroupsTable();
535
536 //Build Primary Key for AccessGroup table
537 DataTable dtGroups = m_dsGlobal.Tables["AccessGroup"];
538 DataColumn dcKey = dtGroups.Columns["ACCESS_GROUP"];
539 DataColumn[] dcKeys = new DataColumn[1];
540 dcKeys[0] = dcKey;
541 dtGroups.PrimaryKey = dcKeys;
542
543 //AccessGroupType
544 LoadAccessGroupTypesTable();
545
546 //Build Primary Key for AccessGroupType table
547 DataTable dtAGTypes = m_dsGlobal.Tables["AccessGroupType"];
548 DataColumn dcGTKey = dtAGTypes.Columns["ACCESS_GROUP_TYPEID"];
549 DataColumn[] dcGTKeys = new DataColumn[1];
550 dcGTKeys[0] = dcGTKey;
551 dtAGTypes.PrimaryKey = dcGTKeys;
552
553 //Build Data Relationship between AccessGroupType and AccessTypes tables
554 DataRelation dr = new DataRelation("AccessGroupType", //Relation Name
555 m_dsGlobal.Tables["AccessGroup"].Columns["BMXIEN"], //Parent
556 m_dsGlobal.Tables["AccessGroupType"].Columns["ACCESS_GROUP_ID"]); //Child
557 m_dsGlobal.Relations.Add(dr);
558
559 //ResourceGroup Table (Resource Groups by User)
560 LoadResourceGroupTable();
561
562 //Resources by user
563 LoadBSDXResourcesTable();
564
565 //Build Primary Key for Resources table
566 DataColumn[] dc = new DataColumn[1];
567 dc[0] = m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"];
568 m_dsGlobal.Tables["Resources"].PrimaryKey = dc;
569
570 //GroupResources table
571 LoadGroupResourcesTable();
572
573 //Build Primary Key for ResourceGroup table
574 dc = new DataColumn[1];
575 dc[0] = m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"];
576 m_dsGlobal.Tables["ResourceGroup"].PrimaryKey = dc;
577
578 //Build Data Relationships between ResourceGroup and GroupResources tables
579 dr = new DataRelation("GroupResource", //Relation Name
580 m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"], //Parent
581 m_dsGlobal.Tables["GroupResources"].Columns["RESOURCE_GROUP"]); //Child
582 CGSchedLib.OutputArray(m_dsGlobal.Tables["GroupResources"], "GroupResources");
583 m_dsGlobal.Relations.Add(dr);
584
585 //HospitalLocation table
586 //cmd.CommandText = "SELECT BMXIEN 'HOSPITAL_LOCATION_ID', NAME 'HOSPITAL_LOCATION', DEFAULT_PROVIDER, STOP_CODE_NUMBER, INACTIVATE_DATE, REACTIVATE_DATE FROM HOSPITAL_LOCATION";
587 sCommandText = "BSDX HOSPITAL LOCATION";
588 ConnectInfo.RPMSDataTable(sCommandText, "HospitalLocation", m_dsGlobal);
589 Debug.Write("LoadGlobalRecordsets -- HospitalLocation loaded\n");
590
591 //Build Primary Key for HospitalLocation table
592 dc = new DataColumn[1];
593 DataTable dtTemp = m_dsGlobal.Tables["HospitalLocation"];
594 dc[0] = dtTemp.Columns["HOSPITAL_LOCATION_ID"];
595 m_dsGlobal.Tables["HospitalLocation"].PrimaryKey = dc;
596
597 //smh
598 //LoadClinicSetupTable();
599
600 //smh
601 //Build Primary Key for ClinicSetupParameters table
602 /*dc = new DataColumn[1];
603 dtTemp = m_dsGlobal.Tables["ClinicSetupParameters"];
604 dc[0] = dtTemp.Columns["HOSPITAL_LOCATION_ID"];
605 m_dsGlobal.Tables["ClinicSetupParameters"].PrimaryKey = dc;
606
607 //Build Data Relationships between ClinicSetupParameters and HospitalLocation tables
608 dr = new DataRelation("HospitalLocationClinic", //Relation Name
609 m_dsGlobal.Tables["HospitalLocation"].Columns["HOSPITAL_LOCATION_ID"], //Parent
610 m_dsGlobal.Tables["ClinicSetupParameters"].Columns["HOSPITAL_LOCATION_ID"], false); //Child
611 m_dsGlobal.Relations.Add(dr);*/
612 /*SMH
613 dtTemp.Columns.Add("PROVIDER", System.Type.GetType("System.String"), "Parent.DEFAULT_PROVIDER");
614 dtTemp.Columns.Add("CLINIC_STOP", System.Type.GetType("System.String"), "Parent.STOP_CODE_NUMBER");
615 dtTemp.Columns.Add("INACTIVATE_DATE", System.Type.GetType("System.String"), "Parent.INACTIVATE_DATE");
616 dtTemp.Columns.Add("REACTIVATE_DATE", System.Type.GetType("System.String"), "Parent.REACTIVATE_DATE");
617 */
618
619 //Build Data Relationships between Resources and HospitalLocation tables
620 dr = new DataRelation("HospitalLocationResource", //Relation Name
621 m_dsGlobal.Tables["HospitalLocation"].Columns["HOSPITAL_LOCATION_ID"], //Parent
622 m_dsGlobal.Tables["Resources"].Columns["HOSPITAL_LOCATION_ID"], false); //Child
623 m_dsGlobal.Relations.Add(dr);
624
625 //Build ScheduleUser table
626 this.LoadScheduleUserTable();
627
628 //Build Primary Key for ScheduleUser table
629 dc = new DataColumn[1];
630 dtTemp = m_dsGlobal.Tables["ScheduleUser"];
631 dc[0] = dtTemp.Columns["USERID"];
632 m_dsGlobal.Tables["ScheduleUser"].PrimaryKey = dc;
633
634 //Build ResourceUser table
635 this.LoadResourceUserTable();
636
637 //Build Primary Key for ResourceUser table
638 dc = new DataColumn[1];
639 dtTemp = m_dsGlobal.Tables["ResourceUser"];
640 dc[0] = dtTemp.Columns["RESOURCEUSER_ID"];
641 m_dsGlobal.Tables["ResourceUser"].PrimaryKey = dc;
642
643 //Create relation between BSDX Resource and BSDX Resource User tables
644 dr = new DataRelation("ResourceUser", //Relation Name
645 m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"], //Parent
646 m_dsGlobal.Tables["ResourceUser"].Columns["RESOURCEID"]); //Child
647 m_dsGlobal.Relations.Add(dr);
648
649 //Build active provider table
650 sCommandText = "SELECT BMXIEN, NAME FROM NEW_PERSON WHERE INACTIVE_DATE = '' AND BMXIEN > 1";
651 ConnectInfo.RPMSDataTable(sCommandText, "Provider", m_dsGlobal);
652 Debug.Write("LoadGlobalRecordsets -- Provider loaded\n");
653
654 //Build the CLINIC_STOP table
655 // sCommandText = "SELECT BMXIEN, CODE, NAME FROM CLINIC_STOP"; //SMH
656 sCommandText = "SELECT BMXIEN, AMIS_REPORTING_STOP_CODE, NAME FROM CLINIC_STOP";
657 ConnectInfo.RPMSDataTable(sCommandText, "ClinicStop", m_dsGlobal);
658 Debug.Write("LoadGlobalRecordsets -- ClinicStop loaded\n");
659
660 //Build the HOLIDAY table
661 sCommandText = "SELECT NAME, DATE FROM HOLIDAY WHERE DATE > '" + DateTime.Today.ToShortDateString() + "'";
662 ConnectInfo.RPMSDataTable(sCommandText, "HOLIDAY", m_dsGlobal);
663 Debug.Write("LoadingGlobalRecordsets -- Holidays loaded\n");
664
665
666 //Save the xml schema
667 //m_dsGlobal.WriteXmlSchema(@"..\..\csSchema20060526.xsd");
668
669 return true;
670 }
671
672 public void RegisterDocumentView(CGDocument doc, CGView view)
673 {
674 //Store the view in the list of views
675 this.Views.Add(view, doc);
676
677 //Hook into the view's 'closed' event
678 view.Closed += new EventHandler(ViewClosed);
679
680 //Hook into the view's mnuRPMSServer.Click event
681 view.mnuRPMSServer.Click += new EventHandler(mnuRPMSServer_Click);
682
683 //Hook into the view's mnuRPMSLogin.Click event
684 view.mnuRPMSLogin.Click += new EventHandler(mnuRPMSLogin_Click);
685
686 }
687
688 public void RegisterAVDocumentView(CGAVDocument doc, CGAVView view)
689 {
690 //Store the view in the list of views
691 this.AvailabilityViews.Add(view, doc);
692
693 //Hook into the view's 'closed' event
694 view.Closed += new EventHandler(AVViewClosed);
695 }
696
697 public CGAVView GetAVViewByResource(ArrayList sResourceArray)
698 {
699 if (sResourceArray == null)
700 return null;
701
702 bool bEqual = true;
703 foreach (CGAVView v in m_AVViews.Keys)
704 {
705 CGAVDocument d = v.Document;
706
707 bEqual = false;
708 if (d.Resources.Count == sResourceArray.Count)
709 {
710 bEqual = true;
711 for (int j = 0; j < sResourceArray.Count; j++)
712 {
713 if (sResourceArray.Contains(d.Resources[j]) == false)
714 {
715 bEqual = false;
716 break;
717 }
718 if (d.Resources.Contains(sResourceArray[j]) == false)
719 {
720 bEqual = false;
721 break;
722 }
723 }
724 if (bEqual == true)
725 return v;
726 }
727 }
728 return null;
729 }
730 /// <summary>
731 /// Return the first view having a resource array matching sResourceArray
732 /// </summary>
733 /// <param name="sResourceArray"></param>
734 /// <returns></returns>
735 public CGView GetViewByResource(ArrayList sResourceArray)
736 {
737 if (sResourceArray == null)
738 return null;
739
740 bool bEqual = true;
741 foreach (CGView v in _views.Keys)
742 {
743 CGDocument d = v.Document;
744
745 bEqual = false;
746 if (d.Resources.Count == sResourceArray.Count)
747 {
748 bEqual = true;
749 for (int j = 0; j < sResourceArray.Count; j++)
750 {
751 if (sResourceArray.Contains(d.Resources[j]) == false)
752 {
753 bEqual = false;
754 break;
755 }
756 if (d.Resources.Contains(sResourceArray[j]) == false)
757 {
758 bEqual = false;
759 break;
760 }
761 }
762 if (bEqual == true)
763 return v;
764 }
765 }
766 return null;
767 }
768
769 private void ViewClosed(object sender, EventArgs e)
770 {
771 //Remove the sender from our document list
772 Views.Remove(sender);
773
774 //If no documents left, then close RPMS connection & exit the application
775 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
776 {
777 m_ConnectInfo.EventPollingEnabled = false;
778 m_ConnectInfo.UnSubscribeEvent("BSDX SCHEDULE");
779 m_ConnectInfo.CloseConnection();
780 Application.Exit();
781 }
782 }
783
784 private void AVViewClosed(object sender, EventArgs e)
785 {
786 //Remove the sender from our document list
787 this.AvailabilityViews.Remove(sender);
788
789 //If no documents left, then close RPMS connection & exit the application
790 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
791 {
792 m_ConnectInfo.bmxNetLib.CloseConnection();
793 Application.Exit();
794 }
795 }
796
797 private void KeepAlive()
798 {
799 foreach (CGView v in _views.Keys)
800 {
801 CGDocument d = v.Document;
802 DateTime dNow = DateTime.Now;
803 DateTime dLast = d.LastRefreshed;
804 TimeSpan tsDiff = dNow - dLast;
805 if (tsDiff.Seconds > 180)
806 {
807 for (int j = 0; j < d.Resources.Count; j++)
808 {
809 v.RaiseRPMSEvent("SCHEDULE-" + d.Resources[j].ToString(), "");
810 }
811
812 break;
813 }
814 }
815 }
816
817 /// <summary>
818 /// Propogate availability updates to all sRresource's doc/views
819 /// </summary>
820 public void UpdateViews(string sResource, string sOldResource)
821 {
822 if (sResource == null)
823 return;
824 foreach (CGView v in _views.Keys)
825 {
826 CGDocument d = v.Document;
827 for (int j = 0; j < d.Resources.Count; j++)
828 {
829 if ((sResource == "") || (sResource == ((string) d.Resources[j])) || (sOldResource == ((string) d.Resources[j])))
830 {
831 d.RefreshDocument();
832 break;
833 }
834 }
835 v.UpdateTree();
836 }
837 }
838
839 /// <summary>
840 /// Propogate availability updates to all doc/views
841 /// </summary>
842 public void UpdateViews()
843 {
844 UpdateViews("","");
845 foreach (CGView v in _views.Keys)
846 {
847 v.UpdateTree();
848 }
849 }
850
851 /// <summary>
852 /// Calls each view associated with document Doc and closes it.
853 /// </summary>
854 public void CloseAllViews(CGDocument doc)
855 {
856 //iterate through all views and call update.
857 Hashtable h = CGDocumentManager.Current.Views;
858
859 CGDocument d;
860 int nTempCount = h.Count;
861 do
862 {
863 nTempCount = h.Count;
864 foreach (CGView v in h.Keys)
865 {
866 d = (CGDocument) h[v];
867 if (d == doc)
868 {
869 v.Close();
870 break;
871 }
872 }
873 } while ((h.Count > 0) && (nTempCount != h.Count));
874 }
875
876 /// <summary>
877 /// Calls each view associated with Availability Doc and closes it.
878 /// </summary>
879 public void CloseAllViews(CGAVDocument doc)
880 {
881 //iterate through all views and call update.
882 Hashtable h = CGDocumentManager.Current.AvailabilityViews;
883
884 CGAVDocument d;
885 int nTempCount = h.Count;
886 do
887 {
888 nTempCount = h.Count;
889 foreach (CGAVView v in h.Keys)
890 {
891 d = (CGAVDocument) h[v];
892 if (d == doc)
893 {
894 v.Close();
895 break;
896 }
897 }
898 } while ((h.Count > 0) && (nTempCount != h.Count));
899
900
901 }
902
903 private void mnuRPMSServer_Click(object sender, EventArgs e)
904 {
905 //Warn that changing servers will close all schedules
906 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)
907 return;
908
909 //Reconnect to RPMS and recreate all global recordsets
910 try
911 {
912 m_bExitOK = false;
913 bool bRetry = true;
914 BMXNetConnectInfo tmpInfo;
915 do
916 {
917 tmpInfo = m_ConnectInfo;
918 try
919 {
920 tmpInfo.ChangeServerInfo();
921 bRetry = false;
922 }
923 catch (Exception ex)
924 {
925 if (ex.Message == "User cancelled.")
926 {
927 bRetry = false;
928 return;
929 }
930 if (MessageBox.Show("Unable to connect to VistA. " + ex.Message , "Clinical Scheduling", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
931 {
932 bRetry = true;
933 }
934 else
935 {
936 bRetry = false;
937 return;
938 }
939 }
940 } while (bRetry == true);
941
942 CloseAll();
943 m_bExitOK = true;
944 m_ConnectInfo = tmpInfo;
945
946 this.InitializeApp();
947
948 //Create a new document
949 CGDocument doc = new CGDocument();
950 doc.DocManager = _current;
951 doc.OnNewDocument();
952
953 }
954 catch (Exception ex)
955 {
956 throw ex;
957 }
958
959 }
960
961 private void mnuRPMSLogin_Click(object sender, EventArgs e)
962 {
963 //Warn that changing login will close all schedules
964 if (MessageBox.Show("Are you sure you want to close all schedules and login to VistA?", "Clinical Scheduling", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
965 return;
966
967 //Reconnect to RPMS and recreate all global recordsets
968 try
969 {
970 m_bExitOK = false;
971 CloseAll();
972 m_bExitOK = true;
973 _current.m_ConnectInfo = new BMXNet.BMXNetConnectInfo();
974 this.InitializeApp(true);
975 //Create a new document
976 CGDocument doc = new CGDocument();
977 doc.DocManager = _current;
978 doc.OnNewDocument();
979 }
980 catch (Exception ex)
981 {
982 throw ex;
983 }
984
985 }
986
987 delegate void CloseAllDelegate(string sMsg);
988
989 private void CloseAll(string sMsg)
990 {
991 if (sMsg == "")
992 {
993 sMsg = "Scheduling System Shutting Down Immediately for Maintenance.";
994 }
995
996 MessageBox.Show(sMsg, "Clinical Scheduling Administrator -- System Shutdown Notification", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
997
998 CloseAll();
999 }
1000
1001 private void CloseAll()
1002 {
1003 //Close all documents, views and connections
1004 Hashtable h = CGDocumentManager.Current.Views;
1005 int nTempCount = h.Count;
1006 do
1007 {
1008 nTempCount = h.Count;
1009 foreach (CGView v in h.Keys)
1010 {
1011 v.Close();
1012 break;
1013 }
1014 } while ((h.Count > 0) && (nTempCount != h.Count));
1015
1016 h = CGDocumentManager.Current.AvailabilityViews;
1017 nTempCount = h.Count;
1018 do
1019 {
1020 nTempCount = h.Count;
1021 foreach (CGAVView v in h.Keys)
1022 {
1023 v.Close();
1024 break;
1025 }
1026 } while ((h.Count > 0) && (nTempCount != h.Count));
1027
1028 }
1029
1030 delegate DataTable RPMSDataTableDelegate(string CommandString, string TableName);
1031
1032 public DataTable RPMSDataTable(string sSQL, string sTableName)
1033 {
1034 //Retrieves a recordset from RPMS
1035 string sErrorMessage = "";
1036 DataTable dtOut;
1037
1038#if TRACE
1039 DateTime sendTime = DateTime.Now;
1040#endif
1041 try
1042 {
1043 System.IntPtr pHandle = this.Handle;
1044 RPMSDataTableDelegate rdtd = new RPMSDataTableDelegate(ConnectInfo.RPMSDataTable);
1045 dtOut = (DataTable) this.Invoke(rdtd, new object[] {sSQL, sTableName});
1046 }
1047
1048 catch (Exception ex)
1049 {
1050 sErrorMessage = "CGDocumentManager.RPMSDataTable error: " + ex.Message;
1051 throw ex;
1052 }
1053
1054#if TRACE
1055 DateTime receiveTime = DateTime.Now;
1056 TimeSpan executionTime = receiveTime - sendTime;
1057 Debug.Write("CGDocumentManager::RPMSDataTable Execution Time: " + executionTime.Milliseconds + " ms.\n");
1058#endif
1059
1060 return dtOut;
1061
1062 }
1063
1064 public void ChangeDivision(System.Windows.Forms.Form frmCaller)
1065 {
1066 this.ConnectInfo.ChangeDivision(frmCaller);
1067 foreach (CGView v in _views.Keys)
1068 {
1069 v.InitializeDocView(v.Document.DocName);
1070 v.Document.RefreshDocument();
1071 }
1072 }
1073
1074 public void ViewRefresh()
1075 {
1076 foreach (CGView v in _views.Keys)
1077 {
1078 try
1079 {
1080 v.Document.RefreshDocument();
1081 }
1082 catch (Exception ex)
1083 {
1084 Debug.Write("CGDocumentManager.ViewRefresh Exception: " + ex.Message + "\n");
1085 }
1086 finally
1087 {
1088 }
1089 }
1090 Debug.Write("DocManager refreshed all views.\n");
1091 }
1092
1093 #endregion Methods & Events
1094
1095 }
1096}
Note: See TracBrowser for help on using the repository browser.