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

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

LoadingSplash: New Form that does... pretty much nothing. Just shows a splash when updating data from server.
CGView:

CGDocumentManager:

CGDocument:

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