source: Scheduling/trunk/cs/bsdx0200GUISourceCode/CGDocument.cs@ 1056

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

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

File size: 31.1 KB
RevLine 
[614]1using System;
2using System.Collections;
3using System.Data;
4using System.Data.OleDb;
5using System.Diagnostics;
6using System.Drawing;
7using System.Windows.Forms;
8using IndianHealthService.BMXNet;
9
10namespace IndianHealthService.ClinicalScheduling
11{
12 /// <summary>
13 /// Contains the array of appointments and availabily that make up the document class
14 /// </summary>
15 public class CGDocument : System.Object
16 {
17
18 public CGDocument()
19 {
20 m_appointments = new CGAppointments();
21 m_pAvArray = new ArrayList();
22 m_sResourcesArray = new ArrayList();
23 }
24
25 #region Member Variables
26 public int m_nColumnCount; //todo: this should point to the view's member for column count
27 public int m_nTimeUnits;
28 private string m_sDocName;
[821]29 public ArrayList m_sResourcesArray; //keeps the resources
[614]30 public ScheduleType m_ScheduleType;
31 private DateTime m_dSelectedDate; //Holds the user's selection from the dtpicker
32 private DateTime m_dStartDate; //Beginning date of document data
33 private DateTime m_dEndDate; //Ending date of document data
34 public CGAppointments m_appointments;
35 private ArrayList m_pAvArray;
36 private CGDocumentManager m_DocManager;
37 private DateTime m_dLastRefresh = DateTime.Now;
38
39 #endregion
40
41 #region Properties
42
43 /// <summary>
44 /// Returns the latest refresh time for this document
45 /// </summary>
46 public DateTime LastRefreshed
47 {
48 get
49 {
50 return m_dLastRefresh;
51 }
52 }
53
54 /// <summary>
55 /// The list of Resource names
56 /// </summary>
57 public ArrayList Resources
58 {
59 get
60 {
61 return this.m_sResourcesArray;
62 }
63 set
64 {
65 this.m_sResourcesArray = value;
66 }
67 }
68
69 /// <summary>
70 /// The array of CGAvailabilities that contains appt type and slots
71 /// </summary>
72 public ArrayList AvailabilityArray
73 {
74 get
75 {
76 return this.m_pAvArray;
77 }
78 }
79
80 public CGDocumentManager DocManager
81 {
82 get
83 {
84 return m_DocManager;
85 }
86 set
87 {
88 m_DocManager = value;
89 }
90 }
91
92 /// <summary>
93 /// Contains the hashtable of appointments
94 /// </summary>
95 public CGAppointments Appointments
96 {
97 get
98 {
99 return m_appointments;
100 }
101 }
102
103 /// <summary>
104 /// Holds the date selected by the user in CGView.dateTimePicker1
105 /// </summary>
106 public DateTime SelectedDate
107 {
108 get
109 {
110 return this.m_dSelectedDate;
111 }
112 set
113 {
114 this.m_dSelectedDate = value;
115 bool bRet = false;
116 if (m_sResourcesArray.Count == 1)
117 {
118 bRet = this.WeekNeedsRefresh(1, m_dSelectedDate, out this.m_dStartDate, out this.m_dEndDate);
119 }
120 else
121 {
122 this.m_dStartDate = m_dSelectedDate;
123 this.m_dEndDate = m_dSelectedDate;
124 this.m_dEndDate = this.m_dEndDate.AddHours(23);
125 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
126 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
127 }
128
129 bRet = RefreshSchedule();
130 }
131 }
132
133 /// <summary>
134 /// Contains the beginning date of the appointment document
135 /// </summary>
136 public DateTime StartDate
137 {
138 get
139 {
140 return this.m_dStartDate;
141 }
142 }
143
144 public string DocName
145 {
146 get
147 {
148 return this.m_sDocName;
149 }
150 set
151 {
152 this.m_sDocName = value;
153 }
154 }
155
156 #endregion
157
158 #region Methods
159
160 public void UpdateAllViews()
161 {
162 //iterate through all views and call update.
163 Hashtable h = CGDocumentManager.Current.Views;
164
165 CGDocument d;
166 foreach (CGView v in h.Keys)
167 {
168 d = (CGDocument) h[v];
169 if (d == this)
170 {
171 v.UpdateArrays();
172 }
173 }
174
175 }
176
177 /// <summary>
178 /// Update schedule based on info in RPMS
179 /// </summary>
180 private bool RefreshDaysSchedule()
181 {
182 try
183 {
184 string sPatientName;
185 string sPatientID;
186 DateTime dStart;
187 DateTime dEnd;
188 DateTime dCheckIn;
189 DateTime dAuxTime;
190 int nKeyID;
191 string sNote;
192 string sResource;
193 bool bNoShow = false;
194 string sNoShow = "0";
195 string sHRN = "";
196 int nAccessTypeID; //used in autorebook
197 string sWalkIn = "0";
198 bool bWalkIn;
199 CGAppointment pAppointment;
200 CGDocumentManager pApp = CGDocumentManager.Current;
201 DataTable rAppointmentSchedule;
202
[821]203 //Nice to know that it gets set here!!!
[614]204 m_dLastRefresh = DateTime.Now;
205
206 this.m_appointments.ClearAllAppointments();
207
[850]208 // calls RPC to get appointments
[614]209 rAppointmentSchedule = CGSchedLib.CreateAppointmentSchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate);
[821]210
211 // Datatable dumper into Debug Log (nice to know that this exists)
212 CGSchedLib.OutputArray(rAppointmentSchedule, "rAppointmentSchedule");
213
214
215 foreach (DataRow r in rAppointmentSchedule.Rows)
[614]216 {
217
218 if (r["APPOINTMENTID"].ToString() == "0")
219 {
220 string sMsg = r["NOTE"].ToString();
221 throw new BMXNetException(sMsg);
222 }
223 nKeyID = Convert.ToInt32(r["APPOINTMENTID"].ToString());
224 sResource = r["RESOURCENAME"].ToString();
225 sPatientName =r["PATIENTNAME"].ToString();
226 sPatientID =r["PATIENTID"].ToString();
227 dStart = (DateTime) r["START_TIME"];
228 dEnd = (DateTime) r["END_TIME"];
229 dCheckIn = new DateTime();
230 dAuxTime = new DateTime();
231
232 if (r["CHECKIN"].GetType() != typeof(System.DBNull))
233 dCheckIn = (DateTime) r["CHECKIN"];
234 if (r["AUXTIME"].GetType() != typeof(System.DBNull))
235 dCheckIn = (DateTime) r["AUXTIME"];
236 sNote = r["NOTE"].ToString();
237 sNoShow = r["NOSHOW"].ToString();
238 bNoShow = (sNoShow == "1")?true: false;
239 sHRN = r["HRN"].ToString();
240 nAccessTypeID = (int) r["ACCESSTYPEID"];
241 sWalkIn = r["WALKIN"].ToString();
242 bWalkIn = (sWalkIn == "1")?true: false;
243
244 pAppointment = new CGAppointment();
245 pAppointment.CreateAppointment(dStart, dEnd, sNote, nKeyID, sResource);
246 pAppointment.PatientName = sPatientName;
247 pAppointment.PatientID = Convert.ToInt32(sPatientID);
248 if (dCheckIn.Ticks > 0)
249 pAppointment.CheckInTime = dCheckIn;
250 if (dAuxTime.Ticks > 0)
251 pAppointment.AuxTime = dAuxTime;
252 pAppointment.NoShow = bNoShow;
253 pAppointment.HealthRecordNumber = sHRN;
254 pAppointment.AccessTypeID = nAccessTypeID;
255 pAppointment.WalkIn = bWalkIn;
256 this.m_appointments.AddAppointment(pAppointment);
257
258 }
259
260 return true;
261 }
262 catch(Exception Ex)
263 {
264 Debug.Write("CGDocument.RefreshDaysSchedule error: " + Ex.Message + "\n");
265 return false;
266 }
267 }
268
269
270 public void OnNewDocument()
271 {
272 /*
273 * TEST EXCEPTION -- REMOVE AFTER TESTING
274 */
275 //throw new Exception("Simulated Uncaught Exception");
276 /*
277 * TEST EXCEPTION -- REMOVE AFTER TESTING
278 */
279
280 //Open an empty document
281 m_sResourcesArray.Clear();
282 m_ScheduleType = ScheduleType.Resource;
283
284 //Set initial From and To dates based on current day
285 // DateTime dDate = new DateTime(2001,12,05); //Testing line
286 DateTime dDate = DateTime.Today;
[821]287
288 //smh: Question: Where does bRet get used? It's a useless varaible so far.
[614]289 bool bRet = this.WeekNeedsRefresh(2,dDate, out this.m_dStartDate, out this.m_dEndDate);
290
291 //Create new View
292 CGView view = new CGView();
293 view.InitializeDocView(this,
294 this.DocManager,
295 m_dStartDate,
296 this.Appointments,
297 DocManager.WindowText);
298
299 view.Show();
300 view.SyncTree();
301 view.Activate();
302 this.UpdateAllViews();
303 }
304
305 private void SetDate(DateTime dDate)
306 {
307 bool bRet = false;
308 if (m_ScheduleType == ScheduleType.Resource)
309 {
310 bRet = this.WeekNeedsRefresh(2,dDate, out this.m_dStartDate, out this.m_dEndDate);
311 }
312 else
313 {
314 this.m_dStartDate = dDate;
315 this.m_dEndDate = dDate;
316 this.m_dEndDate = this.m_dEndDate.AddHours(23);
317 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
318 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
319 }
320
321 bRet = RefreshSchedule();
322 this.UpdateAllViews();
323 }
324
325 public void RefreshDocument()
326 {
327 bool bRet = RefreshSchedule();
328 this.UpdateAllViews();
329 }
330
331 public void OnOpenDocument()
332 {
333 try
334 {
335 //Create new Document
336 m_ScheduleType = (m_sResourcesArray.Count == 1) ? ScheduleType.Resource: ScheduleType.Clinic;
337 bool bRet = false;
338
339 //Set initial From and To dates based on current day
340 DateTime dDate = DateTime.Today;
341 if (m_ScheduleType == ScheduleType.Resource)
342 {
343 bRet = this.WeekNeedsRefresh(1,dDate, out this.m_dStartDate, out this.m_dEndDate);
344 }
345 else
346 {
347 this.m_dStartDate = dDate;
348 this.m_dEndDate = dDate;
349 this.m_dEndDate = this.m_dEndDate.AddHours(23);
350 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
351 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
352 }
353
354 bRet = RefreshSchedule();
355
356 CGView view = null;
357 //If this document already has a view, the use it
358 Hashtable h = CGDocumentManager.Current.Views;
359 CGDocument d;
360 bool bReuseView = false;
361 foreach (CGView v in h.Keys)
362 {
363 d = (CGDocument) h[v];
364 if (d == this)
365 {
366 view = v;
367 bReuseView = true;
368 v.InitializeDocView(this.DocName);
369 break;
370 }
371 }
372
373 //Otherwise, create new View
374 if (bReuseView == false)
375 {
376 view = new CGView();
377
378 view.InitializeDocView(this,
379 this.DocManager,
380 m_dStartDate,
381 this.Appointments,
382 this.DocName);
383
384 view.Show();
385 view.SyncTree();
386
387 }
388 this.UpdateAllViews();
389 }
390 catch (BMXNetException bmxEx)
391 {
392 throw bmxEx;
393 }
394 catch (Exception ex)
395 {
396 throw new BMXNet.BMXNetException("ClinicalScheduling.OnOpenDocument error: " + ex.Message);
397 }
398 }
399
400 private bool RefreshSchedule()
401 {
402 try
403 {
404 bool bRet = this.RefreshAvailabilitySchedule();
405 if (bRet == false)
406 {
407 return bRet;
408 }
409 bRet = this.RefreshDaysSchedule();
410 return bRet;
411 }
412 catch (ApplicationException aex)
413 {
414 Debug.Write("CGDocument.RefreshSchedule Application Error: " + aex.Message + "\n");
415 return false;
416 }
417 catch (Exception ex)
418 {
419 MessageBox.Show("CGDocument.RefreshSchedule error: " + ex.Message + "\n");
420 return false;
421 }
422 }
423
424 private bool RefreshAvailabilitySchedule()
425 {
426 try
427 {
428 if (this.m_DocManager.ConnectInfo.Connected == false)
429 {
430 m_DocManager.ConnectInfo.LoadConnectInfo();
431 }
432
433 m_pAvArray.Clear();
434
435 ArrayList saryApptTypes = new ArrayList();
436 int nApptTypeID = 0;
437
438 //Refresh Availability schedules
439 DataTable rAvailabilitySchedule;
440 rAvailabilitySchedule = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate, saryApptTypes,/**/ m_ScheduleType, "0");
441 CGSchedLib.OutputArray(rAvailabilitySchedule, "rAvailabilitySchedule");
442
443 //Refresh Type Schedule
444 string sResourceName = "";
445 DataTable rTypeSchedule = new DataTable();;
446 for (int j = 0; j < m_sResourcesArray.Count; j++)
447 {
448 sResourceName = m_sResourcesArray[j].ToString();
449 DataTable dtTemp = CGSchedLib.CreateAssignedTypeSchedule(m_DocManager, sResourceName, this.m_dStartDate, this.m_dEndDate, m_ScheduleType);
450 CGSchedLib.OutputArray(dtTemp, "dtTemp");
451 if (j == 0)
452 {
453 rTypeSchedule = dtTemp;
454 }
455 else
456 {
457 rTypeSchedule = CGSchedLib.UnionBlocks(rTypeSchedule, dtTemp);
458 }
459 }
460 CGSchedLib.OutputArray(rTypeSchedule, "rTypeSchedule");
461
462 DateTime dStart;
463 DateTime dEnd;
464 DateTime dTypeStart;
465 DateTime dTypeEnd;
466 int nSlots;
467 Rectangle crRectA = new Rectangle(0,0,1,0);
468 Rectangle crRectB= new Rectangle(0,0,1,0);
469 bool bIsect;
470 string sResourceList;
471 string sAccessRuleList;
472
473
474 foreach (DataRow rTemp in rAvailabilitySchedule.Rows)
475 {
476 //get StartTime, EndTime and Slots
477 dStart = (DateTime) rTemp["START_TIME"];
478 dEnd = (DateTime) rTemp["END_TIME"];
479
480 //TODO: Fix this slots datatype problem
481 string sSlots = rTemp["SLOTS"].ToString();
482 nSlots = Convert.ToInt16(sSlots);
483
484 sResourceList = rTemp["RESOURCE"].ToString();
485 sAccessRuleList = rTemp["ACCESS_TYPE"].ToString();
486
487 string sNote = rTemp["NOTE"].ToString();
488
489 if ((nSlots < -1000)||(sAccessRuleList == ""))
490 {
491 nApptTypeID = 0;
492 }
493 else
494 {
495 foreach (DataRow rType in rTypeSchedule.Rows)
496 {
497
498 dTypeStart = (DateTime) rType["StartTime"];
499 dTypeEnd = (DateTime) rType["EndTime"];
500 //if start & end times overlap, then
501 string sTypeResource = rType["ResourceName"].ToString();
502 if ((dTypeStart.DayOfYear == dStart.DayOfYear) && (sResourceList == sTypeResource))
503 {
504 crRectA.Y = GetTotalMinutes(dStart);
505 crRectA.Height = GetTotalMinutes(dEnd) - crRectA.Top;
506 crRectB.Y = GetTotalMinutes(dTypeStart);
507 crRectB.Height = GetTotalMinutes(dTypeEnd) - crRectB.Top;
508 bIsect = crRectA.IntersectsWith(crRectB);
509 if (bIsect == true)
510 {
511 //TODO: This code:
512 // nApptTypeID = (int) rType["AppointmentTypeID"];
513 //Causes this exception:
514 //Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
515 string sTemp = rType["AppointmentTypeID"].ToString();
516 nApptTypeID = Convert.ToInt16(sTemp);
517 break;
518 }
519 }
520 }//end foreach datarow rType
521 }
522
523 AddAvailability(dStart, dEnd, nApptTypeID, nSlots, false, sResourceList, sAccessRuleList, sNote);
524 }//end foreach datarow rTemp
525
526 return true;
527 }
528 catch (Exception ex)
529 {
530 Debug.Write("CGDocument.RefreshAvailabilitySchedule error: " + ex.Message + "\n");
531 return false;
532 }
533 }
534
535 private int GetTotalMinutes(DateTime dDate)
536 {
537 return ((dDate.Hour * 60) + dDate.Minute);
538 }
539
540 public int AddAvailability(DateTime StartTime, DateTime EndTime, int nType, int nSlots, bool UpdateView, string sResourceList, string sAccessRuleList, string sNote)
541 {
542 //adds it to the object array
543 //Returns the index in the array
544
545 CGAvailability pNewAv = new CGAvailability();
546 pNewAv.Create(StartTime, EndTime, nType, nSlots, sResourceList, sAccessRuleList);
547
548 pNewAv.Note = sNote;
549
550 //Look up the color and type name using the AppointmentTypes datatable
551 DataTable dtType = this.m_DocManager.GlobalDataSet.Tables["AccessTypes"];
552 DataRow dRow = dtType.Rows.Find(nType.ToString());
553 if (dRow != null)
554 {
555 string sColor = dRow["DISPLAY_COLOR"].ToString();
556 pNewAv.DisplayColor = sColor;
557 string sTemp = dRow["RED"].ToString();
558 sTemp = (sTemp == "")?"0":sTemp;
559 int nRed = Convert.ToInt16(sTemp);
560 pNewAv.Red = nRed;
561 sTemp = dRow["GREEN"].ToString();
562 sTemp = (sTemp == "")?"0":sTemp;
563 int nGreen = Convert.ToInt16(sTemp);
564 pNewAv.Green = nGreen;
565 sTemp = dRow["BLUE"].ToString();
566 sTemp = (sTemp == "")?"0":sTemp;
567 int nBlue = Convert.ToInt16(sTemp);
568 pNewAv.Blue = nBlue;
569
570 string sName = dRow["ACCESS_TYPE_NAME"].ToString();
571 pNewAv.AccessTypeName = sName;
572 }
573
574 int nIndex = 0;
575 nIndex = m_pAvArray.Add(pNewAv);
576 if (UpdateView == true)
577 {
578 this.UpdateAllViews();
579 }
580 return nIndex;
581 }
582
583
584 public void AddResource(string sResource)
585 {
586 //TODO: Test that resource is not currently in list, that it IS a resource, etc
587 this.m_sResourcesArray.Add(sResource);
588 this.UpdateAllViews();
589 }
590
591 public void ClearResources()
592 {
593 this.m_sResourcesArray.Clear();
594 }
595
596 public int SlotsAvailable(DateTime dSelStart, DateTime dSelEnd, string sResource, out string sAccessType, out string sAvailabilityMessage)
597 {
598 sAccessType = "";
599 sAvailabilityMessage = "";
600 DateTime dStart;
601 DateTime dEnd;
602 int nAvailableSlots = 999;
603 int nSlots = 0;
604 int i = 0;
605 CGAvailability pAv;
606 Rectangle crRectA = new Rectangle(0,0,1,0);
607 Rectangle crRectB = new Rectangle(0,0,1,0);
608 bool bIsect;
609 crRectB.Y = GetTotalMinutes(dSelStart);
610 crRectB.Height = GetTotalMinutes(dSelEnd)- crRectB.Y;
611
612 // //loop thru m_pAvArray
613 // //Compare the start time and end time of eachblock
614 while (i < m_pAvArray.Count)
615 {
616 pAv = (CGAvailability) m_pAvArray[i];
617 dStart = pAv.StartTime;
618 dEnd = pAv.EndTime;
619 if ((sResource == pAv.ResourceList) &&
620 ((dSelStart.Date == dStart.Date) || (dSelStart.Date == dEnd.Date)))
621 {
622 crRectA.Y = (dStart.Date < dSelStart.Date) ? 0 : GetTotalMinutes(dStart);
623 crRectA.Height = (dEnd.Date > dSelEnd.Date) ? 1440 : GetTotalMinutes(dEnd);
624 crRectA.Height = crRectA.Height - crRectA.Y;
625 bIsect = crRectA.IntersectsWith(crRectB);
626 if (bIsect != false)
627 {
628 nSlots = pAv.Slots;
629 if (nSlots < 1)
630 {
631 nAvailableSlots = 0;
632 break;
633 }
634 if (nSlots < nAvailableSlots)
635 {
636 nAvailableSlots = nSlots;
637 sAccessType = pAv.AccessTypeName;
638 sAvailabilityMessage = pAv.Note;
639
640 }
641 }
642 }
643 i++;
644 }
645 if (nAvailableSlots == 999)
646 {
647 nAvailableSlots = 0;
648 }
649 return nAvailableSlots;
650 }
651
652 /// <summary>
653 /// Given a selected date,
654 /// Calculates StartDay and End Day and returns them in output params.
655 /// nWeeks == number of Weeks to display
[886]656 /// nColumnCount is number of days displayed per week.
657 /// If 5 columns, begin on Second Day of Week
658 /// If 7 Columns, begin on First Day of Week
659 /// (this is a change from the hardcoded behavior for US-based calendars)
[614]660 ///
661 /// Returns TRUE if the document's data needs refreshing based on
662 /// this newly selected date.
663 /// </summary>
664 public bool WeekNeedsRefresh(int nWeeks, DateTime SelectedDate,
665 out DateTime WeekStartDay, out DateTime WeekEndDay)
666 {
667 DateTime OldStartDay = m_dStartDate;
668 DateTime OldEndDay = m_dEndDate;
[908]669 // Week start based on thread locale
670 int nStartWeekDay = (int)System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
[913]671 // Current Day
[868]672 int nWeekDay = (int) SelectedDate.DayOfWeek; //0 == Sunday
[614]673
[886]674 // this offset gets approrpriate day based on locale.
675 int nOff = (nStartWeekDay + 1) % 7;
[614]676 TimeSpan ts = new TimeSpan(nWeekDay - nOff,0,0,0); //d,h,m,s
677
[913]678 // if ts is negative, we will jump to the next week in the logic.
679 // to show the correct week, add 7. Confusing, I know.
680 if (ts < new TimeSpan() ) ts = ts + new TimeSpan(7,0,0,0);
681
682 if (m_nColumnCount == 1) // if one column start and end on the same day.
[614]683 {
684 ts = new TimeSpan(0,23,59,59);
685 WeekStartDay = SelectedDate;
[913]686 WeekEndDay = WeekStartDay + ts;
[614]687 }
[913]688 else if (m_nColumnCount == 5 || m_nColumnCount == 0) // if 5 column start (or default) at the 2nd day of this week and end in 4:23:59:59 days.
689 {
690 // if picked day is start of week (Sunday in US), start in the next day since that's the first day of work week
691 // else, just substract the calculated time span to get to the start of week (first work day)
692 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate + new TimeSpan(1,0,0,0): SelectedDate - ts;
693 // End day calculation
694 int nEnd = 3;
695 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
696 WeekEndDay = WeekStartDay + ts;
697 }
698 else // if 7 column start at the 1st day of this week and end in 6:23:59:59 days.
699 {
700 // if picked day is start of week, use that. Otherwise, go to the fist work day and substract one to get to start of week.
701 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate : SelectedDate - ts - new TimeSpan(1,0,0,0);
702 // End day calculation
703 int nEnd = 1;
704 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
705 WeekEndDay = WeekStartDay + ts;
706 }
707
[614]708 bool bRet = (( WeekStartDay.Date != OldStartDay.Date) || (WeekEndDay.Date != OldEndDay.Date));
709 return bRet;
710 }
711
712 /// <summary>
713 /// Calls RPMS to create appointment then
714 /// adds appointment to the m_appointments collection
715 /// Returns the IEN of the appointment in the RPMS BSDX APPOINTMENT file.
716 /// </summary>
717 /// <param name="rApptInfo"></param>
718 /// <returns></returns>
719 public int CreateAppointment(CGAppointment rApptInfo)
720 {
721 return CreateAppointment(rApptInfo, false);
722 }
723
724 /// <summary>
725 /// Use this overload to create a walkin appointment
726 /// </summary>
727 /// <param name="rApptInfo"></param>
728 /// <param name="bWalkin"></param>
729 /// <returns></returns>
730 public int CreateAppointment(CGAppointment rApptInfo, bool bWalkin)
731 {
732 string sStart;
733 string sEnd;
734 string sPatID;
735 string sResource;
736 string sNote;
737 string sLen;
738 string sApptID;
739
[864]740 //sStart = rApptInfo.StartTime.ToString("M-d-yyyy@HH:mm");
741 //sEnd = rApptInfo.EndTime.ToString("M-d-yyyy@HH:mm");
742
743 // i18n code -- Use culture neutral FMDates
744 sStart = FMDateTime.Create(rApptInfo.StartTime).FMDateString;
745 sEnd = FMDateTime.Create(rApptInfo.EndTime).FMDateString;
746
[614]747 TimeSpan sp = rApptInfo.EndTime - rApptInfo.StartTime;
748 sLen = sp.TotalMinutes.ToString();
749 sPatID = rApptInfo.PatientID.ToString();
750 sNote = rApptInfo.Note;
751 sResource = rApptInfo.Resource;
752 if (bWalkin == true)
753 {
754 sApptID = "WALKIN";
755 }
756 else
757 {
758 sApptID = rApptInfo.AccessTypeID.ToString();
759 }
760
761 CGAppointment aCopy = new CGAppointment();
762 aCopy.CreateAppointment(rApptInfo.StartTime, rApptInfo.EndTime, sNote, 0, sResource);
763 aCopy.PatientID = rApptInfo.PatientID;
764 aCopy.PatientName = rApptInfo.PatientName;
765 aCopy.HealthRecordNumber = rApptInfo.HealthRecordNumber;
766 aCopy.AccessTypeID = rApptInfo.AccessTypeID;
767
768 string sSql = "BSDX ADD NEW APPOINTMENT^" + sStart + "^" + sEnd + "^" + sPatID + "^" + sResource + "^" + sLen + "^" + sNote + "^" + sApptID ;
769 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "NewAppointment");
770 int nApptID;
771
772 Debug.Assert(dtAppt.Rows.Count == 1);
773 DataRow r = dtAppt.Rows[0];
774 nApptID =Convert.ToInt32(r["APPOINTMENTID"]);
775 string sErrorID;
776 sErrorID = r["ERRORID"].ToString();
777 if ((sErrorID != "")||(nApptID < 1))
778 throw new Exception(sErrorID);
779 aCopy.AppointmentKey = nApptID;
780 this.m_appointments.AddAppointment(aCopy);
781
782 bool bRet = RefreshAvailabilitySchedule();
783
784 UpdateAllViews();
785
786 return nApptID;
787 }
788
789 public void EditAppointment(CGAppointment pAppt, string sNote)
790 {
791 try
792 {
793 int nApptID = pAppt.AppointmentKey;
794 string sSql = "BSDX EDIT APPOINTMENT^" + nApptID.ToString() + "^" + sNote;
795
796 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "EditAppointment");
797
798 Debug.Assert(dtAppt.Rows.Count == 1);
799 DataRow r = dtAppt.Rows[0];
800 string sErrorID = r["ERRORID"].ToString();
801 if (sErrorID == "-1")
802 pAppt.Note = sNote;
803
804 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
805 {
806 bool bRet = RefreshAvailabilitySchedule();
807 UpdateAllViews();
808 }
809 }
810 catch (Exception ex)
811 {
812 Debug.Write("CGDocument.EditAppointment Failed: " + ex.Message);
813 }
814 }
815
816 public void CheckInAppointment(int nApptID, DateTime dCheckIn,
817 string ClinicStopIEN,
818 string ProviderIEN,
819 string PrintRouteSlip,
820 string PCCClinicIEN,
821 string PCCFormIEN,
822 string PCCOutGuide
823 )
824 {
825 string sCheckIn = dCheckIn.ToString("M-d-yyyy@HH:mm");
826
827 string sSql = "BSDX CHECKIN APPOINTMENT^" + nApptID.ToString() + "^" + sCheckIn + "^";
828 sSql += ClinicStopIEN + "^" + ProviderIEN + "^" + PrintRouteSlip + "^";
829 sSql += PCCClinicIEN + "^" + PCCFormIEN + "^" + PCCOutGuide;
830
831 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "CheckInAppointment");
832
833 Debug.Assert(dtAppt.Rows.Count == 1);
834 DataRow r = dtAppt.Rows[0];
835 string sErrorID = r["ERRORID"].ToString();
836
837 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
838 {
839 bool bRet = RefreshSchedule();
840 UpdateAllViews();
841 }
842 }
843
844 public string DeleteAppointment(int nApptID)
845 {
846 return DeleteAppointment(nApptID, true, 0, "");
847 }
848
849 public string DeleteAppointment(int nApptID, bool bClinicCancelled, int nReason, string sRemarks)
850 {
851 //Returns "" if deletion successful
852 //Otherwise, returns reason for failure
853
854 string sClinicCancelled = (bClinicCancelled == true)?"C":"PC";
855 string sReasonID = nReason.ToString();
856 string sSql = "BSDX CANCEL APPOINTMENT^" + nApptID.ToString();
857 sSql += "^" + sClinicCancelled;
858 sSql += "^" + sReasonID;
859 sSql += "^" + sRemarks;
860 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "DeleteAppointment");
861
862 Debug.Assert(dtAppt.Rows.Count == 1);
863 DataRow r = dtAppt.Rows[0];
864 string sErrorID = r["ERRORID"].ToString();
865 if (sErrorID != "")
866 return sErrorID;
867
868 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
869 {
870 this.m_appointments.RemoveAppointment(nApptID);
871 bool bRet = RefreshAvailabilitySchedule();
872 UpdateAllViews();
873 }
874 return "";
875 }
876
877 public string AutoRebook(CGAppointment a, int nSearchType, int nMinimumDays, int nMaximumDays, out CGAppointment aRebook)
878 {
879 //If successful Returns "1" and new start date and time returned in aRebook
880 //Otherwise, returns error message
881
882 CGAppointment aCopy = new CGAppointment();
883 aCopy.CreateAppointment(a.StartTime, a.EndTime, a.Note, 0, a.Resource);
884 aCopy.PatientID = a.PatientID;
885 aCopy.PatientName = a.PatientName;
886 aCopy.HealthRecordNumber = a.HealthRecordNumber;
887 aCopy.AccessTypeID = a.AccessTypeID;
888 aRebook = aCopy;
889
890 //Determine Rebook access type
891 //nSearchType = -1: use current, -2: use any non-zero type, >0 use this access type id
892 int nAVType = 0;
893
894 switch (nSearchType)
895 {
896 case -1:
897 nAVType = a.AccessTypeID;
898 break;
899 case -2:
900 nAVType = 0;
901 break;
902 default:
903 nAVType = nSearchType;
904 break;
905 }
906
907 int nSlots = 0;
908 string sSlots = "";
909 int nAccessTypeID; //To compare with nAVType
910
911 DateTime dResult = new DateTime(); //StartTime of access block to autorebook into
912
913 //Next two are empty, but needed to pass to CreateAvailabilitySchedule
914 ArrayList alAccessTypes = new ArrayList();
915 string sSearchInfo = "";
916
917 //Find the StartTime of first availability block of this type for this clinic
918 //between nMinimumDays and nMaximumDays
919
920 string sAVStart = a.StartTime.AddDays(nMinimumDays).ToString("M/d/yyyy@H:mm");
921
922 //dtAVEnd is the last day to search
923 DateTime dtAVEnd = a.StartTime.AddDays(nMinimumDays + nMaximumDays);
924 string sAVEnd = dtAVEnd.ToString("M/d/yyyy@H:mm");
925
926 //Increment start day to search a week (or so) at a time
927 //30 is a test increment. Need to test different values for performance
928 int nIncrement = (nMaximumDays < 30)?nMaximumDays:30;
929
930 //nCount and nCountEnd are the 'moving' counters
931 //that I add to start and end to get the bracket
932 //At the beginning of the DO loop, nCount and nCountEnd are already set
933 bool bFinished = false;
934 bool bFound = false;
935
936 DateTime dStart = a.StartTime.AddDays(nMinimumDays);
[864]937 // v 1.3 i18n support - FM Date passed insated of American Date
938 string sStart = FMDateTime.Create(dStart).DateOnly.FMDateString;
[614]939 DateTime dEnd = dStart.AddDays(nIncrement);
940 do
941 {
[864]942 string sSql = "BSDX REBOOK NEXT BLOCK^" + sStart + "^" + a.Resource + "^" + nAVType.ToString();
[614]943 DataTable dtNextBlock = this.DocManager.RPMSDataTable(sSql, "NextBlock");
944 Debug.Assert(dtNextBlock.Rows.Count == 1);
945 DataRow drNextBlockRow = dtNextBlock.Rows[0];
946
947 object oNextBlock;
948 oNextBlock = drNextBlockRow["NEXTBLOCK"];
949 if (oNextBlock.GetType() == typeof(System.DBNull))
950 break;
951 DateTime dNextBlock = (DateTime) drNextBlockRow["NEXTBLOCK"];
952 if (dNextBlock > dtAVEnd)
953 {
954 break;
955 }
956
957 dStart = dNextBlock;
958 dEnd = dStart.AddDays(nIncrement);
959 if (dEnd > dtAVEnd)
960 dEnd = dtAVEnd;
961
962 DataTable dtResult = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, this.Resources, dStart, dEnd, alAccessTypes, ScheduleType.Resource, sSearchInfo);
963 //Loop thru dtResult looking for a slot having the required availability type.
964 //If found, set bFinished = true;
965 foreach (DataRow dr in dtResult.Rows)
966 {
967
968 sSlots = dr["SLOTS"].ToString();
969 if (sSlots == "")
970 sSlots = "0";
971 nSlots = Convert.ToInt16(sSlots);
972 if (nSlots > 0)
973 {
974 nAccessTypeID = 0; //holds the access type id of the availability block
975 if (dr["ACCESS_TYPE"].ToString() != "")
976 nAccessTypeID =Convert.ToInt16(dr["ACCESS_TYPE"].ToString());
977 if ((nSearchType == -2) && (nAccessTypeID > 0)) //Match on any non-zero type
978 {
979 bFinished = true;
980 bFound = true;
981 dResult = (DateTime) dr["START_TIME"];
982 break;
983 }
984 if (nAccessTypeID == nAVType)
985 {
986 bFinished = true;
987 bFound = true;
988 dResult = (DateTime) dr["START_TIME"];
989 break;
990 }
991 }
992 }
993 dStart = dEnd.AddDays(1);
994 dEnd = dStart.AddDays(nIncrement);
995 if (dEnd > dtAVEnd)
996 dEnd = dtAVEnd;
997 } while (bFinished == false);
998
999 if (bFound == true)
1000 {
1001 aCopy.StartTime = dResult;
1002 aCopy.EndTime = dResult.AddMinutes(a.Duration);
1003 //Create the appointment
1004 //Set the AUTOREBOOKED flag
1005 //and store the "AutoRebooked To DateTime"
1006 //in each autorebooked appointment
1007 this.CreateAppointment(aCopy);
1008 SetAutoRebook(a, dResult);
1009 return "1";
1010 }
1011 else
1012 {
1013 return "0";
1014 }
1015 }
1016
1017 private void SetAutoRebook(CGAppointment a, DateTime dtRebookedTo)
1018 {
1019 string sApptKey = a.AppointmentKey.ToString();
[864]1020 //string sRebookedTo = dtRebookedTo.ToString("M/d/yyyy@HH:mm");
1021 // i18n
1022 string sRebookedTo = FMDateTime.Create(dtRebookedTo).FMDateString;
[614]1023 string sSql = "BSDX REBOOK SET^" + sApptKey + "^" + sRebookedTo;
1024 System.Data.DataTable dtRebook = m_DocManager.RPMSDataTable(sSql, "AutoRebook");
1025
1026 }
1027
1028 public string AppointmentNoShow(int nApptID, bool bNoShow)
1029 {
1030 /*
1031 * BSDX NOSHOW RPC Returns 1 in ERRORID if successfully sets NOSHOW flag in BSDX APPOINTMENT and, if applicable, File 2
[1038]1032 *Otherwise, returns negative numbers for failure and errormessage in ERRORTXT
[614]1033 *
1034 */
1035
1036 string sTest = bNoShow.ToString();
1037 string sNoShow = (bNoShow == true)?"1":"0";
1038 string sSql = "BSDX NOSHOW^" + nApptID.ToString();
1039 sSql += "^";
1040 sSql += sNoShow;
1041
1042 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "AppointmentNoShow");
1043
1044 Debug.Assert(dtAppt.Rows.Count == 1);
1045 DataRow r = dtAppt.Rows[0];
1046 string sErrorID = r["ERRORID"].ToString();
1047 if (sErrorID != "1")
1048 {
1049 return r["ERRORTEXT"].ToString();
1050 }
1051
1052 bool bRet = RefreshSchedule();
1053
1054 return sErrorID;
1055 }
1056
1057 #endregion Methods
1058
1059 }//End class
1060}//End namespace
Note: See TracBrowser for help on using the repository browser.