Files

2276 lines
54 KiB
C++

// PM.cpp : implementation file
//
#include "stdafx.h"
#include "sp.h"
#include "PM.h"
#include "SimpleDate.h"
#include "PartsDlg.h"
#include "WOTypesDlg.h"
#include "ProjectsDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPM dialog
CPM::CPM(CWnd* pParent /*=NULL*/)
: CDialog(CPM::IDD, pParent)
, m_bResave(false)
{
//{{AFX_DATA_INIT(CPM)
//}}AFX_DATA_INIT
m_pApp= (CSpApp*)AfxGetApp();
/*
rs=new GZRset("Error: PM dialog");
rs->SetConnect(m_pApp->strConnectString);
cbrs=new GZRset("Error: PM dialog cbRS");
cbrs->SetConnect(m_pApp->strConnectString);
*/
//Initialize recordset pointer
rs=m_pApp->rsPool->GetRS("CPM (RS)");
cbrs=m_pApp->rsPool->GetRS("CPM (cbrs)");
m_strSelectedTech.Empty();
m_bAddMode=false;
m_bEditing=false;
}
void CPM::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPM)
DDX_Control(pDX, IDC_LBL_SERIES, m_lblSeries);
DDX_Control(pDX, IDC_ED_SERIES, m_edSeries);
DDX_Control(pDX, IDC_LBLTIME5, m_lblTime5);
DDX_Control(pDX, IDC_LBLTIME4, m_lblTime4);
DDX_Control(pDX, IDC_EDTIMEREPEATEVERYWEEKS, m_edTimeRepeatEveryWeeks);
DDX_Control(pDX, IDC_EDTIMEREPEATEVERYDAYS, m_edTimeRepeatEveryDays);
DDX_Control(pDX, IDC_CBCATEGORY, m_cbCategories);
DDX_Control(pDX, IDC_LBLTYPE, m_lblType);
DDX_Control(pDX, IDC_LBLPROJECT, m_lblProject);
DDX_Control(pDX, IDC_CKQUICK, m_ckQuick);
DDX_Control(pDX, IDC_CKONSITE, m_ckOnsite);
DDX_Control(pDX, IDC_CBPROJECTS, m_cbProjects);
DDX_Control(pDX, IDC_BTNEDIT, m_btnEdit);
DDX_Control(pDX, IDC_CKHOLD, m_ckHold);
DDX_Control(pDX, IDC_LBLQUANT, m_lblQuant);
DDX_Control(pDX, IDC_LBLPARTSLIST, m_lblPartsList);
DDX_Control(pDX, IDC_LBLPART, m_lblPart);
DDX_Control(pDX, IDC_LBPARTSREQ, m_lbParts);
DDX_Control(pDX, IDC_EDQUANTITY, m_edPartQuantity);
DDX_Control(pDX, IDC_BTNREMOVEPART, m_btnRemovePart);
DDX_Control(pDX, IDC_BTNADDPART, m_btnAddPart);
DDX_Control(pDX, IDC_CBPARTS, m_cbParts);
DDX_Control(pDX, IDC_RDTIME, m_rdTime);
DDX_Control(pDX, IDC_RDMETRIC, m_rdMetric);
DDX_Control(pDX, IDC_RDAGE, m_rdAge);
DDX_Control(pDX, IDC_LBLTIME3, m_lblTime3);
DDX_Control(pDX, IDC_LBLTIME2, m_lblTime2);
DDX_Control(pDX, IDC_LBLTIME1, m_lblTime1);
DDX_Control(pDX, IDC_LBLTECH, m_lblTech);
DDX_Control(pDX, IDC_LBLPMLIST, m_lblPMList);
DDX_Control(pDX, IDC_LBLMETER4, m_lblMeter4);
DDX_Control(pDX, IDC_LBLMETER3, m_lblMeter3);
DDX_Control(pDX, IDC_LBLMETER2, m_lblMeter2);
DDX_Control(pDX, IDC_LBLMETER1, m_lblMeter1);
DDX_Control(pDX, IDC_LBLDAYOFWEEK, m_lblDayOfWeek);
DDX_Control(pDX, IDC_LBLCONVERTMETER, m_lblConvertMeter);
DDX_Control(pDX, IDC_LBLCONVERTDAYS, m_lblConvertDays);
DDX_Control(pDX, IDC_LBLAGE5, m_lblAge5);
DDX_Control(pDX, IDC_LBLAGE4, m_lblAge4);
DDX_Control(pDX, IDC_LBLAGE3, m_lblAge3);
DDX_Control(pDX, IDC_LBLAGE2, m_lblAge2);
DDX_Control(pDX, IDC_LBLAGE1, m_lblAge1);
DDX_Control(pDX, IDC_EDTIMEREPEATEVERYMONTHS, m_edTimeRepeatEveryMonths);
DDX_Control(pDX, IDC_EDNOTES, m_edNotes);
DDX_Control(pDX, IDC_EDMETERREPEAT, m_edMeterRepeat);
DDX_Control(pDX, IDC_EDMETERLASTREADING, m_edMeterLastReading);
DDX_Control(pDX, IDC_EDMETERFIRSTSERVICE, m_edMeterFirstService);
DDX_Control(pDX, IDC_EDDESCRIPTION, m_edDescription);
DDX_Control(pDX, IDC_EDCONVERTTOWOAFTER, m_edConvertToWoAfter);
DDX_Control(pDX, IDC_EDAGEYRS, m_edAgeYears);
DDX_Control(pDX, IDC_EDAGEREPEAT, m_edAgeRepeat);
DDX_Control(pDX, IDC_EDAGEMONTHS, m_edAgeMonths);
DDX_Control(pDX, IDC_DTTIMENEXTSERVICEDATE, m_dtTimeNextServiceDate);
DDX_Control(pDX, IDC_DTAGEFIRSTSERVICEDATE, m_dtAgeFirstServiceDate);
DDX_Control(pDX, IDC_CKAUTOWO, m_ckAutoWO);
DDX_Control(pDX, IDC_CKAUTOREPEAT, m_ckAutoRepeat);
DDX_Control(pDX, IDC_CBTECH, m_cbTech);
DDX_Control(pDX, IDC_CBPMLIST, m_cbPMList);
DDX_Control(pDX, IDC_CBDAYOFWEEK, m_cbDayOfWeek);
DDX_Control(pDX, IDC_BTNDONE, m_btnDone);
DDX_Control(pDX, IDC_BTNDELETE, m_btnDelete);
DDX_Control(pDX, IDC_BTNCLONE, m_btnClone);
DDX_Control(pDX, IDC_BTNADD, m_btnAdd);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_LBL_START_TIME, m_lblStartTime);
DDX_Control(pDX, IDC_LBL_END_TIME, m_lblEndTime);
DDX_Control(pDX, IDC_DTSTART, m_dtStartTime);
DDX_Control(pDX, IDC_DTEND, m_dtEndtime);
}
BEGIN_MESSAGE_MAP(CPM, CDialog)
//{{AFX_MSG_MAP(CPM)
ON_BN_CLICKED(IDC_RDAGE, OnRdage)
ON_BN_CLICKED(IDC_RDMETRIC, OnRdmetric)
ON_BN_CLICKED(IDC_RDTIME, OnRdtime)
ON_BN_CLICKED(IDC_BTNDONE, OnBtndone)
ON_BN_CLICKED(IDC_CKAUTOREPEAT, OnCkautorepeat)
ON_BN_CLICKED(IDC_CKAUTOWO, OnCkautowo)
ON_BN_CLICKED(IDC_BTNADD, OnBtnadd)
ON_CBN_CLOSEUP(IDC_CBPMLIST, OnCloseupCbpmlist)
ON_BN_CLICKED(IDC_BTNADDPART, OnBtnaddpart)
ON_BN_CLICKED(IDC_BTNREMOVEPART, OnBtnremovepart)
ON_BN_CLICKED(IDC_BTNEDIT, OnBtnedit)
ON_BN_CLICKED(IDC_BTNDELETE, OnBtndelete)
ON_EN_KILLFOCUS(IDC_EDAGEYRS, OnKillfocusEdageyrs)
ON_EN_KILLFOCUS(IDC_EDAGEMONTHS, OnKillfocusEdagemonths)
ON_EN_KILLFOCUS(IDC_EDMETERLASTREADING, OnKillfocusEdmeterlastreading)
ON_BN_CLICKED(IDC_CKQUICK, OnCkquick)
ON_BN_CLICKED(IDC_LBLPART, OnLblpart)
ON_BN_CLICKED(IDC_LBLPROJECT, OnLblproject)
ON_BN_CLICKED(IDC_LBLTYPE, OnLbltype)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPM message handlers
CPM::~CPM()
{
m_pApp->rsPool->ReleaseRS(&rs->m_nID);
m_pApp->rsPool->ReleaseRS(&cbrs->m_nID);
}
BOOL CPM::OnInitDialog()
{
CDialog::OnInitDialog();
//1.9.4.4
m_edDescription.SetLimitText(50);
Security();
//make "hyperlinks"
m_lblPart.SetTextColor(RGB(0,0,255));
m_lblPart.SetFontUnderline(TRUE);
m_lblPart.SetLink(TRUE);
m_lblPart.SetLinkCursor(m_pApp->hcHand);
m_lblPart.SetLinkURL("");
m_lblType.SetTextColor(RGB(0,0,255));
m_lblType.SetFontUnderline(TRUE);
m_lblType.SetLink(TRUE);
m_lblType.SetLinkCursor(m_pApp->hcHand);
m_lblType.SetLinkURL("");
m_lblProject.SetTextColor(RGB(0,0,255));
m_lblProject.SetFontUnderline(TRUE);
m_lblProject.SetLink(TRUE);
m_lblProject.SetLinkCursor(m_pApp->hcHand);
m_lblProject.SetLinkURL("");
m_bReschedule=false;
m_bReadOnly=false;
EnableFields(false);
SetWindowText(m_strPrompt);
m_bAutoRepeat=false;
m_bAutoWO=false;
m_nCurrentMode=-1;//signifies no selection
ASSERT(!m_strCriteria.IsEmpty());//would mean no criteria was passed
if(m_strCriteria.IsEmpty())
{
AfxMessageBox("Error in PM dialog, no Model or Client criteria.");
CDialog::OnCancel();
}
FillPartsList();
FillTechList();
FillProjectList();
FillTypeList();
FillPMList();
if(m_bResave)
{
OnBtnedit();//edit
OnBtnadd();//save
OnBtndone();//exit
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//handle a click on a radio button
//0=time based, 1=metric, 2=age
void CPM::GroupClick(int nClicked)
{
m_rdAge.SetCheck(FALSE);
m_rdMetric.SetCheck(FALSE);
m_rdTime.SetCheck(FALSE);
switch (nClicked)
{
case 0:
m_rdTime.SetCheck(TRUE);
break;
case 1:
m_rdMetric.SetCheck(TRUE);
break;
default:
m_rdAge.SetCheck(TRUE);
break;
}
m_nCurrentMode=nClicked;
SwitchMode();
}
void CPM::OnRdage()
{
if(m_bClientMode)
{
AfxMessageBox("You can't schedule by Age for a client!\r\nOnly a unit.");
return;
}
CString q;
if(!m_bModel)
{
//Look up the purchase date and abort if none entered
q.Format("SELECT units.purchasedate "
"FROM units "
"WHERE (((units.id)=%s));",m_strCriteria);
cbrs->Query(q);
if(cbrs->IsEmpty())
{
AfxMessageBox("There is no purchase date set for this unit.\r\n"
"It can't be scheduled by age. Check the unit record.");
//theory is that this will change back to previous
//whatever was set since we haven't groupclicked yet.
SwitchMode();
return;
}
cbrs->FetchField("purchasedate",&m_dtUnitPurchasedDate);
q.Format(
"According to this unit's record, it was purchased on: %s.\r\n\r\n"
"This date will be used for age calculation when scheduling.\r\n"
"If this date was entered incorrectly, you can change it by\r\n"
"editing this unit's record. Then reschedule here.",m_dtUnitPurchasedDate.Format(VAR_DATEVALUEONLY));
AfxMessageBox(q,MB_OK);
}
GroupClick(2);
}
void CPM::OnRdmetric()
{
GroupClick(1);
}
void CPM::OnRdtime()
{
GroupClick(0);
}
//Presets for form.
void CPM::PreInitialize(bool bClientMode, bool bModel, CString strCriteria, CString strPrompt,bool bResave)
{
m_strCriteria = strCriteria;
m_bClientMode=bClientMode;
m_bModel=bModel;
m_strPrompt=strPrompt;
m_bResave=bResave;
}
//mostly for security or no record situations
void CPM::EnableFields(bool bEnable)
{
if(m_bReadOnly) return;
if(m_bReadOnlySecurity==true && bEnable==true) return;
BOOL enable=bEnable ? TRUE : FALSE;
//m_btnDelete.EnableWindow(enable);
//m_btnEdit.EnableWindow(enable);
//m_btnClone.EnableWindow(enable);
m_cbDayOfWeek.EnableWindow(enable);
m_dtStartTime.EnableWindow(enable);
m_dtEndtime.EnableWindow(enable);
m_cbTech.EnableWindow(enable);
m_ckAutoRepeat.EnableWindow(enable);
m_ckAutoWO.EnableWindow(enable);
m_ckHold.EnableWindow(enable);
m_dtAgeFirstServiceDate.EnableWindow(enable);
m_dtTimeNextServiceDate.EnableWindow(enable);
m_edAgeMonths.EnableWindow(enable);
m_edAgeRepeat.EnableWindow(enable);
m_edAgeYears.EnableWindow(enable);
m_edConvertToWoAfter.EnableWindow(enable);
m_edDescription.EnableWindow(enable);
m_edMeterFirstService.EnableWindow(enable);
m_edMeterLastReading.EnableWindow(TRUE);
m_edMeterRepeat.EnableWindow(enable);
m_edNotes.EnableWindow(enable);
m_edTimeRepeatEveryMonths.EnableWindow(enable);
m_edTimeRepeatEveryWeeks.EnableWindow(enable);
m_edTimeRepeatEveryDays.EnableWindow(enable);
m_edSeries.EnableWindow(enable);
//Hide the workorder specifics
m_ckOnsite.EnableWindow(enable);
m_ckQuick.EnableWindow(enable);
m_cbProjects.EnableWindow(enable);
m_cbCategories.EnableWindow(enable);
m_rdTime.EnableWindow(enable);
m_rdAge.EnableWindow(enable);
m_rdMetric.EnableWindow(enable);
//age and meter can only be activated if it's
//not client based
if(m_bClientMode)
{
m_rdAge.EnableWindow(FALSE);
m_rdMetric.EnableWindow(FALSE);
}
m_btnAddPart.EnableWindow(enable);
m_btnRemovePart.EnableWindow(enable);
m_cbParts.EnableWindow(enable);
m_edPartQuantity.EnableWindow(enable);
}
void CPM::OnBtndone()
{
CDialog::OnOK();
}
//change display based on type of p.m.
void CPM::SwitchMode()
{
BOOL wofields;
BOOL partsfields=m_bQuick ? FALSE : TRUE;
//don't display the parts fields if adding a record
if(m_bAddMode) partsfields=FALSE;
wofields=m_bAutoWO ? TRUE : FALSE;
if(m_bReadOnly || m_nCurrentMode==-1) return;
//Hide everything first
//Hide the workorder specifics
m_lblType.ShowWindow(wofields);
m_lblProject.ShowWindow(wofields);
m_ckOnsite.ShowWindow(wofields);
if(m_bClientMode)
m_ckQuick.ShowWindow(wofields);
else
m_ckQuick.ShowWindow(FALSE);
m_cbProjects.ShowWindow(wofields);
m_cbCategories.ShowWindow(wofields);
//Parts fields only display on standard workorder
m_btnAddPart.ShowWindow(partsfields);
m_btnRemovePart.ShowWindow(partsfields);
m_cbParts.ShowWindow(partsfields);
m_edPartQuantity.ShowWindow(partsfields);
m_lbParts.ShowWindow(partsfields);
m_lblPart.ShowWindow(partsfields);
m_lblPartsList.ShowWindow(partsfields);
m_lblQuant.ShowWindow(partsfields);
//Hide the time based fields:
m_dtTimeNextServiceDate.ShowWindow(FALSE);
m_edTimeRepeatEveryMonths.ShowWindow(FALSE);
m_edTimeRepeatEveryWeeks.ShowWindow(FALSE);
m_edTimeRepeatEveryDays.ShowWindow(FALSE);
m_lblTime1.ShowWindow(FALSE);
m_lblTime2.ShowWindow(FALSE);
m_lblTime3.ShowWindow(FALSE);
m_lblTime4.ShowWindow(FALSE);
m_lblTime5.ShowWindow(FALSE);
//Hide the meter based fields
m_edMeterFirstService.ShowWindow(FALSE);
m_edMeterLastReading.ShowWindow(FALSE);
m_edMeterRepeat.ShowWindow(FALSE);
m_lblMeter1.ShowWindow(FALSE);
m_lblMeter2.ShowWindow(FALSE);
m_lblMeter3.ShowWindow(FALSE);
m_lblMeter4.ShowWindow(FALSE);
//Hide the AGE based fields
m_dtAgeFirstServiceDate.ShowWindow(FALSE);
m_edAgeMonths.ShowWindow(FALSE);
m_edAgeYears.ShowWindow(FALSE);
m_edAgeRepeat.ShowWindow(FALSE);
m_lblAge1.ShowWindow(FALSE);
m_lblAge2.ShowWindow(FALSE);
m_lblAge3.ShowWindow(FALSE);
m_lblAge4.ShowWindow(FALSE);
m_lblAge5.ShowWindow(FALSE);
m_lblConvertDays.ShowWindow(FALSE);
m_lblConvertMeter.ShowWindow(FALSE);
// m_lblConvert.ShowWindow(m_bAutoWO ? TRUE : FALSE);
m_edConvertToWoAfter.ShowWindow(m_bAutoWO ? TRUE : FALSE);
//HIDE THE series controls
m_lblSeries.ShowWindow(FALSE);
m_edSeries.ShowWindow(FALSE);
switch (m_nCurrentMode)
{
//TIME BASED
case 0: //time interval based
m_dtTimeNextServiceDate.ShowWindow(TRUE);
m_lblTime1.ShowWindow(TRUE);
if(m_bAutoRepeat)
{
m_edTimeRepeatEveryMonths.ShowWindow(TRUE);
m_edTimeRepeatEveryWeeks.ShowWindow(TRUE);
m_edTimeRepeatEveryDays.ShowWindow(TRUE);
m_lblTime2.ShowWindow(TRUE);
m_lblTime3.ShowWindow(TRUE);
m_lblTime4.ShowWindow(TRUE);
m_lblTime5.ShowWindow(TRUE);
m_lblSeries.ShowWindow(TRUE);
m_edSeries.ShowWindow(TRUE);
}
if(m_bAutoWO)
m_lblConvertDays.ShowWindow(TRUE);
break;
//METER BASED
case 1:
m_edMeterFirstService.ShowWindow(TRUE);
m_edMeterLastReading.ShowWindow(TRUE);
m_lblMeter1.ShowWindow(TRUE);
m_lblMeter4.ShowWindow(TRUE);
if(m_bAutoRepeat)
{
m_edMeterRepeat.ShowWindow(TRUE);
m_lblMeter2.ShowWindow(TRUE);
m_lblMeter3.ShowWindow(TRUE);
m_lblSeries.ShowWindow(TRUE);
m_edSeries.ShowWindow(TRUE);
}
if(m_bAutoWO)
m_lblConvertMeter.ShowWindow(TRUE);
break;
//AGE BASED
default:
m_dtAgeFirstServiceDate.ShowWindow(TRUE);
m_edAgeMonths.ShowWindow(TRUE);
m_edAgeYears.ShowWindow(TRUE);
m_lblAge1.ShowWindow(TRUE);
m_lblAge2.ShowWindow(TRUE);
m_lblAge3.ShowWindow(TRUE);
if(m_bAutoRepeat)
{
m_lblAge4.ShowWindow(TRUE);
m_lblAge5.ShowWindow(TRUE);
m_edAgeRepeat.ShowWindow(TRUE);
m_lblSeries.ShowWindow(TRUE);
m_edSeries.ShowWindow(TRUE);
}
if(m_bAutoWO)
m_lblConvertDays.ShowWindow(TRUE);
//don't bother displaying the next service date
//since this is a model which doesn't apply
if(m_bModel)
{
m_dtAgeFirstServiceDate.ShowWindow(FALSE);
m_lblAge3.ShowWindow(FALSE);
}
break;
}
}
void CPM::OnCkautorepeat()
{
m_bAutoRepeat=m_ckAutoRepeat.GetCheck() ? true : false;
SwitchMode();
}
void CPM::OnCkautowo()
{
m_bAutoWO = m_ckAutoWO.GetCheck() ? true : false;
SwitchMode();
}
void CPM::FillPartsList()
{
CString strData;
CString strIndex;
long lData;
m_cbParts.Clear();
cbrs->Query("SELECT parts.id, [partnumber] & \" - \" "
"& [description] AS name FROM parts "
"ORDER BY parts.partnumber;");
if(cbrs->IsEmpty())
return;
cbrs->MoveFirst();
do
{
cbrs->FetchField("name",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbParts.AddRow(strData,strIndex);
}while(cbrs->MoveForward());
m_cbParts.SetCurSel(0);
}
void CPM::FillPMList()
{
CString strData,strType,q;
CString strIndex,strModel;
long lData;
m_cbPMList.Clear();
if(m_bClientMode)
strType="True";
else
strType="False";
strModel=m_bModel ? "true" : "false";
//select all schedule records for this
//client or unit model
q.Format("SELECT pmhead.* FROM pmhead "
"WHERE (((pmhead.link)=%s) AND ((pmhead.isclient)=%s) AND ((pmhead.ismodel)=%s)) ORDER BY pmhead.description;",m_strCriteria,strType,strModel);
//m_pApp->ShowStuff(q);
rs->Query(q);
if(rs->IsEmpty())
{
m_bNoRecord=true;
m_btnDelete.EnableWindow(FALSE);
m_btnEdit.EnableWindow(FALSE);
ClearFields();
EnableFields(false);
return;
}
m_bNoRecord=false;
m_btnDelete.EnableWindow(TRUE);
m_btnEdit.EnableWindow(TRUE);
rs->MoveFirst();
do
{
rs->FetchField("description",&strData);
rs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbPMList.AddRow(strData,strIndex);
}while(rs->MoveForward());
//pretend user has selected so that other fields get filled in
if(m_strSelectedPM.IsEmpty()) //first time in
{
m_cbPMList.SetCurSel(0);
m_strSelectedPM=m_cbPMList.GetCurrentRowID();
}
else//something valid was selected before so stick with it
m_cbPMList.Select(m_strSelectedPM);
FillFields();
}
void CPM::FillFields()
{
CString strData,q;
COleDateTime dtData;
bool bData;
long lData;
ClearFields();
q.Format("SELECT pmhead.* FROM pmhead "
"WHERE (((pmhead.id)=%s));",m_cbPMList.GetCurrentRowID());
rs->Query(q);
EnableFields(false);
m_bNoRecord=true;
m_bEditing=false;
m_btnEdit.ShowWindow(FALSE);
if(rs->IsEmpty())
{
m_btnDelete.EnableWindow(FALSE);
return;
}
m_btnDelete.EnableWindow(TRUE);
m_bNoRecord=false;
//EnableFields(true);
m_btnEdit.ShowWindow(TRUE);
//==============================
//get ID number for scheduling functs.
rs->FetchField("id",&m_lCurrentRecordID);
//IS IT A MODEL?
rs->FetchField("ismodel",&m_bModel);
//DESCRIPTION
rs->FetchField("description",&strData);
m_edDescription.SetWindowText(strData);
//NOTES
rs->FetchField("notes",&strData);
m_edNotes.SetWindowText(strData);
//TYPE
rs->FetchField("type",&lData);
m_nCurrentMode=(int)lData;
//CLIENTBASED
rs->FetchField("isclient",&bData);
m_bClientMode=bData;
//AUTOWO
rs->FetchField("autowo",&m_bAutoWO);
m_ckAutoWO.SetCheck(m_bAutoWO ? TRUE : FALSE);
//AUTOREPEAT
rs->FetchField("autorpt",&m_bAutoRepeat);
m_ckAutoRepeat.SetCheck(m_bAutoRepeat ? TRUE : FALSE);
//DAYOFWEEK
//0 =any 1=monday.....7=sunday
rs->FetchField("dow",&lData);
m_cbDayOfWeek.SetCurSel((int)lData);
//Start / End time
rs->FetchField("starttime",&dtData);
m_dtStartTime.SetTime(dtData);
rs->FetchField("endtime",&dtData);
m_dtEndtime.SetTime(dtData);
//TECH - preferred
rs->FetchField("tech",&lData);
m_strSelectedTech.Format("%u",lData);
FillTechList();
//m_cbTech.Select(lData);
//WOCONVERT
rs->FetchField("woconvert",&lData);
strData.Format("%u",lData);
m_edConvertToWoAfter.SetWindowText(strData);
//=================================================
//Quick workorder
rs->FetchField("woquick",&bData);
m_bQuick=bData;
m_ckQuick.SetCheck(bData ? TRUE : FALSE);
//ONSITE
rs->FetchField("woonsite",&bData);
m_ckOnsite.SetCheck(bData ? TRUE : FALSE);
//Project
rs->FetchField("woproject",&lData);
m_strSelProject.Format("%u",lData);
FillProjectList();
//Category - type
rs->FetchField("wotype",&lData);
m_strSelCategory.Format("%u",lData);
FillTypeList();
//======================================
//NEXT SERVICE DATE nextsrvdate
rs->FetchField("nextsrvdate",&dtData);
if(m_nCurrentMode!=1)//not metered
{
if(m_nCurrentMode==0)
m_dtTimeNextServiceDate.SetTime(dtData);
else
m_dtAgeFirstServiceDate.SetTime(dtData);
}
//NEXT METER SERVICE nextsrvmeter
if(m_nCurrentMode==1)//metered
{
rs->FetchField("nextsrvmeter",&lData);
strData.Format("%u",lData);
m_edMeterFirstService.SetWindowText(strData);
}
/*PMDAYS*/
//REPEAT EVERY repeatevery
rs->FetchField("repeatevery",&lData);
strData.Format("%u",lData);
switch (m_nCurrentMode)
{
case 0://time based
//months
m_edTimeRepeatEveryMonths.SetWindowText(strData);
//weeks
rs->FetchField("rptweeks",&lData);
strData.Format("%u",lData);
m_edTimeRepeatEveryWeeks.SetWindowText(strData);
//days
rs->FetchField("rptdays",&lData);
strData.Format("%u",lData);
m_edTimeRepeatEveryDays.SetWindowText(strData);
break;
case 1://meter based
m_edMeterRepeat.SetWindowText(strData);
break;
default://age based
m_edAgeRepeat.SetWindowText(strData);
break;
}
//AGE MONTHS/YEARS
if(m_nCurrentMode==2)//age mode
{
rs->FetchField("ageyears",&lData);
strData.Format("%u",lData);
m_edAgeYears.SetWindowText(strData);
rs->FetchField("agemonths",&lData);
strData.Format("%u",lData);
m_edAgeMonths.SetWindowText(strData);
}
//ACTIVE / ON HOLD
rs->FetchField("active",&bData);
m_ckHold.SetCheck(bData ? FALSE : TRUE);
//GET SERIES for scheduling
rs->FetchField("series",&lData);
m_nSeries=(int)lData;
strData.Format("%u",m_nSeries);
m_edSeries.SetWindowText(strData);
if(!m_bClientMode)
UpdateMeterCount(false);
GroupClick(m_nCurrentMode);
//SwitchMode();
FillRequiredPartsList();
//Added 02/21/2003 Update title bar with object and detail so
//people know what their dealing with.
SetWindowText("Edit master PM record");//default if below fails in any way
CString strTitleBarText="Edit PM for ";
int nType=0;//default unit
if(m_bClientMode) nType=1;
if(m_bModel) nType=2;
switch(nType)
{
case 0://unit
q.Format("SELECT units.sn AS USN, clients.company AS OWNER, unitmodels.model AS MODEL, "
"nonclients.company_person AS MANU, unitmodels.description AS DESCRIPT "
"FROM (((pmhead LEFT JOIN units ON pmhead.link = units.id) "
"LEFT JOIN unitmodels ON units.model = unitmodels.id) "
"LEFT JOIN clients ON units.client = clients.id) "
"LEFT JOIN nonclients ON unitmodels.manufacturer "
"= nonclients.id WHERE (((pmhead.id)=%s));",m_cbPMList.GetCurrentRowID());
if(!cbrs->QueryReadOnly(q)) goto BAIL;
if(cbrs->IsEmpty()) goto BAIL;
//Ok, we have a record and are ready to retrieve the details
if(!cbrs->FetchField("USN",&strData)) goto BAIL;
strTitleBarText+="Unit - sn:" + strData;
if(!cbrs->FetchField("MANU",&strData)) goto BAIL;
strTitleBarText+=" " + strData;
if(!cbrs->FetchField("MODEL",&strData)) goto BAIL;
strTitleBarText+=" " + strData;
if(!cbrs->FetchField("DESCRIPT",&strData)) goto BAIL;
strTitleBarText+=" " + strData;
if(!cbrs->FetchField("OWNER",&strData)) goto BAIL;
strTitleBarText+=" Client: " + strData;
SetWindowText(strTitleBarText);
break;
case 1://Client
q.Format("SELECT clients.company FROM pmhead LEFT JOIN clients "
"ON pmhead.link = clients.id WHERE (((pmhead.id)=%s)); ",m_cbPMList.GetCurrentRowID());
if(!cbrs->QueryReadOnly(q)) goto BAIL;
if(cbrs->IsEmpty()) goto BAIL;
//Ok, we have a record and are ready to retrieve the details
if(!cbrs->FetchField("company",&strData)) goto BAIL;
strTitleBarText+=" Client - " + strData;
SetWindowText(strTitleBarText);
break;
case 2://Model
q.Format("SELECT pmhead.id, nonclients.company_person, unitmodels.model, "
"unitmodels.description, unitmodelcats.name "
"FROM (pmhead LEFT JOIN (unitmodels LEFT JOIN "
"nonclients ON unitmodels.manufacturer = nonclients.id) "
"ON pmhead.link = unitmodels.id) LEFT JOIN unitmodelcats "
"ON unitmodels.category = unitmodelcats.id "
"WHERE (((pmhead.id)=%s));",m_cbPMList.GetCurrentRowID());
if(!cbrs->QueryReadOnly(q)) goto BAIL;
if(cbrs->IsEmpty()) goto BAIL;
//Ok, we have a record and are ready to retrieve the details
if(!cbrs->FetchField("company_person",&strData)) goto BAIL;
strTitleBarText+=" All units of model - " + strData;
if(!cbrs->FetchField("model",&strData)) goto BAIL;
strTitleBarText+=" " + strData;
if(!cbrs->FetchField("description",&strData)) goto BAIL;
strTitleBarText+=" " + strData;
if(!cbrs->FetchField("name",&strData)) goto BAIL;
if(!strData.IsEmpty())
{
strTitleBarText+=" (" + strData;
strTitleBarText+=")";
}
SetWindowText(strTitleBarText);
break;
}
BAIL:
m_btnEdit.SetFocus();
//==============================
}
void CPM::ClearFields()
{
COleDateTime dtData;
m_cbDayOfWeek.SetCurSel(0);
dtData.SetTime(8,0,0);
m_dtStartTime.SetTime(dtData);
dtData.SetTime(9,0,0);
m_dtEndtime.SetTime(dtData);
m_cbTech.SetCurSel(0);
m_ckAutoRepeat.SetCheck(FALSE);
m_ckAutoWO.SetCheck(FALSE);
m_ckOnsite.SetCheck(TRUE);
m_ckQuick.SetCheck(FALSE);
m_bQuick=false;
m_dtAgeFirstServiceDate.SetTime(COleDateTime::GetCurrentTime());
m_dtTimeNextServiceDate.SetTime(COleDateTime::GetCurrentTime());
m_edAgeMonths.SetWindowText("0");
m_edAgeRepeat.SetWindowText("0");
m_edAgeYears.SetWindowText("0");
m_edConvertToWoAfter.SetWindowText("1");
m_edDescription.SetWindowText("");
m_edMeterFirstService.SetWindowText("0");
m_edMeterLastReading.SetWindowText("0");
m_edMeterRepeat.SetWindowText("0");
m_edNotes.SetWindowText("");
m_edTimeRepeatEveryMonths.SetWindowText("0");
m_edTimeRepeatEveryWeeks.SetWindowText("0");
m_edTimeRepeatEveryDays.SetWindowText("0");
m_rdAge.SetCheck(FALSE);
m_rdMetric.SetCheck(FALSE);
m_rdTime.SetCheck(TRUE);
m_nCurrentMode=0;//default is by time interval
m_edSeries.SetWindowText("2");
m_lbParts.Clear();
m_edPartQuantity.SetWindowText("0");
SwitchMode();
}
void CPM::FillTechList()
{
//10/03/00 - fix for the licensing problem
//if the m_strSelected tech isn't in the list then
//add it "manually" after filling the list as normal
//like this: "* Bob Jones (inactive)"
CString strData;
CString strIndex;
CString q;
long lData;
m_cbTech.Clear();
//any tech default
m_cbTech.AddRow("< Any tech. >","0");
//look for selected tech and see if in inactive list:
if(!m_strSelectedTech.IsEmpty())
{
q.Format("SELECT users.id, [last] & \", \" & [first] AS fullname "
"FROM users "
"WHERE (((users.id)=%s) AND ((users.active)=False));",m_strSelectedTech);
cbrs->Query(q);
if(!cbrs->IsEmpty()) //it's an inactive tech put them in the list "manually"
{
cbrs->FetchField("fullname",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
q="<NA> " + strData;
m_cbTech.AddRow(q,strIndex);
}
}
//change to active only 10/03/00
q="SELECT users.id, [last] & \", \" & [first] AS fullname FROM users "
"WHERE (((users.id)<>1) AND ((users.tech)=True) AND ((users.active)=True)) "
"ORDER BY users.last;";
//////////////////m_pApp->ShowStuff(q);
cbrs->Query(q);
if(!cbrs->IsEmpty())
{
cbrs->MoveFirst();
cbrs->FetchField("fullname",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbTech.AddRow(strData,strIndex);
while(cbrs->MoveForward())
{
cbrs->FetchField("fullname",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbTech.AddRow(strData,strIndex);
}
}
if(!m_strSelectedTech.IsEmpty())
m_cbTech.Select(m_strSelectedTech);
else
{//attempt to select by current user id
m_strSelectedTech.Format("%u",m_pApp->m_lusrID);
m_cbTech.Select(m_strSelectedTech);
}
}
//add new item
void CPM::OnBtnadd()
{
CString strData,q,strDescription;
bool bData;
long lData,lConvert,lDays,lWeeks,lSeries;
COleDateTime dtData;
lData=0;lDays=0;lWeeks=0;lSeries=0;
if(!m_bAddMode && !m_bEditing)
{
//Go Add mode
m_bAddMode=true;
m_bQuick=false;
EnableFields(true);
m_lblPart.ShowWindow(FALSE);
m_lblPartsList.ShowWindow(FALSE);
m_lblQuant.ShowWindow(FALSE);
m_lblPMList.ShowWindow(FALSE);
m_cbPMList.ShowWindow(FALSE);
m_lbParts.ShowWindow(FALSE);
m_btnRemovePart.ShowWindow(FALSE);
m_btnAddPart.ShowWindow(FALSE);
m_cbParts.ShowWindow(FALSE);
m_edPartQuantity.ShowWindow(FALSE);
m_btnDone.ShowWindow(FALSE);
m_btnAdd.SetWindowText("SAVE");
m_btnDelete.SetWindowText("CANCEL");
/////////////////////////m_btnClone.ShowWindow(FALSE);
m_btnEdit.ShowWindow(FALSE);
m_edSeries.SetWindowText("5");
ClearFields();
UpdateMeterCount(false);
}
else
{
//validate and save
//v1.9.4.4 meter based items should not allow first service at meter
//count zero when creating a new record or hundreds of workorders will
//be created
if(m_nCurrentMode==1)//meter based
{
long lTemp=0;
m_edMeterLastReading.GetWindowText(strData);
lTemp=atol(strData);
m_edMeterFirstService.GetWindowText(strData);
lConvert=atol(strData);
if(lConvert<1 || lConvert<lTemp)
{
AfxMessageBox("First meter service count can not be zero or less than the last meter reading value.");
m_edMeterFirstService.SetFocus();
return;
}
}
//CONVERT TO WORKORDER AFTER....
m_edConvertToWoAfter.GetWindowText(strData);
lConvert=atol(strData);
if(lConvert<1 && m_bAutoWO)
{
AfxMessageBox("Convert to workorder value must be higher than zero.");
m_edConvertToWoAfter.SetFocus();
return;
}
//SERIES
m_edSeries.GetWindowText(strData);
lSeries=atol(strData);
if(lSeries<2 || lSeries > 6)
{
AfxMessageBox("Series must be greater than 1 and less than 6.\r\n"
"The default of 2 is recommended\r\n\r\n"
"This value has no effect on the number\r\n"
"of times a workorder will be automatically\r\n"
"generated, only what is shown at any given time in the \r\n"
"preventive maintenance list screen for information\r\n"
"and planning purposes.");
m_edSeries.SetWindowText("2");
m_edSeries.SetFocus();
return;
}
//DESCRIPTION
m_edDescription.GetWindowText(strDescription);
if(strDescription.IsEmpty())
{
AfxMessageBox("Description is required to proceed");
return;
}
//Added 02/20/2003 in case user enters quotes here
strDescription.Replace("\"","''");
if(!m_bEditing)//make a new record
{
//open the recordset
rs->Query("SELECT pmhead.* FROM pmhead WHERE (((pmhead.id)=0));");
rs->pTheConnection->BeginTrans();
if(!rs->AddNewRecord())
{
AfxMessageBox("PM EDIT: Error opening empty RS for addition");
rs->pTheConnection->RollbackTrans();
return;
}
else//Added 09/05/2001 to properly set creator created on new record
{
//Set creator and created
dtData=COleDateTime::GetCurrentTime();
rs->UpdateField("creator",&m_pApp->m_lusrID);
rs->UpdateField("created",&dtData);
}
}
else //change an existing one
{
q.Format("SELECT pmhead.* FROM pmhead WHERE (((pmhead.id)=%s));",m_cbPMList.GetCurrentRowID());
if(!rs->Query(q))
{
AfxMessageBox("PM EDIT: Error opening existing record for update");
return;
}
}
//if not editing a transaction has already been started, otherwise start one now
if(m_bEditing)
rs->pTheConnection->BeginTrans();
rs->UpdateField("description",&strDescription);
//NOTES
m_edNotes.GetWindowText(strData);
//Added 02/20/2003 bug with quotation marks
strData.Replace("\"","''");
//added to avoid bug where would crash in routines that create workorder if notes were empty
if(strData.IsEmpty())
strData="N/A";
rs->UpdateField("notes",&strData);
//CLIENT/UNIT LINK
lData=atol(m_strCriteria);
rs->UpdateField("link",&lData);
//TYPE
lData=(long)m_nCurrentMode;
rs->UpdateField("type",&lData);
//CLIENTBASED
rs->UpdateField("isclient",&m_bClientMode);
//ISMODEL
rs->UpdateField("ismodel",&m_bModel);
//AUTOWO
rs->UpdateField("autowo",&m_bAutoWO);
//AUTOREPEAT
rs->UpdateField("autorpt",&m_bAutoRepeat);
//DAYOFWEEK
//0 =any 1=monday.....7=sunday
lData=(long)m_cbDayOfWeek.GetCurSel();
rs->UpdateField("dow",&lData);
//START / END TIME
m_dtStartTime.GetTime(dtData);
rs->UpdateField("starttime",&dtData);
m_dtEndtime.GetTime(dtData);
rs->UpdateField("endtime",&dtData);
//TECH - preferred
lData=atol(m_cbTech.GetCurrentRowID());
rs->UpdateField("tech",&lData);
//WOCONVERT
rs->UpdateField("woconvert",&lConvert);
//=================================================
//Quick workorder
if(m_bClientMode)
bData=m_ckQuick.GetCheck() ? true : false;
else
bData=false;
rs->UpdateField("woquick",&bData);
//ONSITE
bData=m_ckOnsite.GetCheck() ? true : false;
rs->UpdateField("woonsite",&bData);
//Project
lData=atol(m_cbProjects.GetCurrentRowID());
rs->UpdateField("woproject",&lData);
//Category - type
lData=atol(m_cbCategories.GetCurrentRowID());
rs->UpdateField("wotype",&lData);
//======================================
//NEXT SERVICE DATE nextsrvdate
if(m_nCurrentMode!=1)//not metered
{
if(m_nCurrentMode==0)
m_dtTimeNextServiceDate.GetTime(dtData);
else
m_dtAgeFirstServiceDate.GetTime(dtData);
}
rs->UpdateField("nextsrvdate",&dtData);
//NEXT METER SERVICE nextsrvmeter
if(m_nCurrentMode==1)//metered
{
m_edMeterFirstService.GetWindowText(strData);
lData=atol(strData);
rs->UpdateField("nextsrvmeter",&lData);
}
/*PMDAYS*/
//REPEAT EVERY repeatevery
switch (m_nCurrentMode)
{
case 0://time based
//DAYS
m_edTimeRepeatEveryDays.GetWindowText(strData);
lDays=atol(strData);
//WEEKS
m_edTimeRepeatEveryWeeks.GetWindowText(strData);
lWeeks=atol(strData);
//MONTHS
m_edTimeRepeatEveryMonths.GetWindowText(strData);
break;
case 1://meter based
m_edMeterRepeat.GetWindowText(strData);
break;
default://age based
m_edAgeRepeat.GetWindowText(strData);
break;
}
lData=atol(strData);
if(/*MONTHS if time based:*/lData<1 && lDays<1 && lWeeks<1 && m_bAutoRepeat)
{
AfxMessageBox(
"Warning: the Months/weeks/days or Meter repeat value is 0.\r\n\r\n"
"This means that at *all* series of this scheduled item\r\n"
"are going to be booked on the same day/meter reading.\r\n\r\n"
"You could end up with potentially thousands of workorders in\r\n"
"your schedule all at once depending upon the other settings.\r\n\r\n"
"AyaNova has automatically changed the Months / Meter \r\n"
"value to 999 so you can see which field this message\r\n"
"refers to at a glance to correct the problem\r\n\r\n"
"If you do not want this item to repeat\r\n"
"automatically, uncheck the 'Repeat' box\r\n\r\n"
"See the preventive maintenance reference guide\r\n"
"in the AyaNova manual for more information."
);
lData=999;
}
rs->UpdateField("repeatevery",&lData);
rs->UpdateField("rptweeks",&lWeeks);
rs->UpdateField("rptdays",&lDays);
/*PMDAYS*/
//AGE MONTHS/YEARS
if(m_nCurrentMode==2)//age mode
{
m_edAgeYears.GetWindowText(strData);
lData=atol(strData);
rs->UpdateField("ageyears",&lData);
m_edAgeMonths.GetWindowText(strData);
lData=atol(strData);
rs->UpdateField("agemonths",&lData);
}
//ACTIVE / ON HOLD
bData=m_ckHold.GetCheck() ? false : true;
rs->UpdateField("active",&bData);
//SERIES
m_nSeries=(int)lSeries;
rs->UpdateField("series",&lSeries);
//METER COUNT
UpdateMeterCount(true);
//CREATOR FIELDS
//updated 09/05/2001 to remove creator created here
dtData=COleDateTime::GetCurrentTime();
rs->UpdateField("modifier",&m_pApp->m_lusrID);
rs->UpdateField("modified",&dtData);
if(!rs->SaveRecord())
{
MessageBox("Unable to save this record");
rs->pTheConnection->RollbackTrans();
return;
}
rs->pTheConnection->CommitTrans();
//get ID number
rs->FetchField("id",&m_lCurrentRecordID);
rs->Close();
m_bEditing=false;
m_bAddMode=false;
m_lblPart.ShowWindow(TRUE);
m_lblPMList.ShowWindow(TRUE);
m_cbPMList.ShowWindow(TRUE);
m_lbParts.ShowWindow(TRUE);
m_btnRemovePart.ShowWindow(TRUE);
m_btnAddPart.ShowWindow(TRUE);
m_cbParts.ShowWindow(TRUE);
m_lblPartsList.ShowWindow(TRUE);
m_lblQuant.ShowWindow(TRUE);
m_edPartQuantity.ShowWindow(TRUE);
m_btnDone.ShowWindow(TRUE);
m_btnAdd.SetWindowText("Add new");
m_btnDelete.SetWindowText("Delete");
//////////////////////////m_btnClone.ShowWindow(TRUE);
//create the schedule for this item
Schedule();
FillPMList();
SwitchMode();
}
}
void CPM::FillRequiredPartsList()
{
CString strData,q;
CString strIndex;
long lData;
m_lbParts.Clear();
if(m_bNoRecord) return;
q.Format("SELECT parts.id, \"Quantity: \" & [quantity] & \" of \" & [partnumber] & \" - (\" & [description] & \")\" AS name "
"FROM pmparts LEFT JOIN parts ON pmparts.partnum = parts.id "
"WHERE (((pmparts.pmlink)=%s));",m_strSelectedPM);
cbrs->Query(q);
if(cbrs->IsEmpty())
return;
cbrs->MoveFirst();
do
{
cbrs->FetchField("name",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_lbParts.AddRow(strData,strIndex);
}while(cbrs->MoveForward());
}
void CPM::OnCloseupCbpmlist()
{
CString temp=m_cbPMList.GetCurrentRowID();
if(temp==m_strSelectedPM)
return;
m_strSelectedPM=temp;
FillFields();
}
void CPM::OnBtnaddpart()
{
CString q,strData;
float fData;
m_edPartQuantity.GetWindowText(strData);
//02/19/2003 Fix crash on empty field
if(strData.IsEmpty()) strData="0";
//01/31/2003 convert to a variant bstr
_variant_t vtData(strData);
//fData=(float)vtData;//cast will cause variant to convert to float using locale specific routine
try{//v1.9.4.4 added try / catch mechanism to catch dumb-asses entering text in a numeric field
fData=(float)vtData;//cast variant to float (locale friendly)
}
catch( _com_error &e )
{
AfxMessageBox("I could not interpret your entry in the Part quantity field\r\n"
"I can't save this field until a valid entry is made.\r\n"
"If you want to leave it blank, put a zero in it.");
m_edPartQuantity.Undo();
m_edPartQuantity.SetModify(FALSE);
m_edPartQuantity.SetFocus();
return;
}
//v1.9.4.4 moved from top of this function to here to ensure
//that validation is done under any circumstances (new record)
//this is a guess and might have unintended side effects
//but I don't think so and don't have time to screw around tyring
//to figure out why this was put here in the first place
if(m_bNoRecord) return;
q.Format("SELECT pmparts.pmlink FROM pmparts "
"WHERE (((pmparts.pmlink)=%s) AND ((pmparts.partnum)=%s));",m_strSelectedPM,m_cbParts.GetCurrentRowID());
cbrs->Query(q);
if(!cbrs->IsEmpty())//trying to dupe...tsk tsk
{
AfxMessageBox("The same part can only be in the list once\r\n"
"If you want to change the quantity on a part in the list\r\n"
"You will need to delete it first and then re-add\r\n"
"with the correct quantity");
return;
}
//take the value selected and insert it
q.Format("INSERT INTO pmparts ( pmlink, partnum, quantity ) "
"SELECT %s, %s, %f;",m_strSelectedPM,m_cbParts.GetCurrentRowID(),fData);
cbrs->Ex(q);
cbrs->Close();
FillRequiredPartsList();
}
void CPM::OnBtnremovepart()
{
CString str,q;
if(m_bNoRecord) return;
int x = m_lbParts.SelectionCount();
if(x==0) return;
//Loop through and delete each item
for(int y=0;y<x;y++)
{
q.Format("DELETE pmparts.*, pmparts.pmlink, pmparts.partnum FROM pmparts "
"WHERE (((pmparts.pmlink)=%s) AND ((pmparts.partnum)=%s));",m_strSelectedPM,m_lbParts.GetSelectedItem(y));
if(!rs->Ex(q))
break;
}
FillRequiredPartsList();
}
//Allow editing
void CPM::OnBtnedit()
{
m_bEditing=true;
//enable fields, hide drop boxes etc.
EnableFields(true);
m_lblPMList.ShowWindow(FALSE);
m_cbPMList.ShowWindow(FALSE);
//////////////////////////m_btnClone.ShowWindow(FALSE);
m_btnDone.ShowWindow(FALSE);
m_btnEdit.ShowWindow(FALSE);
m_btnAdd.SetWindowText("SAVE");
m_btnDelete.SetWindowText("CANCEL");
}
void CPM::OnBtndelete()
{
if(m_bAddMode || m_bEditing)//then this is the cancel button
{
//cancel adding or editing
m_bEditing=false;
m_bAddMode=false;
m_lblPart.ShowWindow(TRUE);
m_lblPMList.ShowWindow(TRUE);
m_cbPMList.ShowWindow(TRUE);
m_lbParts.ShowWindow(TRUE);
m_btnRemovePart.ShowWindow(TRUE);
m_btnAddPart.ShowWindow(TRUE);
m_cbParts.ShowWindow(TRUE);
m_lblPartsList.ShowWindow(TRUE);
m_lblQuant.ShowWindow(TRUE);
m_edPartQuantity.ShowWindow(TRUE);
m_btnDone.ShowWindow(TRUE);
m_btnAdd.SetWindowText("Add new");
m_btnDelete.SetWindowText("Delete");
/////////////////////m_btnClone.ShowWindow(TRUE);
FillPMList();
}
else //Delete this record
{
if(AfxMessageBox(
"Caution:\r\n About to delete this preventive maintenance item\r\n"
"Continue?",MB_YESNO)==IDNO) return;
CString q;
//DELETE HEADER RECORD
//locate header record ID
//delete header record
q.Format("DELETE pmhead.*, pmhead.id FROM pmhead WHERE (((pmhead.id)=%s));",m_strSelectedPM);
rs->Ex(q);
//delete all detail items
q.Format("DELETE pmitems.*, pmitems.pmschedlink "
"FROM pmitems WHERE (((pmitems.pmschedlink)=%s));",m_strSelectedPM);
rs->Ex(q);
FillPMList();
}
}
void CPM::OnOK()
{
//enter key hack
// CDialog::OnOK();
}
//empty all occurences of this from the schedule
void CPM::ScheduleClear()
{
CString q;
q.Format("DELETE pmitems.*, pmitems.pmschedlink "
"FROM pmitems "
"WHERE (((pmitems.pmschedlink)=%u));",m_lCurrentRecordID);
rs->Ex(q);
}
//-------------------------------------------------
// +Schedule series or one
//-------------------------------------------------
void CPM::Schedule()
{
long lRepeat,lTech,lMeter,lTempMeter,lMonths=0,lDays,lWeeks,lData,lClient;
CString strData,strHold,strAutoWO,q,strType,strLink;
//Added Jan 13 to start date calc loop at -1 if age based so first item is scheduled on date selected
//instead of date selected + service interval as was doing previously
int yy;
bool bDone=false;
if(m_bClientMode)
strType="True";
else
strType="False";
COleDateTime dtData,dtTemp;
int nSeries,x,nDOW,d,nTemp;
CSimpleDate sdTemp;
//remove previous items if any
ScheduleClear();
//Get the technician
lTech=atol(m_cbTech.GetCurrentRowID());
//Get the DayOfWeek
nDOW=m_cbDayOfWeek.GetCurSel();
//Get the hold factor
if(m_ckHold.GetCheck()==TRUE)
strHold="True";
else
strHold="False";
//Get the AutoWO Factor
strAutoWO=m_bAutoWO ? "True" : "False";
//Set the number of series to schedule
if(m_bAutoRepeat)
{
nSeries=m_nSeries;
}
else
nSeries=1;
//get the repeat value
switch (m_nCurrentMode)
{
case 0://time based
m_edTimeRepeatEveryWeeks.GetWindowText(strData);
lWeeks=atol(strData);
m_edTimeRepeatEveryDays.GetWindowText(strData);
lDays=atol(strData);
m_edTimeRepeatEveryMonths.GetWindowText(strData);
lRepeat=atol(strData);
lMeter=0;
m_dtTimeNextServiceDate.GetTime(dtData);
break;
case 1://meter based
m_edMeterRepeat.GetWindowText(strData);
lRepeat=atol(strData);
m_edMeterFirstService.GetWindowText(strData);
lMeter=atol(strData);
//default date
dtData.SetDate(1968,3,12);
break;
default://age based
m_edAgeRepeat.GetWindowText(strData);
lRepeat=atol(strData);
//Added Jan 13 2003 blatant bug...
lDays=0;lWeeks=0;
lMeter=0;
m_dtAgeFirstServiceDate.GetTime(dtData);
break;
}
//Set the link, will get overwritten if it's a model
strLink=m_strCriteria;
//model loop starts here
if(m_bModel)
{
/*q.Format("SELECT units.id, units.client, units.purchasedate "
"FROM units RIGHT JOIN unitmodels ON units.model = unitmodels.id "
"WHERE (((unitmodels.id)=%s));", m_strCriteria);*/
//changed from above 02/21/2003 was including
//even units that were not set to include in model's PM (pmreport)
q.Format("SELECT units.id, units.client, units.purchasedate FROM "
"units RIGHT JOIN unitmodels ON units.model = unitmodels.id "
"WHERE (((unitmodels.id)=%s) AND ((units.pmreport)=True)); ",m_strCriteria);
cbrs->Query(q);
if(cbrs->IsEmpty()) return;//nothing right now to schedule
cbrs->FetchField("id",&lData);
if(m_nCurrentMode==2)//age based, when a model must use looked up purchase date
cbrs->FetchField("purchasedate",&dtData);
cbrs->FetchField("client",&lClient);
strLink.Format("%u",lData);
}
else//not a model, either a unit or a client
{
if(m_bClientMode)//it's a client?
lClient=atol(m_strCriteria);
else
{//it's a single unit
q.Format("SELECT units.client FROM units "
"WHERE (((units.id)=%s));",m_strCriteria);
cbrs->Query(q);
if(cbrs->IsEmpty())
lClient=0;
else
cbrs->FetchField("client",&lClient);
}
}
//this is a hack to force the first pm item to be
//age advanced if it's an age based item since
//the date would be purchase date and needs to be put ahead.
//while in other modes it's whatever the user picks as the first
//service date
if(m_nCurrentMode==2)
nSeries+=1;
//==================================================================
//do the scheduling
while(!bDone)
{
lMonths=0;
lTempMeter=lMeter;
if(m_nCurrentMode!=2)//if it's age based, need to add on the age first
{
//There's always at least one, schedule it now and do others later
//this avoids the overhead of calculating future dates for single
//only items.
q.Format("INSERT INTO pmitems ( pmschedlink, schedate, schedmeter, autowo, hold, schedtech, link, isclient, clientlink) "
"SELECT %u, #%s#, %u, %s, %s, %u, %s, %s, %u;",
m_lCurrentRecordID,dtData.Format(_T("%m/%d/%Y")),lTempMeter,strAutoWO,strHold,lTech, strLink,strType, lClient);
//DATEFIX: date fixed above to conform to int. settings. Nov 3 2000
// m_pApp->ShowStuff(q);
//EXECUTE
if(!rs->Ex(q))
return;
rs->Close();
}
//prepare a simpledate class object for multi series
CSimpleDate sdOriginal(dtData.GetMonth(),dtData.GetDay(),dtData.GetYear());
/*
#ifdef _DEBUG
m_pApp->ShowStuff(sdOriginal.GetFullDateString());
#endif
*/
//Loop X series occurences if repeating or once if not
//if date based, add dates then go up day by day until hit
//selected weekday
//If meter based, just add "every meter" to item and create records
//Added Jan 13 to start date calc loop at -1 if age based so first item is scheduled on date selected
//instead of date selected + service interval as was doing previously
if(m_nCurrentMode==2)
yy=-1;
else
yy=0;
for(x=yy;x<nSeries-1;x++)
{
if(m_nCurrentMode==1) //calculate next meter mode record
{
//this one's easy:
lTempMeter+=lRepeat;
dtTemp=dtData;
}
else //calculate next date based pmitem record
{//this one isn't:
//Add the months, then increment to the right
//day of week if necessary.
//lMonths+=lRepeat;
/*BUG BUG BUG HERE, NOT INCREMENTING BEYOND FIRST ITME*/
/*EACH days/weeks/months should double for every loop */
//add on the months
sdTemp=sdOriginal;
sdTemp.AddDays(lDays*(x+1));
sdTemp.AddDays((lWeeks*(x+1))*7);
sdTemp.AddMonths(lRepeat*(x+1));
//*******************************************************************
//ADDED DAYS 05/27/2001
//*******************************************************************
//Advance to day of week selected.
//temporary version of nDOW to matchup sunday as first day of week
//make our desired date numeric base match the one returned by the getdayofweek
if(nDOW==7) //sunday=0 in CSimpleDate land
nTemp=0;
else
nTemp=nDOW;
/*#ifdef _DEBUG
q.Format("Raw date after adding months:%s\r\nDesired day of week:%i",sdTemp.GetFullDateStringLong(),nTemp);
AfxMessageBox(q);
#endif*/
d=sdTemp.GetDayOfWeek();
if(nDOW==0)//any weekday
{
if(d==0)//sunday
sdTemp.AddDays(1);//move to monday
if(d==6)//saturday
sdTemp.SubtractDays(1);//move to Friday
}
else//specific day
{
while(d!=nTemp)
{
sdTemp.AddDays(1);
d=sdTemp.GetDayOfWeek();
}
}
/*#ifdef _DEBUG
q.Format("Polished date:%s\r\nNumeric weekday in sdtemp:%i",sdTemp.GetFullDateStringLong(),sdTemp.GetDayOfWeek());
AfxMessageBox(q);
#endif*/
//set dtTemp back again.
//CSimpleDate sdOriginal(dtData.GetMonth(),dtData.GetDay(),dtData.GetYear());
dtTemp.SetDate(sdTemp.GetYear(),sdTemp.GetMonth(),sdTemp.GetDay());
}
q.Format("INSERT INTO pmitems ( pmschedlink, schedate, schedmeter, autowo, hold, schedtech, link, isclient, clientlink) "
"SELECT %u, #%s#, %u, %s, %s, %u, %s, %s, %u;",
m_lCurrentRecordID,dtTemp.Format(_T("%m/%d/%Y")),lTempMeter,strAutoWO,strHold,lTech, strLink, strType, lClient);
//DATEFIX: date fixed above to conform to int. settings. Nov 3 2000
//m_pApp->ShowStuff(q);
//EXECUTE
if(!rs->Ex(q))
return;
rs->Close();
}
if(m_bModel)
{
bDone=!cbrs->MoveForward();
if(!bDone)
{
if(m_nCurrentMode==2)//age based, when a model must use looked up purchase date
cbrs->FetchField("purchasedate",&dtData);
cbrs->FetchField("client",&lClient);
cbrs->FetchField("id",&lData);
strLink.Format("%u",lData);
}
}
else
bDone=true;
}//while not done loop
}
void CPM::OnKillfocusEdageyrs()
{
Aging();
}
void CPM::OnKillfocusEdagemonths()
{
Aging();
}
void CPM::Aging()
{
CString strData;
int nYears,nMonths,nDOW;
COleDateTime dtTemp;
m_edAgeYears.GetWindowText(strData);
if(strData.IsEmpty())
strData="0";
nYears=atoi(strData);
m_edAgeMonths.GetWindowText(strData);
if(strData.IsEmpty())
strData="0";
nMonths=atoi(strData);
//Get the DayOfWeek
nDOW=m_cbDayOfWeek.GetCurSel();
//ADD years and months to the purchase date and update
//the date of service control
CSimpleDate sdTemp(m_dtUnitPurchasedDate.GetMonth(),m_dtUnitPurchasedDate.GetDay(),m_dtUnitPurchasedDate.GetYear());
sdTemp.AddYears(nYears);
sdTemp.AddMonths(nMonths);
//Advance to day of week selected.
//temporary version of nDOW to matchup sunday as first day of week
//make our desired date numeric base match the one returned by the getdayofweek
int nTemp,d;
if(nDOW==7) //sunday=0 in CSimpleDate land
nTemp=0;
else
nTemp=nDOW;
d=sdTemp.GetDayOfWeek();
if(nDOW==0)//any weekday
{
if(d==0)//sunday
sdTemp.AddDays(1);//move to monday
if(d==6)//saturday
sdTemp.SubtractDays(1);//move to Friday
}
else//specific day
{
while(d!=nTemp)
{
sdTemp.AddDays(1);
d=sdTemp.GetDayOfWeek();
}
}
dtTemp.SetDate(sdTemp.GetYear(),sdTemp.GetMonth(),sdTemp.GetDay());
m_dtAgeFirstServiceDate.SetTime(dtTemp);
}
//read/write meter count to unit table
void CPM::UpdateMeterCount(bool bWriting)
{
if(m_bClientMode) return;
long lData;
CString q,strData;
q.Format("SELECT units.lastmeter FROM units "
"WHERE (((units.id)=%s));",m_strCriteria);
cbrs->Query(q);
//m_pApp->ShowStuff(q);
if(cbrs->IsEmpty()) return;
if(bWriting)
{
m_edMeterLastReading.GetWindowText(strData);
if(strData.IsEmpty()) return;
//was it modified at all?
if(m_edMeterLastReading.GetModify()==FALSE) return;
if(AfxMessageBox("Save meter count change to unit record?",MB_YESNO)==IDYES)
{
lData=atol(strData);
cbrs->UpdateField("lastmeter",&lData);
cbrs->SaveRecord();
m_edMeterLastReading.SetModify(FALSE);
}
else
{
m_edMeterLastReading.Undo();
m_edMeterLastReading.SetModify(FALSE);
}
return;
}
else
{
cbrs->FetchField("lastmeter",&lData);
strData.Format("%u",lData);
m_edMeterLastReading.SetWindowText(strData);
m_edMeterLastReading.SetModify(FALSE);
return;
}
}
void CPM::OnKillfocusEdmeterlastreading()
{
if(!m_bAddMode)
UpdateMeterCount(true);
}
void CPM::FillProjectList()
{
CString strData;
long lData;
CString strIndex;
//==========================================
//PROJECTS
m_cbProjects.Clear();
strData="< None >";
strIndex="0";
m_cbProjects.AddRow(strData,strIndex);
cbrs->Query("SELECT projects.* FROM projects "
"WHERE (((projects.active)=True)) "
"ORDER BY projects.name;");
if(!cbrs->IsEmpty())
{
do
{
cbrs->FetchField("name",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbProjects.AddRow(strData,strIndex);
}while(cbrs->MoveForward());
}
if(m_strSelProject.IsEmpty())
m_cbProjects.Select(0);
else
m_cbProjects.Select(m_strSelProject);
//============================================
}
void CPM::FillTypeList()
{
CString strData;
long lData;
CString strIndex;
//============================================
//CATEGORIES
m_cbCategories.Clear();
//first enter default item
strData="< None >";
strIndex="0";
m_cbCategories.AddRow(strData,strIndex);
cbrs->Query("SELECT wotypes.* FROM wotypes ORDER BY wotypes.category;");
if(!cbrs->IsEmpty())
{
do
{
cbrs->FetchField("category",&strData);
cbrs->FetchField("id",&lData);
strIndex.Format("%u",lData);
m_cbCategories.AddRow(strData,strIndex);
}while(cbrs->MoveForward());
}
if(m_strSelCategory.IsEmpty())
m_cbCategories.Select(0);
else
m_cbCategories.Select(m_strSelCategory);
//==========================================
}
void CPM::OnCkquick()
{
m_bQuick=m_ckQuick.GetCheck() ? true:false;
SwitchMode();
}
void CPM::OnLblpart()
{
CPartsDlg d;
d.DoModal();
FillPartsList();
}
void CPM::OnLblproject()
{
CProjectsDlg d;
d.DoModal();
FillProjectList();
}
void CPM::OnLbltype()
{
CWOTypesDlg d;
d.DoModal();
FillTypeList();
}
void CPM::Security()
{
m_bReadOnlySecurity=false;
int x=m_pApp->Allowed(RPM,true);
if(x==0)//no access allowed
{
m_pApp->SecurityWarning();
CDialog::OnCancel();
}
if(x==2)//read only
{
m_bReadOnlySecurity=true;
m_btnAdd.EnableWindow(FALSE);
m_btnDelete.EnableWindow(FALSE);
m_btnEdit.EnableWindow(FALSE);
m_btnClone.EnableWindow(FALSE);
/*
CMenu* pMenu=this->GetMenu();
pMenu->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
*/
}
}