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

Last change on this file since 1050 was 1050, checked in by Sam Habiel, 13 years ago

Bumped version number to 1.5
DSplash: Changes intended to support Asynchronous invokation of Splash Screen.
CGDocumentManager: Extensive changes to increase speed and invoke Splash screen async.

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