using System; using System.Collections; using System.Data; //using System.Data.OleDb; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; using IndianHealthService.BMXNet; namespace IndianHealthService.ClinicalScheduling { /// /// Contains array of availability blocks for a scheduling resource /// public class CGAVDocument : System.Object { public CGAVDocument() { m_AVBlocks = new CGAppointments(); m_sResourcesArray = new ArrayList(); } #region Member Variables public int m_nColumnCount; //todo: this should point to the view's member for column count public int m_nTimeUnits; public string m_sSecondary; private string m_sDocName; public ArrayList m_sResourcesArray; public ScheduleType m_ScheduleType; private DateTime m_dSelectedDate; //Holds the user's selection from the dtpicker private DateTime m_dStartDate; //Beginning date of document data private DateTime m_dEndDate; //Ending date of document data public CGAppointments m_AVBlocks; private CGDocumentManager m_DocManager; private int m_nDocID; //Resource IEN in ^BSDXRES #endregion #region Properties /// /// Resource IEN in ^BSDXRES /// public int ResourceID { get { return m_nDocID; } set { m_nDocID = value; } } /// /// The list of Resource names /// public ArrayList Resources { get { return this.m_sResourcesArray; } set { this.m_sResourcesArray = value; } } public CGDocumentManager DocManager { get { return m_DocManager; } set { m_DocManager = value; } } /// /// Contains the hashtable of Availability Blocks /// public CGAppointments AVBlocks { get { return m_AVBlocks; } set { m_AVBlocks = value; } } /// /// Holds the date selected by the user in CGView.dateTimePicker1 /// public DateTime SelectedDate { get { return this.m_dSelectedDate; } set { this.m_dSelectedDate = value; bool bRet = false; if (m_ScheduleType == ScheduleType.Resource) { bRet = this.WeekNeedsRefresh(1, m_dSelectedDate, out this.m_dStartDate, out this.m_dEndDate); } else { this.m_dStartDate = m_dSelectedDate; this.m_dEndDate = m_dSelectedDate; this.m_dEndDate = this.m_dEndDate.AddHours(23); this.m_dEndDate = this.m_dEndDate.AddMinutes(59); this.m_dEndDate = this.m_dEndDate.AddSeconds(59); } bRet = this.RefreshDaysSchedule(); } } /// /// Contains the beginning date of the appointment document /// public DateTime StartDate { get { return this.m_dStartDate; } } public string DocName { get { return this.m_sDocName; } set { this.m_sDocName = value; } } #endregion #region Methods public void ChangeAppointmentTime(CGAppointment pAppt, DateTime dNewStart, DateTime dNewEnd, string sResource) { try { DateTime dOldStart = pAppt.StartTime; DateTime dOldEnd = pAppt.EndTime; if ((dOldStart == dNewStart) && (dOldEnd == dNewEnd)) { //no change in time return; } foreach (CGAppointment a in m_AVBlocks.AppointmentTable.Values) { DateTime sStart2 = a.StartTime; DateTime sEnd2 = a.EndTime; if ((a.AppointmentKey != pAppt.AppointmentKey) && (CGSchedLib.TimesOverlap(dNewStart, dNewEnd, a.StartTime, a.EndTime))) { MessageBox.Show("Access blocks may not overlap.","IHS Clinical Scheduling", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } } this.DeleteAvailability(pAppt.AppointmentKey); pAppt.StartTime = dNewStart; pAppt.EndTime = dNewEnd; pAppt.Resource = sResource; this.CreateAppointment(pAppt); } catch(Exception e) { MessageBox.Show("CGDocument::ChangeAppointmentTime failed: " + e.Message); return; } } public void DeleteAvailability(int nApptID) { if (this.m_AVBlocks.AppointmentTable.ContainsKey(nApptID)) { string sSql = "BSDX CANCEL AVAILABILITY^" + nApptID.ToString(); DataTable dtAppt =m_DocManager.RPMSDataTable(sSql, "DeleteAvailability"); int nErrorID; Debug.Assert(dtAppt.Rows.Count == 1); DataRow r = dtAppt.Rows[0]; nErrorID = Convert.ToInt32(r["ERRORID"]); this.m_AVBlocks.RemoveAppointment(nApptID); UpdateAllViews(); } } /// /// Called by LoadTemplate to create Access Block /// Returns the IEN of the availability block in the RPMS BSDX AVAILABILITY file. /// public int CreateAppointmentAuto(CGAppointment rApptInfo) { try { string sStart; string sEnd; string sResource; string sNote; string sTypeID; string sSlots; sStart = rApptInfo.StartTime.ToString("M-d-yyyy@HH:mm"); sEnd = rApptInfo.EndTime.ToString("M-d-yyyy@HH:mm"); sNote = rApptInfo.Note; sResource = rApptInfo.Resource; sTypeID = rApptInfo.AccessTypeID.ToString(); sSlots = rApptInfo.Slots.ToString(); CGAppointment aCopy = new CGAppointment(); aCopy.CreateAppointment(rApptInfo.StartTime, rApptInfo.EndTime, sNote, 0, sResource); aCopy.AccessTypeID = rApptInfo.AccessTypeID; aCopy.Slots = rApptInfo.Slots; aCopy.IsAccessBlock = true; string sSql = "BSDX ADD NEW AVAILABILITY^" + sStart + "^" + sEnd + "^" + sTypeID + "^" + sResource + "^" + sSlots + "^" + sNote; DataTable dtAppt =m_DocManager.RPMSDataTable(sSql, "NewAvailability"); int nApptID; int nErrorID; Debug.Assert(dtAppt.Rows.Count == 1); DataRow r = dtAppt.Rows[0]; nApptID =Convert.ToInt32(r["AVAILABILITYID"]); nErrorID = Convert.ToInt32(r["ERRORID"]); if (nErrorID != -1) { throw new Exception("RPMS Error"); } Debug.Write("CreateAvailabilityAuto -- new AV block created\n"); UpdateAllViews(); aCopy.AppointmentKey = nApptID; return nApptID; } catch (Exception ex) { Debug.Write("CGAVDocument.CreateAppointmentAuto Failed: " + ex.Message); return -1; } } public int CreateAppointment(CGAppointment rApptInfo) { try { string sStart; string sEnd; string sResource; string sNote; string sTypeID; string sSlots; sStart = rApptInfo.StartTime.ToString("M-d-yyyy@HH:mm"); sEnd = rApptInfo.EndTime.ToString("M-d-yyyy@HH:mm"); sNote = rApptInfo.Note; sResource = rApptInfo.Resource; sTypeID = rApptInfo.AccessTypeID.ToString(); sSlots = rApptInfo.Slots.ToString(); CGAppointment aCopy = new CGAppointment(); aCopy.CreateAppointment(rApptInfo.StartTime, rApptInfo.EndTime, sNote, 0, sResource); aCopy.AccessTypeID = rApptInfo.AccessTypeID; aCopy.Slots = rApptInfo.Slots; aCopy.IsAccessBlock = true; aCopy.AccessTypeName = this.AccessNameFromID(aCopy.AccessTypeID); foreach (CGAppointment a in this.m_AVBlocks.AppointmentTable.Values) { DateTime sStart2 = a.StartTime; DateTime sEnd2 = a.EndTime; if (CGSchedLib.TimesOverlap(aCopy.StartTime, aCopy.EndTime, a.StartTime, a.EndTime)) { // throw new Exception("Access blocks may not overlap."); MessageBox.Show("Access blocks may not overlap.","IHS Clinical Scheduling", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return -1; } } string sSql = "BSDX ADD NEW AVAILABILITY^" + sStart + "^" + sEnd + "^" + sTypeID + "^" + sResource + "^" + sSlots + "^" + sNote; DataTable dtAppt =m_DocManager.RPMSDataTable(sSql, "NewAvailability"); int nApptID; int nErrorID; Debug.Assert(dtAppt.Rows.Count == 1); DataRow r = dtAppt.Rows[0]; nApptID =Convert.ToInt32(r["AVAILABILITYID"]); nErrorID = Convert.ToInt32(r["ERRORID"]); if (nErrorID != -1) { throw new Exception("RPMS Error"); } Debug.Write("CreateAvailability -- new AV block created\n"); aCopy.AppointmentKey = nApptID; this.m_AVBlocks.AddAppointment(aCopy); UpdateAllViews(); return nApptID; } catch (Exception ex) { Debug.Write("CGAVDocument.CreateAppointment Failed: " + ex.Message); return -1; } } private int GetTotalMinutes(DateTime dDate) { return ((dDate.Hour * 60) + dDate.Minute); } private string AccessNameFromID(int nAccessTypeID) { DataView dvTypes = new DataView(this.DocManager.GlobalDataSet.Tables["AccessTypes"]); dvTypes.Sort = "BMXIEN ASC"; int nRow = dvTypes.Find(nAccessTypeID); DataRowView drv = dvTypes[nRow]; string sAccessTypeName = drv["ACCESS_TYPE_NAME"].ToString(); return sAccessTypeName; } /// /// Update availability block schedule based on info in RPMS /// public bool RefreshDaysSchedule() { DateTime dStart; DateTime dEnd; int nKeyID; string sNote; string sResource; string sAccessType; string sSlots; CGAppointment pAppointment; CGDocumentManager pApp = CGDocumentManager.Current; DataTable rAppointmentSchedule; this.m_AVBlocks.ClearAllAppointments(); ArrayList apptTypeIDs = new ArrayList(); rAppointmentSchedule = CGSchedLib.CreateAssignedSlotSchedule(m_DocManager, (string) m_sResourcesArray[0], this.m_dStartDate, this.m_dEndDate, apptTypeIDs,/* */ this.m_ScheduleType, "0"); CGSchedLib.OutputArray(rAppointmentSchedule, "rAppointmentSchedule"); foreach (DataRow r in rAppointmentSchedule.Rows) { nKeyID = Convert.ToInt32(r["AVAILABILITYID"].ToString()); if (nKeyID > 0) { dStart = (DateTime) r["START_TIME"]; dEnd = (DateTime) r["END_TIME"]; sNote = r["NOTE"].ToString(); sResource = r["RESOURCE"].ToString(); sAccessType = r["ACCESS_TYPE"].ToString(); sSlots = r["SLOTS"].ToString(); pAppointment = new CGAppointment(); pAppointment.CreateAppointment(dStart, dEnd, sNote, nKeyID, sResource); pAppointment.AccessTypeID = Convert.ToInt16(sAccessType); pAppointment.Slots = Convert.ToInt16(sSlots); pAppointment.IsAccessBlock = true; pAppointment.AccessTypeName = this.AccessNameFromID(pAppointment.AccessTypeID); this.m_AVBlocks.AddAppointment(pAppointment); } } return true; } /// /// Given a selected date, /// Calculates StartDay and End Day and returns them in output params. /// nWeeks == number of Weeks to display /// nColumnCount is number of days displayed per week. If 5 columns, begin on /// Monday, if 7 Columns, begin on Sunday /// /// Returns TRUE if the document's data needs refreshing based on /// this newly selected date. /// public bool WeekNeedsRefresh(int nWeeks, DateTime SelectedDate, out DateTime WeekStartDay, out DateTime WeekEndDay) { DateTime OldStartDay = m_dStartDate; DateTime OldEndDay = m_dEndDate; int nWeekDay = (int) SelectedDate.DayOfWeek; //0 == Sunday int nOff = 1; TimeSpan ts = new TimeSpan(nWeekDay - nOff,0,0,0); //d,h,m,s if (m_nColumnCount == 1) { ts = new TimeSpan(0,23,59,59); WeekStartDay = SelectedDate; } else { WeekStartDay = SelectedDate - ts; if (m_nColumnCount == 7) { ts = new TimeSpan(1,0,0,0); WeekStartDay -= ts; } int nEnd = (m_nColumnCount == 7) ? 1 : 3; ts = new TimeSpan((7* nWeeks) - nEnd, 23, 59,59); } WeekEndDay = WeekStartDay + ts; bool bRet = (( WeekStartDay.Date != OldStartDay.Date) || (WeekEndDay.Date != OldEndDay.Date)); return bRet; } public void OnOpenDocument() { //Create new Document // DateTime dStart; // DateTime dEnd; Debug.Assert(m_sResourcesArray.Count > 0); m_sSecondary = ""; m_ScheduleType = (m_sResourcesArray.Count == 1) ? ScheduleType.Resource: ScheduleType.Clinic; bool bRet = false; //Set initial From and To dates based on current day // DateTime dDate = new DateTime(2001,12,05); //test line DateTime dDate = DateTime.Today; if (m_ScheduleType == ScheduleType.Resource) { bRet = this.WeekNeedsRefresh(1,dDate, out this.m_dStartDate, out this.m_dEndDate); } else { this.m_dStartDate = dDate; this.m_dEndDate = dDate; this.m_dEndDate = this.m_dEndDate.AddHours(23); this.m_dEndDate = this.m_dEndDate.AddMinutes(59); this.m_dEndDate = this.m_dEndDate.AddSeconds(59); } bRet = this.RefreshDaysSchedule(); CGAVView view = null; //If this document already has a view, the use it Hashtable h = CGDocumentManager.Current.AvailabilityViews; CGAVDocument d; bool bReuseView = false; foreach (CGAVView v in h.Keys) { d = (CGAVDocument) h[v]; if (d == this) { view = v; bReuseView = true; break; } } //Otherwise, create new View if (bReuseView == false) { view = new CGAVView(); view.DocManager = this.DocManager; view.StartDate = m_dStartDate; //Assign the document to the view view.Document = this; //Link the calendargrid's appointments table to the document's table view.AVBlocks = this.AVBlocks; view.Text = "Edit Availability - " + this.DocName; view.Show(); } this.UpdateAllViews(); } public void AddResource(string sResource) { //TODO: Test that resource is not currently in list, that it IS a resource, etc this.m_sResourcesArray.Add(sResource); this.UpdateAllViews(); } /// /// Calls each AVview associated with this AVdocument and tells it to update itself /// public void UpdateAllViews() { //iterate through all views and call update. Hashtable h = CGDocumentManager.Current.AvailabilityViews; CGAVDocument d; foreach (CGAVView v in h.Keys) { d = (CGAVDocument) h[v]; if (d == this) { v.UpdateArrays(); } } } #endregion }//End class }