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

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

CGView:

  • Changed the parameters required for checkin.
  • Removed references to PCC+ and Stop Code processing, as they don't apply in VISTA.

CGDocument:

  • Changed RPC call parameters to check in an appointment (BSDX CHECKIN APPOINTMENT).
  • Date passed to BSDX Checkin Appointment is now an FM Date.
  • Both necessitated server side changes.

DCheckIn:

  • Removed processing for PCC+ and Stop Codes.

CGDocumentManager

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