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

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

CGDocument: Minor Change: Add appointment ID to Appointment
CGDocumentManager: added parameter /culture to set Thread.CurrentThread.CurrentUICulture
CGView: Minor changes in CheckInAppointment: Printing of Routing Slip now always happens.

Routing slip now get parameter for patient order.

Patient: i18n of UserFriendlyAge
Printing: Extensive changes. Support for i18n; new routing slip and appt slip. i18n support only for appt slip.

File size: 54.5 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;
[1097]9using System.Linq;
[1106]10using System.Collections.Generic;
[614]11
12namespace IndianHealthService.ClinicalScheduling
13{
[1071]14 /// <summary>
15 /// Contains the array of appointments and availabily that make up the document class
16 /// </summary>
17 public class CGDocument
18 {
19 #region Member Variables
20 public int m_nColumnCount; //todo: this should point to the view's member for column count
21 public int m_nTimeUnits; //?
22 private string m_sDocName; //Document Name ?
23 public ArrayList m_sResourcesArray; //keeps the resources
24 public ScheduleType m_ScheduleType; //Either a Resource or a Clinic (Group of Resources)
25 private DateTime m_dSelectedDate; //Holds the user's selection from the dtpicker
26 private DateTime m_dStartDate; //Beginning date of document data
27 private DateTime m_dEndDate; //Ending date of document data
28 public CGAppointments m_appointments; //Appointment List
29 private ArrayList m_pAvArray; //Availability List
30 private CGDocumentManager m_DocManager; //Holds a reference to the document manager
31 private DateTime m_dLastRefresh = DateTime.Now; //Holds last refersh date
32 #endregion
[614]33
[1071]34 /// <summary>
35 /// Constructor. Initialize State Data:
36 /// 3 Arrays (Appointments, Availabilities, and Resources)
37 /// Schedule Type is Resource not Clinic
38 /// Selected Date is Today
39 /// Start Date is Today
40 /// End Date is 7 days from Today
41 /// </summary>
42 public CGDocument()
43 {
44 m_appointments = new CGAppointments(); // Holds Appointments
45 m_pAvArray = new ArrayList(); // Holds Availabilites
46 m_sResourcesArray = new ArrayList(); // Holds Resources
47 m_ScheduleType = ScheduleType.Resource; // Default Schedule Type is a Resource
48 m_dSelectedDate = DateTime.Today; // Default Selected Date is Today
49 m_dStartDate = DateTime.Today; // Default Start Date is Today
50 m_dEndDate = DateTime.Today.AddDays(7); // Default End Date is 7 days from Today.
51 }
[614]52
53
[1071]54 #region Properties
[614]55
[1071]56 /// <summary>
57 /// Returns the latest refresh time for this document
58 /// </summary>
59 public DateTime LastRefreshed
60 {
61 get
62 {
63 return m_dLastRefresh;
64 }
65 }
[614]66
[1071]67 /// <summary>
68 /// The list of Resource names
69 /// </summary>
70 public ArrayList Resources
71 {
72 get
73 {
74 return this.m_sResourcesArray;
75 }
76 set
77 {
78 this.m_sResourcesArray = value;
79 }
80 }
[614]81
[1071]82 /// <summary>
83 /// The array of CGAvailabilities that contains appt type and slots
84 /// </summary>
85 public ArrayList AvailabilityArray
86 {
87 get
88 {
89 return this.m_pAvArray;
90 }
91 }
[614]92
[1071]93 public CGDocumentManager DocManager
94 {
95 get
96 {
97 return m_DocManager;
98 }
99 set
100 {
101 m_DocManager = value;
102 }
103 }
[614]104
[1071]105 /// <summary>
106 /// Contains the hashtable of appointments
107 /// </summary>
108 public CGAppointments Appointments
109 {
110 get
111 {
112 return m_appointments;
113 }
114 }
[614]115
[1071]116 /// <summary>
117 /// Holds the date selected by the user in CGView.dateTimePicker1
118 /// </summary>
119 public DateTime SelectedDate
120 {
121 get
122 {
123 return this.m_dSelectedDate;
124 }
125 set
126 {
127 this.m_dSelectedDate = value;
128 }
129 }
[614]130
[1071]131 /// <summary>
132 /// Contains the beginning date of the appointment document
133 /// </summary>
134 public DateTime StartDate
135 {
136 get
137 {
138 return this.m_dStartDate;
139 }
140 }
[614]141
[1071]142 public string DocName
143 {
144 get
145 {
146 return this.m_sDocName;
147 }
148 set
149 {
150 this.m_sDocName = value;
151 }
152 }
[614]153
[1071]154 #endregion
[614]155
[1071]156 #region Methods
[614]157
[1071]158 public void UpdateAllViews()
159 {
160 //iterate through all views and call update.
161 Hashtable h = CGDocumentManager.Current.Views;
[614]162
[1071]163 CGDocument d;
164 foreach (CGView v in h.Keys)
165 {
166 d = (CGDocument)h[v];
167 if (d == this)
168 {
169 v.UpdateArrays();
170 }
171 }
[614]172
[1071]173 }
174
175 /// <summary>
176 /// Update schedule based on info in RPMS
[1095]177 /// <returns>Clears and repopluates m_appointments</returns>
[1071]178 /// </summary>
[1110]179 private bool RefreshAppointments()
[1071]180 {
181 try
182 {
183 string sPatientName;
184 string sPatientID;
185 DateTime dStart;
186 DateTime dEnd;
187 DateTime dCheckIn;
188 DateTime dAuxTime;
189 int nKeyID;
190 string sNote;
191 string sResource;
192 bool bNoShow = false;
193 string sNoShow = "0";
194 string sHRN = "";
195 int nAccessTypeID; //used in autorebook
196 string sWalkIn = "0";
197 bool bWalkIn;
198 CGAppointment pAppointment;
199 CGDocumentManager pApp = CGDocumentManager.Current;
200 DataTable rAppointmentSchedule;
201
[821]202 //Nice to know that it gets set here!!!
[1071]203 m_dLastRefresh = DateTime.Now;
[614]204
[1095]205 //Clear appointments associated with this document
[1071]206 this.m_appointments.ClearAllAppointments();
[614]207
[850]208 // calls RPC to get appointments
[1071]209 rAppointmentSchedule = CGSchedLib.CreateAppointmentSchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate);
210
[1095]211 // loop through datatable: Create CGAppointment and add to CGAppointments
[1071]212 foreach (DataRow r in rAppointmentSchedule.Rows)
213 {
[614]214
[1071]215 if (r["APPOINTMENTID"].ToString() == "0")
216 {
217 string sMsg = r["NOTE"].ToString();
218 throw new BMXNetException(sMsg);
219 }
220 nKeyID = Convert.ToInt32(r["APPOINTMENTID"].ToString());
221 sResource = r["RESOURCENAME"].ToString();
222 sPatientName = r["PATIENTNAME"].ToString();
223 sPatientID = r["PATIENTID"].ToString();
224 dStart = (DateTime)r["START_TIME"];
225 dEnd = (DateTime)r["END_TIME"];
226 dCheckIn = new DateTime();
227 dAuxTime = new DateTime();
[614]228
[1071]229 if (r["CHECKIN"].GetType() != typeof(System.DBNull))
230 dCheckIn = (DateTime)r["CHECKIN"];
231 if (r["AUXTIME"].GetType() != typeof(System.DBNull))
232 dCheckIn = (DateTime)r["AUXTIME"];
233 sNote = r["NOTE"].ToString();
234 sNoShow = r["NOSHOW"].ToString();
235 bNoShow = (sNoShow == "1") ? true : false;
236 sHRN = r["HRN"].ToString();
237 nAccessTypeID = (int)r["ACCESSTYPEID"];
238 sWalkIn = r["WALKIN"].ToString();
239 bWalkIn = (sWalkIn == "1") ? true : false;
[614]240
[1110]241 Patient pt = new Patient()
242 {
243 DFN = Convert.ToInt32(sPatientID),
244 Name = sPatientName,
245 DOB = (DateTime)r["DOB"],
246 ID = r["PID"].ToString(),
247 HRN = sHRN,
248 Sex = r["SEX"].ToString() == "MALE" ? Sex.Male : Sex.Female
249 };
250
[1071]251 pAppointment = new CGAppointment();
[1110]252 pAppointment.Patient = pt;
[1071]253 pAppointment.CreateAppointment(dStart, dEnd, sNote, nKeyID, sResource);
254 pAppointment.PatientName = sPatientName;
255 pAppointment.PatientID = Convert.ToInt32(sPatientID);
256 if (dCheckIn.Ticks > 0)
257 pAppointment.CheckInTime = dCheckIn;
258 if (dAuxTime.Ticks > 0)
259 pAppointment.AuxTime = dAuxTime;
260 pAppointment.NoShow = bNoShow;
261 pAppointment.HealthRecordNumber = sHRN;
262 pAppointment.AccessTypeID = nAccessTypeID;
263 pAppointment.WalkIn = bWalkIn;
264 this.m_appointments.AddAppointment(pAppointment);
[614]265
[1071]266 }
[614]267
[1071]268 return true;
269 }
270 catch (Exception Ex)
271 {
272 Debug.Write("CGDocument.RefreshDaysSchedule error: " + Ex.Message + "\n");
273 return false;
274 }
275 }
[614]276
277
[1071]278 public bool IsRefreshNeeded()
279 {
280 if (m_sResourcesArray.Count == 0) return false;
281 return this.WeekNeedsRefresh(1, m_dSelectedDate, out this.m_dStartDate, out this.m_dEndDate);
282 }
[614]283
[1073]284 //sam: This is a test that duplicates RefreshDocument, but without the UpdateAllViews,
285 // as that has to be done synchornously.
[1083]286 //XXX: Needs to be refactored obviously, but now for testing.
287 //XXX: Tested extensively enough. Less refactoring now. 2011-01-26
[1073]288 public void RefreshDocumentAsync()
289 {
[1083]290 Debug.WriteLine("IN REFERSH DOCUMENT ASYNC\n\n");
291
[1073]292 bool bRet = false;
293 if (m_sResourcesArray.Count == 0)
294 return;
295 if (m_sResourcesArray.Count == 1)
296 {
297 bRet = this.WeekNeedsRefresh(1, m_dSelectedDate, out this.m_dStartDate, out this.m_dEndDate);
298 }
299 else
300 {
301 this.m_dStartDate = m_dSelectedDate;
302 this.m_dEndDate = m_dSelectedDate;
303 this.m_dEndDate = this.m_dEndDate.AddHours(23);
304 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
305 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
306 }
[1071]307
[1073]308 bRet = RefreshSchedule();
309 }
310
311
[1071]312 public void RefreshDocument()
313 {
[1070]314 bool bRet = false;
[1071]315 if (m_sResourcesArray.Count == 0)
316 return;
[1070]317 if (m_sResourcesArray.Count == 1)
318 {
319 bRet = this.WeekNeedsRefresh(1, m_dSelectedDate, out this.m_dStartDate, out this.m_dEndDate);
320 }
321 else
322 {
323 this.m_dStartDate = m_dSelectedDate;
324 this.m_dEndDate = m_dSelectedDate;
325 this.m_dEndDate = this.m_dEndDate.AddHours(23);
326 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
327 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
328 }
[614]329
[1071]330 bRet = RefreshSchedule();
[1073]331
[1071]332 this.UpdateAllViews();
333 }
[614]334
[1106]335 public void OnOpenDocument(DateTime dDate)
[1071]336 {
337 try
338 {
339 //Create new Document
340 m_ScheduleType = (m_sResourcesArray.Count == 1) ? ScheduleType.Resource : ScheduleType.Clinic;
341 bool bRet = false;
[1106]342
[1071]343 if (m_ScheduleType == ScheduleType.Resource)
344 {
345 bRet = this.WeekNeedsRefresh(1, dDate, out this.m_dStartDate, out this.m_dEndDate);
346 }
347 else
348 {
349 this.m_dStartDate = dDate;
350 this.m_dEndDate = dDate;
351 this.m_dEndDate = this.m_dEndDate.AddHours(23);
352 this.m_dEndDate = this.m_dEndDate.AddMinutes(59);
353 this.m_dEndDate = this.m_dEndDate.AddSeconds(59);
354 }
[614]355
[1071]356 bRet = RefreshSchedule();
[614]357
[1071]358 CGView view = null;
359 //If this document already has a view, the use it
[1070]360 //SAM: Why do this again???
[1071]361 Hashtable h = CGDocumentManager.Current.Views;
362 CGDocument d;
363 bool bReuseView = false;
364 foreach (CGView v in h.Keys)
365 {
366 d = (CGDocument)h[v];
367 if (d == this)
368 {
369 view = v;
370 bReuseView = true;
371 v.InitializeDocView(this.DocName);
372 break;
373 }
374 }
[614]375
[1071]376 //Otherwise, create new View
377 if (bReuseView == false)
378 {
379 view = new CGView();
[614]380
[1071]381 view.InitializeDocView(this,
382 this.DocManager,
383 m_dStartDate,
384 this.DocName);
[614]385
[1071]386 view.Show();
387 view.SyncTree();
[614]388
[1071]389 }
390 this.UpdateAllViews();
391 }
392 catch (BMXNetException bmxEx)
393 {
394 throw bmxEx;
395 }
396 catch (Exception ex)
397 {
398 throw new BMXNet.BMXNetException("ClinicalScheduling.OnOpenDocument error: " + ex.Message);
399 }
400 }
[614]401
[1065]402 /// <summary>
403 /// Refreshes Availablility and Schedules from RPMS.
404 /// </summary>
405 /// <returns>Success or Failure. Should be always Success.</returns>
[1071]406 private bool RefreshSchedule()
407 {
[1106]408 this.RefreshAvailabilitySchedule();
[1110]409 this.RefreshAppointments();
[1106]410 return true;
[1071]411 }
[614]412
[1071]413 private bool RefreshAvailabilitySchedule()
414 {
415 try
416 {
417 ArrayList saryApptTypes = new ArrayList();
[1095]418
[1071]419 //Refresh Availability schedules
420 DataTable rAvailabilitySchedule;
421 rAvailabilitySchedule = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, m_sResourcesArray, this.m_dStartDate, this.m_dEndDate, saryApptTypes,/**/ m_ScheduleType, "0");
[614]422
[1095]423 ////NEW
424 //NOTE: This lock makes sure that availabilities aren't queried for slots when the array is an intermediate
425 //state. The other place that has this lock is SlotsAvailable function.
426 lock (this.m_pAvArray)
427 {
428 m_pAvArray.Clear();
429 foreach (DataRow rTemp in rAvailabilitySchedule.Rows)
430 {
431 DateTime dStart = (DateTime)rTemp["START_TIME"];
432 DateTime dEnd = (DateTime)rTemp["END_TIME"];
433
434 //TODO: Fix this slots datatype problem
435 string sSlots = rTemp["SLOTS"].ToString();
436 int nSlots = Convert.ToInt16(sSlots);
437
438 string sResourceList = rTemp["RESOURCE"].ToString();
439 string sAccessRuleList = rTemp["ACCESS_TYPE"].ToString();
440 string sNote = rTemp["NOTE"].ToString();
441
442 int nApptTypeID;
443
444 if ((nSlots < -1000) || (sAccessRuleList == ""))
445 {
446 nApptTypeID = 0;
447 }
448 else
449 {
450 nApptTypeID = Int32.Parse(rTemp["ACCESS_TYPE"].ToString());
451 }
452
453 AddAvailability(dStart, dEnd, nApptTypeID, nSlots, sResourceList, sAccessRuleList, sNote);
454 }
455 }
456 return true;
457
458 /* NOT USED
[1071]459 //Refresh Type Schedule
460 string sResourceName = "";
461 DataTable rTypeSchedule = new DataTable(); ;
462 for (int j = 0; j < m_sResourcesArray.Count; j++)
463 {
464 sResourceName = m_sResourcesArray[j].ToString();
465 DataTable dtTemp = CGSchedLib.CreateAssignedTypeSchedule(m_DocManager, sResourceName, this.m_dStartDate, this.m_dEndDate, m_ScheduleType);
[1095]466
[1071]467 if (j == 0)
468 {
469 rTypeSchedule = dtTemp;
470 }
471 else
472 {
473 rTypeSchedule = CGSchedLib.UnionBlocks(rTypeSchedule, dtTemp);
474 }
475 }
[614]476
[1071]477 DateTime dStart;
478 DateTime dEnd;
479 DateTime dTypeStart;
480 DateTime dTypeEnd;
481 int nSlots;
482 Rectangle crRectA = new Rectangle(0, 0, 1, 0);
483 Rectangle crRectB = new Rectangle(0, 0, 1, 0);
484 bool bIsect;
485 string sResourceList;
486 string sAccessRuleList;
[614]487
[1083]488 //smh: moved clear availabilities down here.
489 //smh: Temporary solution to make sure that people don't touch the availability table at the same time!!!
490 //NOTE: This lock makes sure that availabilities aren't queried for slots when the array is an intermediate
491 //state. The other place that has this lock is SlotsAvailable function.
492 lock (this.m_pAvArray)
[1071]493 {
[1083]494 m_pAvArray.Clear();
[614]495
[1083]496 foreach (DataRow rTemp in rAvailabilitySchedule.Rows)
497 {
498 //get StartTime, EndTime and Slots
499 dStart = (DateTime)rTemp["START_TIME"];
500 dEnd = (DateTime)rTemp["END_TIME"];
[614]501
[1083]502 //TODO: Fix this slots datatype problem
503 string sSlots = rTemp["SLOTS"].ToString();
504 nSlots = Convert.ToInt16(sSlots);
[614]505
[1083]506 sResourceList = rTemp["RESOURCE"].ToString();
507 sAccessRuleList = rTemp["ACCESS_TYPE"].ToString();
[614]508
[1083]509 string sNote = rTemp["NOTE"].ToString();
510
511 if ((nSlots < -1000) || (sAccessRuleList == ""))
[1071]512 {
[1083]513 nApptTypeID = 0;
514 }
515 else
516 {
517 foreach (DataRow rType in rTypeSchedule.Rows)
518 {
[614]519
[1083]520 dTypeStart = (DateTime)rType["StartTime"];
521 dTypeEnd = (DateTime)rType["EndTime"];
522 //if start & end times overlap, then
523 string sTypeResource = rType["ResourceName"].ToString();
524 if ((dTypeStart.DayOfYear == dStart.DayOfYear) && (sResourceList == sTypeResource))
[1071]525 {
[1083]526 crRectA.Y = GetTotalMinutes(dStart);
527 crRectA.Height = GetTotalMinutes(dEnd) - crRectA.Top;
528 crRectB.Y = GetTotalMinutes(dTypeStart);
529 crRectB.Height = GetTotalMinutes(dTypeEnd) - crRectB.Top;
530 bIsect = crRectA.IntersectsWith(crRectB);
531 if (bIsect == true)
532 {
533 //TODO: This code:
534 // nApptTypeID = (int) rType["AppointmentTypeID"];
535 //Causes this exception:
536 //Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
537 string sTemp = rType["AppointmentTypeID"].ToString();
538 nApptTypeID = Convert.ToInt16(sTemp);
539 break;
540 }
[1071]541 }
[1083]542 }//end foreach datarow rType
543 }
[614]544
545
[1095]546 //AddAvailability(dStart, dEnd, nApptTypeID, nSlots, sResourceList, sAccessRuleList, sNote);
[1083]547 }//end foreach datarow rTemp
548 }//end lock
[1071]549 return true;
[1095]550 */
[1071]551 }
552 catch (Exception ex)
553 {
554 Debug.Write("CGDocument.RefreshAvailabilitySchedule error: " + ex.Message + "\n");
555 return false;
556 }
557 }
[614]558
[1071]559 private int GetTotalMinutes(DateTime dDate)
560 {
561 return ((dDate.Hour * 60) + dDate.Minute);
562 }
[614]563
[1083]564 /// <summary>
565 /// Adds Availability to Availability Array held by document
566 /// </summary>
567 /// <param name="StartTime">Self-Explan</param>
568 /// <param name="EndTime">Self-Explan</param>
569 /// <param name="nType"></param>
570 /// <param name="nSlots"></param>
571 /// <param name="UpdateView"></param>
572 /// <param name="sResourceList"></param>
573 /// <param name="sAccessRuleList"></param>
574 /// <param name="sNote"></param>
575 /// <returns></returns>
[1095]576 public int AddAvailability(DateTime StartTime, DateTime EndTime, int nType, int nSlots, string sResourceList, string sAccessRuleList, string sNote)
[1071]577 {
578 //adds it to the object array
579 //Returns the index in the array
[614]580
[1071]581 CGAvailability pNewAv = new CGAvailability();
582 pNewAv.Create(StartTime, EndTime, nType, nSlots, sResourceList, sAccessRuleList);
[614]583
[1071]584 pNewAv.Note = sNote;
[614]585
[1071]586 //Look up the color and type name using the AppointmentTypes datatable
587 DataTable dtType = this.m_DocManager.GlobalDataSet.Tables["AccessTypes"];
588 DataRow dRow = dtType.Rows.Find(nType.ToString());
589 if (dRow != null)
590 {
591 string sColor = dRow["DISPLAY_COLOR"].ToString();
592 pNewAv.DisplayColor = sColor;
593 string sTemp = dRow["RED"].ToString();
594 sTemp = (sTemp == "") ? "0" : sTemp;
595 int nRed = Convert.ToInt16(sTemp);
596 pNewAv.Red = nRed;
597 sTemp = dRow["GREEN"].ToString();
598 sTemp = (sTemp == "") ? "0" : sTemp;
599 int nGreen = Convert.ToInt16(sTemp);
600 pNewAv.Green = nGreen;
601 sTemp = dRow["BLUE"].ToString();
602 sTemp = (sTemp == "") ? "0" : sTemp;
603 int nBlue = Convert.ToInt16(sTemp);
604 pNewAv.Blue = nBlue;
[614]605
[1071]606 string sName = dRow["ACCESS_TYPE_NAME"].ToString();
607 pNewAv.AccessTypeName = sName;
608 }
[614]609
[1071]610 int nIndex = 0;
611 nIndex = m_pAvArray.Add(pNewAv);
[1095]612
[1071]613 return nIndex;
614 }
[614]615
[1071]616
617 public void AddResource(string sResource)
618 {
619 //TODO: Test that resource is not currently in list, that it IS a resource, etc
620 this.m_sResourcesArray.Add(sResource);
621 }
[614]622
[1097]623 /// <summary>
624 /// Gets number of slots left in a certain selection on the grid. Used in Multiple Places.
625 /// </summary>
626 /// <param name="dSelStart">Selection Start Date</param>
627 /// <param name="dSelEnd">Selection End Date</param>
628 /// <param name="sResource">Resource Name</param>
629 /// <param name="sAccessType">Out: Name of Access Type</param>
630 /// <param name="sAvailabilityMessage">Out: Access Note</param>
631 /// <returns>Number of slots</returns>
[1106]632 public int SlotsAvailable(DateTime dSelStart, DateTime dSelEnd, string sResource, int viewTimeScale, out CGAvailability resultantAV)
[1071]633 {
[1097]634
[1106]635 resultantAV = null;
[1097]636
637 double slotsAvailable = 0; //defalut return value
638
[1106]639 double effectiveSlotsAvailable = 0; //Slots available based on the time scale.
640
641
[1097]642 //NOTE: What's this lock? This lock makes sure that nobody is editing the availability array
643 //when we are looking at it. Since the availability array could potentially be updated on
644 //a different thread, we are can be potentially left stuck with an empty array.
645 //
646 //The other place that uses this lock is the RefershAvailabilitySchedule method
647 //
648 //This is a temporary fix until I figure out how to divorce the availbilities here from those drawn
649 //on the calendar. Appointments are cloned b/c they are in an object that supports that; and b/c I
650 //don't need to suddenly query them at runtime like I do with Availabilities.
651
652 //Let's Try Linq
653 lock (this.m_pAvArray)
654 {
655 //This foreach loop looks for an availability that overlaps where the user clicked.
[1106]656 //Availabilites cannot overlap each other (enforced at the DB level)
[1097]657 //If selection hits multiple blocks, get the block with the most slots (reflected by the sorting here)
[1106]658 List<CGAvailability> lstAV = (from avail in this.m_pAvArray.Cast<CGAvailability>()
659 where (sResource == avail.ResourceList && CalendarGrid.TimesOverlap(dSelStart, dSelEnd, avail.StartTime, avail.EndTime))
660 select avail).ToList();
[1097]661
[1106]662 //if we don't have any availabilities, then return with zero slots.
663 if (lstAV.Count == 0) return 0;
664
665 CGAvailability pAV;
[1097]666
[1106]667 //if there is just one, that's it.
668 if (lstAV.Count == 1) pAV = lstAV.First();
669 //otherwise...
670 else
671 {
672 //if availabilities are contigous to each other, need to join them together.
[1097]673
[1106]674 //First, are they the same?
675 string firsttype = lstAV.First().AccessTypeName;
676 bool bAllSameType = lstAV.All(av => av.AccessTypeName == firsttype);
677
678 //Second are they ALL contigous?
679 DateTime lastEndTime = DateTime.Today; //bogus value to please compiler who wants it assigned.
680 int index = 0;
681
682 bool bContigous = lstAV.OrderBy(av => av.StartTime)
683 .All(av =>
684 {
685 index++;
686 if (index == 1)
687 {
688 lastEndTime = av.EndTime;
689 return true;
690 }
691 if (av.StartTime == lastEndTime)
692 {
693 lastEndTime = av.EndTime;
694 return true;
695 }
696
697 return false;
698 });
699
700
701
702 if (bContigous && bAllSameType)
703 {
704 var enumAVOrdered = lstAV.OrderBy(av => av.StartTime);
705
706 pAV = new CGAvailability
707 {
708 StartTime = enumAVOrdered.First().StartTime,
709 EndTime = enumAVOrdered.Last().EndTime,
710 Slots = enumAVOrdered.Sum(av => av.Slots),
711 AccessTypeName = enumAVOrdered.First().AccessTypeName,
712 Note = enumAVOrdered.First().Note
713 };
714 }
715 else
716 {
717 pAV = lstAV.OrderByDescending(av => av.Slots).First();
718 }
719 }
720
721 resultantAV = pAV; // out var
722
723 slotsAvailable = pAV.Slots;
724
[1097]725 //Subtract total slots current appointments take up.
726 slotsAvailable -= (from appt in this.Appointments.AppointmentTable.Values.Cast<CGAppointment>()
727 //If the resource is the same and the user selection overlaps, then...
[1106]728 where (sResource == appt.Resource && CalendarGrid.TimesOverlap(pAV.StartTime, pAV.EndTime, appt.StartTime, appt.EndTime))
[1097]729 // if appt starttime is before avail start time, only count against the avail starting from the availability start time
[1106]730 let startTimeToCountAgainstBlock = appt.StartTime < pAV.StartTime ? pAV.StartTime : appt.StartTime
[1097]731 // if appt endtime is after the avail ends, only count against the avail up to where the avail ends
[1106]732 let endTimeToCountAgainstBlock = appt.EndTime > pAV.EndTime ? pAV.EndTime : appt.EndTime
[1097]733 // theoretical minutes per slot for the availability
[1106]734 let minPerSlot = (pAV.EndTime - pAV.StartTime).TotalMinutes / pAV.Slots
[1097]735 // how many minutes does this appointment take away from the slot
736 let minPerAppt = (endTimeToCountAgainstBlock - startTimeToCountAgainstBlock).TotalMinutes
737 // how many slots the appointment takes up using this availability's scale
738 let slotsConsumed = minPerAppt / minPerSlot
739 select slotsConsumed)
740 // add up SlotsConsumed to substract from slotsAvailable
741 .Sum();
[1106]742
743 //theoretical minutes per slot for the availability
744 double minPerSlot2 = (pAV.EndTime - pAV.StartTime).TotalMinutes / pAV.Slots;
745
746 //Convert it to the view's time scale.
747 effectiveSlotsAvailable = (minPerSlot2 / viewTimeScale) * slotsAvailable;
748
[1097]749 }
[1106]750
751 //round it down.
752 return (int)effectiveSlotsAvailable;
[1097]753
754 /* OLD ALGOTHRIM 2
755
756 lock (this.m_pAvArray)
757 {
758 //This foreach loop looks for an availability that overlaps where the user clicked.
759 //There can only be one, as availabilites cannot overlap each other (enforced at the DB level)
760 //Therefore, we loop, and once we find it, we break.
761 foreach (CGAvailability pAV in this.m_pAvArray)
762 {
763 //If the resource is the same and the user selection overlaps, then...
764 if (sResource == pAV.ResourceList && CalendarGrid.TimesOverlap(dSelStart, dSelEnd, pAV.StartTime, pAV.EndTime))
765 {
766 slotsAvailable = pAV.Slots; //variable now holds the total number of slots
767 sAccessType = pAV.AccessTypeName; //Access Name
768 sAvailabilityMessage = pAV.Note; //Access Block Note
769
770 //Here we substract each appointment weight in slots from slotsAvailable
771 foreach (DictionaryEntry apptDict in this.m_appointments.AppointmentTable)
772 {
773 CGAppointment appt = (CGAppointment)apptDict.Value;
774 //If the appointment is in the same resource and overlaps with this availablity
775 if (sResource == appt.Resource && CalendarGrid.TimesOverlap(pAV.StartTime, pAV.EndTime, appt.StartTime, appt.EndTime))
776 {
777 // if appt starttime is before avail start time, only count against the avail starting from the availability start time
778 DateTime startTimeToCountAgainstBlock = appt.StartTime < pAV.StartTime ? pAV.StartTime : appt.StartTime;
779 // if appt endtime is after the avail ends, only count against the avail up to where the avail ends
780 DateTime endTimeToCountAgainstBlock = appt.EndTime > pAV.EndTime ? pAV.EndTime : appt.EndTime;
781 // theoretical minutes per slot for the availability
782 double minPerSlot = (pAV.EndTime - pAV.StartTime).TotalMinutes/pAV.Slots;
783 // how many minutes does this appointment take away from the slot
784 double minPerAppt = (endTimeToCountAgainstBlock - startTimeToCountAgainstBlock).TotalMinutes;
785 // how many slots the appointment takes up using this availability's scale
786 double slotsConsumed = minPerAppt / minPerSlot;
787 // subscract that from the total slots for the availability
788 slotsAvailable -= slotsConsumed;
789 } //end if
790 //now go to the next appointment in foreach
791 }
792 // As I said above, we can match only one availability. Once we found it and substracted from it; we are done.
793 break;
794 }
795 }
796 // We return the integer portion of the variable for display to the user or for calculations.
797 // That means, if 2.11 slots are left, the user sees 2. If 2.66, still 2.
798 return (int)slotsAvailable;
799 }
800 */
801
802 /* ORIGINAL ALGORITHM
[1071]803 sAccessType = "";
804 sAvailabilityMessage = "";
805 DateTime dStart;
806 DateTime dEnd;
807 int nAvailableSlots = 999;
808 int nSlots = 0;
809 int i = 0;
810 CGAvailability pAv;
811 Rectangle crRectA = new Rectangle(0, 0, 1, 0);
812 Rectangle crRectB = new Rectangle(0, 0, 1, 0);
813 bool bIsect;
814 crRectB.Y = GetTotalMinutes(dSelStart);
815 crRectB.Height = GetTotalMinutes(dSelEnd) - crRectB.Y;
[614]816
[1083]817 //NOTE: What's this lock? This lock makes sure that nobody is editing the availability array
818 //when we are looking at it. Since the availability array could potentially be updated on
819 //a different thread, we are can be potentially left stuck with an empty array.
820 //
821 //The other place that uses this lock is the RefershAvailabilitySchedule method
822 //
823 //This is a temporary fix until I figure out how to divorce the availbilities here from those drawn
824 //on the calendar. Appointments are cloned b/c they are in an object that supports that; and b/c I
825 //don't need to suddenly query them at runtime like I do with Availabilities.
826
827 lock (this.m_pAvArray)
[1071]828 {
[1083]829 //loop thru m_pAvArray
830 //Compare the start time and end time of eachblock
831 while (i < m_pAvArray.Count)
[1071]832 {
[1083]833 pAv = (CGAvailability)m_pAvArray[i];
834 dStart = pAv.StartTime;
835 dEnd = pAv.EndTime;
836 if ((sResource == pAv.ResourceList) &&
837 ((dSelStart.Date == dStart.Date) || (dSelStart.Date == dEnd.Date)))
[1071]838 {
[1083]839 crRectA.Y = (dStart.Date < dSelStart.Date) ? 0 : GetTotalMinutes(dStart);
840 crRectA.Height = (dEnd.Date > dSelEnd.Date) ? 1440 : GetTotalMinutes(dEnd);
841 crRectA.Height = crRectA.Height - crRectA.Y;
842 bIsect = crRectA.IntersectsWith(crRectB);
843 if (bIsect != false)
[1071]844 {
[1083]845 nSlots = pAv.Slots;
846 if (nSlots < 1)
847 {
848 nAvailableSlots = 0;
849 break;
850 }
851 if (nSlots < nAvailableSlots)
852 {
853 nAvailableSlots = nSlots;
854 sAccessType = pAv.AccessTypeName;
855 sAvailabilityMessage = pAv.Note;
[614]856
[1083]857 }
858 }//end if
859 }//end if
860 i++;
861 }//end while
862 }//end lock
863
[1071]864 if (nAvailableSlots == 999)
865 {
866 nAvailableSlots = 0;
867 }
868 return nAvailableSlots;
[1097]869 */
[1071]870 }
871
872 /// <summary>
873 /// Given a selected date,
874 /// Calculates StartDay and End Day and returns them in output params.
875 /// nWeeks == number of Weeks to display
876 /// nColumnCount is number of days displayed per week.
[886]877 /// If 5 columns, begin on Second Day of Week
[1071]878 /// If 7 Columns, begin on First Day of Week
[886]879 /// (this is a change from the hardcoded behavior for US-based calendars)
[1071]880 ///
881 /// Returns TRUE if the document's data needs refreshing based on
882 /// this newly selected date.
883 /// </summary>
884 public bool WeekNeedsRefresh(int nWeeks, DateTime SelectedDate,
885 out DateTime WeekStartDay, out DateTime WeekEndDay)
886 {
887 DateTime OldStartDay = m_dStartDate;
888 DateTime OldEndDay = m_dEndDate;
[908]889 // Week start based on thread locale
890 int nStartWeekDay = (int)System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
[913]891 // Current Day
[1071]892 int nWeekDay = (int)SelectedDate.DayOfWeek; //0 == Sunday
[614]893
[1071]894 // this offset gets approrpriate day based on locale.
[886]895 int nOff = (nStartWeekDay + 1) % 7;
[1071]896 TimeSpan ts = new TimeSpan(nWeekDay - nOff, 0, 0, 0); //d,h,m,s
[614]897
[913]898 // if ts is negative, we will jump to the next week in the logic.
899 // to show the correct week, add 7. Confusing, I know.
[1071]900 if (ts < new TimeSpan()) ts = ts + new TimeSpan(7, 0, 0, 0);
[913]901
[1071]902 if (m_nColumnCount == 1) // if one column start and end on the same day.
903 {
904 ts = new TimeSpan(0, 23, 59, 59);
905 WeekStartDay = SelectedDate;
[913]906 WeekEndDay = WeekStartDay + ts;
[1071]907 }
[913]908 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.
909 {
910 // if picked day is start of week (Sunday in US), start in the next day since that's the first day of work week
911 // else, just substract the calculated time span to get to the start of week (first work day)
[1071]912 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate + new TimeSpan(1, 0, 0, 0) : SelectedDate - ts;
[913]913 // End day calculation
914 int nEnd = 3;
915 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
916 WeekEndDay = WeekStartDay + ts;
917 }
918 else // if 7 column start at the 1st day of this week and end in 6:23:59:59 days.
919 {
920 // 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.
[1071]921 WeekStartDay = (nWeekDay == nStartWeekDay) ? SelectedDate : SelectedDate - ts - new TimeSpan(1, 0, 0, 0);
[913]922 // End day calculation
923 int nEnd = 1;
924 ts = new TimeSpan((7 * nWeeks) - nEnd, 23, 59, 59);
925 WeekEndDay = WeekStartDay + ts;
926 }
927
[1071]928 bool bRet = ((WeekStartDay.Date != OldStartDay.Date) || (WeekEndDay.Date != OldEndDay.Date));
929 return bRet;
930 }
[614]931
[1071]932 /// <summary>
933 /// Calls RPMS to create appointment then
934 /// adds appointment to the m_appointments collection
935 /// Returns the IEN of the appointment in the RPMS BSDX APPOINTMENT file.
936 /// </summary>
937 /// <param name="rApptInfo"></param>
938 /// <returns></returns>
939 public int CreateAppointment(CGAppointment rApptInfo)
940 {
941 return CreateAppointment(rApptInfo, false);
942 }
[614]943
[1071]944 /// <summary>
945 /// Use this overload to create a walkin appointment
946 /// </summary>
947 /// <param name="rApptInfo"></param>
948 /// <param name="bWalkin"></param>
949 /// <returns></returns>
950 public int CreateAppointment(CGAppointment rApptInfo, bool bWalkin)
951 {
952 string sStart;
953 string sEnd;
954 string sPatID;
955 string sResource;
956 string sNote;
957 string sLen;
958 string sApptID;
[864]959
[1071]960 //sStart = rApptInfo.StartTime.ToString("M-d-yyyy@HH:mm");
961 //sEnd = rApptInfo.EndTime.ToString("M-d-yyyy@HH:mm");
962
[864]963 // i18n code -- Use culture neutral FMDates
964 sStart = FMDateTime.Create(rApptInfo.StartTime).FMDateString;
965 sEnd = FMDateTime.Create(rApptInfo.EndTime).FMDateString;
966
[1071]967 TimeSpan sp = rApptInfo.EndTime - rApptInfo.StartTime;
968 sLen = sp.TotalMinutes.ToString();
969 sPatID = rApptInfo.PatientID.ToString();
970 sNote = rApptInfo.Note;
971 sResource = rApptInfo.Resource;
972 if (bWalkin == true)
973 {
974 sApptID = "WALKIN";
975 }
976 else
977 {
978 sApptID = rApptInfo.AccessTypeID.ToString();
979 }
[614]980
[1071]981 CGAppointment aCopy = new CGAppointment();
982 aCopy.CreateAppointment(rApptInfo.StartTime, rApptInfo.EndTime, sNote, 0, sResource);
983 aCopy.PatientID = rApptInfo.PatientID;
984 aCopy.PatientName = rApptInfo.PatientName;
985 aCopy.HealthRecordNumber = rApptInfo.HealthRecordNumber;
986 aCopy.AccessTypeID = rApptInfo.AccessTypeID;
[1083]987 aCopy.WalkIn = bWalkin ? true : false;
[614]988
[1071]989 string sSql = "BSDX ADD NEW APPOINTMENT^" + sStart + "^" + sEnd + "^" + sPatID + "^" + sResource + "^" + sLen + "^" + sNote + "^" + sApptID;
990 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "NewAppointment");
991 int nApptID;
[614]992
[1071]993 Debug.Assert(dtAppt.Rows.Count == 1);
994 DataRow r = dtAppt.Rows[0];
995 nApptID = Convert.ToInt32(r["APPOINTMENTID"]);
996 string sErrorID;
997 sErrorID = r["ERRORID"].ToString();
998 if ((sErrorID != "") || (nApptID < 1))
[1084]999 {
[1071]1000 throw new Exception(sErrorID);
[1084]1001 }
[1071]1002 aCopy.AppointmentKey = nApptID;
1003 this.m_appointments.AddAppointment(aCopy);
[1083]1004
[1112]1005 //TODO: Improve
1006 //Yucky hack for now... haven't investigated why we need to create a new CGAppointment beyond
1007 //the one that we pass.
1008 rApptInfo.AppointmentKey = nApptID;
1009
[1083]1010 //Have make appointment from CGView responsible for requesting an update for the avialability.
1011 //bool bRet = RefreshAvailabilitySchedule();
[614]1012
[1083]1013 //Sam: don't think this is needed as it is called from CGView.
1014 //Make CGView responsible for all drawing.
1015 //UpdateAllViews();
[614]1016
[1071]1017 return nApptID;
1018 }
[614]1019
[1071]1020 public void EditAppointment(CGAppointment pAppt, string sNote)
1021 {
1022 try
1023 {
1024 int nApptID = pAppt.AppointmentKey;
1025 string sSql = "BSDX EDIT APPOINTMENT^" + nApptID.ToString() + "^" + sNote;
[614]1026
[1071]1027 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "EditAppointment");
[614]1028
[1071]1029 Debug.Assert(dtAppt.Rows.Count == 1);
1030 DataRow r = dtAppt.Rows[0];
1031 string sErrorID = r["ERRORID"].ToString();
1032 if (sErrorID == "-1")
1033 pAppt.Note = sNote;
[614]1034
[1071]1035 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
1036 {
1037 bool bRet = RefreshAvailabilitySchedule();
1038 UpdateAllViews();
1039 }
1040 }
1041 catch (Exception ex)
1042 {
1043 Debug.Write("CGDocument.EditAppointment Failed: " + ex.Message);
1044 }
1045 }
[614]1046
[1071]1047 public void CheckInAppointment(int nApptID, DateTime dCheckIn)
1048 {
1049 string sCheckIn = FMDateTime.Create(dCheckIn).FMDateString;
1050
[1062]1051 string sSql = "BSDX CHECKIN APPOINTMENT^" + nApptID.ToString() + "^" + sCheckIn; // +"^";
[1071]1052 //sSql += ClinicStopIEN + "^" + ProviderIEN + "^" + PrintRouteSlip + "^";
1053 //sSql += PCCClinicIEN + "^" + PCCFormIEN + "^" + PCCOutGuide;
[614]1054
[1071]1055 System.Data.DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "CheckInAppointment");
[614]1056
[1071]1057 Debug.Assert(dtAppt.Rows.Count == 1);
1058 DataRow r = dtAppt.Rows[0];
1059 string sErrorID = r["ERRORID"].ToString();
1060 }
[614]1061
[1071]1062 public string DeleteAppointment(int nApptID)
1063 {
1064 return DeleteAppointment(nApptID, true, 0, "");
1065 }
[614]1066
[1071]1067 public string DeleteAppointment(int nApptID, bool bClinicCancelled, int nReason, string sRemarks)
1068 {
1069 //Returns "" if deletion successful
1070 //Otherwise, returns reason for failure
[614]1071
[1071]1072 string sClinicCancelled = (bClinicCancelled == true) ? "C" : "PC";
1073 string sReasonID = nReason.ToString();
1074 string sSql = "BSDX CANCEL APPOINTMENT^" + nApptID.ToString();
1075 sSql += "^" + sClinicCancelled;
1076 sSql += "^" + sReasonID;
1077 sSql += "^" + sRemarks;
1078 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "DeleteAppointment");
[614]1079
[1071]1080 Debug.Assert(dtAppt.Rows.Count == 1);
1081 DataRow r = dtAppt.Rows[0];
1082 string sErrorID = r["ERRORID"].ToString();
1083 if (sErrorID != "")
1084 return sErrorID;
[614]1085
[1071]1086 if (this.m_appointments.AppointmentTable.ContainsKey(nApptID))
1087 {
1088 this.m_appointments.RemoveAppointment(nApptID);
[1084]1089
1090 // View responsible for deciding to redraw the grid; not the document now.
1091 //bool bRet = RefreshAvailabilitySchedule();
1092 //UpdateAllViews();
[1071]1093 }
1094 return "";
1095 }
[614]1096
[1071]1097 public string AutoRebook(CGAppointment a, int nSearchType, int nMinimumDays, int nMaximumDays, out CGAppointment aRebook)
1098 {
1099 //If successful Returns "1" and new start date and time returned in aRebook
1100 //Otherwise, returns error message
[614]1101
[1071]1102 CGAppointment aCopy = new CGAppointment();
1103 aCopy.CreateAppointment(a.StartTime, a.EndTime, a.Note, 0, a.Resource);
1104 aCopy.PatientID = a.PatientID;
1105 aCopy.PatientName = a.PatientName;
1106 aCopy.HealthRecordNumber = a.HealthRecordNumber;
1107 aCopy.AccessTypeID = a.AccessTypeID;
1108 aRebook = aCopy;
[614]1109
[1071]1110 //Determine Rebook access type
1111 //nSearchType = -1: use current, -2: use any non-zero type, >0 use this access type id
1112 int nAVType = 0;
[614]1113
[1071]1114 switch (nSearchType)
1115 {
1116 case -1:
1117 nAVType = a.AccessTypeID;
1118 break;
1119 case -2:
1120 nAVType = 0;
1121 break;
1122 default:
1123 nAVType = nSearchType;
1124 break;
1125 }
[614]1126
[1071]1127 int nSlots = 0;
1128 string sSlots = "";
1129 int nAccessTypeID; //To compare with nAVType
[614]1130
[1071]1131 DateTime dResult = new DateTime(); //StartTime of access block to autorebook into
[614]1132
[1071]1133 //Next two are empty, but needed to pass to CreateAvailabilitySchedule
1134 ArrayList alAccessTypes = new ArrayList();
1135 string sSearchInfo = "";
[614]1136
[1071]1137 //Find the StartTime of first availability block of this type for this clinic
1138 //between nMinimumDays and nMaximumDays
[614]1139
[1071]1140 string sAVStart = a.StartTime.AddDays(nMinimumDays).ToString("M/d/yyyy@H:mm");
[614]1141
[1071]1142 //dtAVEnd is the last day to search
1143 DateTime dtAVEnd = a.StartTime.AddDays(nMinimumDays + nMaximumDays);
1144 string sAVEnd = dtAVEnd.ToString("M/d/yyyy@H:mm");
1145
1146 //Increment start day to search a week (or so) at a time
1147 //30 is a test increment. Need to test different values for performance
1148 int nIncrement = (nMaximumDays < 30) ? nMaximumDays : 30;
1149
1150 //nCount and nCountEnd are the 'moving' counters
1151 //that I add to start and end to get the bracket
1152 //At the beginning of the DO loop, nCount and nCountEnd are already set
1153 bool bFinished = false;
1154 bool bFound = false;
1155
1156 DateTime dStart = a.StartTime.AddDays(nMinimumDays);
[864]1157 // v 1.3 i18n support - FM Date passed insated of American Date
1158 string sStart = FMDateTime.Create(dStart).DateOnly.FMDateString;
[1071]1159 DateTime dEnd = dStart.AddDays(nIncrement);
1160 do
1161 {
1162 string sSql = "BSDX REBOOK NEXT BLOCK^" + sStart + "^" + a.Resource + "^" + nAVType.ToString();
1163 DataTable dtNextBlock = this.DocManager.RPMSDataTable(sSql, "NextBlock");
1164 Debug.Assert(dtNextBlock.Rows.Count == 1);
1165 DataRow drNextBlockRow = dtNextBlock.Rows[0];
[614]1166
[1071]1167 object oNextBlock;
1168 oNextBlock = drNextBlockRow["NEXTBLOCK"];
1169 if (oNextBlock.GetType() == typeof(System.DBNull))
1170 break;
1171 DateTime dNextBlock = (DateTime)drNextBlockRow["NEXTBLOCK"];
1172 if (dNextBlock > dtAVEnd)
1173 {
1174 break;
1175 }
[614]1176
[1071]1177 dStart = dNextBlock;
1178 dEnd = dStart.AddDays(nIncrement);
1179 if (dEnd > dtAVEnd)
1180 dEnd = dtAVEnd;
[614]1181
[1071]1182 DataTable dtResult = CGSchedLib.CreateAvailabilitySchedule(m_DocManager, this.Resources, dStart, dEnd, alAccessTypes, ScheduleType.Resource, sSearchInfo);
1183 //Loop thru dtResult looking for a slot having the required availability type.
1184 //If found, set bFinished = true;
1185 foreach (DataRow dr in dtResult.Rows)
1186 {
[614]1187
[1071]1188 sSlots = dr["SLOTS"].ToString();
1189 if (sSlots == "")
1190 sSlots = "0";
1191 nSlots = Convert.ToInt16(sSlots);
1192 if (nSlots > 0)
1193 {
1194 nAccessTypeID = 0; //holds the access type id of the availability block
1195 if (dr["ACCESS_TYPE"].ToString() != "")
1196 nAccessTypeID = Convert.ToInt16(dr["ACCESS_TYPE"].ToString());
1197 if ((nSearchType == -2) && (nAccessTypeID > 0)) //Match on any non-zero type
1198 {
1199 bFinished = true;
1200 bFound = true;
1201 dResult = (DateTime)dr["START_TIME"];
1202 break;
1203 }
1204 if (nAccessTypeID == nAVType)
1205 {
1206 bFinished = true;
1207 bFound = true;
1208 dResult = (DateTime)dr["START_TIME"];
1209 break;
1210 }
1211 }
1212 }
1213 dStart = dEnd.AddDays(1);
1214 dEnd = dStart.AddDays(nIncrement);
1215 if (dEnd > dtAVEnd)
1216 dEnd = dtAVEnd;
1217 } while (bFinished == false);
[614]1218
[1071]1219 if (bFound == true)
1220 {
1221 aCopy.StartTime = dResult;
1222 aCopy.EndTime = dResult.AddMinutes(a.Duration);
1223 //Create the appointment
1224 //Set the AUTOREBOOKED flag
1225 //and store the "AutoRebooked To DateTime"
1226 //in each autorebooked appointment
1227 this.CreateAppointment(aCopy);
1228 SetAutoRebook(a, dResult);
1229 return "1";
1230 }
1231 else
1232 {
1233 return "0";
1234 }
1235 }
1236
1237 private void SetAutoRebook(CGAppointment a, DateTime dtRebookedTo)
1238 {
1239 string sApptKey = a.AppointmentKey.ToString();
1240 //string sRebookedTo = dtRebookedTo.ToString("M/d/yyyy@HH:mm");
[864]1241 // i18n
1242 string sRebookedTo = FMDateTime.Create(dtRebookedTo).FMDateString;
[1071]1243 string sSql = "BSDX REBOOK SET^" + sApptKey + "^" + sRebookedTo;
1244 System.Data.DataTable dtRebook = m_DocManager.RPMSDataTable(sSql, "AutoRebook");
[614]1245
[1071]1246 }
[614]1247
[1071]1248 public string AppointmentNoShow(int nApptID, bool bNoShow)
1249 {
1250 /*
1251 * BSDX NOSHOW RPC Returns 1 in ERRORID if successfully sets NOSHOW flag in BSDX APPOINTMENT and, if applicable, File 2
1252 *Otherwise, returns negative numbers for failure and errormessage in ERRORTXT
1253 *
1254 */
[614]1255
[1071]1256 string sTest = bNoShow.ToString();
1257 string sNoShow = (bNoShow == true) ? "1" : "0";
1258 string sSql = "BSDX NOSHOW^" + nApptID.ToString();
1259 sSql += "^";
1260 sSql += sNoShow;
[614]1261
[1071]1262 DataTable dtAppt = m_DocManager.RPMSDataTable(sSql, "AppointmentNoShow");
[614]1263
[1071]1264 Debug.Assert(dtAppt.Rows.Count == 1);
1265 DataRow r = dtAppt.Rows[0];
1266 string sErrorID = r["ERRORID"].ToString();
1267 if (sErrorID != "1")
1268 {
1269 return r["ERRORTEXT"].ToString();
1270 }
[614]1271
[1071]1272 bool bRet = RefreshSchedule();
[614]1273
[1071]1274 return sErrorID;
1275 }
1276
1277 #endregion Methods
1278
1279 }//End class
[614]1280}//End namespace
Note: See TracBrowser for help on using the repository browser.