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

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

Progress Bar on Splash Screen and supporting code

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