// ScheduleFrm.cpp : implementation file // #include "stdafx.h" #include "sp.h" #include "ScheduleFrm.h" #include "WOHeaderDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //memory leak debugging help #define _CRTDBG_MAP_ALLOC #include #include #define MARTIN 1 #define DAYSTOCACHE 15 ///////////////////////////////////////////////////////////////////////////// // CScheduleFrm /* View scheduled workorders in the system visually Create new workorders by clicking and dragging a bar of time with the mouse Drag an existing workorder to a different time period Drag an existing workorder to a different technician Positioning the mouse over a time bar shows the client and workorder number at the top Double click on a time bar to open that workorder for editing View a day, week, two weeks or a month at a time Print the schedule as it appears onscreen (will print in color if your printer supports it) Change the start or end time of a workorder by clicking and dragging the ends of a time bar */ IMPLEMENT_DYNCREATE(CScheduleFrm, CFormView) CScheduleFrm::CScheduleFrm() : CFormView(CScheduleFrm::IDD) , m_bShowProblemDetailsInStatusDisplay(false) { //{{AFX_DATA_INIT(CScheduleFrm) //}}AFX_DATA_INIT m_pApp= (CSpApp*)AfxGetApp(); m_dt1900.SetDate(1900,1,1); m_nZoomFactor=60; m_bRefresh=true; m_bLayoutDone=false; m_nTotalAllocated=0; m_bTimerIsActive=false; m_bZoneView=true; } CScheduleFrm::~CScheduleFrm() { //KillTimer(1); //ClearTimeBarObjects(); } void CScheduleFrm::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CScheduleFrm) DDX_Control(pDX, IDC_LBLZONE, m_lblZone); DDX_Control(pDX, IDC_CBZONE, m_cbZone); DDX_Control(pDX, IDC_BTNBACK, m_btnBack); DDX_Control(pDX, IDC_BTNFORWARD, m_btnForward); DDX_Control(pDX, IDC_BTNPRINT, m_btnPrint); DDX_Control(pDX, IDC_LBLVIEW, m_lblView); DDX_Control(pDX, IDC_LBLSTARTDATE, m_lblStartDate); DDX_Control(pDX, IDC_BTNREFRESH, m_btnRefresh); DDX_Control(pDX, IDC_CKLOCk, m_ckLock); DDX_Control(pDX, IDC_RDWEEK, m_rdWeek); DDX_Control(pDX, IDC_RDMONTH, m_rdMonth); DDX_Control(pDX, IDC_RDDAY, m_rdDay); DDX_Control(pDX, IDC_LBLWODETAILS, m_lblDetails); DDX_Control(pDX, IDC_DTDATE, m_dtDate); DDX_Control(pDX, IDC_CTSCHED, m_sc); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CScheduleFrm, CFormView) //{{AFX_MSG_MAP(CScheduleFrm) ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DTDATE, OnDatetimechangeDtdate) ON_BN_CLICKED(IDC_BTNPRINT, OnBtnprint) ON_BN_CLICKED(IDC_BTNBACK, OnBtnback) ON_BN_CLICKED(IDC_BTNFORWARD, OnBtnforward) ON_BN_CLICKED(IDC_RDDAY, OnRdday) ON_BN_CLICKED(IDC_RDMONTH, OnRdmonth) ON_BN_CLICKED(IDC_RDWEEK, OnRdweek) ON_BN_CLICKED(IDC_BTNREFRESH, OnBtnrefresh) ON_BN_CLICKED(IDC_CKLOCk, OnCKLOCk) ON_CBN_CLOSEUP(IDC_CBZONE, OnCloseupCbzone) ON_WM_TIMER() //}}AFX_MSG_MAP ON_WM_HELPINFO() ON_WM_DESTROY() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CScheduleFrm diagnostics #ifdef _DEBUG void CScheduleFrm::AssertValid() const { CFormView::AssertValid(); } void CScheduleFrm::Dump(CDumpContext& dc) const { CFormView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CScheduleFrm message handlers void CScheduleFrm::Activate() { m_ulHighLightedBar=RGB(255,0,0); m_ulStandardBar=RGB(0,0,255); FillZoneList(); FillView(); if(!m_bTimerIsActive) { //AUTOREFRESH TIMER if(m_pApp->m_lSchedRefreshSecs!=0) m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); //m_nTimer = SetTimer(1, 6000, 0); m_bTimerIsActive=true; } } void CScheduleFrm::DeActivate() { KillTimer(1); m_bTimerIsActive=false; } void CScheduleFrm::OnInitialUpdate() { CFormView::OnInitialUpdate(); m_lblDetails.SetFontName("MS Sans Serif"); m_lblDetails.SetFontSize(8); m_lblDetails.SetFontBold(FALSE); m_lblDetails.SetTextColor(RGB(0,0,0)); m_lblDetails.SetBkColor(RGB(255,255,255)); //performance stats m_dLast=m_dFastest=m_dSlowest=m_dAverage=0; m_uiRefreshCount=0; //start off with a day view m_nDayWeekMonth=0;//0-day 1=week 2=Month shown in view m_rdDay.SetCheck(TRUE); m_ckLock.SetCheck(TRUE); m_bLocked=true; m_bUndoing=false; //lock so that get time bar object won't change it because of another even somewhere m_bUpdating=false; //m_nBarStyleOverlapping=m_sc.AddBarStyle(8,-2);//<<<<<<<<<<<<m_lSchedWindowDays/2; long lTechID,lWOID, lStatID, lDaysStart,lDaysEnd,lMinStart,lMinEnd; //time bar status stuff CString strStatus,strWONOTES,strZoneQ; long lRed,lGreen,lBlue; bool bActive,bFirstRunThrough,bContinue; int count=0; int nBar;//used for time bar colors to retrieve and set bar value //added 07/27/01 to accomodate multi-tech scheduled long lThisTech; bool bMatchingTech; int nTech; int nMatchingTechNumber; bFirstRunThrough=true;//used to show non-assigned items //flag used by OnItemMove... to indicate that nothing was //ever highlighted before m_nOldIndex=m_nOldBar=0; //Get the date from the control m_dtDate.GetTime(dtStart); //set the default fore text to white to contrast with //every likely color m_sc.SetBarDefForeColor(RGB(255,255,255)); //set time scroll value to something past the possible values //this is used to determine the earliest date in the schedule //and thus, scroll the schedule to it automatically //a thousand years give or take oughta do... dtTimeScrollStart.SetDate(3000,1,1); //dtTimeScrollStart=COleDateTime::GetCurrentTime(); m_sc.SetBarDefBackColor(m_ulStandardBar); //m_sc.SetTimeStart(); //if it's not a forced refresh, see if it's within the window if(!m_bRefresh) { if(dtStart > m_dtWindowStop || dtStart < m_dtWindowStart) { m_bRefresh=true; dtSpan.SetDateTimeSpan(lWindowSize,0,0,0); m_dtWindowStart=dtStart-dtSpan; m_dtWindowStop=dtStart+dtSpan; } } else { dtSpan.SetDateTimeSpan(lWindowSize,0,0,0); m_dtWindowStart=dtStart-dtSpan; m_dtWindowStop=dtStart+dtSpan; } //***************************************************************** //******************************************************* //Clear the previous schedule if any if(m_bRefresh) { m_sc.ClearSchedule(); //added 07/27/01 to account for changes to sched markers m_sc.ClearColorBars(); ClearTimeBarObjects(); } //******************************************************** //Set the zoom factor in the control //hours or days (maybe weeks...who knows?) if(m_nDayWeekMonth==0) { m_sc.SetWeekends(0); m_sc.SetTimeType(0);//0=hours,1=days,2=weeks m_sc.SetTimeDistance(m_nZoomFactor); m_sc.SetPrintTimeDistance(m_nZoomFactor); m_sc.SetBarTipSize(5);//5 is default m_sc.SetBarTipExtension(5); m_sc.SetRulerDivisions(4); } else { m_sc.SetWeekends(65); m_sc.SetTimeType(1); m_sc.SetRulerDivisions(0); m_sc.SetTimeDistance(75); m_sc.SetPrintTimeDistance(75); m_sc.SetBarTipSize(-200);//5 is default m_sc.SetBarTipExtension(-200); } dtEnd=dtStart+dtSpan; //Set the start and end dates in the control //start date days since 1900 dtSpan=m_dtWindowStart-m_dt1900; lDaysStart=(long)dtSpan.GetTotalDays(); //end date days since 1900 dtSpan=m_dtWindowStop-m_dt1900; lDaysEnd=(long)dtSpan.GetTotalDays(); m_sc.SetDateStart(lDaysStart); m_sc.SetDateEnd(lDaysEnd); //read from the database if it's a refresh situation if(m_bRefresh) { CWaitCursor cw; //Start timing here m_uiRefreshCount++; m_bRefresh=false; //Initialize recordset pointer pTimerSQL.Start(TRUE); rs=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS)"); rs2=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS2)"); rs3=m_pApp->rsPool->GetRS("CScheduleFrm::FillView (RS3)"); pTimerSQL.Stop(); //If by zone..... if(m_bZoneView) { //SELECT USERS BY ZONE strZoneQ=m_cbZone.GetCurrentRowID(); if(strZoneQ=="0") strZoneQ.Empty(); else { strZoneQ.Format("AND ((users.defzone)=%s)",m_cbZone.GetCurrentRowID()); } q.Format("SELECT users.id, users.active, [last] & \", \" & [first] AS fullname FROM users " "WHERE (((users.id)<>1) AND ((users.tech)=True) %s ) " "ORDER BY users.last;",strZoneQ); } //------------------------------------------------------------------------------------------- else { //else if by group //SELECT USERS BY GROUP strZoneQ=m_cbZone.GetCurrentRowID(); q.Format("SELECT users.id, users.active, [last] & \", \" & [first] AS fullname " "FROM schdets LEFT JOIN users ON schdets.techid = users.id " "WHERE (((schdets.grpid)=%s) AND ((users.tech)=True) AND ((users.id)<>1)) " "ORDER BY users.last;",strZoneQ); } //------------------------------------------------------------------------------------------- pTimerSQL.Start(FALSE); rs->QueryReadOnly(q); pTimerSQL.Stop(); if(rs->IsEmpty()) { //AfxMessageBox("There are no technicians for this zone"); m_pApp->rsPool->ReleaseRS(&rs->m_nID); m_pApp->rsPool->ReleaseRS(&rs2->m_nID); m_pApp->rsPool->ReleaseRS(&rs3->m_nID); //don't bother updatnig timer return; } bContinue=true; do { if(bFirstRunThrough) { strData="To be assigned"; lTechID=0; bActive=true; bFirstRunThrough=false; } else { pTimerSQL.Start(FALSE); rs->FetchField("fullname",&strData); rs->FetchField("id",&lTechID); rs->FetchField("active",&bActive); pTimerSQL.Stop(); bContinue=rs->MoveForward(); } m_sc.AddItem(strData); strData.Format("%u",lTechID); m_sc.SetListCargo(count+1,strData); count++; if(!bActive) { m_sc.SetListReadOnly((short)count,TRUE); m_sc.SetListItemBackColor((short)count,(unsigned long)RGB(128,128,128));// dark gray } else m_sc.SetListItemBackColor((short)count,(unsigned long)RGB(255,255,255));//white //********************************************** //********* SHOW TECH TIME OFF BARS ************ //********* Added 07/24/2001 ******************* //********************************************** //FIND ALL ITEMS FOR THIS TECH BETWEEN //m_dtWindowStart and m_dtWindowEnd //And then insert time bar in the m_nBarStyleTimeOff style //********************************************** if(lTechID!=0) { q.Format("SELECT schedmarkers.startdate, schedmarkers.enddate, schedmarkers.notes, schedmarkers.red, schedmarkers.green, schedmarkers.blue " "FROM schedmarkers " "WHERE (((schedmarkers.link)=%u) AND " "((schedmarkers.startdate) Between #%s# And #%s#));",lTechID, m_dtWindowStart.Format(_T("%m/%d/%Y %H:%M:%S")),m_dtWindowStop.Format(_T("%m/%d/%Y %H:%M:%S"))); //m_pApp->ShowStuff(q); rs2->QueryReadOnly(q); if(!rs2->IsEmpty()) { do { rs2->FetchField("notes",&strData); rs2->FetchField("startdate",&dtSchedStart); rs2->FetchField("enddate",&dtSchedEnd); rs2->FetchField("red",&lRed); rs2->FetchField("green",&lGreen); rs2->FetchField("blue",&lBlue); //start date days since 1900 dtSpan=dtSchedStart-m_dt1900; lDaysStart=(long)dtSpan.GetTotalDays();//<---********** //end date days since 1900 dtSpan=dtSchedEnd-m_dt1900; lDaysEnd=(long)dtSpan.GetTotalDays();//<---------************ //Start time minutes since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedStart.GetYear(), dtSchedStart.GetMonth(), dtSchedStart.GetDay(),0,0,0); dtSpan=dtSchedStart-dtTemp; lMinStart = (long) dtSpan.GetTotalMinutes();//<---********** //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); //AfxMessageBox(q); //End time hours since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedEnd.GetYear(), dtSchedEnd.GetMonth(), dtSchedEnd.GetDay(),0,0,0); dtSpan=dtSchedEnd-dtTemp; lMinEnd = (long) dtSpan.GetTotalMinutes();//<-------********* //Insert the bar nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,"off");//all off hours have cargo text id value of off m_sc.SetBarText(count,nBar,strData);//set text as specified in schedmarker record m_sc.SetBarBackColor(count,nBar,RGB(lRed,lGreen,lBlue));//set back color m_sc.SetBarForeColor(count,nBar,RGB(0,0,0));//set text black //m_sc.SetBarTextAlign(count,nBar,2);//set to centered text m_sc.SetBarStyle(count,nBar,m_nBarStyleTimeOff);//set to the style for off hours defined in initinstance }while(rs2->MoveForward()); } }//endif techid<>0 else//tech ID is zero so here is where the milestone bar should go if it's a full day back color (shop closed etc) { //********************************************** //********* SET SHOP CLOSED DAYS *************** //********************************************** //FIND ALL ITEMS BETWEEN m_dtWindowStart and m_dtWindowEnd //And then use the m_sc.AddColorBar to color the background //link=0 because non-zero means a tech time off and zero means whole office //closed //********************************************** q.Format("SELECT schedmarkers.startdate, schedmarkers.enddate, schedmarkers.notes, schedmarkers.red, schedmarkers.green, schedmarkers.blue " "FROM schedmarkers " "WHERE (((schedmarkers.link)=0) AND " "((schedmarkers.startdate) Between #%s# And #%s#));", m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")),m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59"))); //m_pApp->ShowStuff(q); rs2->QueryReadOnly(q); if(!rs2->IsEmpty()) { do { rs2->FetchField("notes",&strData); rs2->FetchField("startdate",&dtSchedStart); rs2->FetchField("enddate",&dtSchedEnd); rs2->FetchField("red",&lRed); rs2->FetchField("green",&lGreen); rs2->FetchField("blue",&lBlue); //start date days since 1900 dtSpan=dtSchedStart-m_dt1900; lDaysStart=(long)dtSpan.GetTotalDays();//<---********** //end date days since 1900 dtSpan=dtSchedEnd-m_dt1900; lDaysEnd=(long)dtSpan.GetTotalDays();//<---------************ //Start time minutes since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedStart.GetYear(), dtSchedStart.GetMonth(), dtSchedStart.GetDay(),0,0,0); dtSpan=dtSchedStart-dtTemp; lMinStart = (long) dtSpan.GetTotalMinutes();//<---********** //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); //AfxMessageBox(q); //End time hours since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedEnd.GetYear(), dtSchedEnd.GetMonth(), dtSchedEnd.GetDay(),0,0,0); dtSpan=dtSchedEnd-dtTemp; lMinEnd = (long) dtSpan.GetTotalMinutes();//<-------********* //Insert the backcolor as appropriate m_sc.AddColorBar(lMinStart,lMinEnd,lDaysStart,lDaysEnd,RGB(lRed,lGreen,lBlue)); //Insert the bar nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,"off");//all off hours have cargo text id value of off m_sc.SetBarText(count,nBar,strData);//set text as specified in schedmarker record //m_sc.SetBarBackColor(count,nBar,RGB(255,128,0));//set back orange m_sc.SetBarForeColor(count,nBar,RGB(0,0,0));//set text black //m_sc.SetBarTextAlign(count,nBar,2);//set to centered text //m_sc.SetBarTextWrap(TRUE); m_sc.SetBarStyle(count,nBar,m_nBarStyleAllDayText);//set to the style for off hours defined in initinstance }while(rs2->MoveForward()); }//endif !rs2 empty }//endif ltechid=0 (not assigned) //************************************************ //Fill view //Modified 07/26/01 - added the wotech 2,3,4 in OR statement all else the same //PROBLEM: START TIMES SHOULD BE FOR EACH TECH SEPARATELY. //LIKE THIS: /* SELECT wo.id, wo.assigntech, wo.starttime, wo.stoptime, wo.assigntech2, wo.starttime2, wo.stoptime2, wo.assigntech3, wo.starttime3, wo.stoptime3, wo.assigntech4, wo.starttime4, wo.stoptime4, wo.notes, clients.company, clients.last, clients.first, clients.bizphone, probstat.notes AS thestatus, projects.name AS projectname FROM wotypes RIGHT JOIN ((probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id) ON wotypes.id = wo.type WHERE (((wo.anytime)=False) AND ((wo.closed)=#3/12/1968#) AND ((wo.quick)=False)) AND ( (((wo.assigntech)=2) AND ((wo.starttime) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR (((wo.assigntech2)=2) AND ((wo.starttime2) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR (((wo.assigntech3)=2) AND ((wo.starttime3) Between #7/1/2001# And #9/1/2001 23:59:59#)) OR (((wo.assigntech4)=2) AND ((wo.starttime4) Between #7/1/2001# And #9/1/2001 23:59:59#)) ) ORDER BY wo.assigntech; */ /* q.Format("SELECT wo.id, wo.anytime, " "wo.assigntech, wo.starttime, wo.stoptime, " "wo.assigntech2, wo.starttime2, wo.stoptime2, " "wo.assigntech3, wo.starttime3, wo.stoptime3, " "wo.assigntech4, wo.starttime4, wo.stoptime4, " "wo.notes, wo.closed, clients.company, clients.last, clients.first, probstat.id as statid, probstat.red, probstat.green, probstat.blue, probstat.notes as thestatus, projects.name AS projectname " "FROM (probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id " "WHERE (((wo.starttime) Between #%s# And #%s#) AND ((wo.quick)=False) AND ((wo.anytime)=False) AND ((wo.assigntech)=%u) OR ((wo.assigntech2)=%u) OR ((wo.assigntech3)=%u) OR ((wo.assigntech4)=%u)) " "ORDER BY wo.assigntech;",m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")),m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59")),lTechID,lTechID,lTechID,lTechID); */ CString strSTART=m_dtWindowStart.Format(_T("%m/%d/%Y 0:0:0")); CString strSTOP=m_dtWindowStop.Format(_T("%m/%d/%Y 23:59:59")); q.Format("SELECT wo.id, wo.anytime, " "wo.assigntech, wo.starttime, wo.stoptime, " "wo.assigntech2, wo.starttime2, wo.stoptime2, " "wo.assigntech3, wo.starttime3, wo.stoptime3, " "wo.assigntech4, wo.starttime4, wo.stoptime4, " "wo.notes, wo.closed, clients.company, clients.bizphone, clients.last, clients.first, probstat.id as statid, probstat.red, probstat.green, probstat.blue, probstat.notes as thestatus, projects.name AS projectname " "FROM (probstat RIGHT JOIN (wo LEFT JOIN clients ON wo.client = clients.id) ON probstat.id = wo.status) LEFT JOIN projects ON wo.project = projects.id " "WHERE (((wo.quick)=False) AND ((wo.anytime)=False)) AND " "( (((wo.assigntech)=%u) AND ((wo.starttime) Between #%s# And #%s#)) OR " "(((wo.assigntech2)=%u) AND ((wo.starttime2) Between #%s# And #%s#)) OR " "(((wo.assigntech3)=%u) AND ((wo.starttime3) Between #%s# And #%s#)) OR " "(((wo.assigntech4)=%u) AND ((wo.starttime4) Between #%s# And #%s#)) );", //"ORDER BY wo.assigntech;", lTechID,strSTART,strSTOP, lTechID,strSTART,strSTOP, lTechID,strSTART,strSTOP, lTechID,strSTART,strSTOP ); #ifdef _DEBUG //m_pApp->ShowStuff(q); #endif //*********************************************************************************** //************************************************************************************ pTimerSQL.Start(FALSE); rs2->QueryReadOnly(q); pTimerSQL.Stop(); if(!rs2->IsEmpty()) { do{ pTimerSQL.Start(FALSE); rs2->FetchField("projectname",&strProjectName); rs2->FetchField("statid",&lStatID); rs2->FetchField("red",&lRed); rs2->FetchField("green",&lGreen); rs2->FetchField("blue",&lBlue); rs2->FetchField("thestatus",&strStatus); rs2->FetchField("notes",&strWONOTES); #ifdef _DEBUG rs2->FetchField("anytime",&bMatchingTech); ASSERT (bMatchingTech==false); #endif rs2->FetchField("id",&lWOID); strWOID.Format("%u",lWOID); rs2->FetchField("company",&strClient); rs2->FetchField("bizphone",&strTemp); strData.Format("%s %s",strClient,strTemp); strClient=strData; pTimerSQL.Stop(); //START OF 4 TIMES LOOP //Pick out each incident for this tech and insert a time bar for each one for(nTech=0;nTech<4;nTech++) { bMatchingTech=false; nMatchingTechNumber=0; /*if(lWOID==67) lThisTech=-2;*/ switch (nTech) { case 0: rs2->FetchField("assigntech",&lThisTech); if(lThisTech==lTechID) { bMatchingTech=true; nMatchingTechNumber=1; rs2->FetchField("starttime",&dtSchedStart); rs2->FetchField("stoptime",&dtSchedEnd); } break; case 1: rs2->FetchField("assigntech2",&lThisTech); if(lThisTech==lTechID) { bMatchingTech=true; nMatchingTechNumber=2; rs2->FetchField("starttime2",&dtSchedStart); rs2->FetchField("stoptime2",&dtSchedEnd); } break; case 2: rs2->FetchField("assigntech3",&lThisTech); if(lThisTech==lTechID) { bMatchingTech=true; nMatchingTechNumber=3; rs2->FetchField("starttime3",&dtSchedStart); rs2->FetchField("stoptime3",&dtSchedEnd); } break; case 3: rs2->FetchField("assigntech4",&lThisTech); if(lThisTech==lTechID) { bMatchingTech=true; nMatchingTechNumber=4; rs2->FetchField("starttime4",&dtSchedStart); rs2->FetchField("stoptime4",&dtSchedEnd); } break; } if(bMatchingTech) { //calculate weird days and minutes //timebars are set based on days since //jan 1 1900 and time is based on //minutes since midnight. //lDaysStart,lDaysEnd,lMinStart,lMinEnd; //start date days since 1900 dtSpan=dtSchedStart-m_dt1900; lDaysStart=(long)dtSpan.GetTotalDays(); //end date days since 1900 dtSpan=dtSchedEnd-m_dt1900; lDaysEnd=(long)dtSpan.GetTotalDays(); //Start time minutes since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedStart.GetYear(), dtSchedStart.GetMonth(), dtSchedStart.GetDay(),0,0,0); dtSpan=dtSchedStart-dtTemp; lMinStart = (long) dtSpan.GetTotalMinutes(); //q.Format("Start time:%s Midnight:%s, minutes:%u",dtSchedStart.Format(),dtTemp.Format(),lMinStart); //AfxMessageBox(q); //End time hours since midnight //set dttemp to 1 second after midnight dtTemp.SetDateTime( dtSchedEnd.GetYear(), dtSchedEnd.GetMonth(), dtSchedEnd.GetDay(),0,0,0); dtSpan=dtSchedEnd-dtTemp; lMinEnd = (long) dtSpan.GetTotalMinutes(); //q.Format("End time: time:%s midnight:%s, Minutes:%u",dtSchedEnd.Format(),dtTemp.Format(),lMinEnd); //AfxMessageBox(q); //Insert the time bar if(!strStatus.IsEmpty()) strStatus=" Status: " + strStatus; if(!strProjectName.IsEmpty()) strProjectName=", PROJECT: " + strProjectName; if(m_bShowProblemDetailsInStatusDisplay) { strTemp.Format("SELECT probs.brief FROM probs WHERE (((probs.wolink)=%u) " "AND ((probs.brief) Is Not Null));",lWOID); if(rs3->QueryReadOnly(strTemp)) { if(!rs3->IsEmpty()) { strWONOTES+="\r\n"; nCounter=0; do{ if(rs3->FetchField("brief",&strTemp)) { nCounter++; strData.Format("%u) %s, ",nCounter,strTemp); strWONOTES+=strData; } }while(rs3->MoveForward()); strWONOTES.TrimRight(' '); strWONOTES.TrimRight(','); } } } //strData.Format("%s - workorder #:%u, Tech#:%i, %s%s\r\n%s",strClient,lWOID, nMatchingTechNumber, strStatus,strProjectName, strWONOTES); strData.Format("%s - WO %u, Tech %i, %s%s, Notes: %s",strClient,lWOID, nMatchingTechNumber, strStatus,strProjectName, strWONOTES); //strStatus.Format("%u",lWOID);//original value without tech number strStatus.Format("%u,%i",lWOID,nMatchingTechNumber); nBar=m_sc.AddKeyTimeBar(count,lMinStart,lMinEnd,lDaysStart,lDaysEnd,strStatus); m_sc.SetBarBackColor(count,nBar,RGB(lRed,lGreen,lBlue)); //flag overlapping bars if(m_sc.FindFirstBar(count,nBar,count)>0) m_sc.SetBarStyle(count,nBar,m_nBarStyleOverlapping); /*************************///allocate and store a new timebar data object m_ptbData=new CScheduleTimeBarData; m_ptbData->m_lStatus=lStatID; m_ptbData->m_lWOID=lWOID; m_ptbData->m_lDateEnd=lDaysEnd; m_ptbData->m_lDateStart=lDaysStart; m_ptbData->m_lTimeEnd=lMinEnd; m_ptbData->m_lTimeStart=lMinStart; m_ptbData->m_lTechID=lTechID; //added o7/27/01 to accomodate multitech situation m_ptbData->m_nTechNumber=nMatchingTechNumber; m_ptbData->m_strDisplayData=strData;//from above m_ptbData->m_nID=arBar.Add(m_ptbData); m_nTotalAllocated++; }//end of ifbmatchingtech //pTimerSQL.Start(TRUE); //pTimerSQL.Stop(); }//END OF 4 TECHS FOR NEXT LOOP HERE }while(rs2->MoveForward()); } }while(bContinue); //release the recordsets no longer needed pTimerSQL.Start(FALSE); m_pApp->rsPool->ReleaseRS(&rs->m_nID); m_pApp->rsPool->ReleaseRS(&rs2->m_nID); m_pApp->rsPool->ReleaseRS(&rs3->m_nID); pTimerSQL.Stop(); //********************************************* //end of if(m_bRefresh...check }//if brefresh //--------------------------------------------------------------- //GET TIMING STATS //stop timer pTimerSQL.Stop(); pTimer.Stop();//overall timer //get this time in ms m_dLast=pTimerSQL.Elapsed(); m_dOverallTime=pTimer.Elapsed(); //add to average time m_dAverage+=m_dLast; //set lowest time if(m_dLast>m_dSlowest || m_dSlowest==0) m_dSlowest=m_dLast; //set fastest time if(m_dLastm_bDefSchedOneDay) { m_sc.SetDateStart(lDaysStart); m_sc.SetDateEnd(lDaysStart); } } //scroll over... m_sc.TimeScroll(lDaysStart,m_lUserStartHour*60); m_sc.ReDraw(FALSE); } void CScheduleFrm::OnDatetimechangeDtdate(NMHDR* pNMHDR, LRESULT* pResult) { FillView(); *pResult = 0; } void CScheduleFrm::OnBtnprint() { long lStart,lEnd; COleDateTime dtToday; COleDateTimeSpan dtSpan; //Get the date from the control m_dtDate.GetTime(dtToday); dtSpan=dtToday-m_dt1900; lStart=(long)dtSpan.GetTotalDays(); //end date days since 1900 dtSpan=dtToday-m_dt1900; lEnd=(long)dtSpan.GetTotalDays(); m_sc.SetDateStart(lStart); m_sc.SetDateEnd(lEnd); m_sc.PrintSchedule(); FillView(); } BEGIN_EVENTSINK_MAP(CScheduleFrm, CFormView) //{{AFX_EVENTSINK_MAP(CScheduleFrm) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 16 /* ItemMove */, OnItemMoveCtsched, VTS_I2 VTS_I2) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 4 /* BarDblClick */, OnBarDblClickCtsched, VTS_I2 VTS_I2) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 14 /* BarSizing */, OnBarSizingCtsched, VTS_I2 VTS_I2 VTS_I2 VTS_I4 VTS_I4 VTS_I4 VTS_I4) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 13 /* BarChanged */, OnBarChangedCtsched, VTS_I2 VTS_I2 VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 8 /* BarAdded */, OnBarAddedCtsched, VTS_I2 VTS_I2 VTS_BOOL VTS_BOOL) ON_EVENT(CScheduleFrm, IDC_CTSCHED, 2 /* BarRightClick */, OnBarRightClickCtsched, VTS_I2 VTS_I2) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() //MOUSE OVER void CScheduleFrm::OnItemMoveCtsched(short nIndex, short nBar) { //do nothing if in the middle of an update if(m_bUpdating) return; //in the process of an adjustment? if(!m_bLocked) return; //not a time bar? if(nBar==0) return; //same time bar as last time? //if((nBar==m_nOldBar) && (nIndex==m_nOldIndex)) return; /* if(m_nOldBar!=0) m_sc.SetBarText(m_nOldIndex,m_nOldBar,""); */ //m_nOldIndex=nIndex; // m_nOldBar=nBar; //m_sc.SetBarText(nIndex,nBar,"*"); //sets the public m_ptbData pointer to the correct record GetTimeBarObject(nIndex,nBar); //Bring to front to help with overlapping issue m_sc.BringToFront(nIndex,nBar); if(m_ptbData!=NULL) m_lblDetails.SetWindowText(m_ptbData->m_strDisplayData); } //open the workorder just double clicked void CScheduleFrm::OnBarDblClickCtsched(short nIndex, short nBar) { CString strWOID; //strWOID=GetWoIDFromTimeBar(nIndex,nBar); //sets the public m_ptbData pointer to the correct record GetTimeBarObject(nIndex,nBar); if(m_ptbData==NULL) return; strWOID.Format("%u",m_ptbData->m_lWOID); /* strWOID=m_sc.GetBarKeyID(nIndex,nBar); if(strWOID=="off") return; */ CWOHeaderDlg wo; wo.SetWorkorderID(strWOID); m_bUpdating=true; wo.DoModal(); FillView(); m_bRefresh=true; FillView(); m_bUpdating=false; } //show detailed times in top area to make //adjustments easier while moving or sizing a time bar void CScheduleFrm::OnBarSizingCtsched(short nIndex, short nBar, short nType, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd) { //do nothing if in the middle of an update if(m_bUpdating) return; COleDateTime dtStart, dtEnd; COleDateTimeSpan dtSpan; CString q; //convert start time dtSpan.SetDateTimeSpan(lDateStart,0,lTimeStart,0); dtStart=m_dt1900+dtSpan; //convert end time dtSpan.SetDateTimeSpan(lDateEnd,0,lTimeEnd,0); dtEnd=m_dt1900+dtSpan; q.Format("%s -> %s",dtStart.Format(VAR_TIMEVALUEONLY), dtEnd.Format(VAR_TIMEVALUEONLY), m_sc.GetBarKeyID(nIndex,nBar)); //VAR_TIMEVALUEONLY m_lblDetails.SetWindowText(q); } //Take a Schedule long date and long time value //set passed OleDateTime variable accordingly void CScheduleFrm::SchedToOleDT(long lSchedDateValue, long lSchedTimeValue, COleDateTime *dt) { COleDateTimeSpan dtSpan; dtSpan.SetDateTimeSpan(lSchedDateValue,0,lSchedTimeValue,0); *dt=m_dt1900+dtSpan; } //update the time and date and technician for this workorder //THIS FUNCTION NOW OBSOLETE (RIGHT CLICK REPLACES IT) //AND KEPT ONLY UNTIL CONFIRMED NOT REQUIRED //FOR SOME OTHER REASON IN FUTURE void CScheduleFrm::OnBarChangedCtsched(short nIndex, short nBar, LPCTSTR cKeyID, long lTimeStart, long lTimeEnd, long lDateStart, long lDateEnd) { //BUGBUG; //this routine is not working with new multi-tech changes if(m_bUndoing) return; Undo(nIndex,nBar); return; /* //do nothing if in the middle of an update if(m_bUpdating) return; if(m_bUndoing) return; //added 08/20/2001 - mouse over to confirm change was changing time bar selected m_bUpdating=true; if(m_ckLock.GetCheck()==TRUE) { } CString strTemp; CString strTechNumber; GetTimeBarObject(nIndex,nBar); if(m_ptbData==NULL) { m_bUpdating=false; return; } #ifdef MARTIN //MARTIN TEST TEST TEST strTemp.Format("Workorder %u has been changed - allow this?",m_ptbData->m_lWOID); if(AfxMessageBox(strTemp,MB_YESNO)==IDNO) { m_bUpdating=false; Undo(nIndex,nBar); return; } #endif m_ptbData->m_lDateStart=lDateStart; m_ptbData->m_lDateEnd=lDateEnd; m_ptbData->m_lTimeStart=lTimeStart; m_ptbData->m_lTimeEnd=lTimeEnd; CString q,strWOID; COleDateTime dtStart,dtEnd; COleDateTimeSpan dtSpan; //CWaitCursor wait; //convert start time dtSpan.SetDateTimeSpan(lDateStart,0,lTimeStart,0); dtStart=m_dt1900+dtSpan; //convert end time dtSpan.SetDateTimeSpan(lDateEnd,0,lTimeEnd,0); dtEnd=m_dt1900+dtSpan; //get workorder number // strWOID=GetWoIDFromTimeBar(nIndex,nBar); strWOID=m_sc.GetBarKeyID(nIndex,nBar); //******************** //handle multiple techs added 08/20/2001 switch (m_ptbData->m_nTechNumber) { case 1: strTechNumber="starttime"; break; case 2: strTechNumber="starttime2"; break; case 3: strTechNumber="starttime3"; break; case 4: strTechNumber="starttime4"; break; } //******************** q.Format("UPDATE wo SET wo.%s = #%s#, wo.stoptime = #%s# " "WHERE (((wo.id)=%u));",strTechNumber,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")),m_ptbData->m_lWOID); rs=m_pApp->rsPool->GetRS("OnBarChangedCtsched recordset"); rs->Ex(q); //ADDED 07/24/2001 AS IT WAS NOTICED THAT A DRAG CHANGE DOESN'T CATCH //THE FIRST TIME. rs->Close(); rs->QueryReadOnly("SELECT defaults.* FROM defaults;"); rs->Close(); m_pApp->rsPool->ReleaseRS(&rs->m_nID); m_bUpdating=false; //relock m_ckLock.SetCheck(TRUE); m_bLocked=true; m_bRefresh=true; FillView(); */ } //new workorder void CScheduleFrm::OnBarAddedCtsched(short nIndex, short nBar, BOOL bMouseBar, BOOL bKeyedBar) { //only proceed if added with the mouse if(!bMouseBar) return; //needed because fillview somehow //causes endless loop as it thinks all //bars added after first are moused for some obscure bug riddled reason if(bKeyedBar) return; long lSchedRndMinutes;//used for rounding to nearest quarter hour long lSchedRndHours;//used for rounding int x=m_pApp->Allowed(RWORKORDER,true); if(x!=1)//no write allowed { m_pApp->SecurityWarning(); return; } //pause the timer and other things m_bUpdating=true; COleDateTimeSpan dtSpan; CWOHeaderDlg wo; //Set the start date and time //round out to nearest quarter hour? if(m_pApp->m_bDefSchedRnd==true) { //get user selection //because it's only minutes set here first so that we can //split out hours and minutes for rounding dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), 0,m_sc.GetBarTimeStart(nIndex,nBar),0); //Get the hours and minutes lSchedRndMinutes=dtSpan.GetMinutes(); lSchedRndHours=dtSpan.GetHours(); RoundTime(&lSchedRndMinutes,&lSchedRndHours); //Set the time and date again dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), (int)lSchedRndHours,lSchedRndMinutes,0); } else { dtSpan.SetDateTimeSpan(m_sc.GetBarDateStart(nIndex,nBar), 0,m_sc.GetBarTimeStart(nIndex,nBar),0); } wo.m_oledtPresetStartDate=m_dt1900+dtSpan; //Set the end date and time //round out to nearest quarter hour? if(m_pApp->m_bDefSchedRnd==true) { //get user selection //because it's only minutes set here first so that we can //split out hours and minutes for rounding dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), 0,m_sc.GetBarTimeEnd(nIndex,nBar),0); //Get the hours and minutes lSchedRndMinutes=dtSpan.GetMinutes(); lSchedRndHours=dtSpan.GetHours(); RoundTime(&lSchedRndMinutes,&lSchedRndHours); //Set the time and date again dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), (int)lSchedRndHours,lSchedRndMinutes,0); } else { dtSpan.SetDateTimeSpan(m_sc.GetBarDateEnd(nIndex,nBar), 0,m_sc.GetBarTimeEnd(nIndex,nBar),0); } wo.m_oledtPresetEndDate=m_dt1900+dtSpan; //Set the tech wo.m_strSelTech=m_sc.GetListCargo(nIndex); //Do the workorder wo.DoModal(); m_bRefresh=true; FillView(); //release the timer and other functions m_bUpdating=false; } void CScheduleFrm::OnBarRightClickCtsched(short nIndex, short nBar) { //get a lock on things m_bUpdating=true; COleDateTime dtStart,dtEnd,dtOriginalStart,dtOriginalEnd; long lRed,lGreen,lBlue,lStatus,lWOID; CString strOriginalTech; CString strTech,strTechNumber,strDateNumber; bool bTechChange=false; bool bStatusChange=false; bool bDateChange=false; //strTech=m_sc.GetListCargo(nIndex); CString strStatus,q; //sets the public m_ptbData pointer to the correct record GetTimeBarObject(nIndex,nBar); //ASSERT(m_ptbData!=NULL); if(m_ptbData==NULL) return; strTechNumber.Format("%i",m_ptbData->m_nTechNumber); lWOID=m_ptbData->m_lWOID; strStatus.Format("%u",m_ptbData->m_lStatus); strOriginalTech.Format("%u",m_ptbData->m_lTechID); strTech=strOriginalTech; CDlgDispStatPopup d; //set start and end date values SchedToOleDT(m_ptbData->m_lDateStart,m_ptbData->m_lTimeStart,&dtStart); dtOriginalStart=dtStart; d.m_pdtStart=&dtStart; SchedToOleDT(m_ptbData->m_lDateEnd,m_ptbData->m_lTimeEnd,&dtEnd); dtOriginalEnd=dtEnd; d.m_pdtEnd=&dtEnd; d.m_pstrSelectedStatus=&strStatus; d.m_plRed=&lRed; d.m_plGreen=&lGreen; d.m_plBlue=&lBlue; d.m_pstrSelectedTech=&strTech; d.m_pstrSelectedTechNumber=&strTechNumber; //added for MASS 12/12/2001 d.m_strWOInfo=m_ptbData->m_strDisplayData; if(d.DoModal()==IDCANCEL)//user cancelled? { m_bUpdating=false; return; } lStatus=atol(strStatus); if(strTech!=strOriginalTech) bTechChange=true; if(lStatus!=m_ptbData->m_lStatus) bStatusChange=true; //check for differing date if(dtEnd!=dtOriginalEnd || dtStart!=dtOriginalStart) bDateChange=true; if(bStatusChange || bTechChange || bDateChange) { rs=m_pApp->rsPool->GetRS("CScheduleFrm::OnBarRightClickCtsched"); //Only do a status change if there is one. if(bStatusChange) { q.Format("Workorder %u\r\n\"%s\"\r\n\r\nStatus has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); if(AfxMessageBox(q,MB_YESNO)==IDYES) { q.Format("UPDATE wo SET wo.status = %u WHERE (((wo.id)=%u));" , lStatus, m_ptbData->m_lWOID); rs->Ex(q); rs->Close(); m_sc.SetBarBackColor(nIndex,nBar,RGB(lRed,lGreen,lBlue)); m_ptbData->m_lStatus=lStatus; } } //only do a tech change if there is one if(bTechChange || bDateChange) { if(bTechChange && bDateChange) { q.Format("Workorder %u\r\n\"%s\"\r\n\r\nDate and technician have changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); } else { if(bDateChange) q.Format("Workorder %u\r\n\"%s\"\r\n\r\nDate has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); else q.Format("Workorder %u\r\n\"%s\"\r\n\r\nAssigned technician has changed.\r\nWorkorder will now be updated - allow this?",m_ptbData->m_lWOID,m_ptbData->m_strDisplayData); } if(AfxMessageBox(q,MB_YESNO)==IDYES) { switch (m_ptbData->m_nTechNumber) { case 1: strTechNumber=""; break; case 2: strTechNumber="2"; break; case 3: strTechNumber="3"; break; case 4: strTechNumber="4"; break; } //updates date and time as well as tech at the same time either way q.Format("UPDATE wo SET wo.assigntech%s = %s, wo.starttime%s = #%s#, wo.stoptime%s = #%s# " "WHERE (((wo.id)=%u));" , strTechNumber,strTech, strTechNumber,dtStart.Format(_T("%m/%d/%Y %H:%M:%S")), strTechNumber,dtEnd.Format(_T("%m/%d/%Y %H:%M:%S")), m_ptbData->m_lWOID); rs->Ex(q); ///////////////////////////////////rs->Close(); m_ptbData->m_lTechID=atol(strTech); } } //axe the recordset m_pApp->rsPool->ReleaseRS(&rs->m_nID); } //release lock on things m_bUpdating=false; if(bTechChange || bStatusChange || bDateChange) { m_bRefresh=true; FillView(); /* //Added July 13th 2001 as refresh isn't catching the change m_bRefresh=true; FillView(); */ } } //go back a day void CScheduleFrm::OnBtnback() { Scroll(false); } //go ahead a day void CScheduleFrm::OnBtnforward() { Scroll(true); } void CScheduleFrm::Scroll(bool bForward) { COleDateTime dtStart; COleDateTimeSpan dtSpan; if(m_nDayWeekMonth==0)//1 day dtSpan.SetDateTimeSpan(1,0,0,0); else if(m_nDayWeekMonth==1)//one week dtSpan.SetDateTimeSpan(8,0,0,0); else if(m_nDayWeekMonth==2)//month dtSpan.SetDateTimeSpan(31,0,0,0); m_dtDate.GetTime(dtStart); if(bForward) dtStart=dtStart+dtSpan; else dtStart=dtStart-dtSpan; m_dtDate.SetTime(dtStart); FillView(); } void CScheduleFrm::ZoomClick(int nItem) { m_nDayWeekMonth=nItem; m_rdDay.SetCheck(FALSE); m_rdWeek.SetCheck(FALSE); m_rdMonth.SetCheck(FALSE); switch (m_nDayWeekMonth) { case 0: m_rdDay.SetCheck(TRUE); break; case 1: m_rdWeek.SetCheck(TRUE); break; default: m_rdMonth.SetCheck(TRUE); break; } m_bRefresh=true; FillView(); } void CScheduleFrm::OnRdday() { ZoomClick(0); } void CScheduleFrm::OnRdmonth() { ZoomClick(2); } void CScheduleFrm::OnRdweek() { ZoomClick(1); } //get the users set preferences for start and stop times //those values are used at the bottom of FillView to //set the schedule hours window displayed void CScheduleFrm::GetUserHoursPreferences() { CString q; q.Format("SELECT users.defschedstarthour, users.defschedstophour " "FROM users WHERE (((users.id)=%u));",m_pApp->m_lusrID); rs->QueryReadOnly(q); rs->FetchField("defschedstarthour",&m_lUserStartHour); rs->FetchField("defschedstophour",&m_lUserStopHour); } //set public pointer to time bar object in question //sets to NULL if not found which currently only //asserts, no other checking done. void CScheduleFrm::GetTimeBarObject(short nIndex, short nBar) { int x; int nComma=0,nLeft,nRight; bool bNoMatch=true; long lWOID; int nTechNumber; CString strWOID=m_sc.GetBarKeyID(nIndex,nBar); ASSERT(!strWOID.IsEmpty()); if(strWOID=="off") //added 07/24/01 to accomodate time off bars { m_ptbData=NULL;//indicates not a regular time bar return; } nComma=strWOID.Find(','); if(nComma!=-1) { nLeft=nComma; nRight=strWOID.GetLength()-nComma-1; lWOID=atol(strWOID.Left(nLeft)); nTechNumber=atoi(strWOID.Right(nRight)); ASSERT(lWOID!=0); //default signalling not a regular time bar m_ptbData=NULL; for(x=0;xm_lWOID==lWOID && m_ptbData->m_nTechNumber==nTechNumber) { bNoMatch=false; break; } } } if(bNoMatch) m_ptbData=NULL;//added 07/24/01 to handle non-wo time bars for now } //Force a refresh void CScheduleFrm::OnBtnrefresh() { //m_bRefresh=true; //FillView(); KillTimer(1); m_bRefresh=true; FillView(); //AUTOREFRESH TIMER if(m_pApp->m_lSchedRefreshSecs!=0) m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); //m_nTimer = SetTimer(1, 6000, 0); m_bTimerIsActive=true; } void CScheduleFrm::OnCKLOCk() { // TODO: Add your control notification handler code here m_bLocked=m_ckLock.GetCheck() ? true:false; } void CScheduleFrm::Undo(short nIndex, short nBar) { m_bUndoing=true; GetTimeBarObject(nIndex,nBar); //ADDED O7/24/2001 TO HANDLE SPECIAL TIME BARS if(m_ptbData==NULL) { m_bUndoing=false; m_bRefresh=true; FillView(); return; } m_sc.SetBarDateStart(nIndex,nBar,m_ptbData->m_lDateStart); m_sc.SetBarDateEnd(nIndex,nBar,m_ptbData->m_lDateEnd); m_sc.SetBarTimeStart(nIndex,nBar,m_ptbData->m_lTimeStart); m_sc.SetBarTimeEnd(nIndex,nBar,m_ptbData->m_lTimeEnd); m_bUndoing=false; } //Modify layout to accomodate different windows sizes void CScheduleFrm::LayoutControls() { if(m_bLayoutDone) return; CRect rectMain, rectCtl; GetWindowRect(rectMain); //this is the start of the window in question int nOffset=rectMain.top; int nLastBottom,nTopOfBottomRow; int nHeight; m_lblDetails.GetWindowRect(rectCtl); rectCtl.right=rectMain.right-50; rectCtl.top-=nOffset; rectCtl.bottom-=nOffset; m_lblDetails.MoveWindow(rectCtl,TRUE); m_sc.GetWindowRect(rectCtl); rectCtl.right=rectMain.right-50; rectCtl.top-=nOffset; rectCtl.bottom=rectMain.bottom-85-nOffset; m_sc.MoveWindow(rectCtl,TRUE); nLastBottom=rectCtl.bottom; m_ckLock.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nLastBottom+1; rectCtl.bottom=rectCtl.top+nHeight; m_ckLock.MoveWindow(rectCtl,TRUE); m_lblStartDate.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nLastBottom+5; //preserve for other controls along bottom nTopOfBottomRow=rectCtl.top; rectCtl.bottom=rectCtl.top+nHeight; m_lblStartDate.MoveWindow(rectCtl,TRUE); nLastBottom=rectCtl.bottom; m_dtDate.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nLastBottom+1; rectCtl.bottom=rectCtl.top+nHeight; m_dtDate.MoveWindow(rectCtl,TRUE); m_lblZone.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nTopOfBottomRow; rectCtl.bottom=rectCtl.top+nHeight; m_lblZone.MoveWindow(rectCtl,TRUE); m_cbZone.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nLastBottom+1; rectCtl.bottom=rectCtl.top+nHeight; m_cbZone.MoveWindow(rectCtl,TRUE); m_lblView.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.top=nTopOfBottomRow; rectCtl.bottom=rectCtl.top+nHeight; m_lblView.MoveWindow(rectCtl,TRUE); nLastBottom=rectCtl.bottom; m_rdDay.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom-7; rectCtl.top=rectCtl.bottom-nHeight; m_rdDay.MoveWindow(rectCtl,TRUE); m_rdMonth.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom-7; rectCtl.top=rectCtl.bottom-nHeight; m_rdMonth.MoveWindow(rectCtl,TRUE); m_rdWeek.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom-7; rectCtl.top=rectCtl.bottom-nHeight; m_rdWeek.MoveWindow(rectCtl,TRUE); m_btnBack.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom; rectCtl.top=rectCtl.bottom-nHeight; m_btnBack.MoveWindow(rectCtl,TRUE); m_btnForward.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom; rectCtl.top=rectCtl.bottom-nHeight; m_btnForward.MoveWindow(rectCtl,TRUE); m_btnRefresh.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom; rectCtl.top=rectCtl.bottom-nHeight; m_btnRefresh.MoveWindow(rectCtl,TRUE); m_btnPrint.GetWindowRect(rectCtl); nHeight=rectCtl.Height(); rectCtl.bottom=nLastBottom; rectCtl.top=rectCtl.bottom-nHeight; m_btnPrint.MoveWindow(rectCtl,TRUE); //only execute once m_bLayoutDone=true; } void CScheduleFrm::ClearTimeBarObjects() { //delete all arBar objects int x; if(m_nTotalAllocated>0) { for(x=0;xrsPool->GetRS("CScheduleFrm::FillZoneList()"); //fill ZONES m_cbZone.Clear(); m_cbZone.AddRow(" < All Techs >","0"); q="SELECT zones.id, zones.name FROM zones ORDER BY zones.name;"; rs->QueryReadOnly(q); if(!rs->IsEmpty()) { do { rs->FetchField("name",&strData); strData+=" zone"; rs->FetchField("id",&lData); strIndex.Format("%u",lData); m_cbZone.AddRow(strData,strIndex); }while(rs->MoveForward()); } //Fill groups q="SELECT schdgrps.id, schdgrps.name FROM schdgrps ORDER BY schdgrps.name;"; rs->QueryReadOnly(q); if(!rs->IsEmpty()) { do { rs->FetchField("name",&strData); strData+=" group"; rs->FetchField("id",&lData); strIndex.Format("%u",lData); m_cbZone.AddRow(strData,strIndex); }while(rs->MoveForward()); } //------------------------------------------------ m_pApp->rsPool->ReleaseRS(&rs->m_nID); m_cbZone.SetCurSel(0); } void CScheduleFrm::OnCloseupCbzone() { CString strData,strID; strID=m_cbZone.GetCurrentRowID(); strData=m_cbZone.GetCurrentRowText(); if(strData.Right(4)=="zone" || strID=="0") m_bZoneView=true; else m_bZoneView=false;//by group m_bRefresh=true; FillView(); } void CScheduleFrm::OnTimer(UINT nIDEvent) { if(nIDEvent==1 && !m_bUpdating) { KillTimer(1); m_bRefresh=true; FillView(); //AUTOREFRESH TIMER if(m_pApp->m_lSchedRefreshSecs!=0) m_nTimer = SetTimer(1, 1000*m_pApp->m_lSchedRefreshSecs, 0); //m_nTimer = SetTimer(1, 6000, 0); m_bTimerIsActive=true; } CFormView::OnTimer(nIDEvent); } //round minutes to nearest quarter hour void CScheduleFrm::RoundTime(long *lMinutes, long* lHours) { if(*lMinutes==0) return; if(*lMinutes==15) return; if(*lMinutes==30) return; if(*lMinutes==45) return; //FIRST QUARTER //0-7 = 0 if(*lMinutes>0 && *lMinutes<8) { *lMinutes=0; return; } //8-14 = 15 if(*lMinutes>7 && *lMinutes < 15) { *lMinutes=15; return; } //SECOND QUARTER //16-22 = 15 if(*lMinutes>15 && *lMinutes < 23) { *lMinutes=15; return; } //23-29 = 30 if(*lMinutes>22 && *lMinutes < 30) { *lMinutes=30; return; } //THIRD QUARTER //31 - 37= 30 if(*lMinutes>30 && *lMinutes < 38) { *lMinutes=30; return; } //38-44 = 45 if(*lMinutes>37 && *lMinutes < 45) { *lMinutes=45; return; } //FOURTH QUARTER //46 - 52 = 45 if(*lMinutes>45 && *lMinutes < 53) { *lMinutes=45; return; } //53-59 = 0 if(*lMinutes>52 && *lMinutes < 60) { *lMinutes=0; *lHours=*lHours+1; return; } } BOOL CScheduleFrm::OnHelpInfo(HELPINFO* pHelpInfo) { WinHelp (0x00020000 + IDD_SCHEDULEFRM_FORM,HELP_CONTEXT); return TRUE; } void CScheduleFrm::CleanupForExit(void) { } void CScheduleFrm::OnDestroy() { KillTimer(1); ClearTimeBarObjects(); CFormView::OnDestroy(); // TODO: Add your message handler code here }