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