Files
ayanova7/archive/ayanova 1.9.4 CE final release db schema 171/sp/ScheduleFrm.cpp

2106 lines
56 KiB
C++

// 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 <stdlib.h>
#include <crtdbg.h>
#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);//<<<<<<<<<<<<<ORIGINAL
m_nBarStyleOverlapping=m_sc.AddBarStyle(8,-5);//<<<<<<<<<<<<<
m_sc.SetStyleStartImage(m_nBarStyleOverlapping,-8);
m_sc.SetStyleEndImage(m_nBarStyleOverlapping,-8);
//added 07/24/2001 to accomodate time off bar style
m_nBarStyleTimeOff=m_sc.AddBarStyle(14,3);//<<<<<<<<<<<<<<<<<<<<<
//added 07/24/2001 to accomodate all day milestone description
m_nBarStyleAllDayText=m_sc.AddBarStyle(20,0);
m_sc.SetStyleMilestone(m_nBarStyleAllDayText,TRUE);
m_sc.SetStyleStartImage(m_nBarStyleAllDayText,-11);
// FillZoneList();
//FillView();
arBar.SetSize(100,10);
}
void CScheduleFrm::FillView()
{
m_bShowProblemDetailsInStatusDisplay=true;
int nCounter;
pTimer.Start(TRUE);
LayoutControls();
CString q,strWOID;
CString strData,strClient,strProjectName, strTemp;
COleDateTime dtStart,dtEnd,dtSchedStart,dtSchedEnd,dtTemp,dtTimeScrollStart;
COleDateTimeSpan dtSpan,dtSpanMinutes,dtSpanDays;
long lWindowSize;
lWindowSize=m_pApp->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_dLast<m_dFastest || m_dFastest==0)
m_dFastest=m_dLast;
strTemp.Format("Refresh query time stats (seconds)\r\n"
"[Overall time:%.3f, Non_db time:%.3f] "
"[DB times: Last:%.3f, Slowest: %.3f, Fastest:%.3f, Average:%.3f]",
m_dOverallTime,m_dOverallTime-m_dLast,
m_dLast,m_dSlowest, m_dFastest,
m_dAverage/(double)m_uiRefreshCount);
//m_lblDetails.SetWindowText(strTemp); //<------------un-remark to show stats
//---------------------------------------------------------------
//scroll the view into place:
//TimeScrollBar date days since 1900
dtSpan=dtStart-m_dt1900;
lDaysStart=(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,1);
dtSpan=dtStart-dtTemp;
lMinStart = (long) dtSpan.GetTotalMinutes();
GetUserHoursPreferences();
if(m_sc.GetTimeType()==0)
{
m_sc.SetTimeStart(m_lUserStartHour*60);
m_sc.SetTimeEnd(m_lUserStopHour*60);
if(m_pApp->m_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;x<m_nTotalAllocated;x++)
{
m_ptbData=(CScheduleTimeBarData*)arBar.GetAt(x);
if(m_ptbData->m_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;x<m_nTotalAllocated;x++)
{
m_ptbData=(CScheduleTimeBarData*)arBar.GetAt(x);
delete m_ptbData;
}
}
arBar.RemoveAll();
//allocate as many as last time for efficiency
// arBar.SetSize(m_nTotalAllocated,1);
m_nTotalAllocated=0;
}
void CScheduleFrm::FillZoneList()
{
CString q, strData,strIndex;
long lData;
rs=m_pApp->rsPool->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
}