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

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

CGAVDocument contains changes for start day of grid based on weekday locale and colummns
CGAVView: Shortcut keys; correct updating when number of columns is changed in grid
CGDocument: changes for start day of grid. Modified algorithm.
DAccessTemplate: Takes any weekday now for applying a template, not just Monday. Then calculation of start day is done in CGAVView based on locale in the same algorithm that the rest of the GUI uses.
DAppointPage: Now says Mobile/Cell instead of Cell Phone.

File size: 31.3 KB
Line 
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;
29 public ArrayList m_sResourcesArray; //keeps the resources
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
203 //Nice to know that it gets set here!!!
204 m_dLastRefresh = DateTime.Now;
205
206 this.m_appointments.ClearAllAppointments();
207
208 // calls RPC to get appointments
209 rAppointmentSchedule = CGSchedLib.CreateAppointmentSchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate);
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)
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;
287
288 //smh: Question: Where does bRet get used? It's a useless varaible so far.
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 System.IntPtr pHandle = m_DocManager.Handle;
433
434 m_pAvArray.Clear();
435
436 ArrayList saryApptTypes = new ArrayList();
437 int nApptTypeID = 0;
438
439 //Refresh Availability schedules
440 DataTable rAvailabilitySchedule;
441 rAvailabilitySchedule = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate, saryApptTypes,/**/ m_ScheduleType, "0");
442 CGSchedLib.OutputArray(rAvailabilitySchedule, "rAvailabilitySchedule");
443
444 //Refresh Type Schedule
445 string sResourceName = "";
446 DataTable rTypeSchedule = new DataTable();;
447 for (int j = 0; j < m_sResourcesArray.Count; j++)
448 {
449 sResourceName = m_sResourcesArray[j].ToString();
450 DataTable dtTemp = CGSchedLib.CreateAssignedTypeSchedule(m_DocManager, sResourceName, this.m_dStartDate, this.m_dEndDate, m_ScheduleType);
451 CGSchedLib.OutputArray(dtTemp, "dtTemp");
452 if (j == 0)
453 {
454 rTypeSchedule = dtTemp;
455 }
456 else
457 {
458 rTypeSchedule = CGSchedLib.UnionBlocks(rTypeSchedule, dtTemp);
459 }
460 }
461 CGSchedLib.OutputArray(rTypeSchedule, "rTypeSchedule");
462
463 DateTime dStart;
464 DateTime dEnd;
465 DateTime dTypeStart;
466 DateTime dTypeEnd;
467 int nSlots;
468 Rectangle crRectA = new Rectangle(0,0,1,0);
469 Rectangle crRectB= new Rectangle(0,0,1,0);
470 bool bIsect;
471 string sResourceList;
472 string sAccessRuleList;
473
474
475 foreach (DataRow rTemp in rAvailabilitySchedule.Rows)
476 {
477 //get StartTime, EndTime and Slots
478 dStart = (DateTime) rTemp["START_TIME"];
479 dEnd = (DateTime) rTemp["END_TIME"];
480
481 //TODO: Fix this slots datatype problem
482 string sSlots = rTemp["SLOTS"].ToString();
483 nSlots = Convert.ToInt16(sSlots);
484
485 sResourceList = rTemp["RESOURCE"].ToString();
486 sAccessRuleList = rTemp["ACCESS_TYPE"].ToString();
487
488 string sNote = rTemp["NOTE"].ToString();
489
490 if ((nSlots < -1000)||(sAccessRuleList == ""))
491 {
492 nApptTypeID = 0;
493 }
494 else
495 {
496 foreach (DataRow rType in rTypeSchedule.Rows)
497 {
498
499 dTypeStart = (DateTime) rType["StartTime"];
500 dTypeEnd = (DateTime) rType["EndTime"];
501 //if start & end times overlap, then
502 string sTypeResource = rType["ResourceName"].ToString();
503 if ((dTypeStart.DayOfYear == dStart.DayOfYear) && (sResourceList == sTypeResource))
504 {
505 crRectA.Y = GetTotalMinutes(dStart);
506 crRectA.Height = GetTotalMinutes(dEnd) - crRectA.Top;
507 crRectB.Y = GetTotalMinutes(dTypeStart);
508 crRectB.Height = GetTotalMinutes(dTypeEnd) - crRectB.Top;
509 bIsect = crRectA.IntersectsWith(crRectB);
510 if (bIsect == true)
511 {
512 //TODO: This code:
513 // nApptTypeID = (int) rType["AppointmentTypeID"];
514 //Causes this exception:
515 //Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
516 string sTemp = rType["AppointmentTypeID"].ToString();
517 nApptTypeID = Convert.ToInt16(sTemp);
518 break;
519 }
520 }
521 }//end foreach datarow rType
522 }
523
524 AddAvailability(dStart, dEnd, nApptTypeID, nSlots, false, sResourceList, sAccessRuleList, sNote);
525 }//end foreach datarow rTemp
526
527 return true;
528 }
529 catch (Exception ex)
530 {
531 Debug.Write("CGDocument.RefreshAvailabilitySchedule error: " + ex.Message + "\n");
532 return false;
533 }
534 }
535
536 private int GetTotalMinutes(DateTime dDate)
537 {
538 return ((dDate.Hour * 60) + dDate.Minute);
539 }
540
541 public int AddAvailability(DateTime StartTime, DateTime EndTime, int nType, int nSlots, bool UpdateView, string sResourceList, string sAccessRuleList, string sNote)
542 {
543 //adds it to the object array
544 //Returns the index in the array
545
546 CGAvailability pNewAv = new CGAvailability();
547 pNewAv.Create(StartTime, EndTime, nType, nSlots, sResourceList, sAccessRuleList);
548
549 pNewAv.Note = sNote;
550
551 //Look up the color and type name using the AppointmentTypes datatable
552 DataTable dtType = this.m_DocManager.GlobalDataSet.Tables["AccessTypes"];
553 DataRow dRow = dtType.Rows.Find(nType.ToString());
554 if (dRow != null)
555 {
556 string sColor = dRow["DISPLAY_COLOR"].ToString();
557 pNewAv.DisplayColor = sColor;
558 string sTemp = dRow["RED"].ToString();
559 sTemp = (sTemp == "")?"0":sTemp;
560 int nRed = Convert.ToInt16(sTemp);
561 pNewAv.Red = nRed;
562 sTemp = dRow["GREEN"].ToString();
563 sTemp = (sTemp == "")?"0":sTemp;
564 int nGreen = Convert.ToInt16(sTemp);
565 pNewAv.Green = nGreen;
566 sTemp = dRow["BLUE"].ToString();
567 sTemp = (sTemp == "")?"0":sTemp;
568 int nBlue = Convert.ToInt16(sTemp);
569 pNewAv.Blue = nBlue;
570
571 string sName = dRow["ACCESS_TYPE_NAME"].ToString();
572 pNewAv.AccessTypeName = sName;
573 }
574
575 int nIndex = 0;
576 nIndex = m_pAvArray.Add(pNewAv);
577 if (UpdateView == true)
578 {
579 this.UpdateAllViews();
580 }
581 return nIndex;
582 }
583
584
585 public void AddResource(string sResource)
586 {
587 //TODO: Test that resource is not currently in list, that it IS a resource, etc
588 this.m_sResourcesArray.Add(sResource);
589 this.UpdateAllViews();
590 }
591
592 public void ClearResources()
593 {
594 this.m_sResourcesArray.Clear();
595 }
596
597 public int SlotsAvailable(DateTime dSelStart, DateTime dSelEnd, string sResource, out string sAccessType, out string sAvailabilityMessage)
598 {
599 sAccessType = "";
600 sAvailabilityMessage = "";
601 DateTime dStart;
602 DateTime dEnd;
603 int nAvailableSlots = 999;
604 int nSlots = 0;
605 int i = 0;
606 CGAvailability pAv;
607 Rectangle crRectA = new Rectangle(0,0,1,0);
608 Rectangle crRectB = new Rectangle(0,0,1,0);
609 bool bIsect;
610 crRectB.Y = GetTotalMinutes(dSelStart);
611 crRectB.Height = GetTotalMinutes(dSelEnd)- crRectB.Y;
612
613 // //loop thru m_pAvArray
614 // //Compare the start time and end time of eachblock
615 while (i < m_pAvArray.Count)
616 {
617 pAv = (CGAvailability) m_pAvArray[i];
618 dStart = pAv.StartTime;
619 dEnd = pAv.EndTime;
620 if ((sResource == pAv.ResourceList) &&
621 ((dSelStart.Date == dStart.Date) || (dSelStart.Date == dEnd.Date)))
622 {
623 crRectA.Y = (dStart.Date < dSelStart.Date) ? 0 : GetTotalMinutes(dStart);
624 crRectA.Height = (dEnd.Date > dSelEnd.Date) ? 1440 : GetTotalMinutes(dEnd);
625 crRectA.Height = crRectA.Height - crRectA.Y;
626 bIsect = crRectA.IntersectsWith(crRectB);
627 if (bIsect != false)
628 {
629 nSlots = pAv.Slots;
630 if (nSlots < 1)
631 {
632 nAvailableSlots = 0;
633 break;
634 }
635 if (nSlots < nAvailableSlots)
636 {
637 nAvailableSlots = nSlots;
638 sAccessType = pAv.AccessTypeName;
639 sAvailabilityMessage = pAv.Note;
640
641 }
642 }
643 }
644 i++;
645 }
646 if (nAvailableSlots == 999)
647 {
648 nAvailableSlots = 0;
649 }
650 return nAvailableSlots;
651 }
652
653 /// <summary>
654 /// Given a selected date,
655 /// Calculates StartDay and End Day and returns them in output params.
656 /// nWeeks == number of Weeks to display
657 /// nColumnCount is number of days displayed per week.
658 /// If 5 columns, begin on Second Day of Week
659 /// If 7 Columns, begin on First Day of Week
660 /// (this is a change from the hardcoded behavior for US-based calendars)
661 ///
662 /// Returns TRUE if the document's data needs refreshing based on
663 /// this newly selected date.
664 /// </summary>
665 public bool WeekNeedsRefresh(int nWeeks, DateTime SelectedDate,
666 out DateTime WeekStartDay, out DateTime WeekEndDay)
667 {
668 DateTime OldStartDay = m_dStartDate;
669 DateTime OldEndDay = m_dEndDate;
670 // Week start based on thread locale
671 int nStartWeekDay = (int)System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
672 // Current Day
673 int nWeekDay = (int) SelectedDate.DayOfWeek; //0 == Sunday
674
675 // this offset gets approrpriate day based on locale.
676 int nOff = (nStartWeekDay + 1) % 7;
677 TimeSpan ts = new TimeSpan(nWeekDay - nOff,0,0,0); //d,h,m,s
678
679 // if ts is negative, we will jump to the next week in the logic.
680 // to show the correct week, add 7. Confusing, I know.
681 if (ts < new TimeSpan() ) ts = ts + new TimeSpan(7,0,0,0);
682
683 if (m_nColumnCount == 1) // if one column start and end on the same day.
684 {
685 ts = new TimeSpan(0,23,59,59);
686 WeekStartDay = SelectedDate;
687 WeekEndDay = WeekStartDay + ts;
688 }
689 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.
690 {
691 // if picked day is start of week (Sunday in US), start in the next day since that's the first day of work week
692 // else, just substract the calculated time span to get to the start of week (first work day)
693 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate + new TimeSpan(1,0,0,0): SelectedDate - ts;
694 // End day calculation
695 int nEnd = 3;
696 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
697 WeekEndDay = WeekStartDay + ts;
698 }
699 else // if 7 column start at the 1st day of this week and end in 6:23:59:59 days.
700 {
701 // 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.
702 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate : SelectedDate - ts - new TimeSpan(1,0,0,0);
703 // End day calculation
704 int nEnd = 1;
705 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
706 WeekEndDay = WeekStartDay + ts;
707 }
708
709 bool bRet = (( WeekStartDay.Date != OldStartDay.Date) || (WeekEndDay.Date != OldEndDay.Date));
710 return bRet;
711 }
712
713 /// <summary>
714 /// Calls RPMS to create appointment then
715 /// adds appointment to the m_appointments collection
716 /// Returns the IEN of the appointment in the RPMS BSDX APPOINTMENT file.
717 /// </summary>
718 /// <param name="rApptInfo"></param>
719 /// <returns></returns>
720 public int CreateAppointment(CGAppointment rApptInfo)
721 {
722 return CreateAppointment(rApptInfo, false);
723 }
724
725 /// <summary>
726 /// Use this overload to create a walkin appointment
727 /// </summary>
728 /// <param name="rApptInfo"></param>
729 /// <param name="bWalkin"></param>
730 /// <returns></returns>
731 public int CreateAppointment(CGAppointment rApptInfo, bool bWalkin)
732 {
733 string sStart;
734 string sEnd;
735 string sPatID;
736 string sResource;
737 string sNote;
738 string sLen;
739 string sApptID;
740
741 //sStart = rApptInfo.StartTime.ToString("M-d-yyyy@HH:mm");
742 //sEnd = rApptInfo.EndTime.ToString("M-d-yyyy@HH:mm");
743
744 // i18n code -- Use culture neutral FMDates
745 sStart = FMDateTime.Create(rApptInfo.StartTime).FMDateString;
746 sEnd = FMDateTime.Create(rApptInfo.EndTime).FMDateString;
747
748 TimeSpan sp = rApptInfo.EndTime - rApptInfo.StartTime;
749 sLen = sp.TotalMinutes.ToString();
750 sPatID = rApptInfo.PatientID.ToString();
751 sNote = rApptInfo.Note;
752 sResource = rApptInfo.Resource;
753 if (bWalkin == true)
754 {
755 sApptID = "WALKIN";
756 }
757 else
758 {
759 sApptID = rApptInfo.AccessTypeID.ToString();
760 }
761
762 CGAppointment aCopy = new CGAppointment();
763 aCopy.CreateAppointment(rApptInfo.StartTime, rApptInfo.EndTime, sNote, 0, sResource);
764 aCopy.PatientID = rApptInfo.PatientID;
765 aCopy.PatientName = rApptInfo.PatientName;
766 aCopy.HealthRecordNumber = rApptInfo.HealthRecordNumber;
767 aCopy.AccessTypeID = rApptInfo.AccessTypeID;
768
769 string sSql = "BSDX ADD NEW APPOINTMENT^" + sStart + "^" + sEnd + "^" + sPatID + "^" + sResource + "^" + sLen + "^" + sNote + "^" + sApptID ;
770 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "NewAppointment");
771 int nApptID;
772
773 Debug.Assert(dtAppt.Rows.Count == 1);
774 DataRow r = dtAppt.Rows[0];
775 nApptID =Convert.ToInt32(r["APPOINTMENTID"]);
776 string sErrorID;
777 sErrorID = r["ERRORID"].ToString();
778 if ((sErrorID != "")||(nApptID < 1))
779 throw new Exception(sErrorID);
780 aCopy.AppointmentKey = nApptID;
781 this.m_appointments.AddAppointment(aCopy);
782
783 bool bRet = RefreshAvailabilitySchedule();
784
785 UpdateAllViews();
786
787 return nApptID;
788 }
789
790 public void EditAppointment(CGAppointment pAppt, string sNote)
791 {
792 try
793 {
794 int nApptID = pAppt.AppointmentKey;
795 string sSql = "BSDX EDIT APPOINTMENT^" + nApptID.ToString() + "^" + sNote;
796
797 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "EditAppointment");
798
799 Debug.Assert(dtAppt.Rows.Count == 1);
800 DataRow r = dtAppt.Rows[0];
801 string sErrorID = r["ERRORID"].ToString();
802 if (sErrorID == "-1")
803 pAppt.Note = sNote;
804
805 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
806 {
807 bool bRet = RefreshAvailabilitySchedule();
808 UpdateAllViews();
809 }
810 }
811 catch (Exception ex)
812 {
813 Debug.Write("CGDocument.EditAppointment Failed: " + ex.Message);
814 }
815 }
816
817 public void CheckInAppointment(int nApptID, DateTime dCheckIn,
818 string ClinicStopIEN,
819 string ProviderIEN,
820 string PrintRouteSlip,
821 string PCCClinicIEN,
822 string PCCFormIEN,
823 string PCCOutGuide
824 )
825 {
826 string sCheckIn = dCheckIn.ToString("M-d-yyyy@HH:mm");
827
828 string sSql = "BSDX CHECKIN APPOINTMENT^" + nApptID.ToString() + "^" + sCheckIn + "^";
829 sSql += ClinicStopIEN + "^" + ProviderIEN + "^" + PrintRouteSlip + "^";
830 sSql += PCCClinicIEN + "^" + PCCFormIEN + "^" + PCCOutGuide;
831
832 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "CheckInAppointment");
833
834 Debug.Assert(dtAppt.Rows.Count == 1);
835 DataRow r = dtAppt.Rows[0];
836 string sErrorID = r["ERRORID"].ToString();
837
838 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
839 {
840 bool bRet = RefreshSchedule();
841 UpdateAllViews();
842 }
843 }
844
845 public string DeleteAppointment(int nApptID)
846 {
847 return DeleteAppointment(nApptID, true, 0, "");
848 }
849
850 public string DeleteAppointment(int nApptID, bool bClinicCancelled, int nReason, string sRemarks)
851 {
852 //Returns "" if deletion successful
853 //Otherwise, returns reason for failure
854
855 string sClinicCancelled = (bClinicCancelled == true)?"C":"PC";
856 string sReasonID = nReason.ToString();
857 string sSql = "BSDX CANCEL APPOINTMENT^" + nApptID.ToString();
858 sSql += "^" + sClinicCancelled;
859 sSql += "^" + sReasonID;
860 sSql += "^" + sRemarks;
861 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "DeleteAppointment");
862
863 Debug.Assert(dtAppt.Rows.Count == 1);
864 DataRow r = dtAppt.Rows[0];
865 string sErrorID = r["ERRORID"].ToString();
866 if (sErrorID != "")
867 return sErrorID;
868
869 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
870 {
871 this.m_appointments.RemoveAppointment(nApptID);
872 bool bRet = RefreshAvailabilitySchedule();
873 UpdateAllViews();
874 }
875 return "";
876 }
877
878 public string AutoRebook(CGAppointment a, int nSearchType, int nMinimumDays, int nMaximumDays, out CGAppointment aRebook)
879 {
880 //If successful Returns "1" and new start date and time returned in aRebook
881 //Otherwise, returns error message
882
883 CGAppointment aCopy = new CGAppointment();
884 aCopy.CreateAppointment(a.StartTime, a.EndTime, a.Note, 0, a.Resource);
885 aCopy.PatientID = a.PatientID;
886 aCopy.PatientName = a.PatientName;
887 aCopy.HealthRecordNumber = a.HealthRecordNumber;
888 aCopy.AccessTypeID = a.AccessTypeID;
889 aRebook = aCopy;
890
891 //Determine Rebook access type
892 //nSearchType = -1: use current, -2: use any non-zero type, >0 use this access type id
893 int nAVType = 0;
894
895 switch (nSearchType)
896 {
897 case -1:
898 nAVType = a.AccessTypeID;
899 break;
900 case -2:
901 nAVType = 0;
902 break;
903 default:
904 nAVType = nSearchType;
905 break;
906 }
907
908 int nSlots = 0;
909 string sSlots = "";
910 int nAccessTypeID; //To compare with nAVType
911
912 DateTime dResult = new DateTime(); //StartTime of access block to autorebook into
913
914 //Next two are empty, but needed to pass to CreateAvailabilitySchedule
915 ArrayList alAccessTypes = new ArrayList();
916 string sSearchInfo = "";
917
918 //Find the StartTime of first availability block of this type for this clinic
919 //between nMinimumDays and nMaximumDays
920
921 string sAVStart = a.StartTime.AddDays(nMinimumDays).ToString("M/d/yyyy@H:mm");
922
923 //dtAVEnd is the last day to search
924 DateTime dtAVEnd = a.StartTime.AddDays(nMinimumDays + nMaximumDays);
925 string sAVEnd = dtAVEnd.ToString("M/d/yyyy@H:mm");
926
927 //Increment start day to search a week (or so) at a time
928 //30 is a test increment. Need to test different values for performance
929 int nIncrement = (nMaximumDays < 30)?nMaximumDays:30;
930
931 //nCount and nCountEnd are the 'moving' counters
932 //that I add to start and end to get the bracket
933 //At the beginning of the DO loop, nCount and nCountEnd are already set
934 bool bFinished = false;
935 bool bFound = false;
936
937 DateTime dStart = a.StartTime.AddDays(nMinimumDays);
938 // v 1.3 i18n support - FM Date passed insated of American Date
939 string sStart = FMDateTime.Create(dStart).DateOnly.FMDateString;
940 DateTime dEnd = dStart.AddDays(nIncrement);
941 do
942 {
943 string sSql = "BSDX REBOOK NEXT BLOCK^" + sStart + "^" + a.Resource + "^" + nAVType.ToString();
944 DataTable dtNextBlock = this.DocManager.RPMSDataTable(sSql, "NextBlock");
945 Debug.Assert(dtNextBlock.Rows.Count == 1);
946 DataRow drNextBlockRow = dtNextBlock.Rows[0];
947
948 object oNextBlock;
949 oNextBlock = drNextBlockRow["NEXTBLOCK"];
950 if (oNextBlock.GetType() == typeof(System.DBNull))
951 break;
952 DateTime dNextBlock = (DateTime) drNextBlockRow["NEXTBLOCK"];
953 if (dNextBlock > dtAVEnd)
954 {
955 break;
956 }
957
958 dStart = dNextBlock;
959 dEnd = dStart.AddDays(nIncrement);
960 if (dEnd > dtAVEnd)
961 dEnd = dtAVEnd;
962
963 DataTable dtResult = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, this.Resources, dStart, dEnd, alAccessTypes, ScheduleType.Resource, sSearchInfo);
964 //Loop thru dtResult looking for a slot having the required availability type.
965 //If found, set bFinished = true;
966 foreach (DataRow dr in dtResult.Rows)
967 {
968
969 sSlots = dr["SLOTS"].ToString();
970 if (sSlots == "")
971 sSlots = "0";
972 nSlots = Convert.ToInt16(sSlots);
973 if (nSlots > 0)
974 {
975 nAccessTypeID = 0; //holds the access type id of the availability block
976 if (dr["ACCESS_TYPE"].ToString() != "")
977 nAccessTypeID =Convert.ToInt16(dr["ACCESS_TYPE"].ToString());
978 if ((nSearchType == -2) && (nAccessTypeID > 0)) //Match on any non-zero type
979 {
980 bFinished = true;
981 bFound = true;
982 dResult = (DateTime) dr["START_TIME"];
983 break;
984 }
985 if (nAccessTypeID == nAVType)
986 {
987 bFinished = true;
988 bFound = true;
989 dResult = (DateTime) dr["START_TIME"];
990 break;
991 }
992 }
993 }
994 dStart = dEnd.AddDays(1);
995 dEnd = dStart.AddDays(nIncrement);
996 if (dEnd > dtAVEnd)
997 dEnd = dtAVEnd;
998 } while (bFinished == false);
999
1000 if (bFound == true)
1001 {
1002 aCopy.StartTime = dResult;
1003 aCopy.EndTime = dResult.AddMinutes(a.Duration);
1004 //Create the appointment
1005 //Set the AUTOREBOOKED flag
1006 //and store the "AutoRebooked To DateTime"
1007 //in each autorebooked appointment
1008 this.CreateAppointment(aCopy);
1009 SetAutoRebook(a, dResult);
1010 return "1";
1011 }
1012 else
1013 {
1014 return "0";
1015 }
1016 }
1017
1018 private void SetAutoRebook(CGAppointment a, DateTime dtRebookedTo)
1019 {
1020 string sApptKey = a.AppointmentKey.ToString();
1021 //string sRebookedTo = dtRebookedTo.ToString("M/d/yyyy@HH:mm");
1022 // i18n
1023 string sRebookedTo = FMDateTime.Create(dtRebookedTo).FMDateString;
1024 string sSql = "BSDX REBOOK SET^" + sApptKey + "^" + sRebookedTo;
1025 System.Data.DataTable dtRebook = m_DocManager.RPMSDataTable(sSql, "AutoRebook");
1026
1027 }
1028
1029 public string AppointmentNoShow(int nApptID, bool bNoShow)
1030 {
1031 /*
1032 * BSDX NOSHOW RPC Returns 1 in ERRORID if successfully sets NOSHOW flag in BSDX APPOINTMENT and, if applicable, File 2
1033 *Otherwise, returns 0 for failure and errormessage in ERRORTXT
1034 *THIS routine returns "" if success or the message in ERRORTEXT if failed
1035 *Exceptions should be caught by caller
1036 *
1037 */
1038
1039 string sTest = bNoShow.ToString();
1040 string sNoShow = (bNoShow == true)?"1":"0";
1041 string sSql = "BSDX NOSHOW^" + nApptID.ToString();
1042 sSql += "^";
1043 sSql += sNoShow;
1044
1045 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "AppointmentNoShow");
1046
1047 Debug.Assert(dtAppt.Rows.Count == 1);
1048 DataRow r = dtAppt.Rows[0];
1049 string sErrorID = r["ERRORID"].ToString();
1050 if (sErrorID != "1")
1051 {
1052 return r["ERRORTEXT"].ToString();
1053 }
1054
1055 bool bRet = RefreshSchedule();
1056
1057 return sErrorID;
1058 }
1059
1060 #endregion Methods
1061
1062 }//End class
1063}//End namespace
Note: See TracBrowser for help on using the repository browser.