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

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

Release build for Scheduling v 1.42 for .net 3.5.

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